# HG changeset patch # User Tom Rodriguez # Date 1416932253 28800 # Node ID f3867734051925a503038dcdf7841110505da07f # Parent 9f06d9b2cc43dab3a7a525299b18d1236a548745 Add memory operations to MetaspacePointer diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Tue Nov 25 08:17:33 2014 -0800 @@ -258,7 +258,7 @@ * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass * is an object class, which might not be the case in other parts of the compiled method. */ - return graph.unique(FloatingReadNode.create(arrayHub, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(anchor))); + return graph.unique(FloatingReadNode.create(arrayHub, location, null, KlassPointerStamp.klassNonNull(), BeginNode.prevBegin(anchor))); } @Override diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Tue Nov 25 08:17:33 2014 -0800 @@ -35,6 +35,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -43,7 +44,6 @@ import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; -import com.oracle.graal.word.*; /** * Snippet used for lowering {@link CheckCastDynamicNode}. @@ -51,12 +51,12 @@ public class CheckCastDynamicSnippets implements Snippets { @Snippet - public static Object checkcastDynamic(Word hub, Object object) { + public static Object checkcastDynamic(KlassPointer hub, Object object) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { isNull.inc(); } else { GuardingNode anchorNode = SnippetAnchorNode.anchor(); - Pointer objectHub = loadHubIntrinsic(object, anchorNode).asWord(); + KlassPointer objectHub = loadHubIntrinsic(object, anchorNode); if (!checkUnknownSubType(hub, objectHub)) { DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); } diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Tue Nov 25 08:17:33 2014 -0800 @@ -51,7 +51,7 @@ // Class for primitive type return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; } else { - return klass.asWord().readInt(klassModifierFlagsOffset(), KLASS_MODIFIER_FLAGS_LOCATION); + return klass.readInt(klassModifierFlagsOffset(), KLASS_MODIFIER_FLAGS_LOCATION); } } @@ -63,7 +63,7 @@ if (klass.isNull()) { return false; } else { - int accessFlags = klass.asWord().readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION); + int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION); return (accessFlags & Modifier.INTERFACE) != 0; } } @@ -94,12 +94,11 @@ @MacroSubstitution(macro = ClassGetSuperclassNode.class, isStatic = false) @MethodSubstitution(isStatic = false) public static Class getSuperclass(final Class thisObj) { - KlassPointer klassPtr = ClassGetHubNode.readClass(thisObj); - if (!klassPtr.isNull()) { - Pointer klass = klassPtr.asWord(); + KlassPointer klass = ClassGetHubNode.readClass(thisObj); + if (!klass.isNull()) { int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION); if ((accessFlags & Modifier.INTERFACE) == 0) { - if (klassIsArray(klassPtr)) { + if (klassIsArray(klass)) { return Object.class; } else { Word superKlass = klass.readWord(klassSuperKlassOffset(), KLASS_SUPER_KLASS_LOCATION); @@ -120,7 +119,7 @@ KlassPointer klass = ClassGetHubNode.readClass(thisObj); if (!klass.isNull()) { if (klassIsArray(klass)) { - return piCastExactNonNull(klass.asWord().readObject(arrayKlassComponentMirrorOffset(), ARRAY_KLASS_COMPONENT_MIRROR), Class.class); + return piCastExactNonNull(klass.readObject(arrayKlassComponentMirrorOffset(), ARRAY_KLASS_COMPONENT_MIRROR), Class.class); } } return null; @@ -146,7 +145,7 @@ // primitive types, only true if equal. return thisClass == otherClass; } - if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub.asWord(), otherHub.asWord())) { + if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub, otherHub)) { return false; } return true; diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java Tue Nov 25 08:17:33 2014 -0800 @@ -43,6 +43,6 @@ // so we are guaranteed to read a non-null value here. As long as NodeClass // is final, the stamp of the PiNode below will automatically be exact. KlassPointer klass = loadHub(node); - return piCastNonNull(klass.asWord().readObject(Word.signed(instanceKlassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class); + return piCastNonNull(klass.readObject(Word.signed(instanceKlassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class); } } diff -r 9f06d9b2cc43 -r f38677340519 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 Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Tue Nov 25 08:17:33 2014 -0800 @@ -629,11 +629,11 @@ * @param hub the hub of an InstanceKlass * @return true is the InstanceKlass represented by hub is fully initialized */ - public static boolean isInstanceKlassFullyInitialized(Pointer hub) { + public static boolean isInstanceKlassFullyInitialized(KlassPointer hub) { return readInstanceKlassState(hub) == instanceKlassStateFullyInitialized(); } - private static byte readInstanceKlassState(Pointer hub) { + private static byte readInstanceKlassState(KlassPointer hub) { return hub.readByte(instanceKlassInitStateOffset(), CLASS_STATE_LOCATION); } diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Tue Nov 25 08:17:33 2014 -0800 @@ -50,7 +50,6 @@ import com.oracle.graal.replacements.SnippetTemplate.Arguments; import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.word.*; /** * Snippets used for implementing the type test of an instanceof instruction. Since instanceof is a @@ -142,8 +141,8 @@ return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - Pointer objectHub = loadHubIntrinsic(object, anchorNode).asWord(); - if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, PRIMARY_SUPERS_LOCATION).notEqual(hub.asWord()))) { + KlassPointer objectHub = loadHubIntrinsic(object, anchorNode); + if (probability(NOT_LIKELY_PROBABILITY, objectHub.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).notEqual(hub))) { displayMiss.inc(); return falseValue; } @@ -172,7 +171,7 @@ return positive ? trueValue : falseValue; } } - if (!checkSecondarySubType(hub.asWord(), objectHub.asWord())) { + if (!checkSecondarySubType(hub, objectHub)) { return falseValue; } return trueValue; @@ -190,7 +189,7 @@ GuardingNode anchorNode = SnippetAnchorNode.anchor(); KlassPointer hub = ClassGetHubNode.readClass(mirror, anchorNode); KlassPointer objectHub = loadHubIntrinsic(object, anchorNode); - if (hub.isNull() || !checkUnknownSubType(hub.asWord(), objectHub.asWord())) { + if (hub.isNull() || !checkUnknownSubType(hub, objectHub)) { return falseValue; } return trueValue; diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue Nov 25 08:17:33 2014 -0800 @@ -40,6 +40,7 @@ import com.oracle.graal.graph.iterators.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.debug.*; @@ -128,7 +129,7 @@ } else { // The bias pattern is present in the object's mark word. Need to check // whether the bias owner and the epoch are both still current. - Pointer hub = loadHubIntrinsic(object, anchorNode).asWord(); + KlassPointer hub = loadHubIntrinsic(object, anchorNode); final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); final Word thread = registerAsWord(threadRegister); final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace()); diff -r 9f06d9b2cc43 -r f38677340519 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 Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Nov 25 08:17:33 2014 -0800 @@ -153,11 +153,10 @@ @Snippet public static Object allocateInstanceDynamic(Class type, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter String typeContext) { - KlassPointer hubPtr = ClassGetHubNode.readClass(type); - if (probability(FAST_PATH_PROBABILITY, !hubPtr.isNull())) { - Pointer hub = hubPtr.asWord(); + KlassPointer hub = ClassGetHubNode.readClass(type); + if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) { if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(hub))) { - int layoutHelper = readLayoutHelper(hubPtr); + int layoutHelper = readLayoutHelper(hub); /* * src/share/vm/oops/klass.hpp: For instances, layout helper is a positive number, * the instance size. This size is already passed through align_object_size and @@ -166,7 +165,7 @@ */ if (probability(FAST_PATH_PROBABILITY, (layoutHelper & 1) == 0)) { Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - return allocateInstance(layoutHelper, KlassPointer.fromWord(hub), prototypeMarkWord, fillContents, threadRegister, false, typeContext); + return allocateInstance(layoutHelper, hub, prototypeMarkWord, fillContents, threadRegister, false, typeContext); } } } @@ -347,7 +346,7 @@ * Formats some allocated memory with an object header and zeroes out the rest. */ protected static Object formatObject(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean useSnippetCounters) { - Word prototypeMarkWord = useBiasedLocking() ? hub.asWord().readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; + Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { zeroMemory(size, memory, constantSize, instanceHeaderSize(), false, useSnippetCounters); diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Tue Nov 25 08:17:33 2014 -0800 @@ -32,6 +32,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.type.*; +import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.*; import com.oracle.graal.word.*; @@ -43,9 +44,9 @@ */ public class TypeCheckSnippetUtils { - static boolean checkSecondarySubType(Pointer t, Pointer s) { + static boolean checkSecondarySubType(KlassPointer t, KlassPointer s) { // if (S.cache == T) return true - if (s.readWord(secondarySuperCacheOffset(), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) { + if (s.readKlassPointer(secondarySuperCacheOffset(), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) { cacheHit.inc(); return true; } @@ -53,13 +54,13 @@ return checkSelfAndSupers(t, s); } - static boolean checkUnknownSubType(Pointer t, Pointer s) { + static boolean checkUnknownSubType(KlassPointer t, KlassPointer s) { // int off = T.offset int superCheckOffset = t.readInt(superCheckOffsetOffset(), KLASS_SUPER_CHECK_OFFSET_LOCATION); boolean primary = superCheckOffset != secondarySuperCacheOffset(); // if (T = S[off]) return true - if (s.readWord(superCheckOffset, PRIMARY_SUPERS_LOCATION).equal(t)) { + if (s.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).equal(t)) { if (primary) { cacheHit.inc(); } else { @@ -77,7 +78,7 @@ return checkSelfAndSupers(t, s); } - private static boolean checkSelfAndSupers(Pointer t, Pointer s) { + private static boolean checkSelfAndSupers(KlassPointer t, KlassPointer s) { // if (T == S) return true if (s.equal(t)) { T_equals_S.inc(); @@ -89,7 +90,7 @@ int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), METASPACE_ARRAY_LENGTH_LOCATION); for (int i = 0; i < length; i++) { if (probability(NOT_LIKELY_PROBABILITY, t.equal(loadSecondarySupersElement(secondarySupers, i)))) { - s.writeWord(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION); + s.writeKlassPointer(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION); secondariesHit.inc(); return true; } @@ -139,8 +140,8 @@ return new Hints(hubs, isPositive); } - static Word loadSecondarySupersElement(Word metaspaceArray, int index) { - return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), SECONDARY_SUPERS_ELEMENT_LOCATION); + static KlassPointer loadSecondarySupersElement(Word metaspaceArray, int index) { + return KlassPointer.fromWord(metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), SECONDARY_SUPERS_ELEMENT_LOCATION)); } private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("TypeCheck") : null; diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Tue Nov 25 08:17:33 2014 -0800 @@ -102,14 +102,13 @@ * The type is known to be an instance so Klass::_layout_helper is the instance size as a * raw number */ - Pointer hubPtr = hub.asWord(); int sizeInBytes = loadKlassLayoutHelperIntrinsic(hub); Word thread = registerAsWord(threadRegister); if (!forceSlowPath() && inlineContiguousAllocationSupported()) { - if (isInstanceKlassFullyInitialized(hubPtr)) { + if (isInstanceKlassFullyInitialized(hub)) { Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging()); if (memory.notEqual(0)) { - Word prototypeMarkWord = hubPtr.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); + Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); NewObjectSnippets.formatObjectForStub(hub, sizeInBytes, memory, prototypeMarkWord); return verifyObject(memory.toObject()); } diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotOperation.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotOperation.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotOperation.java Tue Nov 25 08:17:33 2014 -0800 @@ -34,7 +34,8 @@ TO_METHOD_POINTER, POINTER_EQ, POINTER_NE, - IS_NULL + IS_NULL, + READ_KLASS_POINTER } HotspotOpcode opcode(); diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java Tue Nov 25 08:17:33 2014 -0800 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.word; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode.*; import com.oracle.graal.api.meta.*; @@ -33,9 +34,13 @@ import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.Word.*; import com.oracle.graal.word.phases.*; public class HotSpotWordTypeRewriterPhase extends WordTypeRewriterPhase { @@ -51,24 +56,22 @@ @Override protected void changeToWord(StructuredGraph graph, ValueNode node) { - AbstractPointerStamp pointerStamp = getPointerStamp(node); - if (pointerStamp != null) { - node.setStamp(pointerStamp); + ResolvedJavaType baseType = StampTool.typeOrNull(node); + if (baseType != null && baseType.equals(klassPointerType)) { + node.setStamp(KlassPointerStamp.klass()); + } else if (baseType != null && baseType.equals(methodPointerType)) { + node.setStamp(MethodPointerStamp.method()); } else { super.changeToWord(graph, node); } } - private AbstractPointerStamp getPointerStamp(ValueNode node) { - ResolvedJavaType type = StampTool.typeOrNull(node); - if (type != null) { - if (klassPointerType.isAssignableFrom(type)) { - return KlassPointerStamp.klass(); - } else if (methodPointerType.isAssignableFrom(type)) { - return MethodPointerStamp.method(); - } + @Override + protected Kind asKind(JavaType type) { + if (type.equals(klassPointerType) || type.equals(methodPointerType)) { + return wordKind; } - return null; + return super.asKind(type); } @Override @@ -88,7 +91,12 @@ ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); HotSpotOperation operation = targetMethod.getAnnotation(HotSpotOperation.class); if (operation == null) { - super.rewriteInvoke(graph, callTargetNode); + Operation wordOperation = targetMethod.getAnnotation(Word.Operation.class); + if (wordOperation != null) { + super.rewriteWordOperation(graph, callTargetNode, targetMethod); + } else { + super.rewriteInvoke(graph, callTargetNode); + } } else { Invoke invoke = callTargetNode.invoke(); NodeInputList arguments = callTargetNode.arguments(); @@ -120,12 +128,40 @@ replace(invoke, graph.unique(PointerCastNode.create(MethodPointerStamp.method(), arguments.get(0)))); break; + case READ_KLASS_POINTER: + assert arguments.size() == 2 || arguments.size() == 3; + Kind readKind = asKind(callTargetNode.returnType()); + Stamp readStamp = KlassPointerStamp.klass(); + LocationNode location; + if (arguments.size() == 2) { + location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION); + } else { + location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2)); + } + replace(invoke, readKlassOp(graph, arguments.get(0), invoke, location, readStamp, operation.opcode())); + break; + default: throw GraalInternalError.shouldNotReachHere("unknown operation: " + operation.opcode()); } } } + protected ValueNode readKlassOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, Stamp readStamp, HotspotOpcode op) { + assert op == READ_KLASS_POINTER; + final BarrierType barrier = BarrierType.NONE; + final boolean compressible = false; + + JavaReadNode read = graph.add(JavaReadNode.create(base, location, readStamp, barrier, 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. + */ + read.setGuard(BeginNode.prevBegin(invoke.asNode())); + return read; + } + private static ValueNode pointerComparisonOp(StructuredGraph graph, HotspotOpcode opcode, ValueNode left, ValueNode right) { assert left.stamp() instanceof MetaspacePointerStamp && right.stamp() instanceof MetaspacePointerStamp; assert opcode == POINTER_EQ || opcode == POINTER_NE; diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/KlassPointer.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/KlassPointer.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/KlassPointer.java Tue Nov 25 08:17:33 2014 -0800 @@ -24,7 +24,10 @@ import static com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.word.*; +import com.oracle.graal.word.Word.Opcode; +import com.oracle.graal.word.Word.Operation; /** * Marker type for a metaspace pointer to a type. @@ -39,4 +42,10 @@ @HotSpotOperation(opcode = TO_KLASS_POINTER) public static native KlassPointer fromWord(Pointer pointer); + + @HotSpotOperation(opcode = READ_KLASS_POINTER) + public native KlassPointer readKlassPointer(int secondarySuperCacheOffset, LocationIdentity secondarySuperCacheLocation); + + @Operation(opcode = Opcode.WRITE_POINTER) + public native void writeKlassPointer(int secondarySuperCacheOffset, KlassPointer t, LocationIdentity secondarySuperCacheLocation); } diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/MetaspacePointer.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/MetaspacePointer.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/MetaspacePointer.java Tue Nov 25 08:17:33 2014 -0800 @@ -24,7 +24,12 @@ import static com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.HeapAccess.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.word.*; +import com.oracle.graal.word.Word.Opcode; +import com.oracle.graal.word.Word.Operation; /** * Marker type for a metaspace pointer. @@ -36,4 +41,900 @@ @HotSpotOperation(opcode = FROM_POINTER) public abstract Pointer asWord(); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract byte readByte(WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract char readChar(WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract short readShort(WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract int readInt(WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract long readLong(WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract float readFloat(WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract double readDouble(WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract Word readWord(WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract Object readObject(WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract byte readByte(int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract char readChar(int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract short readShort(int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract int readInt(int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract long readLong(int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract float readFloat(int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract double readDouble(int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract Word readWord(int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ_POINTER) + public abstract Object readObject(int offset, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeChar(WordBase offset, char val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeShort(WordBase offset, short val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeInt(WordBase offset, int val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeLong(WordBase offset, long val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity); + + /** + * Initializes the memory at address {@code (this + offset)}. Both the base address and offset + * are in bytes. The memory must be uninitialized or zero prior to this operation. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeByte(int offset, byte val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeChar(int offset, char val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeShort(int offset, short val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeInt(int offset, int val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeLong(int offset, long val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeFloat(int offset, float val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeDouble(int offset, double val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeWord(int offset, WordBase val, LocationIdentity locationIdentity); + + /** + * Initializes the memory at address {@code (this + offset)}. Both the base address and offset + * are in bytes. The memory must be uninitialized or zero prior to this operation. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void initializeLong(int offset, long val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + public abstract void writeObject(int offset, Object val, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract byte readByte(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract char readChar(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract short readShort(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract int readInt(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract long readLong(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract float readFloat(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract double readDouble(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract Word readWord(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract Object readObject(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. This access will decompress the oop if + * the VM uses compressed oops, and it can be parameterized to allow read barriers (G1 referent + * field). + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param barrierType the type of the read barrier to be added + * @return the result of the memory access + */ + public abstract Object readObject(WordBase offset, BarrierType barrierType); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract byte readByte(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract char readChar(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract short readShort(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract int readInt(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract long readLong(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract float readFloat(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract double readDouble(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract Word readWord(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + public abstract Object readObject(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. This access will decompress the oop if + * the VM uses compressed oops, and it can be parameterized to allow read barriers (G1 referent + * field). + * + * @param offset the signed offset for the memory access + * @param barrierType the type of the read barrier to be added + * @return the result of the memory access + */ + public abstract Object readObject(int offset, BarrierType barrierType); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeByte(WordBase offset, byte val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeChar(WordBase offset, char val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeShort(WordBase offset, short val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeInt(WordBase offset, int val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeLong(WordBase offset, long val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeFloat(WordBase offset, float val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeDouble(WordBase offset, double val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeWord(WordBase offset, WordBase val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeObject(WordBase offset, Object val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeByte(int offset, byte val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeChar(int offset, char val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeShort(int offset, short val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeInt(int offset, int val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeLong(int offset, long val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeFloat(int offset, float val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeDouble(int offset, double val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeWord(int offset, WordBase val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + public abstract void writeObject(int offset, Object val); } diff -r 9f06d9b2cc43 -r f38677340519 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Tue Nov 25 08:17:33 2014 -0800 @@ -42,11 +42,20 @@ return new JavaReadNode(object, location, barrierType, compressible); } + public static JavaReadNode create(ValueNode object, LocationNode location, Stamp readStamp, BarrierType barrierType, boolean compressible) { + return new JavaReadNode(object, location, readStamp, barrierType, compressible); + } + protected JavaReadNode(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) { super(object, location, StampFactory.forKind(location.getValueKind()), barrierType); this.compressible = compressible; } + protected JavaReadNode(ValueNode object, LocationNode location, Stamp readStamp, BarrierType barrierType, boolean compressible) { + super(object, location, readStamp, barrierType); + this.compressible = compressible; + } + public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); } diff -r 9f06d9b2cc43 -r f38677340519 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 Tue Nov 25 13:40:59 2014 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Tue Nov 25 08:17:33 2014 -0800 @@ -185,11 +185,16 @@ return; } - Invoke invoke = callTargetNode.invoke(); if (!callTargetNode.isStatic()) { assert callTargetNode.receiver().getKind() == wordKind : "changeToWord() missed the receiver " + callTargetNode.receiver(); - targetMethod = wordImplType.resolveConcreteMethod(targetMethod, invoke.getContextType()); + assert wordImplType.isLinked(); + targetMethod = wordImplType.resolveConcreteMethod(targetMethod, callTargetNode.invoke().getContextType()); } + rewriteWordOperation(graph, callTargetNode, targetMethod); + } + + protected void rewriteWordOperation(StructuredGraph graph, MethodCallTargetNode callTargetNode, ResolvedJavaMethod targetMethod) throws GraalInternalError { + Invoke invoke = callTargetNode.invoke(); Operation operation = targetMethod.getAnnotation(Word.Operation.class); assert operation != null : targetMethod; @@ -374,7 +379,7 @@ return materialize; } - private LocationNode makeLocation(StructuredGraph graph, ValueNode offset, Kind readKind, ValueNode locationIdentity) { + protected LocationNode makeLocation(StructuredGraph graph, ValueNode offset, Kind readKind, ValueNode locationIdentity) { if (locationIdentity.isConstant()) { return makeLocation(graph, offset, readKind, (LocationIdentity) snippetReflection.asObject(locationIdentity.asJavaConstant())); }