# HG changeset patch # User Lukas Stadler # Date 1374502779 -7200 # Node ID 63c3d7b5edd9949717b172d86070c403cafb978f # Parent 020f63bfd781a5e1b409e514bdc27d0961ec766f# Parent 02a5f5abd8425fe68d6b99f1db79e438fa530af5 Merge diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Mon Jul 22 16:19:39 2013 +0200 @@ -137,7 +137,9 @@ } /** - * Represents a reference to data from the code. The associated data can be any constant. + * Represents a reference to data from the code. The associated data can be either a + * {@link Constant} or a raw byte array. The raw byte array is patched as is, no endian swapping + * is done on it. */ public static final class DataPatch extends Site { @@ -161,6 +163,8 @@ private DataPatch(int pcOffset, Constant data, byte[] rawData, int alignment, boolean inlined) { super(pcOffset); + assert (data == null) != (rawData == null) : "only one of data and rawData is allowed"; + assert !inlined || rawData == null : "rawData can not be inlined"; this.constant = data; this.rawConstant = rawData; this.alignment = alignment; diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/AbstractHSAILAssembler.java --- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/AbstractHSAILAssembler.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/AbstractHSAILAssembler.java Mon Jul 22 16:19:39 2013 +0200 @@ -54,4 +54,9 @@ protected void patchJumpTarget(int branch, int jumpTarget) { // Nothing to do } + + @Override + protected String createLabelName(Label l, int id) { + return "@L" + id; + } } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java --- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Mon Jul 22 16:19:39 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import static com.oracle.graal.api.code.ValueUtil.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.hsail.*; import com.oracle.graal.graph.GraalInternalError; @@ -144,12 +145,10 @@ } /** - * The mapping to stack slots is always relative to the beginning - * of the spillseg. HSAIL.getStackOffset returns the positive - * version of the originally negative offset. Then we back up - * from that by the argSize in bytes. This ensures that slots of - * different size do not overlap, even though we have converted - * from negative to positive offsets. + * The mapping to stack slots is always relative to the beginning of the spillseg. + * HSAIL.getStackOffset returns the positive version of the originally negative offset. Then we + * back up from that by the argSize in bytes. This ensures that slots of different size do not + * overlap, even though we have converted from negative to positive offsets. */ public static String mapStackSlot(Value reg, int argSize) { long offset = HSAIL.getStackOffset(reg); @@ -213,8 +212,7 @@ public void emitCompare(Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) { String prefix = "cmp_" + condition + (unordered ? "u" : "") + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : getArgType(src1)); - String comment = (isConstant(src1) && (src1.getKind() == Kind.Object) - && (asConstant(src1).asObject() == null) ? " // null test " : ""); + String comment = (isConstant(src1) && (src1.getKind() == Kind.Object) && (asConstant(src1).asObject() == null) ? " // null test " : ""); emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";" + comment); } @@ -269,7 +267,6 @@ emit(mnemonic + "_" + prefix, dest, "", src0, src1); } - private void emit(String instr, Value dest, String controlRegString, Value src0, Value src1) { assert (!isConstant(dest)); emitString(String.format("%s %s, %s%s, %s;", instr, HSAIL.mapRegister(dest), controlRegString, mapRegOrConstToString(src0), mapRegOrConstToString(src1))); @@ -277,17 +274,14 @@ private void emit(String instr, Value dest, Value src0, Value src1, Value src2) { assert (!isConstant(dest)); - emitString(String.format("%s %s, %s, %s, %s;", instr, HSAIL.mapRegister(dest), mapRegOrConstToString(src0), - mapRegOrConstToString(src1), mapRegOrConstToString(src2))); + emitString(String.format("%s %s, %s, %s, %s;", instr, HSAIL.mapRegister(dest), mapRegOrConstToString(src0), mapRegOrConstToString(src1), mapRegOrConstToString(src2))); } - public final void cmovCommon(Value dest, Value trueReg, Value falseReg, int width) { String instr = (width == 32 ? "cmov_b32" : "cmov_b64"); emit(instr, dest, "$c0, ", trueReg, falseReg); } - /** * Emit code to build a 64-bit pointer from a compressed-oop and the associated base and shift. * We only emit this if base and shift are not both zero. @@ -309,9 +303,8 @@ } /** - * Emit code to build a 32-bit compressed pointer from a full - * 64-bit pointer using the associated base and shift. We only - * emit this if base and shift are not both zero. + * Emit code to build a 32-bit compressed pointer from a full 64-bit pointer using the + * associated base and shift. We only emit this if base and shift are not both zero. */ public void emitCompressedOopEncode(Value result, long narrowOopBase, int narrowOopShift) { if (narrowOopBase != 0) { diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java --- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Mon Jul 22 16:19:39 2013 +0200 @@ -64,9 +64,10 @@ * * @param l the label for which a name is being created * @param id a label identifier that is unique with the scope of this assembler + * @return a label name in the form of "L123" */ protected String createLabelName(Label l, int id) { - return "@L" + id; + return "L" + id; } /** diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Mon Jul 22 16:19:39 2013 +0200 @@ -181,7 +181,7 @@ } private static boolean isCompressCandidate(DeoptimizingNode access) { - return access != null && ((HeapAccess) access).compress(); + return access != null && ((HeapAccess) access).isCompressible(); } @Override diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Jul 22 16:19:39 2013 +0200 @@ -405,7 +405,7 @@ } private static boolean isCompressCandidate(DeoptimizingNode access) { - return access != null && ((HeapAccess) access).compress(); + return access != null && ((HeapAccess) access).isCompressible(); } @Override @@ -488,7 +488,7 @@ RegisterValue raxRes = AMD64.rax.asValue(kind); emitMove(raxRes, expected); - if (runtime().config.useCompressedOops && node.compress()) { + if (runtime().config.useCompressedOops && node.isCompressible()) { Variable scratch = newVariable(Kind.Long); append(new CompareAndSwapCompressedOp(raxRes, address, raxRes, newValue, scratch, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment)); } else { diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Mon Jul 22 16:19:39 2013 +0200 @@ -35,7 +35,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.HeapAccess.WriteBarrierType; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.phases.*; @@ -165,7 +165,7 @@ */ @Test public void test6() throws Exception { - test2("test6Snippet", wr, new Long(referentOffset()), null); + test2("testUnsafeLoad", wr, new Long(referentOffset()), null); } /** @@ -174,7 +174,7 @@ */ @Test public void test7() throws Exception { - test2("test6Snippet", con, new Long(referentOffset()), null); + test2("testUnsafeLoad", con, new Long(referentOffset()), null); } /** @@ -184,7 +184,7 @@ */ @Test public void test8() throws Exception { - test2("test6Snippet", wr, new Long(32), null); + test2("testUnsafeLoad", wr, new Long(32), null); } /** @@ -194,7 +194,7 @@ */ @Test public void test10() throws Exception { - test2("test6Snippet", wr, new Long(8), new Integer(8)); + test2("testUnsafeLoad", wr, new Long(8), new Integer(8)); } /** @@ -204,10 +204,10 @@ */ @Test public void test9() throws Exception { - test2("test6Snippet", wr, new Long(16), new Integer(16)); + test2("testUnsafeLoad", wr, new Long(16), new Integer(16)); } - public static Object test6Snippet(Object a, Object b, Object c) throws Exception { + public static Object testUnsafeLoad(Object a, Object b, Object c) throws Exception { final int offset = (c == null ? 0 : ((Integer) c).intValue()); final long displacement = (b == null ? 0 : ((Long) b).longValue()); return UnsafeLoadNode.load(a, offset, displacement, Kind.Object); @@ -233,20 +233,20 @@ int barriers = 0; if (useG1GC()) { - barriers = graph.getNodes(G1PreWriteBarrier.class).count() + graph.getNodes(G1PostWriteBarrier.class).count(); + barriers = graph.getNodes(G1ReferentFieldReadBarrier.class).count() + graph.getNodes(G1PreWriteBarrier.class).count() + graph.getNodes(G1PostWriteBarrier.class).count(); } else { barriers = graph.getNodes(SerialWriteBarrier.class).count(); } Assert.assertTrue(barriers == expectedBarriers); for (WriteNode write : graph.getNodes(WriteNode.class)) { if (useG1GC()) { - if (write.getWriteBarrierType() != WriteBarrierType.NONE) { + if (write.getBarrierType() != BarrierType.NONE) { Assert.assertTrue(write.successors().count() == 1); Assert.assertTrue(write.next() instanceof G1PostWriteBarrier); Assert.assertTrue(write.predecessor() instanceof G1PreWriteBarrier); } } else { - if (write.getWriteBarrierType() != WriteBarrierType.NONE) { + if (write.getBarrierType() != BarrierType.NONE) { Assert.assertTrue(write.successors().count() == 1); Assert.assertTrue(write.next() instanceof SerialWriteBarrier); } @@ -254,15 +254,15 @@ } for (ReadNode read : graph.getNodes(ReadNode.class)) { - if (read.getWriteBarrierType() != WriteBarrierType.NONE) { + if (read.getBarrierType() != BarrierType.NONE) { if (read.location() instanceof ConstantLocationNode) { Assert.assertTrue(((ConstantLocationNode) (read.location())).getDisplacement() == referentOffset()); } else { Assert.assertTrue(((IndexedLocationNode) (read.location())).getDisplacement() == referentOffset()); } Assert.assertTrue(useG1GC()); - Assert.assertTrue(read.getWriteBarrierType() == WriteBarrierType.PRECISE); - Assert.assertTrue(read.next() instanceof G1PreWriteBarrier); + Assert.assertTrue(read.getBarrierType() == BarrierType.PRECISE); + Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier); } } } diff -r 020f63bfd781 -r 63c3d7b5edd9 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 Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Jul 22 16:19:39 2013 +0200 @@ -66,6 +66,7 @@ import com.oracle.graal.api.code.CompilationResult.Infopoint; import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect; @@ -78,7 +79,7 @@ import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.HeapAccess.WriteBarrierType; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -205,8 +206,8 @@ * be re-executed. * @param killedLocations the memory locations killed by the stub call */ - protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, LocationIdentity... killedLocations) { - return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF, reexecutable, killedLocations)); + protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, Transition transition, LocationIdentity... killedLocations) { + return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, transition, reexecutable, killedLocations)); } /** @@ -279,11 +280,11 @@ registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); - link(new NewInstanceStub(this, r, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, ANY_LOCATION))); - link(new NewArrayStub(this, r, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, ANY_LOCATION))); + link(new NewInstanceStub(this, r, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); + link(new NewArrayStub(this, r, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); link(new ExceptionHandlerStub(this, r, target, foreignCalls.get(EXCEPTION_HANDLER))); - link(new UnwindExceptionToCallerStub(this, r, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, ANY_LOCATION))); - link(new VerifyOopStub(this, r, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, NO_LOCATIONS))); + link(new UnwindExceptionToCallerStub(this, r, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); + link(new VerifyOopStub(this, r, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF, NO_LOCATIONS))); linkForeignCall(r, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, MARK_WORD_LOCATION); linkForeignCall(r, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); @@ -487,7 +488,7 @@ ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; ValueNode array = arrayLengthNode.array(); ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt(), - WriteBarrierType.NONE, false)); + BarrierType.NONE, false)); tool.createNullCheckGuard(arrayLengthRead, array); graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); } else if (n instanceof Invoke) { @@ -522,7 +523,7 @@ // compiled code entry as HotSpot does not guarantee they are final // values. ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), - StampFactory.forKind(wordKind()), WriteBarrierType.NONE, false)); + StampFactory.forKind(wordKind()), BarrierType.NONE, false)); loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall)); @@ -545,7 +546,7 @@ HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object(); assert loadField.kind() != Kind.Illegal; - WriteBarrierType barrierType = getFieldLoadBarrierType(field); + BarrierType barrierType = getFieldLoadBarrierType(field); ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object))); tool.createNullCheckGuard(memoryRead, object); @@ -561,7 +562,7 @@ StoreFieldNode storeField = (StoreFieldNode) n; HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object(); - WriteBarrierType barrierType = getFieldStoreBarrierType(storeField); + BarrierType barrierType = getFieldStoreBarrierType(storeField); WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field), barrierType, storeField.field().getKind() == Kind.Object)); tool.createNullCheckGuard(memoryWrite, object); memoryWrite.setStateAfter(storeField.stateAfter()); @@ -580,16 +581,16 @@ CompareAndSwapNode cas = (CompareAndSwapNode) n; LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1); cas.setLocation(location); - cas.setWriteBarrierType(getCompareAndSwapBarrier(cas)); + cas.setBarrierType(getCompareAndSwapBarrier(cas)); if (cas.expected().kind() == Kind.Object) { - cas.setCompress(); + cas.setCompressible(); } } else if (n instanceof LoadIndexedNode) { LoadIndexedNode loadIndexed = (LoadIndexedNode) n; GuardingNode boundsCheck = createBoundsCheck(loadIndexed, tool); Kind elementKind = loadIndexed.elementKind(); LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index()); - ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), WriteBarrierType.NONE, elementKind == Kind.Object)); + ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object)); memoryRead.setGuard(boundsCheck); graph.replaceFixedWithFixed(loadIndexed, memoryRead); } else if (n instanceof StoreIndexedNode) { @@ -619,7 +620,7 @@ value = checkcast; } } - WriteBarrierType barrierType = getArrayStoreBarrierType(storeIndexed); + BarrierType barrierType = getArrayStoreBarrierType(storeIndexed); WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object)); memoryWrite.setGuard(boundsCheck); memoryWrite.setStateAfter(storeIndexed.stateAfter()); @@ -628,12 +629,12 @@ } else if (n instanceof UnsafeLoadNode) { UnsafeLoadNode load = (UnsafeLoadNode) n; assert load.kind() != Kind.Illegal; - boolean compress = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); + boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); if (addReadBarrier(load, tool)) { unsafeLoadSnippets.lower(load, tool); } else { IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), WriteBarrierType.NONE, compress)); + ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible)); // An unsafe read must not float outside its block otherwise // it may float above an explicit null check on its object. memoryRead.setGuard(AbstractBeginNode.prevBegin(load)); @@ -643,7 +644,7 @@ UnsafeStoreNode store = (UnsafeStoreNode) n; IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1); ValueNode object = store.object(); - WriteBarrierType barrierType = getUnsafeStoreBarrierType(store); + BarrierType barrierType = getUnsafeStoreBarrierType(store); WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object)); write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); @@ -704,7 +705,7 @@ value = allocations[commit.getVirtualObjects().indexOf(value)]; } if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { - WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i)), WriteBarrierType.NONE, + WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i)), BarrierType.NONE, virtualInstance.field(i).getKind() == Kind.Object); graph.addBeforeFixed(commit, graph.add(write)); @@ -722,7 +723,7 @@ value = allocations[indexOf]; } if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { - WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), WriteBarrierType.NONE, + WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), BarrierType.NONE, value.kind() == Kind.Object); graph.addBeforeFixed(commit, graph.add(write)); } @@ -769,7 +770,7 @@ int size = FrameStateBuilder.stackSlots(osrLocal.kind()); int offset = localsOffset - (osrLocal.index() + size - 1) * 8; IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1); - ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), WriteBarrierType.NONE, false)); + ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false)); osrLocal.replaceAndDelete(load); graph.addBeforeFixed(migrationEnd, load); } @@ -806,6 +807,8 @@ writeBarrierSnippets.lower((G1PreWriteBarrier) n, tool); } else if (n instanceof G1PostWriteBarrier) { writeBarrierSnippets.lower((G1PostWriteBarrier) n, tool); + } else if (n instanceof G1ReferentFieldReadBarrier) { + writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, tool); } else if (n instanceof SerialWriteBarrier) { writeBarrierSnippets.lower((SerialWriteBarrier) n, tool); } else if (n instanceof SerialArrayRangeWriteBarrier) { @@ -849,68 +852,67 @@ assert vtableEntryOffset > 0; // We use LocationNode.ANY_LOCATION for the reads that access the vtable // entry as HotSpot does not guarantee that this is a final value. - ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()), WriteBarrierType.NONE, - false)); + ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()), BarrierType.NONE, false)); return metaspaceMethod; } private ReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object) { LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph); assert !object.isConstant() || object.asConstant().isNull(); - return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, config.useCompressedKlassPointers)); + return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), BarrierType.NONE, config.useCompressedKlassPointers)); } private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) { LocationNode location = ConstantLocationNode.create(ANY_LOCATION, wordKind, config.hubOffset, graph); assert !object.isConstant() || object.asConstant().isNull(); - return graph.add(new WriteNode(object, value, location, WriteBarrierType.NONE, config.useCompressedKlassPointers)); + return graph.add(new WriteNode(object, value, location, BarrierType.NONE, config.useCompressedKlassPointers)); } - private static WriteBarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) { - WriteBarrierType barrierType = WriteBarrierType.NONE; + private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) { + BarrierType barrierType = BarrierType.NONE; if (config().useG1GC && loadField.getKind() == Kind.Object && loadField.getDeclaringClass().mirror() == java.lang.ref.Reference.class && loadField.getName().equals("referent")) { - barrierType = WriteBarrierType.PRECISE; + barrierType = BarrierType.PRECISE; } return barrierType; } - private static WriteBarrierType getFieldStoreBarrierType(StoreFieldNode storeField) { - WriteBarrierType barrierType = WriteBarrierType.NONE; + private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) { + BarrierType barrierType = BarrierType.NONE; if (storeField.field().getKind() == Kind.Object && !storeField.value().objectStamp().alwaysNull()) { - barrierType = WriteBarrierType.IMPRECISE; + barrierType = BarrierType.IMPRECISE; } return barrierType; } - private static WriteBarrierType getArrayStoreBarrierType(StoreIndexedNode store) { - WriteBarrierType barrierType = WriteBarrierType.NONE; + private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) { + BarrierType barrierType = BarrierType.NONE; if (store.elementKind() == Kind.Object && !store.value().objectStamp().alwaysNull()) { - barrierType = WriteBarrierType.PRECISE; + barrierType = BarrierType.PRECISE; } return barrierType; } - private static WriteBarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) { - WriteBarrierType barrierType = WriteBarrierType.NONE; + private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) { + BarrierType barrierType = BarrierType.NONE; if (store.value().kind() == Kind.Object && !store.value().objectStamp().alwaysNull()) { ResolvedJavaType type = store.object().objectStamp().type(); if (type != null && type.isArray()) { - barrierType = WriteBarrierType.PRECISE; + barrierType = BarrierType.PRECISE; } else { - barrierType = WriteBarrierType.IMPRECISE; + barrierType = BarrierType.IMPRECISE; } } return barrierType; } - private static WriteBarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) { - WriteBarrierType barrierType = WriteBarrierType.NONE; + private static BarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) { + BarrierType barrierType = BarrierType.NONE; if (cas.expected().kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) { ResolvedJavaType type = cas.object().objectStamp().type(); if (type != null && type.isArray()) { - barrierType = WriteBarrierType.PRECISE; + barrierType = BarrierType.PRECISE; } else { - barrierType = WriteBarrierType.IMPRECISE; + barrierType = BarrierType.IMPRECISE; } } return barrierType; @@ -933,6 +935,44 @@ return IndexedLocationNode.create(NamedLocationIdentity.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale); } + @Override + public ValueNode reconstructArrayIndex(LocationNode location) { + Kind elementKind = location.getValueKind(); + assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind)); + + long base; + ValueNode index; + int scale = getScalingFactor(elementKind); + + if (location instanceof ConstantLocationNode) { + base = ((ConstantLocationNode) location).getDisplacement(); + index = null; + } else if (location instanceof IndexedLocationNode) { + IndexedLocationNode indexedLocation = (IndexedLocationNode) location; + assert indexedLocation.getIndexScaling() == scale; + base = indexedLocation.getDisplacement(); + index = indexedLocation.getIndex(); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + + base -= getArrayBaseOffset(elementKind); + assert base >= 0 && base % scale == 0; + + base /= scale; + assert NumUtil.isInt(base); + + if (index == null) { + return ConstantNode.forInt((int) base, location.graph()); + } else { + if (base == 0) { + return index; + } else { + return IntegerArithmeticNode.add(ConstantNode.forInt((int) base, location.graph()), index); + } + } + } + private static GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { StructuredGraph graph = n.graph(); ArrayLengthNode arrayLength = graph.add(new ArrayLengthNode(n.array())); diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Mon Jul 22 16:19:39 2013 +0200 @@ -25,7 +25,7 @@ import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.HeapAccess.WriteBarrierType; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; @@ -54,22 +54,20 @@ } private static void addReadNodeBarriers(ReadNode node, StructuredGraph graph) { - if (node.getWriteBarrierType() == WriteBarrierType.PRECISE) { + if (node.getBarrierType() == BarrierType.PRECISE) { assert useG1GC(); - G1PreWriteBarrier barrier = graph.add(new G1PreWriteBarrier(node.object(), node, node.location(), false, node.getNullCheck())); - barrier.setDeoptimizationState(node.getDeoptimizationState()); - node.setNullCheck(false); + G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.object(), node, node.location(), false, false)); graph.addAfterFixed(node, barrier); } else { - assert node.getWriteBarrierType() == WriteBarrierType.NONE : "Non precise write barrier has been attached to read node."; + assert node.getBarrierType() == BarrierType.NONE : "Non precise read barrier has been attached to read node."; } } private static void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) { - WriteBarrierType barrierType = node.getWriteBarrierType(); - if (barrierType == WriteBarrierType.PRECISE) { + BarrierType barrierType = node.getBarrierType(); + if (barrierType == BarrierType.PRECISE) { if (useG1GC()) { - if (node.isInitialized()) { + if (!node.isInitialization()) { G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck())); preBarrier.setDeoptimizationState(node.getDeoptimizationState()); node.setNullCheck(false); @@ -79,7 +77,7 @@ } else { graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), true))); } - } else if (barrierType == WriteBarrierType.IMPRECISE) { + } else if (barrierType == BarrierType.IMPRECISE) { if (useG1GC()) { G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck())); preBarrier.setDeoptimizationState(node.getDeoptimizationState()); @@ -90,21 +88,21 @@ graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), false))); } } else { - assert barrierType == WriteBarrierType.NONE; + assert barrierType == BarrierType.NONE; } } private static void addCASBarriers(CompareAndSwapNode node, StructuredGraph graph) { - WriteBarrierType barrierType = node.getWriteBarrierType(); - if (barrierType == WriteBarrierType.PRECISE) { + BarrierType barrierType = node.getBarrierType(); + if (barrierType == BarrierType.PRECISE) { if (useG1GC()) { graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false, false))); graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.newValue(), node.getLocation(), true))); } else { graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getLocation(), true))); } - } else if (barrierType == WriteBarrierType.IMPRECISE) { + } else if (barrierType == BarrierType.IMPRECISE) { if (useG1GC()) { graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false, false))); graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.newValue(), node.getLocation(), false))); @@ -112,13 +110,13 @@ graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getLocation(), false))); } } else { - assert barrierType == WriteBarrierType.NONE; + assert barrierType == BarrierType.NONE; } } private static void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) { if (useG1GC()) { - if (node.isInitialized()) { + if (!node.isInitialization()) { G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(node.getArray(), node.getIndex(), node.getLength())); graph.addBeforeFixed(node, g1ArrayRangePreWriteBarrier); } diff -r 020f63bfd781 -r 63c3d7b5edd9 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 Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Mon Jul 22 16:19:39 2013 +0200 @@ -30,7 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.HeapAccess.WriteBarrierType; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; @@ -112,8 +112,8 @@ } private static boolean isObjectWrite(Node node) { - if ((node instanceof WriteNode && (((WriteNode) node).getWriteBarrierType() != WriteBarrierType.NONE)) || - (node instanceof CompareAndSwapNode && (((CompareAndSwapNode) node).getWriteBarrierType() != WriteBarrierType.NONE))) { + if ((node instanceof WriteNode && (((WriteNode) node).getBarrierType() != BarrierType.NONE)) || + (node instanceof CompareAndSwapNode && (((CompareAndSwapNode) node).getBarrierType() != BarrierType.NONE))) { return true; } return false; diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -83,8 +83,8 @@ } @Override - public boolean isInitialized() { - return true; + public boolean isInitialization() { + return false; } public Kind getElementKind() { diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Mon Jul 22 16:19:39 2013 +0200 @@ -26,6 +26,7 @@ import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; @@ -40,9 +41,9 @@ public static Object lowerUnsafeLoad(Object object, long offset, int disp) { long displacement = disp + offset; if (object instanceof java.lang.ref.Reference && referentOffset() == displacement) { - return Word.fromObject(object).readObject((int) displacement, 1, true); + return Word.fromObject(object).readObject((int) displacement, BarrierType.PRECISE, true); } else { - return Word.fromObject(object).readObject((int) displacement, 0, true); + return Word.fromObject(object).readObject((int) displacement, BarrierType.NONE, true); } } diff -r 020f63bfd781 -r 63c3d7b5edd9 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 Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Mon Jul 22 16:19:39 2013 +0200 @@ -33,6 +33,7 @@ import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -118,7 +119,7 @@ // 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 (probability(LIKELY_PROBABILITY, doLoad)) { - previousOop = (Word) Word.fromObject(field.readObject(0, 0, true)); + previousOop = (Word) Word.fromObject(field.readObject(0, BarrierType.NONE, true)); if (trace) { log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), previousOop.rawValue()); verifyOop(previousOop.toObject()); @@ -225,7 +226,7 @@ for (int i = startIndex; i < length; i++) { Word address = (Word) Word.fromObject(dest).add(header).add(Word.unsigned(i * (long) scale)); - oop = (Word) Word.fromObject(address.readObject(0, 0, true)); + oop = (Word) Word.fromObject(address.readObject(0, BarrierType.NONE, true)); if (oop.notEqual(0)) { if (indexValue.notEqual(0)) { Word nextIndex = indexValue.subtract(wordSize()); @@ -294,6 +295,8 @@ 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 g1ReferentReadBarrier = snippet(WriteBarrierSnippets.class, "g1PreWriteBarrier"); private final SnippetInfo g1PostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PostWriteBarrier"); private final SnippetInfo g1ArrayRangePreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier"); private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier"); @@ -329,6 +332,17 @@ template(args).instantiate(runtime, writeBarrierPre, DEFAULT_REPLACER, args); } + public void lower(G1ReferentFieldReadBarrier readBarrier, @SuppressWarnings("unused") LoweringTool tool) { + Arguments args = new Arguments(g1ReferentReadBarrier); + args.add("object", readBarrier.getObject()); + args.add("expectedObject", readBarrier.getExpectedObject()); + args.add("location", readBarrier.getLocation()); + args.addConst("doLoad", readBarrier.doLoad()); + args.addConst("nullCheck", readBarrier.getNullCheck()); + args.addConst("trace", traceBarrier()); + template(args).instantiate(runtime, readBarrier, DEFAULT_REPLACER, args); + } + public void lower(G1PostWriteBarrier writeBarrierPost, @SuppressWarnings("unused") LoweringTool tool) { Arguments args = new Arguments(g1PostWriteBarrier); args.add("object", writeBarrierPost.getObject()); diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Mon Jul 22 16:19:39 2013 +0200 @@ -270,12 +270,12 @@ public static class StoreConstantOp extends MemOp { protected final Constant input; - private final boolean compress; + private final boolean compressible; - public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state, boolean compress) { + public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state, boolean compressible) { super(kind, address, state); this.input = input; - this.compress = compress; + this.compressible = compressible; } @Override @@ -294,7 +294,7 @@ break; case Long: if (NumUtil.isInt(input.asLong())) { - if (compress) { + if (compressible) { masm.movl(address.toAddress(), (int) input.asLong()); } else { masm.movslq(address.toAddress(), (int) input.asLong()); @@ -310,7 +310,7 @@ throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); case Object: if (input.isNull()) { - if (compress) { + if (compressible) { masm.movl(address.toAddress(), 0); } else { masm.movptr(address.toAddress(), 0); diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java Mon Jul 22 16:19:39 2013 +0200 @@ -190,10 +190,13 @@ } LIRInstruction branch = instructions.get(instructions.size() - 2); - if (!(branch instanceof StandardOp.BranchOp) || branch.hasState()) { - // not a valid case for optimization - // currently, only blocks that end with two branches (conditional branch followed - // by unconditional branch) are optimized + if (!(branch instanceof StandardOp.BranchOp) || branch.hasOperands()) { + // Only blocks that end with two branches (conditional branch followed + // by unconditional branch) are optimized. + // In addition, a conditional branch with operands (including state) cannot + // be optimized. Moving a successor instruction before such a branch may + // interfere with the operands of the branch. For example, a successive move + // instruction may redefine an input operand of the branch. return; } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ReferentFieldReadBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ReferentFieldReadBarrier.java Mon Jul 22 16:19:39 2013 +0200 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.extended.*; + +/** + * The {@code G1ReferentFieldReadBarrier} is added when a read access is performed to the referent + * field of a {@link java.lang.ref.Reference} object (through a {@code LoadFieldNode} or an + * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the + * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled. + */ +public class G1ReferentFieldReadBarrier extends WriteBarrier implements DeoptimizingNode { + + @Input private ValueNode expectedObject; + private final boolean doLoad; + + @Input private FrameState deoptimizationState; + private final boolean nullCheck; + + public ValueNode getExpectedObject() { + return expectedObject; + } + + public boolean doLoad() { + return doLoad; + } + + public boolean getNullCheck() { + return nullCheck; + } + + public G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) { + super(object, location, true); + this.doLoad = doLoad; + this.nullCheck = nullCheck; + this.expectedObject = expectedObject; + } + + @Override + public boolean canDeoptimize() { + return nullCheck; + } + + @Override + public FrameState getDeoptimizationState() { + return deoptimizationState; + } + + @Override + public void setDeoptimizationState(FrameState state) { + updateUsages(deoptimizationState, state); + deoptimizationState = state; + } + + @Override + public DeoptimizationReason getDeoptimizationReason() { + return DeoptimizationReason.NullCheckException; + } +} diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -46,6 +46,10 @@ return object; } + public LogicNode condition() { + return condition; + } + /** * Constructor for {@link #guardingNonNull(Object)} node intrinsic. */ diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/HeapAccess.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/HeapAccess.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/HeapAccess.java Mon Jul 22 16:19:39 2013 +0200 @@ -23,25 +23,24 @@ package com.oracle.graal.nodes; /** - * A HeapAccess is a node that access the heap and therefore may be subjected to certain rules of - * the underlying runtime. + * Encapsulates properties of a node describing how it accesses the heap. */ public interface HeapAccess { - /* - * The types of write barriers attached to stores. + /** + * The types of (write/read) barriers attached to stores. */ - public enum WriteBarrierType { - /* - * Primitive stores which do not necessitate write barriers. + public enum BarrierType { + /** + * Primitive stores which do not necessitate barriers. */ NONE, - /* - * Array object stores which necessitate precise write barriers. + /** + * Array object stores which necessitate precise barriers. */ PRECISE, - /* - * Field object stores which necessitate imprecise write barriers. + /** + * Field object stores which necessitate imprecise barriers. */ IMPRECISE } @@ -49,10 +48,10 @@ /** * Gets the write barrier type for that particular access. */ - WriteBarrierType getWriteBarrierType(); + BarrierType getBarrierType(); /** * Returns whether or not the heap access is a compressed pointer candidate. */ - boolean compress(); + boolean isCompressible(); } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -30,7 +30,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.HeapAccess.WriteBarrierType; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -200,9 +200,9 @@ ConstantNode arrayConstant = ConstantNode.forObject(COUNTERS, runtime, graph); ConstantLocationNode location = ConstantLocationNode.create(NamedLocationIdentity.getArrayLocation(Kind.Long), Kind.Long, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph); - ReadNode read = graph.add(new ReadNode(arrayConstant, location, StampFactory.forKind(Kind.Long), WriteBarrierType.NONE, false)); + ReadNode read = graph.add(new ReadNode(arrayConstant, location, StampFactory.forKind(Kind.Long), BarrierType.NONE, false)); IntegerAddNode add = graph.add(new IntegerAddNode(Kind.Long, read, ConstantNode.forLong(increment, graph))); - WriteNode write = graph.add(new WriteNode(arrayConstant, add, location, WriteBarrierType.NONE, false)); + WriteNode write = graph.add(new WriteNode(arrayConstant, add, location, BarrierType.NONE, false)); graph.addBeforeFixed(position, read); graph.addBeforeFixed(position, write); diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -37,8 +37,8 @@ @Input private ValueNode object; @Input private ValueNode location; private boolean nullCheck; - private WriteBarrierType barrierType; - private boolean compress; + private BarrierType barrierType; + private boolean compressible; public ValueNode object() { return object; @@ -61,20 +61,20 @@ } public AccessNode(ValueNode object, ValueNode location, Stamp stamp) { - this(object, location, stamp, null, WriteBarrierType.NONE, false); + this(object, location, stamp, null, BarrierType.NONE, false); } - public AccessNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) { - this(object, location, stamp, null, barrierType, compress); + public AccessNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType, boolean compressible) { + this(object, location, stamp, null, barrierType, compressible); } - public AccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) { + public AccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) { super(stamp); this.object = object; this.location = location; this.guard = guard; this.barrierType = barrierType; - this.compress = compress; + this.compressible = compressible; } @Override @@ -104,12 +104,12 @@ } @Override - public WriteBarrierType getWriteBarrierType() { + public BarrierType getBarrierType() { return barrierType; } @Override - public boolean compress() { - return compress; + public boolean isCompressible() { + return compressible; } } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -56,8 +56,9 @@ public abstract boolean isObjectArray(); /** - * If {@link #isInitialized()} is true, the memory location contains a valid value. If - * {@link #isInitialized()} is false, the memory location is uninitialized or zero. + * Returns whether this write is the initialization of the written location. If it is true, the + * old value of the memory location is either uninitialized or zero. If it is false, the memory + * location is guaranteed to contain a valid value or zero. */ - public abstract boolean isInitialized(); + public abstract boolean isInitialization(); } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -35,12 +35,12 @@ super(object, location, stamp); } - public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) { - super(object, location, stamp, guard, barrierType, compress); + public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) { + super(object, location, stamp, guard, barrierType, compressible); } - public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) { - super(object, location, stamp, barrierType, compress); + public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType, boolean compressible) { + super(object, location, stamp, barrierType, compressible); } public abstract FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess); @@ -51,6 +51,6 @@ * an attached write barrier with pre-semantics can not also float. */ public boolean canFloat() { - return location().getLocationIdentity() != LocationIdentity.ANY_LOCATION && getWriteBarrierType() == WriteBarrierType.NONE; + return location().getLocationIdentity() != LocationIdentity.ANY_LOCATION && getBarrierType() == BarrierType.NONE; } } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -32,8 +32,8 @@ @Input private LocationNode location; @Input private FrameState deoptState; private boolean nullCheck; - private WriteBarrierType barrierType; - private boolean compress; + private BarrierType barrierType; + private boolean compressible; public ValueNode object() { return object; @@ -61,12 +61,12 @@ this.location = location; } - public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) { + public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) { super(stamp, guard); this.object = object; this.location = location; this.barrierType = barrierType; - this.compress = compress; + this.compressible = compressible; } @Override @@ -96,13 +96,13 @@ } @Override - public WriteBarrierType getWriteBarrierType() { + public BarrierType getBarrierType() { return barrierType; } @Override - public boolean compress() { - return compress; + public boolean isCompressible() { + return compressible; } public abstract Access asFixedNode(); diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -37,11 +37,11 @@ @Input private Node lastLocationAccess; public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp) { - this(object, location, lastLocationAccess, stamp, null, WriteBarrierType.NONE, false); + this(object, location, lastLocationAccess, stamp, null, BarrierType.NONE, false); } - public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) { - super(object, location, stamp, guard, barrierType, compress); + public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) { + super(object, location, stamp, guard, barrierType, compressible); this.lastLocationAccess = lastLocationAccess; } @@ -57,11 +57,11 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - return ReadNode.canonicalizeRead(this, location(), object(), tool, compress()); + return ReadNode.canonicalizeRead(this, location(), object(), tool, isCompressible()); } @Override public Access asFixedNode() { - return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard(), getWriteBarrierType(), compress())); + return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard(), getBarrierType(), isCompressible())); } } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -34,12 +34,12 @@ */ public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable, PiPushable, Virtualizable { - public ReadNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) { - super(object, location, stamp, barrierType, compress); + public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType, boolean compressible) { + super(object, location, stamp, barrierType, compressible); } - public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) { - super(object, location, stamp, guard, barrierType, compress); + public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) { + super(object, location, stamp, guard, barrierType, compressible); } public ReadNode(ValueNode object, int displacement, LocationIdentity locationIdentity, Kind kind) { @@ -51,7 +51,7 @@ * Used by node intrinsics. Since the initial value for location is a parameter, i.e., a * LocalNode, the constructor cannot use the declared type LocationNode. */ - super(object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, WriteBarrierType.NONE, false); + super(object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, BarrierType.NONE, false); } @Override @@ -62,12 +62,12 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - return canonicalizeRead(this, location(), object(), tool, compress()); + return canonicalizeRead(this, location(), object(), tool, isCompressible()); } @Override public FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess) { - return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getWriteBarrierType(), compress())); + return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getBarrierType(), isCompressible())); } public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool, boolean compressedPointer) { diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -37,7 +37,7 @@ @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; - private final boolean initialized; + private final boolean initialization; public FrameState stateAfter() { return stateAfter; @@ -58,21 +58,22 @@ } /** - * If {@link #isInitialized()} is true, the memory location contains a valid value. If - * {@link #isInitialized()} is false, the memory location is uninitialized or zero. + * Returns whether this write is the initialization of the written location. If it is true, the + * old value of the memory location is either uninitialized or zero. If it is false, the memory + * location is guaranteed to contain a valid value or zero. */ - public boolean isInitialized() { - return initialized; + public boolean isInitialization() { + return initialization; } - public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType, boolean compress) { - this(object, value, location, barrierType, compress, true); + public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible) { + this(object, value, location, barrierType, compressible, false); } - public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType, boolean compress, boolean initialized) { - super(object, location, StampFactory.forVoid(), barrierType, compress); + public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) { + super(object, location, StampFactory.forVoid(), barrierType, compressible); this.value = value; - this.initialized = initialized; + this.initialization = initialization; } @Override @@ -82,7 +83,7 @@ } @NodeIntrinsic - public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter WriteBarrierType barrierType, @ConstantNodeParameter boolean compress); + public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter BarrierType barrierType, @ConstantNodeParameter boolean compressible); @Override public LocationIdentity getLocationIdentity() { diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -43,8 +43,8 @@ @Input private ValueNode newValue; @Input private LocationNode location; private final int displacement; - private WriteBarrierType barrierType; - private boolean compress; + private BarrierType barrierType; + private boolean compressible; public ValueNode object() { return object; @@ -76,21 +76,21 @@ } @Override - public WriteBarrierType getWriteBarrierType() { + public BarrierType getBarrierType() { return barrierType; } - public void setWriteBarrierType(WriteBarrierType type) { + public void setBarrierType(BarrierType type) { this.barrierType = type; } @Override - public boolean compress() { - return compress; + public boolean isCompressible() { + return compressible; } - public void setCompress() { - this.compress = true; + public void setCompressible() { + this.compressible = true; } public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) { @@ -101,8 +101,8 @@ this.expected = expected; this.newValue = newValue; this.displacement = displacement; - this.barrierType = WriteBarrierType.NONE; - this.compress = false; + this.barrierType = BarrierType.NONE; + this.compressible = false; } @Override diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -57,7 +57,20 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { MetaAccessProvider runtime = tool.runtime(); - if (tool.canonicalizeReads() && runtime != null) { + if (tool.canonicalizeReads()) { + ConstantNode constant = asConstant(runtime); + if (constant != null) { + return constant; + } + } + return this; + } + + /** + * Gets a constant value for this load if possible. + */ + public ConstantNode asConstant(MetaAccessProvider runtime) { + if (runtime != null) { Constant constant = null; if (isStatic()) { constant = field().readConstantValue(null); @@ -68,7 +81,7 @@ return ConstantNode.forConstant(constant, runtime, graph()); } } - return this; + return null; } @Override diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Mon Jul 22 16:19:39 2013 +0200 @@ -25,6 +25,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; /** * Graal-specific extensions for the code cache provider interface. @@ -44,4 +46,13 @@ InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph); void lower(Node n, LoweringTool tool); + + /** + * Reconstruct the array index from a location node that was created as a lowering of an indexed + * access to an array. + * + * @param location a location pointing to an element in an array + * @return a node that gives the index of the element + */ + ValueNode reconstructArrayIndex(LocationNode location); } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Jul 22 16:19:39 2013 +0200 @@ -68,7 +68,7 @@ } long lowerBound = stamp1.lowerBound() + stamp2.lowerBound(); long upperBound = stamp1.upperBound() + stamp2.upperBound(); - long mask = IntegerStamp.maskFor(kind, lowerBound, upperBound) & (stamp1.mask() | stamp2.mask()); + long mask = IntegerStamp.maskFor(kind, lowerBound, upperBound); return StampFactory.forInteger(kind, lowerBound, upperBound, mask); } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Mon Jul 22 16:19:39 2013 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.HeapAccess.WriteBarrierType; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -66,7 +66,7 @@ @Override public void lower(LoweringTool tool, LoweringType loweringType) { IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, value.kind(), displacement, offset, graph(), 1); - WriteNode write = graph().add(new WriteNode(object, value, location, WriteBarrierType.NONE, value.kind() == Kind.Object)); + WriteNode write = graph().add(new WriteNode(object, value, location, BarrierType.NONE, value.kind() == Kind.Object)); graph().replaceFixedWithFixed(this, write); } } diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Mon Jul 22 16:19:39 2013 +0200 @@ -107,6 +107,7 @@ } Assumptions tmpAssumptions = new Assumptions(false); + optimizeGraph(newGraph, tmpAssumptions); HighTierContext context = new HighTierContext(metaAccessProvider, tmpAssumptions, replacements); @@ -153,9 +154,11 @@ CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), null, null); + EarlyReadEliminationPhase earlyRead = new EarlyReadEliminationPhase(new CanonicalizerPhase(true)); + HighTierContext context = new HighTierContext(metaAccessProvider, assumptions, replacements); Integer maxNodes = TruffleCompilerOptions.TruffleOperationCacheMaxNodes.getValue(); - contractGraph(newGraph, eliminate, convertDeoptimizeToGuardPhase, canonicalizerPhase); + contractGraph(newGraph, eliminate, convertDeoptimizeToGuardPhase, canonicalizerPhase, earlyRead, context); while (newGraph.getNodeCount() <= maxNodes) { @@ -168,7 +171,7 @@ break; } - contractGraph(newGraph, eliminate, convertDeoptimizeToGuardPhase, canonicalizerPhase); + contractGraph(newGraph, eliminate, convertDeoptimizeToGuardPhase, canonicalizerPhase, earlyRead, context); } if (newGraph.getNodeCount() > maxNodes && (TruffleCompilerOptions.TraceTruffleCacheDetails.getValue() || TruffleCompilerOptions.TraceTrufflePerformanceWarnings.getValue())) { @@ -177,10 +180,13 @@ } private static void contractGraph(StructuredGraph newGraph, ConditionalEliminationPhase eliminate, ConvertDeoptimizeToGuardPhase convertDeoptimizeToGuardPhase, - CanonicalizerPhase.Instance canonicalizerPhase) { + CanonicalizerPhase.Instance canonicalizerPhase, EarlyReadEliminationPhase earlyRead, HighTierContext context) { // Canonicalize / constant propagate. canonicalizerPhase.apply(newGraph); + // Early read eliminiation + earlyRead.apply(newGraph, context); + // Convert deopt to guards. convertDeoptimizeToGuardPhase.apply(newGraph); diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Jul 22 16:19:39 2013 +0200 @@ -54,7 +54,7 @@ @Option(help = "") public static final OptionValue TruffleConstantUnrollLimit = new OptionValue<>(32); @Option(help = "") - public static final OptionValue TruffleOperationCacheMaxNodes = new OptionValue<>(200); + public static final OptionValue TruffleOperationCacheMaxNodes = new OptionValue<>(350); @Option(help = "") public static final OptionValue TruffleGraphMaxNodes = new OptionValue<>(12000); @Option(help = "") diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Mon Jul 22 16:19:39 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.word; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; public interface Pointer extends Unsigned { @@ -619,10 +620,10 @@ * * @param offset the signed offset for the memory access * @param barrierType the type of the read barrier to be added - * @param compress whether or not the object is a decompression candidate + * @param compressible whether or not the object is a decompression candidate * @return the result of the memory access */ - Object readObject(WordBase offset, int barrierType, boolean compress); + Object readObject(WordBase offset, BarrierType barrierType, boolean compressible); /** * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in @@ -711,10 +712,10 @@ * * @param offset the signed offset for the memory access * @param barrierType the type of the read barrier to be added - * @param compress whether or not the object is a decompression candidate + * @param compressible whether or not the object is a decompression candidate * @return the result of the memory access */ - Object readObject(int offset, int barrierType, boolean compress); + Object readObject(int offset, BarrierType barrierType, boolean compressible); /** * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Jul 22 16:19:39 2013 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.calc.*; public abstract class Word implements Signed, Unsigned, Pointer { @@ -881,7 +882,7 @@ public native Object readObject(WordBase offset); @Operation(opcode = Opcode.READ_HEAP) - public native Object readObject(WordBase offset, int barrierType, boolean compress); + public native Object readObject(WordBase offset, BarrierType barrierType, boolean compressible); @Override @Operation(opcode = Opcode.READ) @@ -938,8 +939,8 @@ } @Operation(opcode = Opcode.READ_HEAP) - public Object readObject(int offset, int barrierType, boolean compress) { - return readObject(signed(offset), barrierType, compress); + public Object readObject(int offset, BarrierType barrierType, boolean compressible) { + return readObject(signed(offset), barrierType, compressible); } @Override diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Jul 22 16:19:39 2013 +0200 @@ -29,7 +29,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.HeapAccess.WriteBarrierType; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -98,6 +98,14 @@ } } + // Fold constant field reads (e.g. enum constants) + for (LoadFieldNode load : graph.getNodes(LoadFieldNode.class).snapshot()) { + ConstantNode constant = load.asConstant(metaAccess); + if (constant != null) { + graph.replaceFixedWithFloating(load, constant); + } + } + // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are // words for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) { @@ -175,14 +183,15 @@ } else { location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2)); } - replace(invoke, readOp(graph, arguments.get(0), invoke, location, 0, false)); + replace(invoke, readOp(graph, arguments.get(0), invoke, location, BarrierType.NONE, false)); break; } case READ_HEAP: { assert arguments.size() == 4; Kind readKind = asKind(callTargetNode.returnType()); LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION); - replace(invoke, readOp(graph, arguments.get(0), invoke, location, arguments.get(2).asConstant().asInt(), arguments.get(3).asConstant().asInt() == 0 ? false : true)); + BarrierType barrierType = (BarrierType) arguments.get(2).asConstant().asObject(); + replace(invoke, readOp(graph, arguments.get(0), invoke, location, barrierType, arguments.get(3).asConstant().asInt() == 0 ? false : true)); break; } case WRITE: @@ -323,8 +332,8 @@ return IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, 1); } - private static ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, int barrierType, boolean compress) { - ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp(), WriteBarrierType.values()[barrierType], compress)); + private static ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) { + ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp(), barrierType, compressible)); graph.addBeforeFixed(invoke.asNode(), read); // The read must not float outside its block otherwise it may float above an explicit zero // check on its base address @@ -334,7 +343,7 @@ private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location, Opcode op) { assert op == Opcode.WRITE || op == Opcode.INITIALIZE; - WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE, false, op == Opcode.WRITE)); + WriteNode write = graph.add(new WriteNode(base, value, location, BarrierType.NONE, false, op == Opcode.INITIALIZE)); write.setStateAfter(invoke.stateAfter()); graph.addBeforeFixed(invoke.asNode(), write); return write; diff -r 020f63bfd781 -r 63c3d7b5edd9 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Mon Jul 22 16:18:55 2013 +0200 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Mon Jul 22 16:19:39 2013 +0200 @@ -24,7 +24,7 @@ import java.lang.annotation.*; -@Retention(RetentionPolicy.CLASS) +@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Specialization {