hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp
changeset 42650 1f304d0c888b
parent 41697 94ef14db8a20
child 42861 1d4dfdf4390b
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -172,6 +172,69 @@
   return map;
 }
 
+AOTOopRecorder::AOTOopRecorder(Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) {
+  _meta_strings = new GrowableArray<const char*>();
+}
+
+int AOTOopRecorder::nr_meta_strings() const {
+  return _meta_strings->length();
+}
+
+const char* AOTOopRecorder::meta_element(int pos) const {
+  return _meta_strings->at(pos);
+}
+
+int AOTOopRecorder::find_index(Metadata* h) {
+  int index =  this->OopRecorder::find_index(h);
+
+  Klass* klass = NULL;
+  if (h->is_klass()) {
+    klass = (Klass*) h;
+    record_meta_string(klass->signature_name(), index);
+  } else if (h->is_method()) {
+    Method* method = (Method*) h;
+    // Need klass->signature_name() in method name
+    klass = method->method_holder();
+    const char* klass_name = klass->signature_name();
+    int klass_name_len  = (int)strlen(klass_name);
+    Symbol* method_name = method->name();
+    Symbol* signature   = method->signature();
+    int method_name_len = method_name->utf8_length();
+    int method_sign_len = signature->utf8_length();
+    int len             = klass_name_len + 1 + method_name_len + method_sign_len;
+    char* dest          = NEW_RESOURCE_ARRAY(char, len + 1);
+    strcpy(dest, klass_name);
+    dest[klass_name_len] = '.';
+    strcpy(&dest[klass_name_len + 1], method_name->as_C_string());
+    strcpy(&dest[klass_name_len + 1 + method_name_len], signature->as_C_string());
+    dest[len] = 0;
+    record_meta_string(dest, index);
+  }
+
+  return index;
+}
+
+int AOTOopRecorder::find_index(jobject h) {
+  if (h == NULL) {
+    return 0;
+  }
+  oop javaMirror = JNIHandles::resolve(h);
+  Klass* klass = java_lang_Class::as_Klass(javaMirror);
+  return find_index(klass);
+}
+
+void AOTOopRecorder::record_meta_string(const char* name, int index) {
+  assert(index > 0, "must be 1..n");
+  index -= 1; // reduce by one to convert to array index
+
+  if (index < _meta_strings->length()) {
+    assert(strcmp(name, _meta_strings->at(index)) == 0, "must match");
+  } else {
+    assert(index == _meta_strings->length(), "must be last");
+    _meta_strings->append(name);
+  }
+}
+
 void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
   /*
    * This method needs to return a raw (untyped) pointer, since the value of a pointer to the base
@@ -481,7 +544,10 @@
 JVMCIEnv::CodeInstallResult CodeInstaller::gather_metadata(Handle target, Handle compiled_code, CodeMetadata& metadata, TRAPS) {
   CodeBuffer buffer("JVMCI Compiler CodeBuffer for Metadata");
   jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
-  initialize_dependencies(JNIHandles::resolve(compiled_code_obj), NULL, CHECK_OK);
+  AOTOopRecorder* recorder = new AOTOopRecorder(&_arena, true);
+  initialize_dependencies(JNIHandles::resolve(compiled_code_obj), recorder, CHECK_OK);
+
+  metadata.set_oop_recorder(recorder);
 
   // Get instructions and constants CodeSections early because we need it.
   _instructions = buffer.insts();
@@ -553,7 +619,7 @@
                                        stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
                                        compiler, _debug_recorder, _dependencies, env, id,
                                        has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log);
-    cb = nm;
+    cb = nm->as_codeblob_or_null();
     if (nm != NULL && env == NULL) {
       DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler);
       bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption;
@@ -623,25 +689,40 @@
 }
 
 int CodeInstaller::estimate_stubs_size(TRAPS) {
-  // Estimate the number of static call stubs that might be emitted.
+  // Estimate the number of static and aot call stubs that might be emitted.
   int static_call_stubs = 0;
+  int aot_call_stubs = 0;
   objArrayOop sites = this->sites();
   for (int i = 0; i < sites->length(); i++) {
     oop site = sites->obj_at(i);
-    if (site != NULL && site->is_a(site_Mark::klass())) {
-      oop id_obj = site_Mark::id(site);
-      if (id_obj != NULL) {
-        if (!java_lang_boxing_object::is_instance(id_obj, T_INT)) {
-          JVMCI_ERROR_0("expected Integer id, got %s", id_obj->klass()->signature_name());
+    if (site != NULL) {
+      if (site->is_a(site_Mark::klass())) {
+        oop id_obj = site_Mark::id(site);
+        if (id_obj != NULL) {
+          if (!java_lang_boxing_object::is_instance(id_obj, T_INT)) {
+            JVMCI_ERROR_0("expected Integer id, got %s", id_obj->klass()->signature_name());
+          }
+          jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+          if (id == INVOKESTATIC || id == INVOKESPECIAL) {
+            static_call_stubs++;
+          }
         }
-        jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
-        if (id == INVOKESTATIC || id == INVOKESPECIAL) {
-          static_call_stubs++;
+      }
+      if (UseAOT && site->is_a(site_Call::klass())) {
+        oop target = site_Call::target(site);
+        InstanceKlass* target_klass = InstanceKlass::cast(target->klass());
+        if (!target_klass->is_subclass_of(SystemDictionary::HotSpotForeignCallTarget_klass())) {
+          // Add far aot trampolines.
+          aot_call_stubs++;
         }
       }
     }
   }
-  return static_call_stubs * CompiledStaticCall::to_interp_stub_size();
+  int size = static_call_stubs * CompiledStaticCall::to_interp_stub_size();
+#if INCLUDE_AOT
+  size += aot_call_stubs * CompiledStaticCall::to_aot_stub_size();
+#endif
+  return size;
 }
 
 // perform data and call relocation on the CodeBuffer
@@ -1063,6 +1144,10 @@
 
   if (foreign_call.not_null()) {
     jlong foreign_call_destination = HotSpotForeignCallTarget::address(foreign_call);
+    if (_immutable_pic_compilation) {
+      // Use fake short distance during PIC compilation.
+      foreign_call_destination = (jlong)(_instructions->start() + pc_offset);
+    }
     CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination, CHECK);
   } else { // method != NULL
     if (debug_info.is_null()) {
@@ -1075,6 +1160,10 @@
       // Need a static call stub for transitions from compiled to interpreted.
       CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset);
     }
+#if INCLUDE_AOT
+    // Trampoline to far aot code.
+    CompiledStaticCall::emit_to_aot_stub(buffer, _instructions->start() + pc_offset);
+#endif
   }
 
   _next_call_type = INVOKE_INVALID;
@@ -1093,9 +1182,18 @@
     if (constant.is_null()) {
       THROW(vmSymbols::java_lang_NullPointerException());
     } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
-      pd_patch_OopConstant(pc_offset, constant, CHECK);
+      if (!_immutable_pic_compilation) {
+        // Do not patch during PIC compilation.
+        pd_patch_OopConstant(pc_offset, constant, CHECK);
+      }
     } else if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
-      pd_patch_MetaspaceConstant(pc_offset, constant, CHECK);
+      if (!_immutable_pic_compilation) {
+        pd_patch_MetaspaceConstant(pc_offset, constant, CHECK);
+      }
+    } else if (constant->is_a(HotSpotSentinelConstant::klass())) {
+      if (!_immutable_pic_compilation) {
+        JVMCI_ERROR("sentinel constant not supported for normal compiles: %s", constant->klass()->signature_name());
+      }
     } else {
       JVMCI_ERROR("unknown constant type in data patch: %s", constant->klass()->signature_name());
     }
@@ -1158,6 +1256,8 @@
       case HEAP_END_ADDRESS:
       case NARROW_KLASS_BASE_ADDRESS:
       case CRC_TABLE_ADDRESS:
+      case LOG_OF_HEAP_REGION_GRAIN_BYTES:
+      case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
         break;
       default:
         JVMCI_ERROR("invalid mark id: %d", id);