-
Notifications
You must be signed in to change notification settings - Fork 0
/
jikesrvm-3.1.0-gcassertions.diff
6166 lines (6135 loc) · 218 KB
/
jikesrvm-3.1.0-gcassertions.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
diff -ruN jikesrvm-3.1.0/GCASSERTIONS.README jikesrvm-3.1.0-gcassertions/GCASSERTIONS.README
--- jikesrvm-3.1.0/GCASSERTIONS.README 1970-01-01 00:00:00.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/GCASSERTIONS.README 2010-03-19 14:09:52.000000000 +0000
@@ -0,0 +1,254 @@
+This is the README file for the Jikes RVM part of the GC Assertions
+framework, version 3.
+
+
+If you have not yet the README for the ECJ part of the GC Assertions
+framework for this version, do so now, as this README only covers
+low-level matters.
+
+
+
+Configuring
+===========
+Make sure to set your .ant.properties, in your project root, to the
+correct architecture, e.g.
+
+ host.name=x86_64-linux
+
+if you are on AMD64 and Linux.
+
+Building
+========
+Quick build:
+
+ ant -Dconfig.name=BaseBaseGCAssertions
+
+
+Build for fast runtime:
+
+ ant -Dconfig.name=FastAdaptiveGCAssertions
+
+
+Testing
+=======
+ make
+
+or, for the fast adaptive tests,
+
+ make fastadaptive
+
+
+Running
+=======
+
+ The system supports the following command-line arguments:
+
+ -X:gc:dummyGCAssertion=true
+ This ensures that during every GC that does not check a regular
+ assertion, we will instead apply a dummy assertion check to each
+ object encountered. The assertion check is minimal and therefore
+ ideal to measure system overhead.
+
+ -X:gc:dummyGCAssertionwithtraversalID=true
+ (should only be used in conjunction with
+ -X:gc:dummyGCAssertion=true)
+ This extends -X:gc:dummyGCAssertion=true to also track traversal
+ IDs on each object.
+
+ -X:gc:assertfrequency=<n>
+ Assertion checking frequency:
+ -1: never
+ 0: always (default)
+ n: every (n+1)st time
+
+ -X:gc:assertonheapfull=true
+ If we decided not assertion checking by frequency: check GC
+ heuristics and collect if we'd normally GC now
+
+
+
+
+Limitations
+===========
+This won't work on PPC for now (the code generator would have to be
+updated.)
+
+Overlap checks are limited to 15 nested checks: you can check that
+the reachable or dominated nodes of S0 and S1 do (or do not) overlap,
+then that S2 does (or does not) overlap with (S0 \union S1), and so
+on, up to S14, due to limitations on the number of bits we have
+available.
+
+
+Using the system `by hand'
+==========================
+The easiest way to use this system is to use the ECJ frontend. If
+that is not available (or not powerful enough or not a good enough
+choice for other reasons), below are the steps needed to run a
+GCAssertion.
+
+First, all relevant classes are in the package
+
+ org.mmtk.plan.marksweep.gcassertions.spec
+
+Assertion
+---------
+This is the main entry point for running assertions. The static
+`doAssert' method invokes an assertion and returns a boolean to
+determine whether the assertion held up or failed. Usage:
+
+ PredicateFamily[] predicate_families = ...
+ Step[] steps = ...
+ doAssert(new Assertion(predicate_families, steps));
+
+where PredicateFamily and Step are described below.
+
+PredicateFamily
+---------------
+Each assertion tests a list of predicate families. Each predicate
+family describes one quantified expression (forall ..., exists ...).
+However, as we pass through different regions on the heap, each of
+these quantified expressions has to test different properties. For
+example, to check
+
+ forall Node x : (reach(a)[x] -> x.v == 0) &&( reach(b)[x] -> x.v == 1)
+
+has to test three different things: when `x' is reachable from `a',
+it has to test `x.v == 0' (if `x' is a node); when `x' is reachable
+from `b', it has to test `x.v == 1', and otherwise it has to test
+`true'. These three cases are three different predicates. When we
+construct a predicate family, we must provide implementations for each
+of these predicates, as a static helper method in some class C, of the
+following form:
+
+
+ // 2nd static method in this file
+ public static boolean
+ P_a(Object _x, Object[] env)
+ {
+ if (!(_x instanceof Node))
+ return false;
+ final Node x = (Node) _x;
+ return !(x.v == 0);
+ }
+
+ // 3rd static method in this file
+ public static boolean
+ P_b(Object _x, Object[] env)
+ {
+ if (!(_x instanceof Node))
+ return false;
+ final Node x = (Node) _x;
+ return !(x.v == 1);
+ }
+
+Note two things: first, we included the type check in the
+predicate, and second, negated the return value (only in the case that
+_x had the right type.) Negating the return value is necessary for
+universal quantification (`forall') due to a technical reason: the
+predicate should return `true' iff the check is `done,' and for
+`forall' the word `done' means `failed' and for `exists' the word
+`done' means `succeeded' (this hack slightly simplifies the common
+case of the runtime logic.)
+
+To pass P_a and P_b to the PredicateFamily, we tell the family the
+how-many-eth static method in that particular class they are, as
+follows:
+
+PredicateFamily fam =
+ new PredicateFamily(C.class, // which class
+ new int { 1, 2, -1 }, // which methods
+ null, // env
+ PredicateFamily.UNIVERSAL);
+
+The first parameter is the class storing the predicates. The second
+is an array of ints containing the indices. The 2nd static method
+(offset 1) would be represented by `1', the 3rd method (offset 2) by
+`2', and so on. Methods that always return `not finished yet', i.e.,
+`false' in the existential case or `true' in the universal case, can
+be denoted as -1 (which is slightly faster than producing a `proper'
+predicate.)
+
+The `env' parameter is an optional array of objects. These are passed
+to the predicates as the second, `env,' parameter. In conjunction
+with the ECJ frontend they are used to pass the local environment to
+the predicates.
+
+The last parameter can be either PredicateFamily.UNIVERSAL or
+PredicateFamily.EXISTENTIAL and is fairly self-explanatory.
+
+
+Step
+----
+The second parameter to an Assertion is a list of Step objects. Step
+itself is an abstract class; the remaindeer of this section lists
+various valid steps. Note that the array of steps must be well-formed,
+accoriding to the following criteria:
+
+- the first entry in the array must be null (used by the Assertion to
+ exclude internal assertion data from the traversal)
+- the last three entries in the array must be null (as above)
+- no other entry may be `null'
+- there must be at least one root node traversal
+- each `ExcludeNodesStep(N)' must eventually be followed by an
+ `IncludeNodesStep(N)', which must in turn be eventually followed by
+ a `TraversalStep(N).'
+
+
+ExcludeNodesStep
+----------------
+Removes a list of nodes from traversal by marking them as `already
+visited.' This can be exploited for dominance checks or other kinds
+of filtering.
+
+
+IncludeNodesStep
+----------------
+Marks a list of nodes as not having been visited yet. This operation
+cancels out the ExcludeNodesStep.
+
+
+SetTraversalPredicatesStep
+--------------------------
+This operation sets, for each predicate family (in order) the
+predicate that should be tested during the next TraversalStep. For
+example, with
+
+SetTraversalPredicatesStep({ 1, 1, 0 })
+
+predicate family #0 would test their predicate at offset 1
+predicate family #1 would test their predicate at offset 1
+predicate family #2 would test their predicate at offset 0
+
+
+SetTraversalIdStep
+------------------
+This operation sets an ID for the current traversal. If, during the
+traversal, we encounter a heap node that has been tagged with a lower
+ID, we record this fact (cf. Assertion.traversalOverlapped()). Note
+that using SetTraversalIdStep in a traversal program will activate
+additional code in the GC Assertions system that may slow down
+traversal by up to 10% (over total GC runtime.) This slowdown is per
+traversal program and independent of where in the program the first
+`SetTraversalIdStep' appears.
+
+TraversalStep
+-------------
+This operation exists in two forms: without a parameter or with a
+list of nodes. Without a parameter, this operation recursively marks
+the heap, starting from the root set, ignoring any previously touched
+(or excluded-and-not-yet-re-included) nodes and applying traversal
+predicates and checking for overlap.
+
+With a parameter, the operation does the same, except that it starts
+on the nodes specified as parameter rather than at the root set.
+
+
+See gtest/Test.java for examples.
+
+
+Playing around with the system
+==============================
+Most of the system logic is in
+MMTk/src/org/mmtk/plan/marksweep/gcassertions/, with some support
+throughout the RVM code.
diff -ruN jikesrvm-3.1.0/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ObjectModel.java jikesrvm-3.1.0-gcassertions/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ObjectModel.java
--- jikesrvm-3.1.0/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ObjectModel.java 2009-04-24 15:00:43.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ObjectModel.java 2010-02-10 15:35:41.000000000 +0000
@@ -14,6 +14,7 @@
import org.mmtk.utility.alloc.Allocator;
+import org.jikesrvm.VM;
import org.jikesrvm.runtime.Magic;
import org.jikesrvm.objectmodel.JavaHeaderConstants;
import org.jikesrvm.objectmodel.TIB;
@@ -427,5 +428,8 @@
public void dumpObject(ObjectReference object) {
DebugUtil.dumpRef(object);
}
+
+
+
}
diff -ruN jikesrvm-3.1.0/MMTk/harness/vmmagic/org/vmmagic/StaticOptTable.java jikesrvm-3.1.0-gcassertions/MMTk/harness/vmmagic/org/vmmagic/StaticOptTable.java
--- jikesrvm-3.1.0/MMTk/harness/vmmagic/org/vmmagic/StaticOptTable.java 1970-01-01 00:00:00.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/harness/vmmagic/org/vmmagic/StaticOptTable.java 2010-01-26 18:33:02.000000000 +0000
@@ -0,0 +1,27 @@
+package org.vmmagic;
+
+import org.vmmagic.unboxed.Address;
+
+public class StaticOptTable
+{
+
+ /* [CR]
+ * Magic method table operations
+ */
+
+ /** Opt-compile method and return a handle to it for later use. */
+ public static int registerStaticMethodHook(Class<?> c, int static_method_index) {
+ return -1;
+ }
+
+ public static Address lookupStaticMethodHook(int hook) {
+ return null;
+ }
+
+ public static void flushStaticMethodHooks() {
+ }
+
+ public static boolean invokeStaticMethod(Object param1, Object[] param2, Address address) {
+ return false;
+ }
+}
\ No newline at end of file
diff -ruN jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/Plan.java jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/Plan.java
--- jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/Plan.java 2009-04-24 15:00:43.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/Plan.java 2010-07-24 03:33:51.000000000 +0000
@@ -114,6 +114,9 @@
private static final Word LOG_CLEAR_MASK = LOG_SET_MASK.not();
public static final Word UNLOGGED_BIT = VM.activePlan.constraints().unloggedBit();
+ /* Some plans may need to reserve extra bits otherwise used by the `policy' code (i.e., spaces) */
+ public static final int EXTRA_RESERVED_BITS = 0; //VM.activePlan.constraints().extraBitsInHeader();
+
/****************************************************************************
* Class variables
*/
@@ -934,7 +937,7 @@
* @param spaceFull Space request failed, must recover pages within 'space'.
* @return True if a collection is requested by the plan.
*/
- protected boolean collectionRequired(boolean spaceFull) {
+ public boolean collectionRequired(boolean spaceFull) {
boolean stressForceGC = stressTestGCRequired();
boolean heapFull = getPagesReserved() > getTotalPages();
@@ -942,6 +945,16 @@
}
/**
+ * @return True if a collection is coming up reasonably soon.
+ */
+ public boolean collectionAlmostRequired() {
+ boolean stressForceGC = stressTestGCRequired();
+ boolean heapNearFull = (getPagesReserved() * 100l) > (getTotalPages() * 95l);
+
+ return stressForceGC || heapNearFull;
+ }
+
+ /**
* This method controls the triggering of an atomic phase of a concurrent
* collection. It is called periodically during allocation.
*
diff -ruN jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/PlanConstraints.java jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/PlanConstraints.java
--- jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/PlanConstraints.java 2009-05-27 00:07:59.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/PlanConstraints.java 2010-02-19 14:53:17.000000000 +0000
@@ -89,4 +89,7 @@
/** @return A bit which represents that a header is unlogged */
public Word logSetBitMask() {return Word.zero(); }
+
+ /** @return The number of additional bits (max 3) that the MarkSweepSpace should leave untouched */
+ public int extraBitsInheader() { return 0; }
}
diff -ruN jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/TraceLocal.java jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/TraceLocal.java
--- jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/TraceLocal.java 2009-04-24 15:00:43.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/TraceLocal.java 2010-03-22 23:57:25.000000000 +0000
@@ -34,6 +34,9 @@
*/
@Uninterruptible
public abstract class TraceLocal extends TransitiveClosure implements Constants {
+
+ public static final boolean DEBUG_TRACING = false; // [CR] Dump objects and collection phases for external debuggery
+
/****************************************************************************
*
* Instance variables
@@ -102,6 +105,11 @@
*/
@Inline
public final void reportDelayedRootEdge(Address slot) {
+ if (DEBUG_TRACING) {
+ Log.write(" @@root ");
+ Log.write(slot);
+ Log.writeln("");
+ }
rootLocations.push(slot);
}
@@ -116,6 +124,7 @@
*/
@Inline
public final void processRootEdge(Address slot, boolean untraced) {
+// Log.writeln(" (processing root edge)");
ObjectReference object;
if (untraced) object = slot.loadObjectReference();
else object = VM.activePlan.global().loadObjectReference(slot);
@@ -134,6 +143,7 @@
* @param root True if this is a root edge.
*/
public final void processInteriorEdge(ObjectReference target, Address slot, boolean root) {
+// Log.writeln(" (processing interior edge)");
Address interiorRef = slot.loadAddress();
Offset offset = interiorRef.diff(target.toAddress());
ObjectReference newTarget = traceObject(target, root);
@@ -163,6 +173,7 @@
*/
@Inline
protected void scanObject(ObjectReference object) {
+// Log.writeln(" (scanning object)");
if (specializedScan >= 0) {
VM.scanning.specializedScanObject(specializedScan, this, object);
} else {
@@ -183,10 +194,30 @@
*/
@Inline
public final void processNode(ObjectReference object) {
+ if (DEBUG_TRACING) {
+ Log.write(" @@tracing ");
+ Log.write(object);
+ Log.writeln("");
+ }
values.push(object);
+ postProcessNode(object);
+// ++processed_count;
}
/**
+ * Hook for handling a node after it has been pushed to the values queue
+ *
+ * @param obj A recently added object
+ */
+ @Inline
+ protected void
+ postProcessNode(ObjectReference obj)
+ {
+ }
+
+// public int processed_count = 0;
+
+ /**
* Flush the local buffers of all deques.
*/
public final void flush() {
@@ -254,6 +285,11 @@
*/
@Inline
public ObjectReference traceObject(ObjectReference object) {
+// if (DEBUG_TRACING) {
+// Log.write(" @@tracing ");
+// Log.write(object);
+// Log.writeln("");
+// }
if (Space.isInSpace(Plan.VM_SPACE, object))
return (Plan.SCAN_BOOT_IMAGE) ? object : Plan.vmSpace.traceObject(this, object);
if (Space.isInSpace(Plan.IMMORTAL, object))
@@ -461,7 +497,11 @@
public void processRoots() {
logMessage(5, "processing delayed root objects");
while (!rootLocations.isEmpty()) {
- processRootEdge(rootLocations.pop(), true);
+ final Address a = rootLocations.pop();
+// Log.write(" -- root object ");
+// Log.write(a);
+// Log.writeln("");
+ processRootEdge(a, true);
}
}
@@ -480,6 +520,9 @@
do {
while (!values.isEmpty()) {
ObjectReference v = values.pop();
+// Log.write(" -- object reference ");
+// Log.write(v);
+// Log.writeln("");
scanObject(v);
}
processRememberedSets();
diff -ruN jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/TransitiveClosure.java jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/TransitiveClosure.java
--- jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/TransitiveClosure.java 2009-04-24 15:00:43.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/TransitiveClosure.java 2010-01-29 16:31:20.000000000 +0000
@@ -15,6 +15,7 @@
import org.mmtk.vm.VM;
import org.vmmagic.pragma.*;
import org.vmmagic.unboxed.*;
+import org.mmtk.utility.Log;
/**
* This abstract class is the fundamental mechanism for performing a
diff -ruN jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/MS.java jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/MS.java
--- jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/MS.java 2009-04-24 15:00:43.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/MS.java 2010-02-07 17:30:13.000000000 +0000
@@ -146,4 +146,5 @@
TransitiveClosure.registerSpecializedScan(SCAN_MARK, MSTraceLocal.class);
super.registerSpecializedMethods();
}
+
}
diff -ruN jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/MSCollector.java jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/MSCollector.java
--- jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/MSCollector.java 2009-04-24 15:00:43.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/MSCollector.java 2010-02-08 15:12:21.000000000 +0000
@@ -14,6 +14,7 @@
import org.mmtk.plan.*;
import org.mmtk.vm.VM;
+import org.mmtk.utility.Log;
import org.vmmagic.pragma.*;
@@ -39,9 +40,24 @@
/****************************************************************************
* Instance fields
*/
- protected MSTraceLocal fullTrace = new MSTraceLocal(global().msTrace, null);;
- protected TraceLocal currentTrace = fullTrace;
+ protected MSTraceLocal fullTrace;
+ protected TraceLocal currentTrace;
+
+ /****************************************************************************
+ * Initialization
+ */
+ /**
+ * Constructor
+ */
+ public MSCollector() {
+ this(new MSTraceLocal(global().msTrace, null));
+ }
+
+ public MSCollector(MSTraceLocal trace) {
+ fullTrace = trace;
+ currentTrace = fullTrace;
+ }
/****************************************************************************
* Collection
@@ -57,6 +73,7 @@
@Override
public void collectionPhase(short phaseId, boolean primary) {
if (phaseId == MS.PREPARE) {
+// fullTrace.processed_count = 0;
super.collectionPhase(phaseId, primary);
fullTrace.prepare();
return;
@@ -70,6 +87,8 @@
if (phaseId == MS.RELEASE) {
fullTrace.release();
super.collectionPhase(phaseId, primary);
+// Log.write("processed nodes: ");
+// Log.writeln(fullTrace.processed_count);
return;
}
diff -ruN jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/MSTraceLocal.java jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/MSTraceLocal.java
--- jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/MSTraceLocal.java 2009-04-24 15:00:43.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/MSTraceLocal.java 2010-02-07 17:30:46.000000000 +0000
@@ -26,7 +26,7 @@
* closure over a mark-sweep space.
*/
@Uninterruptible
-public final class MSTraceLocal extends TraceLocal {
+public class MSTraceLocal extends TraceLocal {
/****************************************************************************
* Instance fields
*/
diff -ruN jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/gcassertions/GCAssertions.java jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/gcassertions/GCAssertions.java
--- jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/gcassertions/GCAssertions.java 1970-01-01 00:00:00.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/gcassertions/GCAssertions.java 2010-03-22 12:32:20.000000000 +0000
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.plan.marksweep.gcassertions;
+
+import org.mmtk.vm.Lock;
+import org.mmtk.vm.SynchronizedCounter;
+import org.mmtk.plan.Phase;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.marksweep.MS;
+import org.mmtk.plan.marksweep.gcassertions.GCAssertionsHeader;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.deque.SharedDeque;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.options.GCAssertionsDummy;
+import org.mmtk.utility.options.GCAssertionsCollectionOnPressure;
+import org.mmtk.utility.options.GCAssertionsCollectionFrequency;
+import org.mmtk.utility.options.PrintGCAssertionsWarnings;
+import org.mmtk.utility.options.PrintGCAssertionsStats;
+import org.mmtk.utility.ArrayHelpers;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the global state of a our GCAssertions collector.
+ * It is based on the full-heap mark-sweep collector.
+ *
+ */
+@Uninterruptible
+public class GCAssertions extends MS {
+
+ /* We require locks to ensure that multiple mutator threads calling assertions
+ * at the same time do not step on one another.
+ */
+ private static final SynchronizedCounter gcLock = VM.newSynchronizedCounter();
+ private static final Lock lock = VM.newLock("Finalizer");
+
+ public static final short PROCESS = Phase.createSimple("gca");
+ protected static final short processPhase = Phase.createComplex("gca.process", null,
+ Phase.scheduleGlobal (PROCESS),
+ Phase.scheduleCollector (PROCESS));
+
+ /**
+ * Constructor
+ */
+ public GCAssertions() {
+ super();
+
+ // Reachability and dominator phases need to happen befor
+ this.insertPhaseAfter(Phase.scheduleCollector(PRECOPY), Phase.scheduleComplex(processPhase));
+
+ Options.printGCAssertionsWarnings = new PrintGCAssertionsWarnings();
+ Options.printGCAssertionsStats = new PrintGCAssertionsStats();
+ Options.dummyAssertion = new GCAssertionsDummy();
+ Options.assertOnHeapFull = new GCAssertionsCollectionOnPressure();
+ Options.assertFrequency = new GCAssertionsCollectionFrequency();
+ }
+
+ /**
+ * This assertion tells the system that this is the start of a region of
+ * allocation we want to examine. Used in conjunction with
+ * {@link #allDead()}.
+ */
+ @Interruptible
+ public static void startRegion() {
+ ((GCAssertionsMutator)VM.activePlan.mutator()).inRegion = true;
+ }
+
+// /**
+// * This assertion tells the system that all objects allocated since the
+// * last call to {@link #startRegion()} should be unreachable at
+// * the next garbage collection.
+// */
+// @Interruptible
+// public static void allDead() {
+// GCAssertionsMutator mutatorContext = (GCAssertionsMutator)VM.activePlan.mutator();
+// mutatorContext.allDead();
+// }
+
+
+ /**
+ * Register specialized methods.
+ */
+ @Interruptible
+ protected void registerSpecializedMethods() {
+ super.registerSpecializedMethods();
+ TransitiveClosure.registerSpecializedScan(SCAN_MARK, GCAssertionsTraceLocal.class);
+ }
+
+ /****************************************************************************
+ *
+ * Collection
+ */
+
+ public void collectionPhase(short phaseId) {
+
+ // msTrace.prepare();
+
+ if (phaseId == GCAssertions.PROCESS)
+ return;
+
+ else {
+
+ super.collectionPhase(phaseId);
+
+ }
+ }
+
+}
diff -ruN jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/gcassertions/GCAssertionsCollector.java jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/gcassertions/GCAssertionsCollector.java
--- jikesrvm-3.1.0/MMTk/src/org/mmtk/plan/marksweep/gcassertions/GCAssertionsCollector.java 1970-01-01 00:00:00.000000000 +0000
+++ jikesrvm-3.1.0-gcassertions/MMTk/src/org/mmtk/plan/marksweep/gcassertions/GCAssertionsCollector.java 2010-03-23 02:06:42.000000000 +0000
@@ -0,0 +1,333 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.plan.marksweep.gcassertions;
+
+import org.mmtk.plan.marksweep.gcassertions.spec.Step;
+import org.mmtk.plan.marksweep.gcassertions.spec.*;
+import org.mmtk.plan.CollectorContext;
+import org.mmtk.plan.StopTheWorldCollector;
+import org.mmtk.plan.Phase;
+import org.mmtk.plan.marksweep.MS;
+import org.mmtk.plan.marksweep.MSCollector;
+import org.mmtk.plan.marksweep.MSMutator;
+import org.mmtk.utility.options.Options;
+import org.mmtk.vm.VM;
+import org.mmtk.policy.Space;
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+import org.mmtk.utility.Log;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior
+ * and state for the <i>MS</i> plan, which implements a full-heap
+ * mark-sweep collector.<p>
+ *
+ * Specifically, this class defines <i>MS</i> collection behavior
+ * (through <code>trace</code> and the <code>collectionPhase</code>
+ * method).<p>
+ *
+ * @see MS for an overview of the mark-sweep algorithm.<p>
+ *
+ * FIXME The SegregatedFreeList class (and its descendants such as
+ * MarkSweepLocal) does not properly separate mutator and collector
+ * behaviors, so the ms field below should really not exist in
+ * this class as there is no collection-time allocation in this
+ * collector.
+ *
+ * @see MS
+ * @see MSMutator
+ * @see StopTheWorldCollector
+ * @see CollectorContext
+ */
+@Uninterruptible
+public class GCAssertionsCollector extends MSCollector {
+
+ /** Trivial magic query method, used if we are running a fake query */
+ private static final boolean
+ __magic_true(Object _, Object[] __)
+ {
+ return false;
+ }
+
+ /** magic instance-of query method, for running a fake query */
+ private static final boolean
+ __magic_true3(Object obj, Object[] __)
+ {
+ return (obj instanceof Faux);
+ }
+
+
+ public static final boolean ASSERTIONS_ENABLED = true; // set to false to disable all assertion processing (and, hopefully, overhead)
+ public static final boolean ALWAYS_TAG_TRAVERSAL = false; // If true: disable the `don't traversal tag unless GCAsserting' optimisation
+
+ /****************************************************************************
+ * Instance fields
+ */
+ protected GCAssertionsTraceLocal gcaTrace;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ */
+ public GCAssertionsCollector() {
+
+ super(new GCAssertionsTraceLocal(
+ ((GCAssertions)VM.activePlan.global()).msTrace, null));
+ gcaTrace = (GCAssertionsTraceLocal)fullTrace;
+ init_static();
+ }
+
+
+ /****************************************************************************
+ *
+ * Hooks for predicate execution
+ */
+
+ @Inline
+ public final void
+ excludeNode(Object object)
+ {
+ final ObjectReference obj = ObjectReference.fromObject(object);
+
+ if (!obj.isNull()
+ && Space.isInSpace(MS.MARK_SWEEP, obj)) {
+// Log.write("Excluding: ");
+// Log.writeln(obj);
+
+ GCAssertionsHeader.setExcludedVisited(obj, GCAssertions.msSpace.isLive(obj));
+
+ GCAssertions.msSpace.mark(obj);
+ GCAssertionsHeader.setTraversalId(obj, GCAssertionsHeader.MAX_TRAVERSAL_ID);
+ }
+ }
+
+ /**
+ * Untag a boundary nodes and add it to the to-trace set
+ *
+ */
+ @Inline
+ public final void
+ includeNode(Object object)
+ {
+ final ObjectReference obj = ObjectReference.fromObject(object);
+
+ if (!obj.isNull()
+ && Space.isInSpace(MS.MARK_SWEEP, obj)) {
+// Log.write("Including: ");
+// Log.writeln(obj);
+ if (GCAssertionsHeader.isExcludedVisited(obj))
+ GCAssertions.msSpace.mark(obj);
+ else
+ GCAssertions.msSpace.unmark(obj);
+ GCAssertionsHeader.setTraversalId(obj, GCAssertionsTraceLocal.getTraversalId());
+ }
+ }
+
+ /**
+ * Sets the Id to apply to heap traversals and activates traversal ID/overlap checking
+ *
+ */
+ public final void
+ setTraversalId(final int _trace_id)
+ {
+ GCAssertionsTraceLocal.setTraversalId(_trace_id);
+ }
+
+ /**
+ * Enqueues a node for (parallel) collection
+ *
+ */
+ @Inline
+ public final void
+ enqueueNodeForCollection(final Object obj)
+ {
+// Log.write("Enqueueing: ");
+// Log.writeln(ObjectReference.fromObject(obj));
+ MS.msSpace.traceObject(gcaTrace, ObjectReference.fromObject(obj));
+ // gcaTrace.processNode(ObjectReference.fromObject(obj));
+ }
+
+ /**
+ * Enqueues the root set for traversal
+ */
+ public final void
+ enqueueRootSet()
+ {
+// Log.writeln("Root set traversal...");
+ VM.scanning.computeThreadRoots(getCurrentTrace());
+ VM.scanning.computeGlobalRoots(getCurrentTrace());
+ VM.scanning.computeStaticRoots(getCurrentTrace());
+ VM.scanning.computeBootImageRoots(getCurrentTrace());
+ gcaTrace.processRoots();
+ }
+
+ /****************************************************************************
+ *
+ * Collection
+ */
+
+ /**
+ * Perform a per-collector collection phase.
+ *
+ * @param phaseId The collection phase to perform
+ * @param primary Perform any single-threaded activities using this thread.
+ */
+ @Inline
+ public void collectionPhase(short phaseId, boolean primary) {
+ if (org.mmtk.plan.TraceLocal.DEBUG_TRACING) {
+ Log.write(" collectionPhase: ");
+ Log.write(phaseId);
+ Log.write(": ");
+ Log.writeln(org.mmtk.plan.Phase.getName(phaseId));
+ }
+
+ if (phaseId == MS.ROOTS) // handled in the assertion program
+ return;
+ else if (phaseId == MS.STACK_ROOTS) // handled in the assertion program
+ return;
+ else if (phaseId == GCAssertions.INITIATE) {
+ super.collectionPhase(phaseId, primary);
+
+ } else if (phaseId == GCAssertions.PROCESS) {
+ if (Assertion.getAssertion() == null) {
+ int dummyAssertion = Options.dummyAssertion.getValue();
+ if (dummyAssertion > 0) {
+ switch (dummyAssertion) {
+ case 1:
+ Assertion.setAssertion(fake_debug_assertion);
+ //Log.writeln("Always true");
+ break;
+ case 2:
+ Assertion.setAssertion(fake_debug_assertion2);
+ //Log.writeln("Always true with traversal ID");
+ break;
+ case 3:
+ Assertion.setAssertion(fake_debug_assertion3);
+ //Log.writeln("instanceof");
+ break;
+ case 4:
+ Assertion.setAssertion(fake_debug_assertion4);
+ //Log.writeln("instanceof with traversal ID");
+ break;
+ default:
+ VM.assertions._assert(false, "Invalid dummy assertion");
+ }
+ }
+ else
+ Assertion.setAssertion(default_assertion);
+ }
+
+ final Assertion assertion = Assertion.getAssertion();
+
+ final Step[] steps = assertion.getSteps();
+ int program_counter = 0;
+ setTraversalId(0);
+
+ // execute program
+ while (program_counter < steps.length) {
+
+ final boolean needs_closure = steps[program_counter++].run(this);
+
+ if (needs_closure)
+ super.collectionPhase(MS.CLOSURE, primary);
+
+ if (GCAssertionsTraceLocal.getOverlapObject() != null) {
+ Assertion.getAssertion().setTouchedFlag();
+ }
+ }
+ // finished executing
+
+ return;
+ }
+
+ super.collectionPhase(phaseId, primary);
+ }
+
+
+ // --------------------------------------------------------------------------------
+ // Debug predicate
+ private static Assertion fake_debug_assertion;
+ private static Assertion fake_debug_assertion2;
+ private static Assertion fake_debug_assertion3;
+ private static Assertion fake_debug_assertion4;
+ private static Assertion default_assertion;
+
+ @Interruptible
+ static private final void init_static ()
+ {
+ default_assertion =
+ new Assertion(new PredicateFamily[0],
+ new Step[] { null,
+ new TraversalStep(), // mark everything from the roots
+ null,
+ null,
+ null });
+
+
+ final PredicateFamily dummy_predicate =
+ new PredicateFamily(GCAssertionsCollector.class,
+ new int[] { 0 },
+ new Object[] {},
+ PredicateFamily.UNIVERSAL);
+
+ final PredicateFamily dummy_predicate3 =
+ new PredicateFamily(GCAssertionsCollector.class,
+ new int[] { 1 },
+ new Object[] {},
+ PredicateFamily.UNIVERSAL);
+
+ fake_debug_assertion =
+ new Assertion(new PredicateFamily[] { dummy_predicate },
+ new Step[] { null,
+ new SetTraversalPredicatesStep(new int[] { 0 }), // activate test
+ new TraversalStep(), // mark everything from the roots
+ null,
+ null,
+ null });
+
+ fake_debug_assertion2 =
+ new Assertion(new PredicateFamily[] { dummy_predicate },
+ new Step[] { null,
+ new SetTraversalIdStep(0), // Nonsensical traversal ID setting will trigger traversal ID accounting
+ new SetTraversalPredicatesStep(new int[] { 0 }), // activate test
+ new TraversalStep(), // mark everything from the roots
+ null,
+ null,
+ null });