# HG changeset patch # User Thomas Wuerthinger # Date 1373232725 -7200 # Node ID 8660a090c3e2535146d6fdb87e50d793e2ea126e # Parent 2ea604c4c6eca11a2993b94e6180db8c2da6cce8# Parent cb2d97f002d443a75d28829b1ed76e0a24d5eaa2 Merge. diff -r 2ea604c4c6ec -r 8660a090c3e2 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Sun Jul 07 22:28:18 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Sun Jul 07 23:32:05 2013 +0200 @@ -32,6 +32,7 @@ import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -630,10 +631,15 @@ new SafepointInsertionPhase().apply(graph); new WriteBarrierAdditionPhase().apply(graph); + int barriers = 0; // First, the total number of expected barriers is checked. - final int barriers = graph.getNodes(SerialWriteBarrier.class).count(); - Assert.assertTrue(expectedBarriers == barriers); - + if (((HotSpotRuntime) runtime()).config.useG1GC) { + barriers = graph.getNodes(G1PreWriteBarrier.class).count() + graph.getNodes(G1PostWriteBarrier.class).count(); + Assert.assertTrue(expectedBarriers * 2 == barriers); + } else { + barriers = graph.getNodes(SerialWriteBarrier.class).count(); + Assert.assertTrue(expectedBarriers == barriers); + } // Iterate over all write nodes and remove barriers according to input indices. NodeIteratorClosure closure = new NodeIteratorClosure() { @@ -653,10 +659,10 @@ } } } - } else if (node instanceof SerialWriteBarrier) { + } else if (node instanceof SerialWriteBarrier || node instanceof G1PostWriteBarrier) { // Remove flagged write barriers. if (currentState) { - graph.removeFixed(((SerialWriteBarrier) node)); + graph.removeFixed(((FixedWithNextNode) node)); return false; } } @@ -692,7 +698,7 @@ try { ReentrantNodeIterator.apply(closure, graph.start(), false, null); Debug.setConfig(Debug.fixedConfig(false, false, false, false, config.dumpHandlers(), config.output())); - new WriteBarrierVerificationPhase().apply(graph); + new WriteBarrierVerificationPhase(((HotSpotRuntime) runtime()).config.useG1GC).apply(graph); } catch (AssertionError error) { /* * Catch assertion, test for expected one and re-throw in order to validate unit diff -r 2ea604c4c6ec -r 8660a090c3e2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sun Jul 07 22:28:18 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sun Jul 07 23:32:05 2013 +0200 @@ -50,6 +50,7 @@ public boolean usePopCountInstruction; public boolean useAESIntrinsics; public boolean useG1GC; + public long gcTotalCollectionsAddress; // Compressed Oops related values. public boolean useCompressedOops; diff -r 2ea604c4c6ec -r 8660a090c3e2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Sun Jul 07 22:28:18 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Sun Jul 07 23:32:05 2013 +0200 @@ -1214,7 +1214,7 @@ ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase()); if (VerifyPhases.getValue()) { - ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase()); + ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config.useG1GC)); } return ret; diff -r 2ea604c4c6ec -r 8660a090c3e2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Sun Jul 07 22:28:18 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Sun Jul 07 23:32:05 2013 +0200 @@ -41,12 +41,18 @@ */ public class WriteBarrierVerificationPhase extends Phase { + private final boolean useG1GC; + + public WriteBarrierVerificationPhase(boolean useG1GC) { + this.useG1GC = useG1GC; + } + @Override protected void run(StructuredGraph graph) { processWrites(graph); } - private static void processWrites(StructuredGraph graph) { + private void processWrites(StructuredGraph graph) { for (Node node : graph.getNodes()) { if (isObjectWrite(node)) { validateWrite(node); @@ -54,7 +60,7 @@ } } - private static void validateWrite(Node write) { + private void validateWrite(Node write) { /* * The currently validated write is checked in order to discover if it has an appropriate * attached write barrier. @@ -68,14 +74,25 @@ while (iterator.hasNext()) { Node currentNode = iterator.next(); assert !isSafepoint(currentNode) : "Write barrier must be present"; - if (!(currentNode instanceof SerialWriteBarrier) || ((currentNode instanceof SerialWriteBarrier) && !validateBarrier(write, (SerialWriteBarrier) currentNode))) { - expandFrontier(frontier, currentNode); + if (useG1GC) { + if (!(currentNode instanceof G1PostWriteBarrier) || ((currentNode instanceof G1PostWriteBarrier) && !validateBarrier(write, (WriteBarrier) currentNode))) { + expandFrontier(frontier, currentNode); + } + } else { + if (!(currentNode instanceof SerialWriteBarrier) || ((currentNode instanceof SerialWriteBarrier) && !validateBarrier(write, (WriteBarrier) currentNode))) { + expandFrontier(frontier, currentNode); + } } } } - private static boolean hasAttachedBarrier(Node node) { - return (((FixedWithNextNode) node).next() instanceof SerialWriteBarrier) && validateBarrier(node, (SerialWriteBarrier) ((FixedWithNextNode) node).next()); + private boolean hasAttachedBarrier(Node node) { + if (useG1GC) { + return ((FixedWithNextNode) node).next() instanceof G1PostWriteBarrier && ((FixedWithNextNode) node).predecessor() instanceof G1PreWriteBarrier && + validateBarrier(node, (G1PostWriteBarrier) ((FixedWithNextNode) node).next()) && validateBarrier(node, (G1PreWriteBarrier) ((FixedWithNextNode) node).predecessor()); + } else { + return (((FixedWithNextNode) node).next() instanceof SerialWriteBarrier) && validateBarrier(node, (SerialWriteBarrier) ((FixedWithNextNode) node).next()); + } } private static boolean isObjectWrite(Node node) { @@ -103,7 +120,7 @@ return ((node instanceof DeoptimizingNode) && ((DeoptimizingNode) node).canDeoptimize()) || (node instanceof LoopBeginNode); } - private static boolean validateBarrier(Node write, SerialWriteBarrier barrier) { + private static boolean validateBarrier(Node write, WriteBarrier barrier) { ValueNode writtenObject = null; LocationNode writtenLocation = null; if (write instanceof WriteNode) { diff -r 2ea604c4c6ec -r 8660a090c3e2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Sun Jul 07 22:28:18 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Sun Jul 07 23:32:05 2013 +0200 @@ -692,4 +692,9 @@ public static int verifiedEntryPointOffset() { return config().nmethodEntryOffset; } + + @Fold + public static long gcTotalCollectionsAddress() { + return config().gcTotalCollectionsAddress; + } } diff -r 2ea604c4c6ec -r 8660a090c3e2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Sun Jul 07 22:28:18 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Sun Jul 07 23:32:05 2013 +0200 @@ -259,7 +259,7 @@ args.addConst("size", size); args.add("hub", hub); args.add("prototypeMarkWord", type.prototypeMarkWord()); - args.addConst("fillContents", newInstanceNode.fillContents()); + args.addConst("fillContents", useG1GC() ? true : newInstanceNode.fillContents()); SnippetTemplate template = template(args); Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); @@ -284,7 +284,7 @@ args.add("prototypeMarkWord", arrayType.prototypeMarkWord()); args.addConst("headerSize", headerSize); args.addConst("log2ElementSize", log2ElementSize); - args.addConst("fillContents", newArrayNode.fillContents()); + args.addConst("fillContents", useG1GC() ? true : newArrayNode.fillContents()); SnippetTemplate template = template(args); Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); @@ -295,7 +295,7 @@ Arguments args = new Arguments(allocateArrayDynamic); args.add("elementType", newArrayNode.getElementType()); args.add("length", newArrayNode.length()); - args.addConst("fillContents", newArrayNode.fillContents()); + args.addConst("fillContents", useG1GC() ? true : newArrayNode.fillContents()); SnippetTemplate template = template(args); template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args); diff -r 2ea604c4c6ec -r 8660a090c3e2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Sun Jul 07 22:28:18 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Sun Jul 07 23:32:05 2013 +0200 @@ -54,7 +54,7 @@ private static Object instanceClone(Object src, Word hub, int layoutHelper) { int instanceSize = layoutHelper; Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - Object result = NewObjectSnippets.allocateInstance(instanceSize, hub, prototypeMarkWord, false); + Object result = NewObjectSnippets.allocateInstance(instanceSize, hub, prototypeMarkWord, useG1GC() ? true : false); Pointer memory = Word.fromObject(result); for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) { @@ -71,7 +71,7 @@ int sizeInBytes = NewObjectSnippets.computeArrayAllocationSize(arrayLength, wordSize(), headerSize, log2ElementSize); Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - Object result = NewObjectSnippets.allocateArray(hub, arrayLength, prototypeMarkWord, headerSize, log2ElementSize, false); + Object result = NewObjectSnippets.allocateArray(hub, arrayLength, prototypeMarkWord, headerSize, log2ElementSize, useG1GC() ? true : false); Pointer memory = Word.fromObject(result); for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) { diff -r 2ea604c4c6ec -r 8660a090c3e2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Sun Jul 07 22:28:18 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Sun Jul 07 23:32:05 2013 +0200 @@ -28,11 +28,13 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.Node.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; @@ -40,12 +42,14 @@ import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; +import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; public class WriteBarrierSnippets implements Snippets { private static final SnippetCounter.Group countersWriteBarriers = SnippetCounters.getValue() ? new SnippetCounter.Group("WriteBarriers") : null; private static final SnippetCounter serialFieldWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialFieldWriteBarrier", "Number of Serial Field Write Barriers"); private static final SnippetCounter serialArrayWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialArrayWriteBarrier", "Number of Serial Array Write Barriers"); + private static final int gcStartCycles = GraalOptions.GCDebugStartCycle.getValue(); @Snippet public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) { @@ -85,19 +89,15 @@ } } - /** - * Log method of debugging purposes. - */ - static void log(boolean enabled, String format, WordBase value) { - if (enabled) { - Log.printf(format, value.rawValue()); + @Snippet + public static void g1PreWriteBarrier(Object object, Object expectedObject, Object location, @ConstantParameter boolean doLoad, @ConstantParameter boolean nullCheck, + @ConstantParameter boolean trace) { + if (nullCheck && object == null) { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); } - } - - @Snippet - public static void g1PreWriteBarrier(Object object, Object expectedObject, Object location, @ConstantParameter boolean doLoad) { Word thread = thread(); Object fixedObject = FixedValueAnchorNode.getObject(object); + verifyOop(fixedObject); Object fixedExpectedObject = FixedValueAnchorNode.getObject(expectedObject); Word field = (Word) Word.fromArray(fixedObject, location); Word previousOop = (Word) Word.fromObject(fixedExpectedObject); @@ -105,19 +105,33 @@ Word bufferAddress = thread.readWord(g1SATBQueueBufferOffset()); Word indexAddress = thread.add(g1SATBQueueIndexOffset()); Word indexValue = indexAddress.readWord(0); - + int gcCycle = 0; + if (trace) { + gcCycle = (int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress()).readLong(0); + log(trace, "[%d] G1-Pre Thread %p Object %p\n", gcCycle, thread.rawValue(), Word.fromObject(fixedObject).rawValue()); + log(trace, "[%d] G1-Pre Thread %p Expected Object %p\n", gcCycle, thread.rawValue(), Word.fromObject(fixedExpectedObject).rawValue()); + log(trace, "[%d] G1-Pre Thread %p Field %p\n", gcCycle, thread.rawValue(), field.rawValue()); + log(trace, "[%d] G1-Pre Thread %p Marking %d\n", gcCycle, thread.rawValue(), markingValue); + log(trace, "[%d] G1-Pre Thread %p DoLoad %d\n", gcCycle, thread.rawValue(), doLoad ? 1L : 0L); + } // If the concurrent marker is enabled, the barrier is issued. - if (markingValue != (byte) 0) { + if (probability(NOT_LIKELY_PROBABILITY, markingValue != (byte) 0)) { // If the previous value has to be loaded (before the write), the load is issued. // The load is always issued except the cases of CAS and referent field. - if (doLoad) { + if (probability(LIKELY_PROBABILITY, doLoad)) { previousOop = (Word) Word.fromObject(field.readObjectCompressed(0)); + if (trace) { + if (previousOop.notEqual(Word.zero())) { + verifyOop(previousOop.toObject()); + } + log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), previousOop.rawValue()); + } } // If the previous value is null the barrier should not be issued. - if (previousOop.notEqual(0)) { + if (probability(FREQUENT_PROBABILITY, previousOop.notEqual(0))) { // If the thread-local SATB buffer is full issue a native call which will // initialize a new one and add the entry. - if (indexValue.notEqual(0)) { + if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) { Word nextIndex = indexValue.subtract(wordSize()); Word logAddress = bufferAddress.add(nextIndex); // Log the object to be marked as well as update the SATB's buffer next index. @@ -131,10 +145,12 @@ } @Snippet - public static void g1PostWriteBarrier(Object object, Object value, Object location, @ConstantParameter boolean usePrecise) { + public static void g1PostWriteBarrier(Object object, Object value, Object location, @ConstantParameter boolean usePrecise, @ConstantParameter boolean trace) { Word thread = thread(); Object fixedObject = FixedValueAnchorNode.getObject(object); Object fixedValue = FixedValueAnchorNode.getObject(value); + verifyOop(fixedObject); + verifyOop(fixedValue); Word oop = (Word) Word.fromObject(fixedObject); Word field; if (usePrecise) { @@ -142,7 +158,12 @@ } else { field = oop; } - + int gcCycle = 0; + if (trace) { + gcCycle = (int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress()).readLong(0); + log(trace, "[%d] G1-Post Thread: %p Object: %p Field: %p\n", gcCycle, thread.rawValue(), Word.fromObject(fixedObject).rawValue()); + log(trace, "[%d] G1-Post Thread: %p Field: %p\n", gcCycle, thread.rawValue(), field.rawValue()); + } Word writtenValue = (Word) Word.fromObject(fixedValue); Word bufferAddress = thread.readWord(g1CardQueueBufferOffset()); Word indexAddress = thread.add(g1CardQueueIndexOffset()); @@ -163,16 +184,17 @@ } Word cardAddress = cardBase.add(displacement); - if (xorResult.notEqual(0)) { + if (probability(LIKELY_PROBABILITY, xorResult.notEqual(0))) { // If the written value is not null continue with the barrier addition. - if (writtenValue.notEqual(0)) { + if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) { byte cardByte = cardAddress.readByte(0); // If the card is already dirty, (hence already enqueued) skip the insertion. - if (cardByte != (byte) 0) { + if (probability(LIKELY_PROBABILITY, cardByte != (byte) 0)) { + log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), Word.unsigned(cardByte).rawValue()); cardAddress.writeByte(0, (byte) 0); // If the thread local card queue is full, issue a native call which will // initialize a new one and add the card entry. - if (indexValue.notEqual(0)) { + if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) { Word nextIndex = indexValue.subtract(wordSize()); Word logAddress = bufferAddress.add(nextIndex); // Log the object to be scanned as well as update @@ -305,6 +327,8 @@ args.add("expectedObject", writeBarrierPre.getExpectedObject()); args.add("location", writeBarrierPre.getLocation()); args.addConst("doLoad", writeBarrierPre.doLoad()); + args.addConst("nullCheck", !writeBarrierPre.getObject().stamp().nonNull()); + args.addConst("trace", traceBarrier()); template(args).instantiate(runtime, writeBarrierPre, DEFAULT_REPLACER, args); } @@ -314,6 +338,7 @@ args.add("value", writeBarrierPost.getValue()); args.add("location", writeBarrierPost.getLocation()); args.addConst("usePrecise", writeBarrierPost.usePrecise()); + args.addConst("trace", traceBarrier()); template(args).instantiate(runtime, writeBarrierPost, DEFAULT_REPLACER, args); } @@ -333,4 +358,29 @@ template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } } + + /** + * Log method of debugging purposes. + */ + private static void log(boolean enabled, String format, long value) { + if (enabled) { + Log.printf(format, value); + } + } + + private static void log(boolean enabled, String format, long value1, long value2) { + if (enabled) { + Log.printf(format, value1, value2); + } + } + + private static void log(boolean enabled, String format, long value1, long value2, long value3) { + if (enabled) { + Log.printf(format, value1, value2, value3); + } + } + + private static boolean traceBarrier() { + return gcStartCycles > 0 && ((int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress()).readLong(0) > gcStartCycles); + } } diff -r 2ea604c4c6ec -r 8660a090c3e2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Sun Jul 07 22:28:18 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Sun Jul 07 23:32:05 2013 +0200 @@ -143,7 +143,8 @@ // Debug settings: @Option(help = "") public static final OptionValue BootstrapReplacements = new OptionValue<>(false); - + @Option(help = "") + public static final OptionValue GCDebugStartCycle = new OptionValue<>(-1); // Ideal graph visualizer output settings @Option(help = "") public static final OptionValue PrintBinaryGraphs = new OptionValue<>(true); diff -r 2ea604c4c6ec -r 8660a090c3e2 src/share/vm/gc_interface/collectedHeap.hpp --- a/src/share/vm/gc_interface/collectedHeap.hpp Sun Jul 07 22:28:18 2013 +0200 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Sun Jul 07 23:32:05 2013 +0200 @@ -490,7 +490,9 @@ // Total number of GC collections (started) unsigned int total_collections() const { return _total_collections; } unsigned int total_full_collections() const { return _total_full_collections;} - +#ifdef GRAAL + void* total_collections_address() { return &_total_collections;} +#endif // Increment total number of GC collections (started) // Should be protected but used by PSMarkSweep - cleanup for 1.4.2 void increment_total_collections(bool full = false) { diff -r 2ea604c4c6ec -r 8660a090c3e2 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Sun Jul 07 22:28:18 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Sun Jul 07 23:32:05 2013 +0200 @@ -907,6 +907,7 @@ set_int("g1SATBQueueBufferOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf())); set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre); set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post); + set_address("gcTotalCollectionsAddress", (jlong)(address)(Universe::heap()->total_collections_address())); BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) {