Mercurial > hg > graal-compiler
changeset 10494:6f331db530f6
Add G1 Barrier Snippets
author | Christos Kotselidis <christos.kotselidis@oracle.com> |
---|---|
date | Fri, 21 Jun 2013 11:59:34 +0200 |
parents | a46c3180faed |
children | 0fe1b0886dbf |
files | graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java |
diffstat | 1 files changed, 113 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Jun 21 11:41:34 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Jun 21 11:59:34 2013 +0200 @@ -76,10 +76,105 @@ } } + @Snippet + public static void g1PreWriteBarrier(Object object, Object expectedObject, Object location, @ConstantParameter boolean doLoad) { + Word thread = thread(); + Object fixedObject = FixedValueAnchorNode.getObject(object); + Object fixedExpectedObject = FixedValueAnchorNode.getObject(expectedObject); + Word field = (Word) Word.fromArray(fixedObject, location); + Word previousOop = (Word) Word.fromObject(fixedExpectedObject); + byte markingValue = thread.readByte(HotSpotReplacementsUtil.g1SATBQueueMarkingOffset()); + Word bufferAddress = thread.readWord(HotSpotReplacementsUtil.g1SATBQueueBufferOffset()); + Word indexAddress = thread.add(HotSpotReplacementsUtil.g1SATBQueueIndexOffset()); + Word indexValue = indexAddress.readWord(0); + + // If the concurrent marker is enabled, the barrier is issued. + if (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) { + previousOop = (Word) Word.fromObject(field.readObject(0)); + } + // If the previous value is null the barrier should not be issued. + if (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)) { + Word nextIndex = indexValue.subtract(HotSpotReplacementsUtil.wordSize()); + Word logAddress = bufferAddress.add(nextIndex); + // Log the object to be marked as well as update the SATB's buffer next index. + logAddress.writeWord(0, previousOop); + indexAddress.writeWord(0, nextIndex); + } else { + G1PreWriteBarrierStubCall.call(previousOop.toObject()); + } + } + } + } + + @Snippet + public static void g1PostWriteBarrier(Object object, Object value, Object location, @ConstantParameter boolean usePrecise) { + Word thread = thread(); + Object fixedObject = FixedValueAnchorNode.getObject(object); + Object fixedValue = FixedValueAnchorNode.getObject(value); + Word oop = (Word) Word.fromObject(fixedObject); + Word field; + if (usePrecise) { + field = (Word) Word.fromArray(fixedObject, location); + } else { + field = oop; + } + + Word writtenValue = (Word) Word.fromObject(fixedValue); + Word bufferAddress = thread.readWord(HotSpotReplacementsUtil.g1CardQueueBufferOffset()); + Word indexAddress = thread.add(HotSpotReplacementsUtil.g1CardQueueIndexOffset()); + Word indexValue = thread.readWord(HotSpotReplacementsUtil.g1CardQueueIndexOffset()); + // The result of the xor reveals whether the installed pointer crosses heap regions. + // In case it does the write barrier has to be issued. + Word xorResult = (field.xor(writtenValue)).unsignedShiftRight(HotSpotReplacementsUtil.logOfHRGrainBytes()); + + // Calculate the address of the card to be enqueued to the + // thread local card queue. + Word cardBase = field.unsignedShiftRight(cardTableShift()); + long startAddress = cardTableStart(); + int displacement = 0; + if (((int) startAddress) == startAddress) { + displacement = (int) startAddress; + } else { + cardBase = cardBase.add(Word.unsigned(cardTableStart())); + } + Word cardAddress = cardBase.add(displacement); + + if (xorResult.notEqual(0)) { + // If the written value is not null continue with the barrier addition. + if (writtenValue.notEqual(0)) { + byte cardByte = cardAddress.readByte(0); + // If the card is already dirty, (hence already enqueued) skip the insertion. + if (cardByte != (byte) 0) { + 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)) { + Word nextIndex = indexValue.subtract(HotSpotReplacementsUtil.wordSize()); + Word logAddress = bufferAddress.add(nextIndex); + // Log the object to be scanned as well as update + // the card queue's next index. + logAddress.writeWord(0, cardAddress); + indexAddress.writeWord(0, nextIndex); + } else { + G1PostWriteBarrierStubCall.call(cardAddress); + } + } + } + } + } + public static class Templates extends AbstractTemplates { private final SnippetInfo serialArrayWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayWriteBarrier"); private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier"); + private final SnippetInfo g1PreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PreWriteBarrier"); + private final SnippetInfo g1PostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PostWriteBarrier"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { super(runtime, replacements, target); @@ -100,5 +195,23 @@ args.add("length", arrayRangeWriteBarrier.getLength()); template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } + + public void lower(G1PreWriteBarrier writeBarrierPre, @SuppressWarnings("unused") LoweringTool tool) { + Arguments args = new Arguments(g1PreWriteBarrier); + args.add("object", writeBarrierPre.getObject()); + args.add("expectedObject", writeBarrierPre.getExpectedObject()); + args.add("location", writeBarrierPre.getLocation()); + args.addConst("doLoad", writeBarrierPre.doLoad()); + template(args).instantiate(runtime, writeBarrierPre, DEFAULT_REPLACER, args); + } + + public void lower(G1PostWriteBarrier writeBarrierPost, @SuppressWarnings("unused") LoweringTool tool) { + Arguments args = new Arguments(g1PostWriteBarrier); + args.add("object", writeBarrierPost.getObject()); + args.add("value", writeBarrierPost.getValue()); + args.add("location", writeBarrierPost.getLocation()); + args.addConst("usePrecise", writeBarrierPost.usePrecise()); + template(args).instantiate(runtime, writeBarrierPost, DEFAULT_REPLACER, args); + } } }