changeset 10684:6ff467cdb105

Code installer changes for SPARC.
author twisti
date Tue, 09 Jul 2013 14:39:34 -0700
parents ae4c79ee71d1
children 431eca622358
files src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp src/cpu/sparc/vm/sharedRuntime_sparc.cpp src/cpu/x86/vm/graalCodeInstaller_x86.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCodeInstaller.hpp src/share/vm/prims/methodHandles.cpp
diffstat 6 files changed, 211 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Tue Jul 09 22:05:40 2013 +0200
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Tue Jul 09 14:39:34 2013 -0700
@@ -20,17 +20,82 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 #ifndef CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
 #define CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
 
+#include "graal/graalCompiler.hpp"
+#include "graal/graalCompilerToVM.hpp"
+#include "graal/graalJavaAccess.hpp"
+
 inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
-  fatal("CodeInstaller::pd_next_offset - sparc unimp");
-  return 0;
+  assert(inst->is_call() || inst->is_jump(), "sanity");
+  return pc_offset + NativeCall::instruction_size;
 }
 
-inline void CodeInstaller::pd_site_DataPatch(oop constant, oop kind, bool inlined,
-                                             address instruction, int alignment, char typeChar) {
-  fatal("CodeInstaller::pd_site_DataPatch - sparc unimp");
+inline void CodeInstaller::pd_site_DataPatch(int pc_offset, oop site) {
+  oop constant = CompilationResult_DataPatch::constant(site);
+  int alignment = CompilationResult_DataPatch::alignment(site);
+  bool inlined = CompilationResult_DataPatch::inlined(site) == JNI_TRUE;
+
+  oop kind = Constant::kind(constant);
+  char typeChar = Kind::typeChar(kind);
+
+  address pc = _instructions->start() + pc_offset;
+
+  tty->print_cr("CodeInstaller::pd_site_DataPatch: typeChar=%c, inlined=%d", typeChar, inlined);
+
+  switch (typeChar) {
+    case 'z':
+    case 'b':
+    case 's':
+    case 'c':
+    case 'i':
+      fatal("int-sized values not expected in DataPatch");
+      break;
+    case 'f':
+    case 'j':
+    case 'd': {
+      if (inlined) {
+        fatal(err_msg("inlined: type=%c, constant=%lx", inlined, Constant::primitive(constant)));
+      } else {
+        int size = _constants->size();
+        if (alignment > 0) {
+          guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
+          size = align_size_up(size, alignment);
+        }
+        // we don't care if this is a long/double/etc., the primitive field contains the right bits
+        address dest = _constants->start() + size;
+        _constants->set_end(dest);
+        uint64_t value = Constant::primitive(constant);
+        _constants->emit_int64(value);
+
+        NativeMovRegMem* load = nativeMovRegMem_at(pc);
+        int disp = _constants_size + pc_offset - size - BytesPerInstWord;
+        load->set_offset(-disp);
+
+//        assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+//        *((jint*) operand) = (jint) disp;
+
+//        _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS) /*, Assembler::disp32_operand*/);
+//        TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size);
+      }
+      break;
+    }
+    case 'a': {
+//      address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
+//      Handle obj = Constant::object(constant);
+//
+//      jobject value = JNIHandles::make_local(obj());
+//      *((jobject*) operand) = value;
+//      _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+//      TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand);
+      break;
+    }
+    default:
+      fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar));
+      break;
+  }
 }
 
 inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
@@ -41,8 +106,49 @@
   fatal("CodeInstaller::pd_relocate_ForeignCall - sparc unimp");
 }
 
-inline void CodeInstaller::pd_relocate_JavaMethod(oop method, jint pc_offset) {
-  fatal("CodeInstaller::pd_relocate_JavaMethod - sparc unimp");
+inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+  Method* method = NULL;
+  // we need to check, this might also be an unresolved method
+  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
+    method = getMethodFromHotSpotMethod(hotspot_method);
+  }
+#endif
+  switch (_next_call_type) {
+    case MARK_INLINE_INVOKE:
+      break;
+    case MARK_INVOKEVIRTUAL:
+    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);
+      fatal("NYI");
+      break;
+    }
+    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;
+    }
+    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);
+      fatal("NYI");
+      break;
+    }
+    default:
+      fatal("invalid _next_call_type value");
+      break;
+  }
 }
 
 inline int32_t* CodeInstaller::pd_locate_operand(address instruction) {
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Jul 09 22:05:40 2013 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Jul 09 14:39:34 2013 -0700
@@ -1826,6 +1826,31 @@
   verify_oop_args(masm, method, sig_bt, regs);
   vmIntrinsics::ID iid = method->intrinsic_id();
 
+#ifdef GRAAL
+  if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // We are called from compiled code here. The three object arguments
+    // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The
+    // fourth argument (j_rarg3) is a pointer to the HotSpotInstalledCode object.
+
+    // Load the nmethod pointer from the HotSpotInstalledCode object
+//    __ movq(j_rarg3, Address(j_rarg3, sizeof(oopDesc)));
+
+    // Check whether the nmethod was invalidated
+//    __ testq(j_rarg3, j_rarg3);
+//    Label invalid_nmethod;
+//    __ jcc(Assembler::zero, invalid_nmethod);
+
+    // Perform a tail call to the verified entry point of the nmethod.
+//    __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+
+//    __ bind(invalid_nmethod);
+
+//    __ jump(RuntimeAddress(StubRoutines::throw_InvalidInstalledCodeException_entry()));
+    __ stop("_CompilerToVMImpl_executeCompiledMethod not implemented");
+    return;
+  }
+#endif
+
   // Now write the args into the outgoing interpreter space
   bool     has_receiver   = false;
   Register receiver_reg   = noreg;
--- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Tue Jul 09 22:05:40 2013 +0200
+++ b/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Tue Jul 09 14:39:34 2013 -0700
@@ -56,8 +56,16 @@
   }
 }
 
-inline void CodeInstaller::pd_site_DataPatch(oop constant, oop kind, bool inlined,
-                                             address instruction, int alignment, char typeChar) {
+inline void CodeInstaller::pd_site_DataPatch(int pc_offset, oop site) {
+  oop constant = CompilationResult_DataPatch::constant(site);
+  int alignment = CompilationResult_DataPatch::alignment(site);
+  bool inlined = CompilationResult_DataPatch::inlined(site) == JNI_TRUE;
+
+  oop kind = Constant::kind(constant);
+  char typeChar = Kind::typeChar(kind);
+
+  address pc = _instructions->start() + pc_offset;
+
   switch (typeChar) {
     case 'z':
     case 'b':
@@ -70,11 +78,11 @@
     case 'j':
     case 'd': {
       if (inlined) {
-        address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
+        address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
         *((jlong*) operand) = Constant::primitive(constant);
       } else {
-        address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand);
-        address next_instruction = Assembler::locate_next_instruction(instruction);
+        address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
+        address next_instruction = Assembler::locate_next_instruction(pc);
         int size = _constants->size();
         if (alignment > 0) {
           guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
@@ -82,26 +90,27 @@
         }
         // we don't care if this is a long/double/etc., the primitive field contains the right bits
         address dest = _constants->start() + size;
-        _constants->set_end(dest + BytesPerLong);
-        *(jlong*) dest = Constant::primitive(constant);
+        _constants->set_end(dest);
+        uint64_t value = Constant::primitive(constant);
+        _constants->emit_int64(value);
 
         long disp = dest - next_instruction;
         assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
         *((jint*) operand) = (jint) disp;
 
-        _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
-        TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size);
+        _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+        TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, pc, operand, dest, size);
       }
       break;
     }
     case 'a': {
-      address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
+      address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
       Handle obj = Constant::object(constant);
 
       jobject value = JNIHandles::make_local(obj());
       *((jobject*) operand) = value;
-      _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
-      TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand);
+      _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+      TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand);
       break;
     }
     default:
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Tue Jul 09 22:05:40 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Tue Jul 09 14:39:34 2013 -0700
@@ -171,7 +171,7 @@
 
   if (value->is_a(RegisterValue::klass())) {
     jint number = code_Register::number(RegisterValue::reg(value));
-    if (number < 16) {
+    if (number < RegisterImpl::number_of_registers) {
       if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE || type == T_ADDRESS) {
         locationType = Location::int_in_long;
       } else if (type == T_LONG) {
@@ -366,6 +366,10 @@
   jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
   initialize_assumptions(JNIHandles::resolve(compiled_code_obj));
 
+  // Get instructions and constants CodeSections early because we need it.
+  _instructions = buffer.insts();
+  _constants = buffer.consts();
+
   {
     No_Safepoint_Verifier no_safepoint;
     initialize_fields(JNIHandles::resolve(compiled_code_obj));
@@ -397,6 +401,11 @@
         GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, false, leaf_graph_ids, installed_code, triggered_deoptimizations);
     cb = nm;
   }
+
+  if (cb != NULL) {
+    // Make sure the pre-calculated constants section size was correct.
+    guarantee((cb->code_begin() - cb->content_begin()) == _constants_size, err_msg("%d != %d", cb->code_begin() - cb->content_begin(), _constants_size));
+  }
 }
 
 void CodeInstaller::initialize_fields(oop compiled_code) {
@@ -417,11 +426,12 @@
   _code = (arrayOop) CompilationResult::targetCode(comp_result);
   _code_size = CompilationResult::targetCodeSize(comp_result);
   // The frame size we get from the target method does not include the return address, so add one word for it here.
-  _total_frame_size = CompilationResult::frameSize(comp_result) + HeapWordSize;
+  _total_frame_size = CompilationResult::frameSize(comp_result) + HeapWordSize;  // FIXME this is an x86-ism
   _custom_stack_area_offset = CompilationResult::customStackAreaOffset(comp_result);
 
-  // (very) conservative estimate: each site needs a constant section entry
-  _constants_size = _sites->length() * (BytesPerLong*2);
+  // Pre-calculate the constants section size.  This is required for PC-relative addressing.
+  _constants_size = calculate_constants_size();
+
 #ifndef PRODUCT
   _comments = (arrayOop) HotSpotCompiledCode::comments(compiled_code);
 #endif
@@ -442,9 +452,6 @@
 
   buffer.initialize_oop_recorder(_oop_recorder);
 
-  _instructions = buffer.insts();
-  _constants = buffer.consts();
-
   // copy the code into the newly created CodeBuffer
   address end_pc = _instructions->start() + _code_size;
   if (!_instructions->allocates2(end_pc)) {
@@ -454,7 +461,7 @@
   _instructions->set_end(end_pc);
 
   for (int i = 0; i < _sites->length(); i++) {
-    oop site=((objArrayOop) (_sites))->obj_at(i);
+    oop site = ((objArrayOop) (_sites))->obj_at(i);
     jint pc_offset = CompilationResult_Site::pcOffset(site);
 
     if (site->is_a(CompilationResult_Call::klass())) {
@@ -485,7 +492,7 @@
 #ifndef PRODUCT
   if (_comments != NULL) {
     for (int i = 0; i < _comments->length(); i++) {
-      oop comment=((objArrayOop) (_comments))->obj_at(i);
+      oop comment = ((objArrayOop) (_comments))->obj_at(i);
       assert(comment->is_a(HotSpotCompiledCode_Comment::klass()), "cce");
       jint offset = HotSpotCompiledCode_Comment::pcOffset(comment);
       char* text = java_lang_String::as_utf8_string(HotSpotCompiledCode_Comment::text(comment));
@@ -496,6 +503,35 @@
   return true;
 }
 
+/**
+ * Calculate the constants section size by iterating over all DataPatches.
+ * Knowing the size of the constants section before patching instructions
+ * is necessary for PC-relative addressing.
+ */
+int CodeInstaller::calculate_constants_size() {
+  int size = 0;
+
+  for (int i = 0; i < _sites->length(); i++) {
+    oop site = ((objArrayOop) (_sites))->obj_at(i);
+    jint pc_offset = CompilationResult_Site::pcOffset(site);
+
+    if (site->is_a(CompilationResult_DataPatch::klass())) {
+      oop constant = CompilationResult_DataPatch::constant(site);
+      int alignment = CompilationResult_DataPatch::alignment(site);
+      bool inlined = CompilationResult_DataPatch::inlined(site) == JNI_TRUE;
+
+      if (!inlined) {
+        if (alignment > 0) {
+          guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
+          size = align_size_up(size, alignment);
+        }
+        size = size + sizeof(int64_t);
+      }
+    }
+  }
+  return size == 0 ? 0 : align_size_up(size, _constants->alignment());
+}
+
 void CodeInstaller::assumption_MethodContents(Handle assumption) {
   Handle method_handle = Assumptions_MethodContents::method(assumption());
   methodHandle method = getMethodFromHotSpotMethod(method_handle());
@@ -732,11 +768,7 @@
 
 void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) {
   oop constant = CompilationResult_DataPatch::constant(site);
-  int alignment = CompilationResult_DataPatch::alignment(site);
-  bool inlined = CompilationResult_DataPatch::inlined(site) == JNI_TRUE;
   oop kind = Constant::kind(constant);
-
-  address instruction = _instructions->start() + pc_offset;
   char typeChar = Kind::typeChar(kind);
   switch (typeChar) {
     case 'f':
@@ -745,7 +777,7 @@
       record_metadata_in_constant(constant, _oop_recorder);
       break;
   }
-  CodeInstaller::pd_site_DataPatch(constant, kind, inlined, instruction, alignment, typeChar);
+  CodeInstaller::pd_site_DataPatch(pc_offset, site);
 }
 
 void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) {
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Tue Jul 09 22:05:40 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Tue Jul 09 14:39:34 2013 -0700
@@ -76,7 +76,7 @@
   ExceptionHandlerTable     _exception_handler_table;
 
   jint pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method);
-  void pd_site_DataPatch(oop constant, oop kind, bool inlined, address instruction, int alignment, char typeChar);
+  void pd_site_DataPatch(int pc_offset, oop site);
   void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst);
   void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination);
   void pd_relocate_JavaMethod(oop method, jint pc_offset);
@@ -96,6 +96,8 @@
   // perform data and call relocation on the CodeBuffer
   bool initialize_buffer(CodeBuffer& buffer);
 
+  int calculate_constants_size();
+
   void assumption_MethodContents(Handle assumption);
   void assumption_NoFinalizableSubclass(Handle assumption);
   void assumption_ConcreteSubtype(Handle assumption);
--- a/src/share/vm/prims/methodHandles.cpp	Tue Jul 09 22:05:40 2013 +0200
+++ b/src/share/vm/prims/methodHandles.cpp	Tue Jul 09 14:39:34 2013 -0700
@@ -342,7 +342,7 @@
 
 
 Symbol* MethodHandles::signature_polymorphic_intrinsic_name(vmIntrinsics::ID iid) {
-  assert(is_signature_polymorphic_intrinsic(iid), err_msg("iid=%d", iid));
+  assert(is_signature_polymorphic_intrinsic(iid), err_msg("%d %s", iid, vmIntrinsics::name_at(iid)));
   switch (iid) {
   case vmIntrinsics::_invokeBasic:      return vmSymbols::invokeBasic_name();
   case vmIntrinsics::_linkToVirtual:    return vmSymbols::linkToVirtual_name();
@@ -350,7 +350,7 @@
   case vmIntrinsics::_linkToSpecial:    return vmSymbols::linkToSpecial_name();
   case vmIntrinsics::_linkToInterface:  return vmSymbols::linkToInterface_name();
   }
-  assert(false, "");
+  fatal(err_msg("unknown intrinsic id: %d %s", iid, vmIntrinsics::name_at(iid)));
   return 0;
 }
 
@@ -362,7 +362,7 @@
   case vmIntrinsics::_linkToSpecial:    return JVM_REF_invokeSpecial;
   case vmIntrinsics::_linkToInterface:  return JVM_REF_invokeInterface;
   }
-  assert(false, err_msg("iid=%d", iid));
+  fatal(err_msg("unknown intrinsic id: %d %s", iid, vmIntrinsics::name_at(iid)));
   return 0;
 }