# HG changeset patch # User Doug Simon # Date 1342106194 -7200 # Node ID f238fe91dc7f35703d0451ad9a7c01d6b6af009d # Parent ec65d0d0c873d291e6c3b545f6152e0f7d3ef036 partial (non XIR) support for inlining virtual dispatch at call sites - still needs fixing diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Thu Jul 12 17:16:34 2012 +0200 @@ -273,6 +273,7 @@ public static String HIRLowerCheckcast = ""; public static String HIRLowerNewInstance = ""; public static String HIRLowerNewArray = ""; + public static String HIRLowerInlineVirtualInvokes = ""; /** * Use XIR to lower {@link Invoke} nodes. diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Jul 12 17:16:34 2012 +0200 @@ -50,6 +50,11 @@ static final int INITIAL_ID = -1; static final int ALIVE_ID_START = 0; + /** + * Denotes a node input. This should be applied to exactly the fields of a node that are of type {@link Node}. + * Nodes that update their inputs outside of their constructor should call {@link Node#updateUsages(Node, Node)} + * just prior to doing the update of the input. + */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public static @interface Input { diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Jul 12 17:16:34 2012 +0200 @@ -232,12 +232,34 @@ SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.array(), StructuredGraph.INVALID_GRAPH_ID); graph.replaceFixedWithFixed(arrayLengthNode, safeReadArrayLength); } else if (n instanceof Invoke) { - Invoke invoke = (Invoke) n; - MethodCallTargetNode callTarget = invoke.callTarget(); - NodeInputList parameters = callTarget.arguments(); - ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0); - if (!callTarget.isStatic() && firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) { - invoke.node().dependencies().add(tool.createNullCheckGuard(firstParam, invoke.leafGraphId())); + if (!GraalOptions.XIRLowerInvokes) { + Invoke invoke = (Invoke) n; + MethodCallTargetNode callTarget = invoke.callTarget(); + NodeInputList parameters = callTarget.arguments(); + ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); + if (!callTarget.isStatic() && receiver.kind() == Kind.Object && !receiver.objectStamp().nonNull()) { + invoke.node().dependencies().add(tool.createNullCheckGuard(receiver, invoke.leafGraphId())); + } + + int vtableEntryOffset = 0; + if (matches(graph, GraalOptions.HIRLowerInlineVirtualInvokes) || (GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || invoke.isMegamorphic()))) { + // TODO: successive inlined invokevirtuals to the same method cause register allocation to fail - fix this! + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); + if (!hsMethod.holder().isInterface()) { + vtableEntryOffset = hsMethod.vtableEntryOffset(); + assert vtableEntryOffset != 0; + SafeReadNode hub = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID); + Kind wordKind = graalRuntime.getTarget().wordKind; + Stamp nonNullWordStamp = StampFactory.forWord(wordKind, true); + ReadNode methodOop = graph.add(new ReadNode(hub, LocationNode.create(LocationNode.FINAL_LOCATION, wordKind, vtableEntryOffset, graph), nonNullWordStamp)); + ReadNode compiledEntry = graph.add(new ReadNode(methodOop, LocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), nonNullWordStamp)); + callTarget.setAddress(compiledEntry); + + graph.addBeforeFixed(invoke.node(), hub); + graph.addAfterFixed(hub, methodOop); + graph.addAfterFixed(methodOop, compiledEntry); + } + } } } else if (n instanceof LoadFieldNode) { LoadFieldNode field = (LoadFieldNode) n; @@ -374,15 +396,15 @@ memoryRead.dependencies().add(tool.createNullCheckGuard(objectClassNode.object(), StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixed(objectClassNode, memoryRead); } else if (n instanceof CheckCastNode) { - if (shouldLower(graph, GraalOptions.HIRLowerCheckcast)) { + if (matches(graph, GraalOptions.HIRLowerCheckcast)) { checkcastSnippets.lower((CheckCastNode) n, tool); } } else if (n instanceof NewInstanceNode) { - if (shouldLower(graph, GraalOptions.HIRLowerNewInstance)) { + if (matches(graph, GraalOptions.HIRLowerNewInstance)) { newObjectSnippets.lower((NewInstanceNode) n, tool); } } else if (n instanceof NewArrayNode) { - if (shouldLower(graph, GraalOptions.HIRLowerNewArray)) { + if (matches(graph, GraalOptions.HIRLowerNewArray)) { newObjectSnippets.lower((NewArrayNode) n, tool); } } else if (n instanceof TLABAllocateNode) { @@ -396,13 +418,13 @@ } } - private static boolean shouldLower(StructuredGraph graph, String option) { - if (option != null) { - if (option.length() == 0) { + private static boolean matches(StructuredGraph graph, String filter) { + if (filter != null) { + if (filter.length() == 0) { return true; } ResolvedJavaMethod method = graph.method(); - return method != null && MetaUtil.format("%H.%n", method).contains(option); + return method != null && MetaUtil.format("%H.%n", method).contains(filter); } return false; } diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java Thu Jul 12 17:16:34 2012 +0200 @@ -62,6 +62,7 @@ public static final Integer MARK_INVOKESTATIC = 0x2002; public static final Integer MARK_INVOKESPECIAL = 0x2003; public static final Integer MARK_INVOKEVIRTUAL = 0x2004; + public static final Integer MARK_INLINE_INVOKEVIRTUAL = 0x2005; public static final Integer MARK_IMPLICIT_NULL = 0x3000; public static final Integer MARK_POLL_NEAR = 0x3001; @@ -167,7 +168,7 @@ // load entry point from methodOop asm.mark(MARK_IMPLICIT_NULL); asm.pload(target.wordKind, temp, method, asm.i(config.methodCompiledEntryOffset), true); - asm.mark(MARK_INVOKEVIRTUAL); + asm.mark(MARK_INLINE_INVOKEVIRTUAL); return asm.finishTemplate(temp, "invokevirtual"); } diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Thu Jul 12 17:16:34 2012 +0200 @@ -145,9 +145,13 @@ // that loads the klassOop from the inline cache so that the C++ code can find it // and replace the inline null value with Universe::non_oop_word() assert invokeKind == Virtual || invokeKind == Interface; - tasm.recordMark(invokeKind == Virtual ? MARK_INVOKEVIRTUAL : MARK_INVOKEINTERFACE); - AMD64MacroAssembler masm = (AMD64MacroAssembler) tasm.asm; - AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Object), Constant.NULL_OBJECT); + if (callTarget.address() == null) { + tasm.recordMark(invokeKind == Virtual ? MARK_INVOKEVIRTUAL : MARK_INVOKEINTERFACE); + AMD64MacroAssembler masm = (AMD64MacroAssembler) tasm.asm; + AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Object), Constant.NULL_OBJECT); + } else { + tasm.recordMark(MARK_INLINE_INVOKEVIRTUAL); + } } } public void atCall(TargetMethodAssembler tasm) { diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Thu Jul 12 17:16:34 2012 +0200 @@ -38,6 +38,7 @@ } public void setAddress(ValueNode address) { + updateUsages(this.address, address); this.address = address; } diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Thu Jul 12 17:16:34 2012 +0200 @@ -45,7 +45,7 @@ */ public IsNullNode(ValueNode object) { super(StampFactory.condition()); - assert object.kind() == Kind.Object : object.kind(); + assert object.kind() == Kind.Object : object; this.object = object; } diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Thu Jul 12 17:16:34 2012 +0200 @@ -25,6 +25,11 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; +/** + * Accesses a value at an memory address specified by an {@linkplain #object object} + * and a {@linkplain #location() location}. The access does not include a null check + * on the object. + */ public abstract class AccessNode extends FixedWithNextNode implements Access { @Input private ValueNode object; diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Thu Jul 12 17:16:34 2012 +0200 @@ -40,12 +40,20 @@ private Kind valueKind; private Object locationIdentity; + /** + * Denotes any location. A write to such a location kills all values in a memory map + * during an analysis of memory accesses in a graph. + */ public static final Object ANY_LOCATION = new Object() { @Override public String toString() { return "ANY_LOCATION"; } }; + + /** + * Denotes the location of a value that is guaranteed to be final. + */ public static final Object FINAL_LOCATION = new Object() { @Override public String toString() { diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Thu Jul 12 17:16:34 2012 +0200 @@ -28,7 +28,9 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; - +/** + * Reads an {@linkplain AccessNode accessed} value. + */ public final class ReadNode extends AccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable { public ReadNode(ValueNode object, LocationNode location, Stamp stamp) { diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java Thu Jul 12 17:16:34 2012 +0200 @@ -26,6 +26,10 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +/** + * An analog to {@link ReadNode} with the additional semantics of null-checking + * the receiver object before reading from it. + */ public class SafeReadNode extends SafeAccessNode implements Lowerable { public SafeReadNode(ValueNode object, LocationNode location, Stamp stamp, long leafGraphId) { diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java Thu Jul 12 17:16:34 2012 +0200 @@ -26,6 +26,10 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +/** + * An analog to {@link WriteNode} with the additional semantics of null-checking + * the receiver object before writing to it. + */ public class SafeWriteNode extends SafeAccessNode implements StateSplit, Lowerable { @Input private ValueNode value; diff -r ec65d0d0c873 -r f238fe91dc7f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Thu Jul 12 12:04:27 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Thu Jul 12 17:16:34 2012 +0200 @@ -27,6 +27,9 @@ import com.oracle.graal.nodes.type.*; +/** + * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}. + */ public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable { @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; diff -r ec65d0d0c873 -r f238fe91dc7f src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Thu Jul 12 12:04:27 2012 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Thu Jul 12 17:16:34 2012 +0200 @@ -695,10 +695,10 @@ TRACE_graal_3("method call"); switch (_next_call_type) { + case MARK_INLINE_INVOKEVIRTUAL: { + break; + } case MARK_INVOKEVIRTUAL: - if (is_call_reg) { - break; - } case MARK_INVOKEINTERFACE: { assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); @@ -843,6 +843,7 @@ // Add relocation record for the klassOop embedded in the inline cache _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); } + case MARK_INLINE_INVOKEVIRTUAL: case MARK_INVOKE_INVALID: case MARK_INVOKESPECIAL: case MARK_INVOKESTATIC: diff -r ec65d0d0c873 -r f238fe91dc7f src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Thu Jul 12 12:04:27 2012 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Thu Jul 12 17:16:34 2012 +0200 @@ -43,6 +43,7 @@ MARK_INVOKESTATIC = 0x2002, MARK_INVOKESPECIAL = 0x2003, MARK_INVOKEVIRTUAL = 0x2004, + MARK_INLINE_INVOKEVIRTUAL = 0x2005, MARK_IMPLICIT_NULL = 0x3000, MARK_POLL_NEAR = 0x3001, MARK_POLL_RETURN_NEAR = 0x3002,