# HG changeset patch # User Tom Rodriguez # Date 1415986379 28800 # Node ID ed0fce2e999ac58ff7cc273cf496af699d14c331 # Parent e11768d6136e7ccdc9dda44b9fb8ac66f493d8ca Fold klass._java_mirror._klass into klass and improve stamps from layout_helper diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java Fri Nov 14 09:32:59 2014 -0800 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2014, 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.hotspot.test; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; + +public class ClassSubstitutionsTests extends GraalCompilerTest { + + public Number instanceField; + + public Object[] arrayField; + + public String[] stringArrayField; + + protected StructuredGraph test(final String snippet) { + try (Scope s = Debug.scope("ClassSubstitutionsTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { + StructuredGraph graph = parseEager(snippet); + compile(graph.method(), graph); + assertNotInGraph(graph, Invoke.class); + Debug.dump(graph, snippet); + return graph; + } catch (Throwable e) { + throw Debug.handle(e); + } + } + + protected static StructuredGraph assertNotInGraph(StructuredGraph graph, Class clazz) { + for (Node node : graph.getNodes()) { + if (clazz.isInstance(node)) { + fail(node.toString()); + } + } + return graph; + } + + public boolean constantIsArray() { + return "".getClass().isArray(); + } + + public boolean constantIsInterface() { + return "".getClass().isInterface(); + } + + public boolean constantIsPrimitive() { + return "".getClass().isPrimitive(); + } + + @Test + public void testIsArray() { + testConstantReturn("constantIsArray", 0); + } + + @Test + public void testIsInterface() { + testConstantReturn("constantIsInterface", 0); + } + + @Test + public void testIsPrimitive() { + testConstantReturn("constantIsPrimitive", 0); + } + + public boolean fieldIsNotArray() { + if (instanceField != null) { + // The base type of instanceField is not Object or an Interface, so it's provably an + // instance type, so isArray will always return false. + return instanceField.getClass().isArray(); + } + return false; + } + + @Test + public void testFieldIsNotArray() { + testConstantReturn("fieldIsNotArray", 0); + } + + public boolean foldComponentType() { + return stringArrayField.getClass().getComponentType() == String.class; + } + + @Test + public void testFoldComponenetType() { + testConstantReturn("foldComponentType", 1); + } + + @Ignore("Can't constant fold LoadHubNode == 0 yet") + @Test + public void testFieldIsArray() { + testConstantReturn("fieldIsArray", 1); + } + + public boolean fieldIsArray() { + if (arrayField != null) { + // The base type of arrayField is an array of some sort so isArray will always return + // true. + return arrayField.getClass().isArray(); + } + return true; + } + + private void testConstantReturn(String name, Object value) { + StructuredGraph result = test(name); + ReturnNode ret = result.getNodes(ReturnNode.class).first(); + assertDeepEquals(1, result.getNodes(ReturnNode.class).count()); + + assertDeepEquals(true, ret.result().isConstant()); + assertDeepEquals(value, ret.result().asJavaConstant().asBoxedPrimitive()); + } +} diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowPointerStamp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowPointerStamp.java Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowPointerStamp.java Fri Nov 14 09:32:59 2014 -0800 @@ -84,6 +84,7 @@ @Override public Stamp constant(Constant c, MetaAccessProvider meta) { + assert (c instanceof HotSpotMetaspaceConstantImpl) && ((HotSpotMetaspaceConstantImpl) c).isCompressed(); return this; } diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Nov 14 09:32:59 2014 -0800 @@ -93,7 +93,7 @@ UnsafeArrayCopyNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, baseKind); } - private static int checkArrayType(Pointer hub) { + private static int checkArrayType(TypePointer hub) { int layoutHelper = readLayoutHelper(hub); if (probability(SLOW_PATH_PROBABILITY, layoutHelper >= 0)) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); @@ -183,9 +183,9 @@ public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) { Object nonNullSrc = guardingNonNull(src); Object nonNullDest = guardingNonNull(dest); - Pointer srcHub = loadHub(nonNullSrc); - Pointer destHub = loadHub(nonNullDest); - if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, nonNullSrc != nonNullDest)) { + TypePointer srcHub = loadHub(nonNullSrc); + TypePointer destHub = loadHub(nonNullDest); + if (probability(FAST_PATH_PROBABILITY, Word.equal(srcHub, destHub)) && probability(FAST_PATH_PROBABILITY, nonNullSrc != nonNullDest)) { int layoutHelper = checkArrayType(srcHub); final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0); diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java Fri Nov 14 09:32:59 2014 -0800 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014, 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.hotspot.replacements; + +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodeinfo.*; +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.word.*; + +/** + * Read Class::_klass to get the hub for a {@link java.lang.Class}. This node mostly exists to + * replace _klass._java_mirror._klass with _klass. The constant folding could be handled by + * {@link ReadNode#canonicalizeRead(ValueNode, LocationNode, ValueNode, CanonicalizerTool)}. + */ +@NodeInfo +public class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable { + @Input protected ValueNode clazz; + + public static ClassGetHubNode create(ValueNode clazz) { + return new ClassGetHubNode(clazz); + } + + public static ClassGetHubNode create(ValueNode clazz, ValueNode guard) { + return new ClassGetHubNode(clazz, guard); + } + + protected ClassGetHubNode(ValueNode clazz) { + super(StampFactory.forPointer(PointerType.Type), null); + this.clazz = clazz; + } + + protected ClassGetHubNode(ValueNode clazz, ValueNode guard) { + super(StampFactory.forPointer(PointerType.Type), (GuardingNode) guard); + this.clazz = clazz; + } + + public ValueNode getHub() { + return clazz; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (usages().isEmpty()) { + return null; + } else { + if (clazz.isConstant()) { + MetaAccessProvider metaAccess = tool.getMetaAccess(); + if (metaAccess != null) { + HotSpotResolvedJavaType exactType = (HotSpotResolvedJavaType) tool.getConstantReflection().asJavaType(clazz.asJavaConstant()); + if (exactType instanceof HotSpotResolvedObjectType) { + HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) exactType; + ConstantNode cn = ConstantNode.forConstant(stamp(), objectType.getObjectHub(), metaAccess); + return cn; + } else if (exactType instanceof HotSpotResolvedPrimitiveType) { + /* + * The constant value is null but we don't have a JavaConstant subclass to + * talk about a NULL pointer yet. + */ + } + } + } + if (clazz instanceof HubGetClassNode) { + // replace _klass._java_mirror._klass -> _klass + return ((HubGetClassNode) clazz).getHub(); + } + return this; + } + } + + @Override + public void lower(LoweringTool tool) { + if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) { + return; + } + + HotSpotVMConfig config = runtime().getConfig(); + LocationNode location = ConstantLocationNode.create(CLASS_KLASS_LOCATION, getWordKind(), config.klassOffset, graph()); + assert !clazz.isConstant(); + FloatingReadNode read = graph().unique(FloatingReadNode.create(clazz, location, null, stamp(), getGuard(), BarrierType.NONE)); + graph().replaceFloating(this, read); + } + + @NodeIntrinsic + public static native TypePointer readClass(Class clazz); + + @NodeIntrinsic + public static native TypePointer readClass(Class clazz, GuardingNode guard); + +} diff -r e11768d6136e -r ed0fce2e999a 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 Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Fri Nov 14 09:32:59 2014 -0800 @@ -40,21 +40,23 @@ public class ClassSubstitutions { @MacroSubstitution(macro = ClassGetModifiersNode.class, isStatic = false) - @MethodSubstitution(isStatic = false) + @MethodSubstitution(isStatic = false, forced = true) public static int getModifiers(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset(), CLASS_KLASS_LOCATION); - if (klass.equal(0)) { + TypePointer klass = ClassGetHubNode.readClass(thisObj); + TypePointer zero = Word.unsigned(0).toTypePointer(); + if (Word.equal(klass, zero)) { // Class for primitive type return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; } else { - return klass.readInt(klassModifierFlagsOffset(), KLASS_MODIFIER_FLAGS_LOCATION); + return Word.fromTypePointer(klass).readInt(klassModifierFlagsOffset(), KLASS_MODIFIER_FLAGS_LOCATION); } } + // This MacroSubstitution should be removed once non-null klass pointers can be optimized @MacroSubstitution(macro = ClassIsInterfaceNode.class, isStatic = false) - @MethodSubstitution(isStatic = false) + @MethodSubstitution(isStatic = false, forced = true) public static boolean isInterface(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset(), CLASS_KLASS_LOCATION); + Pointer klass = Word.fromTypePointer(ClassGetHubNode.readClass(thisObj)); if (klass.equal(0)) { return false; } else { @@ -63,21 +65,24 @@ } } + // This MacroSubstitution should be removed once non-null klass pointers can be optimized @MacroSubstitution(macro = ClassIsArrayNode.class, isStatic = false) - @MethodSubstitution(isStatic = false) + @MethodSubstitution(isStatic = false, forced = true) public static boolean isArray(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset(), CLASS_KLASS_LOCATION); + TypePointer klassPtr = ClassGetHubNode.readClass(thisObj); + Pointer klass = Word.fromTypePointer(klassPtr); if (klass.equal(0)) { return false; } else { - return klassIsArray(klass); + return klassIsArray(klassPtr); } } + // This MacroSubstitution should be removed once non-null klass pointers can be optimized @MacroSubstitution(macro = ClassIsPrimitiveNode.class, isStatic = false) - @MethodSubstitution(isStatic = false) + @MethodSubstitution(isStatic = false, forced = true) public static boolean isPrimitive(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset(), CLASS_KLASS_LOCATION); + Pointer klass = Word.fromTypePointer(ClassGetHubNode.readClass(thisObj)); return klass.equal(0); } @@ -87,11 +92,12 @@ @MacroSubstitution(macro = ClassGetSuperclassNode.class, isStatic = false) @MethodSubstitution(isStatic = false) public static Class getSuperclass(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset(), CLASS_KLASS_LOCATION); + TypePointer klassPtr = ClassGetHubNode.readClass(thisObj); + Pointer klass = Word.fromTypePointer(klassPtr); if (klass.notEqual(0)) { int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION); if ((accessFlags & Modifier.INTERFACE) == 0) { - if (klassIsArray(klass)) { + if (klassIsArray(klassPtr)) { return Object.class; } else { Word superKlass = klass.readWord(klassSuperKlassOffset(), KLASS_SUPER_KLASS_LOCATION); @@ -109,9 +115,10 @@ @MacroSubstitution(macro = ClassGetComponentTypeNode.class, isStatic = false) @MethodSubstitution(isStatic = false) public static Class getComponentType(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset(), CLASS_KLASS_LOCATION); + TypePointer klassPtr = ClassGetHubNode.readClass(thisObj); + Pointer klass = Word.fromTypePointer(klassPtr); if (klass.notEqual(0)) { - if (klassIsArray(klass)) { + if (klassIsArray(klassPtr)) { return piCastExactNonNull(klass.readObject(arrayKlassComponentMirrorOffset(), ARRAY_KLASS_COMPONENT_MIRROR), Class.class); } } diff -r e11768d6136e -r ed0fce2e999a 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 Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java Fri Nov 14 09:32:59 2014 -0800 @@ -41,7 +41,7 @@ // HotSpot creates the NodeClass for each Node subclass while initializing it // 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. - Pointer klass = loadHub(node); - return piCastNonNull(klass.readObject(Word.signed(instanceKlassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class); + TypePointer klass = loadHub(node); + return piCastNonNull(Word.fromTypePointer(klass).readObject(Word.signed(instanceKlassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class); } } diff -r e11768d6136e -r ed0fce2e999a 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 Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Fri Nov 14 09:32:59 2014 -0800 @@ -34,6 +34,7 @@ import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; @@ -297,10 +298,18 @@ return config().klassLayoutHelperOffset; } - public static int readLayoutHelper(Pointer hub) { - return hub.readInt(klassLayoutHelperOffset(), KLASS_LAYOUT_HELPER_LOCATION); + public static int readLayoutHelper(TypePointer hub) { + // return hub.readInt(klassLayoutHelperOffset(), KLASS_LAYOUT_HELPER_LOCATION); + GuardingNode anchorNode = SnippetAnchorNode.anchor(); + return loadKlassLayoutHelperIntrinsic(hub, anchorNode); } + @NodeIntrinsic(value = KlassLayoutHelperNode.class) + public static native int loadKlassLayoutHelperIntrinsic(TypePointer object, GuardingNode anchor); + + @NodeIntrinsic(value = KlassLayoutHelperNode.class) + public static native int loadKlassLayoutHelperIntrinsic(TypePointer object); + /** * Checks if class {@code klass} is an array. * @@ -309,7 +318,7 @@ * @param klass the class to be checked * @return true if klass is an array, false otherwise */ - public static boolean klassIsArray(Word klass) { + public static boolean klassIsArray(TypePointer klass) { /* * The less-than check only works if both values are ints. We use local variables to make * sure these are still ints and haven't changed. @@ -540,8 +549,8 @@ /** * Loads the hub of an object (without null checking it first). */ - public static Pointer loadHub(Object object) { - return Word.fromTypePointer(loadHubIntrinsic(object)); + public static TypePointer loadHub(Object object) { + return loadHubIntrinsic(object); } public static Object verifyOop(Object object) { diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java Fri Nov 14 09:32:59 2014 -0800 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, 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.hotspot.replacements; + +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; +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.word.*; + +/** + * Read Klass::_java_mirror and incorporate non-null type information into stamp. This is also used + * by {@link ClassGetHubNode} to eliminate chains of klass._java_mirror._klass. + */ +@NodeInfo +public class HubGetClassNode extends FloatingGuardedNode implements Lowerable, Canonicalizable { + @Input protected ValueNode hub; + + public static HubGetClassNode create(ValueNode hub) { + return new HubGetClassNode(hub); + } + + protected HubGetClassNode(ValueNode hub) { + super(StampFactory.declaredNonNull(runtime().fromClass(Class.class)), null); + this.hub = hub; + } + + public ValueNode getHub() { + return hub; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (usages().isEmpty()) { + return null; + } else { + MetaAccessProvider metaAccess = tool.getMetaAccess(); + if (metaAccess != null) { + if (hub.isConstant()) { + ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asJavaConstant()); + return ConstantNode.forConstant(exactType.getJavaClass(), metaAccess); + } + } + return this; + } + } + + @Override + public void lower(LoweringTool tool) { + if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) { + return; + } + + HotSpotVMConfig config = runtime().getConfig(); + LocationNode location = ConstantLocationNode.create(CLASS_MIRROR_LOCATION, Kind.Object, config.classMirrorOffset, graph()); + assert !hub.isConstant(); + FloatingReadNode read = graph().unique(FloatingReadNode.create(hub, location, null, stamp(), getGuard(), BarrierType.NONE)); + graph().replaceFloating(this, read); + } + + @NodeIntrinsic + public static native Class readClass(TypePointer hub); + +} diff -r e11768d6136e -r ed0fce2e999a 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 Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Nov 14 09:32:59 2014 -0800 @@ -186,7 +186,7 @@ return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - Word hub = loadWordFromObject(mirror, klassOffset(), CLASS_KLASS_LOCATION); + Pointer hub = Word.fromTypePointer(ClassGetHubNode.readClass(mirror, anchorNode)); Pointer objectHub = Word.fromTypePointer(loadHubIntrinsic(object, anchorNode)); if (hub.equal(0) || !checkUnknownSubType(hub, objectHub)) { return falseValue; diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java Fri Nov 14 09:32:59 2014 -0800 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014, 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.hotspot.replacements; + +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Read Klass::_layout_helper and incorporate any useful stamp information based on any type + * information in {@code klass}. + */ +@NodeInfo +public class KlassLayoutHelperNode extends FloatingGuardedNode implements Canonicalizable, Lowerable { + + @Input protected ValueNode klass; + + public static KlassLayoutHelperNode create(ValueNode klass) { + return new KlassLayoutHelperNode(klass); + } + + public static KlassLayoutHelperNode create(ValueNode klass, ValueNode guard) { + return new KlassLayoutHelperNode(klass, guard); + } + + protected KlassLayoutHelperNode(ValueNode klass) { + super(StampFactory.forKind(Kind.Int)); + this.klass = klass; + } + + protected KlassLayoutHelperNode(ValueNode klass, ValueNode guard) { + super(StampFactory.forKind(Kind.Int), (GuardingNode) guard); + this.klass = klass; + } + + @Override + public boolean inferStamp() { + if (klass instanceof LoadHubNode) { + LoadHubNode hub = (LoadHubNode) klass; + Stamp hubStamp = hub.getValue().stamp(); + if (hubStamp instanceof ObjectStamp) { + ObjectStamp objectStamp = (ObjectStamp) hubStamp; + ResolvedJavaType type = objectStamp.type(); + if (type != null && !type.isJavaLangObject()) { + if (!type.isArray() && !type.isInterface()) { + /* + * Definitely some form of instance type. + */ + return updateStamp(StampFactory.forInteger(Kind.Int, runtime().getConfig().klassLayoutHelperNeutralValue, Integer.MAX_VALUE)); + } + if (type.isArray()) { + return updateStamp(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, runtime().getConfig().klassLayoutHelperNeutralValue - 1)); + } + } + } + } + return false; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (usages().isEmpty()) { + return null; + } else { + if (klass.isConstant()) { + long base = klass.asJavaConstant().asLong(); + if (base != 0L) { + Constant constant = stamp().readConstant(tool.getConstantReflection(), klass.asJavaConstant(), runtime().getConfig().klassLayoutHelperOffset); + return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess()); + } + } + if (klass instanceof LoadHubNode) { + LoadHubNode hub = (LoadHubNode) klass; + Stamp hubStamp = hub.getValue().stamp(); + if (hubStamp instanceof ObjectStamp) { + ObjectStamp ostamp = (ObjectStamp) hubStamp; + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type(); + if (type != null && type.isArray() && !type.getComponentType().isPrimitive()) { + // The layout for all object arrays is the same. + Constant constant = stamp().readConstant(tool.getConstantReflection(), type.klass(), runtime().getConfig().klassLayoutHelperOffset); + return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess()); + } + } + } + return this; + } + } + + @Override + public void lower(LoweringTool tool) { + if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) { + return; + } + LocationNode location = ConstantLocationNode.create(KLASS_LAYOUT_HELPER_LOCATION, Kind.Int, runtime().getConfig().klassLayoutHelperOffset, graph()); + assert !klass.isConstant(); + graph().replaceFloating(this, graph().unique(FloatingReadNode.create(klass, location, null, stamp(), getGuard(), BarrierType.NONE))); + } +} diff -r e11768d6136e -r ed0fce2e999a 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 Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Nov 14 09:32:59 2014 -0800 @@ -151,10 +151,11 @@ @Snippet public static Object allocateInstanceDynamic(Class type, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter String typeContext) { - Word hub = loadWordFromObject(type, klassOffset(), CLASS_KLASS_LOCATION); + TypePointer hubPtr = ClassGetHubNode.readClass(type); + Pointer hub = Word.fromTypePointer(hubPtr); if (probability(FAST_PATH_PROBABILITY, !hub.equal(Word.zero()))) { if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(hub))) { - int layoutHelper = readLayoutHelper(hub); + int layoutHelper = readLayoutHelper(hubPtr); /* * 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 @@ -223,7 +224,7 @@ return dynamicNewArrayStub(DYNAMIC_NEW_ARRAY, elementType, length); } - int layoutHelper = readLayoutHelper(hub); + int layoutHelper = readLayoutHelper(hub.toTypePointer()); //@formatter:off // from src/share/vm/oops/klass.hpp: // diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java Thu Nov 13 18:18:50 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2013, 2014, 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.hotspot.replacements; - -import static com.oracle.graal.compiler.common.GraalOptions.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * This macro node will replace itself with the correct Java {@link Class} as soon as the object's - * type is known (exact). - */ -@NodeInfo -public class ObjectGetClassNode extends MacroNode implements Virtualizable, Canonicalizable { - - public static ObjectGetClassNode create(Invoke invoke) { - return new ObjectGetClassNode(invoke); - } - - protected ObjectGetClassNode(Invoke invoke) { - super(invoke); - } - - private ValueNode getObject() { - return arguments.get(0); - } - - @Override - public void virtualize(VirtualizerTool tool) { - if (ImmutableCode.getValue()) { - return; - } - State state = tool.getObjectState(getObject()); - if (state != null) { - JavaConstant clazz = state.getVirtualObject().type().getJavaClass(); - tool.replaceWithValue(ConstantNode.forConstant(clazz, tool.getMetaAccessProvider(), graph())); - } - } - - @Override - public Node canonical(CanonicalizerTool tool) { - if (ImmutableCode.getValue()) { - return this; - } - if (usages().isEmpty()) { - return null; - } else { - ResolvedJavaType type = StampTool.typeOrNull(getObject()); - if (StampTool.isExactType(getObject())) { - JavaConstant clazz = type.getJavaClass(); - return ConstantNode.forConstant(clazz, tool.getMetaAccess()); - } - if (type != null && tool.assumptions().useOptimisticAssumptions()) { - ResolvedJavaType exactType = type.findUniqueConcreteSubtype(); - if (exactType != null) { - tool.assumptions().recordConcreteSubtype(type, exactType); - JavaConstant clazz = exactType.getJavaClass(); - return ConstantNode.forConstant(clazz, tool.getMetaAccess()); - } - } - return this; - } - } -} diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Fri Nov 14 09:32:59 2014 -0800 @@ -23,9 +23,9 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.PiNode.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -36,11 +36,10 @@ @ClassSubstitution(java.lang.Object.class) public class ObjectSubstitutions { - @MacroSubstitution(macro = ObjectGetClassNode.class, isStatic = false, forced = true) @MethodSubstitution(isStatic = false, forced = true) public static Class getClass(final Object thisObj) { - Pointer hub = loadHub(thisObj); - return piCastExactNonNull(hub.readObject(Word.signed(classMirrorOffset()), CLASS_MIRROR_LOCATION), Class.class); + TypePointer hub = loadHub(GuardingPiNode.guardingNonNull(thisObj)); + return HubGetClassNode.readClass(hub); } @MethodSubstitution(isStatic = false) diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Nov 14 09:32:59 2014 -0800 @@ -84,7 +84,7 @@ */ @Snippet private static Object newArray(TypePointer hub, int length, @ConstantParameter TypePointer intArrayHub, @ConstantParameter Register threadRegister) { - int layoutHelper = Word.fromTypePointer(hub).readInt(klassLayoutHelperOffset(), KLASS_LAYOUT_HELPER_LOCATION); + int layoutHelper = loadKlassLayoutHelperIntrinsic(hub); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask(); diff -r e11768d6136e -r ed0fce2e999a 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 Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Fri Nov 14 09:32:59 2014 -0800 @@ -102,7 +102,7 @@ * raw number */ Pointer hubPtr = Word.fromTypePointer(hub); - int sizeInBytes = hubPtr.readInt(klassLayoutHelperOffset(), KLASS_LAYOUT_HELPER_LOCATION); + int sizeInBytes = loadKlassLayoutHelperIntrinsic(hub); Word thread = registerAsWord(threadRegister); if (!forceSlowPath() && inlineContiguousAllocationSupported()) { if (isInstanceKlassFullyInitialized(hubPtr)) { diff -r e11768d6136e -r ed0fce2e999a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Thu Nov 13 18:18:50 2014 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Fri Nov 14 09:32:59 2014 -0800 @@ -62,6 +62,9 @@ @Override public void lower(LoweringTool tool) { + if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) { + return; + } tool.getLowerer().lower(this, tool); }