changeset 5000:b5dc2403c1e7

add option to inline VTable stubs
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 01 Mar 2012 12:11:19 +0100
parents 71bcf0a9e875
children 5fdc9bbe0be7
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolved.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java src/cpu/x86/vm/nativeInst_x86.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalJavaAccess.hpp
diffstat 13 files changed, 104 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Thu Mar 01 12:10:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Thu Mar 01 12:11:19 2012 +0100
@@ -35,6 +35,8 @@
     // Checkstyle: resume
 
 
+
+
     public static int     Threads                            = 4;
     public static boolean Lower                              = true;
 
@@ -151,6 +153,7 @@
     public static boolean GenSafepoints                      = true;
     public static boolean GenLoopSafepoints                  = true;
     public static boolean UseTypeCheckHints                  = true;
+    public static boolean InlineVTableStubs                  = ____;
 
     public static boolean GenAssertionCode                   = ____;
     public static boolean AlignCallsForPatching              = true;
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotVMConfig.java	Thu Mar 01 12:10:41 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotVMConfig.java	Thu Mar 01 12:11:19 2012 +0100
@@ -72,6 +72,7 @@
     public int klassOopOffset;
     public int graalMirrorKlassOffset;
     public int nmethodEntryOffset;
+    public int methodCompiledEntryOffset;
 
     // methodData information
     public int methodDataOopDataOffset;
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java	Thu Mar 01 12:10:41 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java	Thu Mar 01 12:11:19 2012 +0100
@@ -37,7 +37,7 @@
     private static final long serialVersionUID = 156632908220561612L;
 
     private final RiResolvedMethod method;
-    private long nmethod;
+    public long nmethod;
 
     public HotSpotCompiledMethod(Compiler compiler, RiResolvedMethod method) {
         super(compiler);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolved.java	Thu Mar 01 12:10:41 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolved.java	Thu Mar 01 12:11:19 2012 +0100
@@ -29,4 +29,5 @@
 
     RiResolvedMethod uniqueConcreteMethod();
     void dumpProfile();
+    int vtableEntryOffset();
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Thu Mar 01 12:10:41 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Thu Mar 01 12:11:19 2012 +0100
@@ -61,6 +61,7 @@
     private boolean canBeInlined;
     private CiGenericCallback callback;
     private int compilationComplexity;
+    private int vtableEntryOffset;
 
     private HotSpotMethodResolvedImpl() {
         super(null);
@@ -353,4 +354,9 @@
     public void setCallback(CiGenericCallback callback) {
         this.callback = callback;
     }
+
+    @Override
+    public int vtableEntryOffset() {
+        return vtableEntryOffset;
+    }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Thu Mar 01 12:10:41 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Thu Mar 01 12:11:19 2012 +0100
@@ -249,24 +249,45 @@
         }
     };
 
-    private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) {
+    private IndexTemplates invokeVirtualTemplates = new IndexTemplates(NULL_CHECK) {
 
         @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
-            asm.restart();
-            XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
-            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
-            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
-            XirOperand tempO = asm.createRegister("tempO", CiKind.Object, AMD64.rax);
+        protected XirTemplate create(CiXirAssembler asm, long flags, int vtableEntryOffset) {
+            if (GraalOptions.InlineVTableStubs) {
+                asm.restart();
+                XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
+                XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
+                XirOperand method = asm.createRegisterTemp("method", CiKind.Object, AMD64.rbx);
 
-            if (is(NULL_CHECK, flags)) {
+                // load class from receiver
+                if (is(NULL_CHECK, flags)) {
+                    asm.mark(MARK_IMPLICIT_NULL);
+                }
+                asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), true);
+                // load vtable entry
+                asm.pload(target.wordKind, method, temp, asm.i(vtableEntryOffset), false);
+                // load entry point from methodOop
                 asm.mark(MARK_IMPLICIT_NULL);
-                asm.pload(target.wordKind, temp, receiver, true);
+                asm.pload(target.wordKind, temp, method, asm.i(config.methodCompiledEntryOffset), true);
+                asm.mark(MARK_INVOKEVIRTUAL);
+
+                return asm.finishTemplate(temp, "invokevirtual");
+            } else {
+                asm.restart();
+                XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
+                XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
+                XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
+                XirOperand tempO = asm.createRegister("tempO", CiKind.Object, AMD64.rax);
+
+                if (is(NULL_CHECK, flags)) {
+                    asm.mark(MARK_IMPLICIT_NULL);
+                    asm.pload(target.wordKind, temp, receiver, true);
+                }
+                asm.mark(MARK_INVOKEVIRTUAL);
+                asm.mov(tempO, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
+
+                return asm.finishTemplate(addr, "invokevirtual");
             }
-            asm.mark(MARK_INVOKEVIRTUAL);
-            asm.mov(tempO, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
-
-            return asm.finishTemplate(addr, "invokevirtual");
         }
     };
 
@@ -1230,7 +1251,12 @@
 
     @Override
     public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) {
-        return new XirSnippet(invokeVirtualTemplates.get(site), receiver, wordArg(0));
+        HotSpotMethodResolved hsMethod = (HotSpotMethodResolved) method;
+        if (GraalOptions.InlineVTableStubs) {
+            return new XirSnippet(invokeVirtualTemplates.get(site, hsMethod.vtableEntryOffset()), receiver);
+        } else {
+            return new XirSnippet(invokeVirtualTemplates.get(site, hsMethod.vtableEntryOffset()), receiver, wordArg(0));
+        }
     }
 
     @Override
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeNode.java	Thu Mar 01 12:10:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeNode.java	Thu Mar 01 12:11:19 2012 +0100
@@ -37,7 +37,7 @@
 public final class InvokeNode extends AbstractStateSplit implements Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint  {
 
     @Input private final MethodCallTargetNode callTarget;
-    private final int bci;
+    @Data private final int bci;
     private boolean useForInlining;
 
     /**
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java	Thu Mar 01 12:10:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java	Thu Mar 01 12:11:19 2012 +0100
@@ -26,6 +26,7 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.Node.*;
 import com.oracle.max.graal.nodes.extended.*;
 import com.oracle.max.graal.nodes.java.*;
 import com.oracle.max.graal.nodes.spi.*;
@@ -37,7 +38,7 @@
 
     @Input private final MethodCallTargetNode callTarget;
     @Input private FrameState stateAfter;
-    private final int bci;
+    @Data private final int bci;
     private boolean useForInlining;
 
     /**
--- a/src/cpu/x86/vm/nativeInst_x86.hpp	Thu Mar 01 12:10:41 2012 +0100
+++ b/src/cpu/x86/vm/nativeInst_x86.hpp	Thu Mar 01 12:11:19 2012 +0100
@@ -61,6 +61,7 @@
   bool is_nop()                        { return ubyte_at(0) == nop_instruction_code; }
   bool is_dtrace_trap();
   inline bool is_call();
+  inline bool is_call_reg();
   inline bool is_illegal();
   inline bool is_return();
   inline bool is_jump();
@@ -181,6 +182,28 @@
   return call;
 }
 
+class NativeCallReg: public NativeInstruction {
+ public:
+  enum Intel_specific_constants {
+    instruction_code            = 0xFF,
+    instruction_size            =    2,
+    instruction_offset          =    0,
+    return_address_offset       =    2
+  };
+
+  address instruction_address() const       { return addr_at(instruction_offset); }
+  address next_instruction_address() const  { return addr_at(return_address_offset); }
+
+
+  static bool is_call_reg_at(address instr) {
+    return ((*instr) & 0xFF) == NativeCallReg::instruction_code;
+  }
+
+  static bool is_call_reg_before(address return_address) {
+    return is_call_reg_at(return_address - NativeCallReg::return_address_offset);
+  }
+};
+
 // An interface for accessing/manipulating native mov reg, imm32 instructions.
 // (used to manipulate inlined 32bit data dll calls, etc.)
 class NativeMovConstReg: public NativeInstruction {
@@ -532,6 +555,7 @@
 
 inline bool NativeInstruction::is_illegal()      { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
 inline bool NativeInstruction::is_call()         { return ubyte_at(0) == NativeCall::instruction_code; }
+inline bool NativeInstruction::is_call_reg()     { return ubyte_at(0) == NativeCallReg::instruction_code; }
 inline bool NativeInstruction::is_return()       { return ubyte_at(0) == NativeReturn::instruction_code ||
                                                           ubyte_at(0) == NativeReturnX::instruction_code; }
 inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Thu Mar 01 12:10:41 2012 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu Mar 01 12:11:19 2012 +0100
@@ -605,6 +605,7 @@
 
   NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
   jint next_pc_offset = 0x0;
+  bool is_call_reg = false;
   if (inst->is_call() || inst->is_jump()) {
     assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
     next_pc_offset = pc_offset + NativeCall::instruction_size;
@@ -614,6 +615,11 @@
     u_char* call = (u_char*) (_instructions->start() + next_pc_offset);
     assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
     next_pc_offset += 3; /* prefix byte + opcode byte + modrm byte */
+  } else if (inst->is_call_reg()) {
+    // the inlined vtable stub contains a "call register" instruction, which isn't recognized here
+    assert(hotspot_method != NULL, "only valid for virtual calls");
+    is_call_reg = true;
+    next_pc_offset = pc_offset + NativeCallReg::instruction_size;
   } else {
     runtime_call->print();
     fatal("unsupported type of instruction for call site");
@@ -665,7 +671,6 @@
     _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
     TRACE_graal_3("relocating (stub)  at %016x", inst);
   } else { // method != NULL
-    NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
     assert(hotspot_method != NULL, "unexpected RiMethod");
     assert(debug_info != NULL, "debug info expected");
 
@@ -680,9 +685,13 @@
     TRACE_graal_3("method call");
     switch (_next_call_type) {
       case MARK_INVOKEVIRTUAL:
+        if (is_call_reg) {
+          break;
+        }
       case MARK_INVOKEINTERFACE: {
         assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
 
+        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
         call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
         _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand);
         break;
@@ -690,6 +699,7 @@
       case MARK_INVOKESTATIC: {
         assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
 
+        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
         call->set_destination(SharedRuntime::get_resolve_static_call_stub());
         _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand);
         break;
@@ -697,6 +707,7 @@
       case MARK_INVOKESPECIAL: {
         assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
 
+        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
         call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
         _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand);
         break;
--- a/src/share/vm/graal/graalCompiler.cpp	Thu Mar 01 12:10:41 2012 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Thu Mar 01 12:11:19 2012 +0100
@@ -274,6 +274,17 @@
   HotSpotMethodResolved::set_maxLocals(obj, method->max_locals());
   HotSpotMethodResolved::set_maxStackSize(obj, method->max_stack());
   HotSpotMethodResolved::set_canBeInlined(obj, !CompilerOracle::should_not_inline(method));
+
+  int vtable_entry_offset;
+  if (instanceKlass::cast(method->method_holder())->is_interface()) {
+    vtable_entry_offset = -1;
+  } else {
+    // get entry offset in words
+    vtable_entry_offset = instanceKlass::vtable_start_offset() + method->vtable_index() * vtableEntry::size();
+    // convert to bytes
+    vtable_entry_offset = vtable_entry_offset * wordSize + vtableEntry::method_offset_in_bytes();
+  }
+  HotSpotMethodResolved::set_vtableEntryOffset(obj, vtable_entry_offset);
   
   method->set_graal_mirror(obj());
   return obj;
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Mar 01 12:10:41 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Mar 01 12:11:19 2012 +0100
@@ -808,6 +808,7 @@
   set_int(env, config, "klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset()));
   set_int(env, config, "graalMirrorKlassOffset", in_bytes(Klass::graal_mirror_offset()));
   set_int(env, config, "klassOopOffset", java_lang_Class::klass_offset_in_bytes());
+  set_int(env, config, "methodCompiledEntryOffset", in_bytes(methodOopDesc::from_compiled_offset()));
 
   set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far());
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Thu Mar 01 12:10:41 2012 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Mar 01 12:11:19 2012 +0100
@@ -69,6 +69,7 @@
     int_field(HotSpotMethodResolved, maxStackSize)                                      \
     boolean_field(HotSpotMethodResolved, canBeInlined)                                  \
     oop_field(HotSpotMethodResolved, callback, "Lcom/oracle/max/cri/ci/CiGenericCallback;") \
+    int_field(HotSpotMethodResolved, vtableEntryOffset)                                 \
   end_class                                                                             \
   start_class(HotSpotMethodData)                                                        \
     oop_field(HotSpotMethodData, compiler, "Lcom/oracle/max/graal/hotspot/Compiler;")   \