changeset 1427:149b1d2316de

basic invokeinterface and invokevirtual support
author Lukas Stadler <lukas.stadler@oracle.com>
date Wed, 18 Aug 2010 16:47:06 -0700
parents ed6bd46ad55e
children 695451afc619
files c1x4hotspotsrc/HotSpotTest/src/jttTests.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotProxy.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotTargetMethod.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotXirGenerator.java src/share/vm/c1x/c1x_Compiler.hpp src/share/vm/c1x/c1x_VMEntries.cpp
diffstat 6 files changed, 153 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/c1x4hotspotsrc/HotSpotTest/src/jttTests.java	Wed Aug 18 11:44:04 2010 -0700
+++ b/c1x4hotspotsrc/HotSpotTest/src/jttTests.java	Wed Aug 18 16:47:06 2010 -0700
@@ -4,7 +4,7 @@
 public class jttTests {
 
 	public static void main(String[] args) {
-		runTests(182, 182);
+		runTests(0, 200);
 		Logger.info("total: " + executed + " tests executed, " + passed + " passed, " + failed + " failed");
 	}
 
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotProxy.java	Wed Aug 18 11:44:04 2010 -0700
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotProxy.java	Wed Aug 18 16:47:06 2010 -0700
@@ -29,13 +29,14 @@
 
     private enum CompilerObjectType {
         // this enum needs to have the same values as the one in c1x_Compiler.hpp
-        STUB(0x100000000000000l),
-        METHOD(0x200000000000000l),
-        CLASS(0x300000000000000l),
-        SYMBOL(0x400000000000000l),
-        CONSTANT_POOL(0x500000000000000l),
-        CONSTANT(0x600000000000000l),
-        TYPE_MASK(0xf00000000000000l);
+        STUB(0x100000000000000L),
+        METHOD(0x200000000000000L),
+        CLASS(0x300000000000000L),
+        SYMBOL(0x400000000000000L),
+        CONSTANT_POOL(0x500000000000000L),
+        CONSTANT(0x600000000000000L),
+        TYPE_MASK(0xf00000000000000L),
+        DUMMY_CONSTANT(0x6ffffffffffffffL);
 
         public final long bits;
 
@@ -44,6 +45,8 @@
         }
     }
 
+    public static final Long DUMMY_CONSTANT_OBJ = CompilerObjectType.DUMMY_CONSTANT.bits;
+
     private static boolean isType(long id, CompilerObjectType type) {
         return (id & CompilerObjectType.TYPE_MASK.bits) == type.bits;
     }
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotTargetMethod.java	Wed Aug 18 11:44:04 2010 -0700
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotTargetMethod.java	Wed Aug 18 16:47:06 2010 -0700
@@ -20,7 +20,7 @@
 import java.util.*;
 
 import com.sun.cri.ci.*;
-import com.sun.cri.ci.CiTargetMethod.Site;
+import com.sun.cri.ci.CiTargetMethod.*;
 
 /**
  * CiTargetMethod augmented with HotSpot-specific information.
@@ -54,21 +54,27 @@
     private Site[] getSortedSites(CiTargetMethod target) {
         List<?>[] lists = new List<?>[] {target.directCalls, target.indirectCalls, target.safepoints, target.dataReferences, target.exceptionHandlers, target.marks};
         int count = 0;
-        for (List<?> list: lists) {
+        for (List<?> list : lists) {
             count += list.size();
         }
         Site[] result = new Site[count];
         int pos = 0;
-        for (List<?> list: lists) {
-            for (Object elem: list) {
-                result[pos++] = (Site)elem;
+        for (List<?> list : lists) {
+            for (Object elem : list) {
+                result[pos++] = (Site) elem;
             }
         }
         Arrays.sort(result, new Comparator<Site>() {
+
             public int compare(Site s1, Site s2) {
+                if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
+                    return s1 instanceof Mark ? -1 : 1;
+                }
                 return s1.pcOffset - s2.pcOffset;
             }
         });
+        for(Site site : result)
+            System.out.println(site.pcOffset + ": " + site);
         return result;
     }
 
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotXirGenerator.java	Wed Aug 18 11:44:04 2010 -0700
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotXirGenerator.java	Wed Aug 18 16:47:06 2010 -0700
@@ -38,8 +38,15 @@
     // this needs to correspond to c1x_Compiler.hpp
     private static final Integer MARK_VERIFIED_ENTRY = 1;
     private static final Integer MARK_UNVERIFIED_ENTRY = 2;
+    private static final Integer MARK_OSR_ENTRY = 3;
     private static final Integer MARK_STATIC_CALL_STUB = 1000;
 
+    private static final Integer MARK_INVOKE_INVALID = 2000;
+    private static final Integer MARK_INVOKEINTERFACE = 2001;
+    private static final Integer MARK_INVOKESTATIC = 2002;
+    private static final Integer MARK_INVOKESPECIAL = 2003;
+    private static final Integer MARK_INVOKEVIRTUAL = 2004;
+
     private final HotSpotVMConfig config;
     private final CiTarget target;
     private final RiRegisterConfig registerConfig;
@@ -56,6 +63,8 @@
     private XirTemplate exceptionObjectTemplate;
     private XirTemplate invokeStaticTemplate;
     private XirTemplate invokeSpecialTemplate;
+    private XirTemplate invokeInterfaceTemplate;
+    private XirTemplate invokeVirtualTemplate;
     private XirTemplate newInstanceTemplate;
 
     static class XirPair {
@@ -122,6 +131,8 @@
         instanceofTemplateNonnull = buildInstanceof(true);
         invokeStaticTemplate = buildInvokeStatic();
         invokeSpecialTemplate = buildInvokeSpecial();
+        invokeInterfaceTemplate = buildInvokeInterface();
+        invokeVirtualTemplate = buildInvokeVirtual();
         newInstanceTemplate = buildNewInstance();
 
         return templates;
@@ -133,6 +144,7 @@
         XirOperand frame_pointer = asm.createRegister("frame pointer", CiKind.Word, AMD64.rbp);
 
         asm.align(config.codeEntryAlignment);
+        asm.mark(MARK_OSR_ENTRY);
         asm.mark(MARK_UNVERIFIED_ENTRY);
         if (!staticMethod) {
             // TODO do some checking...
@@ -368,7 +380,8 @@
         asm.restart();
         XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word);
 
-        XirLabel stub = asm.createOutOfLineLabel("staticCallStub");
+        XirLabel stub = asm.createOutOfLineLabel("call stub");
+        asm.mark(MARK_INVOKESTATIC);
 
         asm.bindOutOfLine(stub);
         XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx);
@@ -385,7 +398,8 @@
         asm.restart();
         XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word);
 
-        XirLabel stub = asm.createOutOfLineLabel("specialCallStub");
+        XirLabel stub = asm.createOutOfLineLabel("call stub");
+        asm.mark(MARK_INVOKESPECIAL);
 
         asm.bindOutOfLine(stub);
         XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx);
@@ -398,6 +412,44 @@
         return asm.finishTemplate(addr, "invokespecial");
     }
 
+    private XirTemplate buildInvokeInterface() {
+        asm.restart();
+        XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word);
+        XirOperand method = asm.createRegister("method", CiKind.Object, AMD64.rbx);
+
+        XirLabel stub = asm.createOutOfLineLabel("call stub");
+        asm.mark(MARK_INVOKEINTERFACE);
+        asm.mov(method, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
+
+        asm.bindOutOfLine(stub);
+        asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE);
+        asm.mov(method, asm.w(0l));
+        XirLabel dummy = asm.createOutOfLineLabel("dummy");
+        asm.jmp(dummy);
+        asm.bindOutOfLine(dummy);
+
+        return asm.finishTemplate(addr, "invokespecial");
+    }
+
+    private XirTemplate buildInvokeVirtual() {
+        asm.restart();
+        XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word);
+        XirOperand method = asm.createRegister("method", CiKind.Object, AMD64.rbx);
+
+        XirLabel stub = asm.createOutOfLineLabel("call stub");
+        asm.mark(MARK_INVOKEVIRTUAL);
+        asm.mov(method, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
+
+        asm.bindOutOfLine(stub);
+        asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE);
+        asm.mov(method, asm.w(0l));
+        XirLabel dummy = asm.createOutOfLineLabel("dummy");
+        asm.jmp(dummy);
+        asm.bindOutOfLine(dummy);
+
+        return asm.finishTemplate(addr, "invokespecial");
+    }
+
     private XirTemplate buildNewInstance() {
         XirOperand result = asm.restart(CiKind.Word);
         XirOperand type = asm.createInputParameter("type", CiKind.Object);
@@ -515,7 +567,7 @@
 
     @Override
     public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, RiMethod method) {
-        return new XirSnippet(emptyTemplates[CiKind.Word.ordinal()]);
+        return new XirSnippet(invokeInterfaceTemplate, XirArgument.forWord(0));
     }
 
     @Override
@@ -530,7 +582,7 @@
 
     @Override
     public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) {
-        return new XirSnippet(emptyTemplates[CiKind.Word.ordinal()]);
+        return new XirSnippet(invokeVirtualTemplate, XirArgument.forWord(0));
     }
 
     @Override
--- a/src/share/vm/c1x/c1x_Compiler.hpp	Wed Aug 18 11:44:04 2010 -0700
+++ b/src/share/vm/c1x/c1x_Compiler.hpp	Wed Aug 18 16:47:06 2010 -0700
@@ -60,7 +60,13 @@
   enum MarkId {
     MARK_VERIFIED_ENTRY     = 1,
     MARK_UNVERIFIED_ENTRY   = 2,
-    MARK_STATIC_CALL_STUB   = 1000
+    MARK_OSR_ENTRY          = 3,
+    MARK_STATIC_CALL_STUB   = 1000,
+    MARK_INVOKE_INVALID     = 2000,
+    MARK_INVOKEINTERFACE    = 2001,
+    MARK_INVOKESTATIC       = 2002,
+    MARK_INVOKESPECIAL      = 2003,
+    MARK_INVOKEVIRTUAL      = 2004
   };
 
 /*
@@ -83,13 +89,14 @@
 public:
   // this enum needs to have the same values as the one in HotSpotProxy.java
   enum CompilerObjectType {
-    STUB          = 0x100000000000000l,
-    METHOD        = 0x200000000000000l,
-    CLASS         = 0x300000000000000l,
-    SYMBOL        = 0x400000000000000l,
-    CONSTANT_POOL = 0x500000000000000l,
-    CONSTANT      = 0x600000000000000l,
-    TYPE_MASK     = 0xf00000000000000l
+    STUB           = 0x100000000000000l,
+    METHOD         = 0x200000000000000l,
+    CLASS          = 0x300000000000000l,
+    SYMBOL         = 0x400000000000000l,
+    CONSTANT_POOL  = 0x500000000000000l,
+    CONSTANT       = 0x600000000000000l,
+    TYPE_MASK      = 0xf00000000000000l,
+    DUMMY_CONSTANT = 0x6ffffffffffffffl
   };
 
   static void initializeObjects();
--- a/src/share/vm/c1x/c1x_VMEntries.cpp	Wed Aug 18 11:44:04 2010 -0700
+++ b/src/share/vm/c1x/c1x_VMEntries.cpp	Wed Aug 18 16:47:06 2010 -0700
@@ -322,9 +322,6 @@
   arrayOop register_map = (arrayOop)CiDebugInfo::registerRefMap(debug_info);
   arrayOop frame_map = (arrayOop)CiDebugInfo::frameRefMap(debug_info);
 
-  jint register_count = VMRegImpl::stack2reg(0)->value();
-  tty->print_cr("register count: %i", register_count);
-
   for (jint i=0; i<C1X_REGISTER_COUNT; i++) {
     unsigned char byte = ((unsigned char*)register_map->base(T_BYTE))[i / 8];
     bool is_oop = (byte & (1 << (i % 8))) != 0;
@@ -382,6 +379,9 @@
   jint          _constants_size;
   jint          _total_size;
 
+  C1XCompiler::MarkId _next_call_type;
+  address       _invoke_mark_pc;
+
   CodeSection*  _instructions;
   CodeSection*  _constants;
 
@@ -451,6 +451,8 @@
     // (very) conservative estimate: each site needs a constant section entry
     _constants_size = _sites->length() * BytesPerLong;
     _total_size = align_size_up(_code_size, HeapWordSize) + _constants_size;
+
+    _next_call_type = C1XCompiler::MARK_INVOKE_INVALID;
   }
 
   void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) {
@@ -556,28 +558,47 @@
       oop frame = CiDebugInfo::frame(debug_info);
       record_frame(next_pc_offset, code_pos, frame);
 
-      if (method->is_static()) {
-        tty->print_cr("static method");
+      switch(_next_call_type) {
+        case C1XCompiler::MARK_INVOKEVIRTUAL:
+        case C1XCompiler::MARK_INVOKEINTERFACE: {
+          assert(!method->is_static(), "cannot call static method with invokeinterface");
+
+          address dest = SharedRuntime::get_resolve_virtual_call_stub();
+          long disp = dest - next_instruction;
+          assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+          *((jint*)operand) = (jint)disp;
 
-        address dest = SharedRuntime::get_resolve_static_call_stub();
-        long disp = dest - next_instruction;
-        assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
-        *((jint*)operand) = (jint)disp;
+          _instructions->relocate(instruction, virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand);
+          break;
+        }
+        case C1XCompiler::MARK_INVOKESTATIC: {
+          assert(method->is_static(), "cannot call non-static method with invokestatic");
+
+          address dest = SharedRuntime::get_resolve_static_call_stub();
+          long disp = dest - next_instruction;
+          assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+          *((jint*)operand) = (jint)disp;
 
-        _instructions->relocate(instruction, relocInfo::static_call_type, Assembler::call32_operand);
-        tty->print_cr("relocating (Long) %016x/%016x", instruction, operand);
-      } else {
-        tty->print_cr("non-static method");
+          _instructions->relocate(instruction, relocInfo::static_call_type, Assembler::call32_operand);
+          break;
+        }
+        case C1XCompiler::MARK_INVOKESPECIAL: {
+          assert(!method->is_static(), "cannot call static method with invokespecial");
 
-        address dest = SharedRuntime::get_resolve_opt_virtual_call_stub();
-        long disp = dest - next_instruction;
-        assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
-        *((jint*)operand) = (jint)disp;
+          address dest = SharedRuntime::get_resolve_opt_virtual_call_stub();
+          long disp = dest - next_instruction;
+          assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+          *((jint*)operand) = (jint)disp;
 
-        _instructions->relocate(instruction, relocInfo::opt_virtual_call_type, Assembler::call32_operand);
-        tty->print_cr("relocating (Long) %016x/%016x", instruction, operand);
+          _instructions->relocate(instruction, relocInfo::opt_virtual_call_type, Assembler::call32_operand);
+          break;
+        }
+        case C1XCompiler::MARK_INVOKE_INVALID:
+        default:
+          ShouldNotReachHere();
+          break;
       }
-
+      _next_call_type = C1XCompiler::MARK_INVOKE_INVALID;
       _debug_recorder->end_safepoint(pc_offset);
     }
   }
@@ -630,35 +651,14 @@
 
           address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
 
-          *((jobject*)operand) = JNIHandles::make_local(C1XObjects::get<oop>(id));
+          if (id == C1XObjects::DUMMY_CONSTANT) {
+            *((jobject*)operand) = (jobject)Universe::non_oop_word();
+          } else {
+            *((jobject*)operand) = JNIHandles::make_local(C1XObjects::get<oop>(id));
+          }
           _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
           tty->print_cr("relocating (oop constant) at %016x/%016x", instruction, operand);
         }
-
-        /*
-        jlong id = com_sun_hotspot_c1x_HotSpotProxy::get_id(obj);
-        switch (id & C1XObjects::TYPE_MASK) {
-          case C1XObjects::CONSTANT: {
-            address operand = Assembler::locate_operand(inst, Assembler::imm_operand);
-
-            *((jobject*)operand) = JNIHandles::make_local(C1XObjects::get<oop>(id));
-            instructions->relocate(inst, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
-            tty->print_cr("relocating (HotSpotType) %02x at %016x/%016x", inst_byte, inst, operand);
-            break;
-          }
-          case C1XObjects::STUB: {
-            address operand = Assembler::locate_operand(inst, Assembler::call32_operand);
-
-            long dest = (long)C1XObjects::getStub(id);
-            long disp = dest - (long)(operand + 4);
-            assert(disp == (int) disp, "disp doesn't fit in 32 bits");
-            *((int*)operand) = (int)disp;
-
-            instructions->relocate(inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
-            tty->print_cr("relocating (Long) %02x at %016x/%016x", inst_byte, inst, operand);
-            break;
-          }
-        }*/
         break;
       }
       default:
@@ -688,6 +688,9 @@
         case C1XCompiler::MARK_VERIFIED_ENTRY:
           _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset);
           break;
+        case C1XCompiler::MARK_OSR_ENTRY:
+          _offsets.set_value(CodeOffsets::OSR_Entry, pc_offset);
+          break;
         case C1XCompiler::MARK_STATIC_CALL_STUB: {
           assert(references->length() == 1, "static call stub needs one reference");
           oop ref = ((oop*)references->base(T_OBJECT))[0];
@@ -695,6 +698,17 @@
           _instructions->relocate(instruction, static_stub_Relocation::spec(call_pc));
           break;
         }
+        case C1XCompiler::MARK_INVOKE_INVALID:
+        case C1XCompiler::MARK_INVOKEINTERFACE:
+        case C1XCompiler::MARK_INVOKESTATIC:
+        case C1XCompiler::MARK_INVOKESPECIAL:
+        case C1XCompiler::MARK_INVOKEVIRTUAL:
+          _next_call_type = (C1XCompiler::MarkId)id;
+          _invoke_mark_pc = instruction;
+          break;
+        default:
+          ShouldNotReachHere();
+          break;
       }
     }
   }