8132547: [AOT] support invokedynamic instructions
authordlong
Thu, 19 Oct 2017 19:23:48 -0700
changeset 47668 fc4cfca10556
parent 47667 390896759aa2
child 47670 80267ddfdcfa
child 47671 4dd1715f647f
8132547: [AOT] support invokedynamic instructions Reviewed-by: iveresov, kvn
src/hotspot/share/aot/aotCodeHeap.cpp
src/hotspot/share/aot/aotCodeHeap.hpp
src/hotspot/share/aot/aotLoader.cpp
src/hotspot/share/aot/aotLoader.hpp
src/hotspot/share/classfile/klassFactory.cpp
src/hotspot/share/jvmci/compilerRuntime.cpp
src/hotspot/share/jvmci/compilerRuntime.hpp
src/hotspot/share/jvmci/jvmciCodeInstaller.cpp
src/hotspot/share/jvmci/jvmciCodeInstaller.hpp
src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
src/hotspot/share/jvmci/jvmciJavaClasses.hpp
src/hotspot/share/jvmci/vmStructs_compiler_runtime.hpp
src/hotspot/share/jvmci/vmStructs_jvmci.cpp
src/hotspot/share/oops/instanceKlass.cpp
src/hotspot/share/oops/instanceKlass.hpp
src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallInfo.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java
test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java
test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java
test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java
test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
--- a/src/hotspot/share/aot/aotCodeHeap.cpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp	Thu Oct 19 19:23:48 2017 -0700
@@ -60,7 +60,14 @@
       fatal("Shared file %s error: klass %s should be resolved already", _lib->name(), klass_name);
       vm_exit(1);
     }
+    // Patch now to avoid extra runtime lookup
     _klasses_got[klass_data->_got_index] = k;
+    if (k->is_instance_klass()) {
+      InstanceKlass* ik = InstanceKlass::cast(k);
+      if (ik->is_initialized()) {
+        _klasses_got[klass_data->_got_index - 1] = ik;
+      }
+    }
   }
   return k;
 }
@@ -433,6 +440,7 @@
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_exception_handler_for_return_address", address, SharedRuntime::exception_handler_for_return_address);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_register_finalizer", address, SharedRuntime::register_finalizer);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_OSR_migration_end", address, SharedRuntime::OSR_migration_end);
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_dynamic_invoke", address, CompilerRuntime::resolve_dynamic_invoke);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_string_by_symbol", address, CompilerRuntime::resolve_string_by_symbol);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_klass_by_symbol", address, CompilerRuntime::resolve_klass_by_symbol);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_method_by_symbol_and_load_counters", address, CompilerRuntime::resolve_method_by_symbol_and_load_counters);
@@ -609,9 +617,13 @@
   return m;
 }
 
+AOTKlassData* AOTCodeHeap::find_klass(const char *name) {
+  return (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), name);
+}
+
 AOTKlassData* AOTCodeHeap::find_klass(InstanceKlass* ik) {
   ResourceMark rm;
-  AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), ik->signature_name());
+  AOTKlassData* klass_data = find_klass(ik->signature_name());
   return klass_data;
 }
 
@@ -640,35 +652,52 @@
   return false;
 }
 
+void AOTCodeHeap::sweep_dependent_methods(int* indexes, int methods_cnt) {
+  int marked = 0;
+  for (int i = 0; i < methods_cnt; ++i) {
+    int code_id = indexes[i];
+    // Invalidate aot code.
+    if (Atomic::cmpxchg(invalid, &_code_to_aot[code_id]._state, not_set) != not_set) {
+      if (_code_to_aot[code_id]._state == in_use) {
+        AOTCompiledMethod* aot = _code_to_aot[code_id]._aot;
+        assert(aot != NULL, "aot should be set");
+        if (!aot->is_runtime_stub()) { // Something is wrong - should not invalidate stubs.
+          aot->mark_for_deoptimization(false);
+          marked++;
+        }
+      }
+    }
+  }
+  if (marked > 0) {
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+}
+
 void AOTCodeHeap::sweep_dependent_methods(AOTKlassData* klass_data) {
   // Make dependent methods non_entrant forever.
   int methods_offset = klass_data->_dependent_methods_offset;
   if (methods_offset >= 0) {
-    int marked = 0;
     address methods_cnt_adr = _dependencies + methods_offset;
     int methods_cnt = *(int*)methods_cnt_adr;
     int* indexes = (int*)(methods_cnt_adr + 4);
-    for (int i = 0; i < methods_cnt; ++i) {
-      int code_id = indexes[i];
-      // Invalidate aot code.
-      if (Atomic::cmpxchg(invalid, &_code_to_aot[code_id]._state, not_set) != not_set) {
-        if (_code_to_aot[code_id]._state == in_use) {
-          AOTCompiledMethod* aot = _code_to_aot[code_id]._aot;
-          assert(aot != NULL, "aot should be set");
-          if (!aot->is_runtime_stub()) { // Something is wrong - should not invalidate stubs.
-            aot->mark_for_deoptimization(false);
-            marked++;
-          }
-        }
-      }
-    }
-    if (marked > 0) {
-      VM_Deoptimize op;
-      VMThread::execute(&op);
-    }
+    sweep_dependent_methods(indexes, methods_cnt);
   }
 }
 
+void AOTCodeHeap::sweep_dependent_methods(InstanceKlass* ik) {
+  AOTKlassData* klass_data = find_klass(ik);
+  vmassert(klass_data != NULL, "dependency data missing");
+  sweep_dependent_methods(klass_data);
+}
+
+void AOTCodeHeap::sweep_method(AOTCompiledMethod *aot) {
+  int indexes[] = {aot->method_index()};
+  sweep_dependent_methods(indexes, 1);
+  vmassert(aot->method()->code() != aot && aot->method()->aot_code() == NULL, "method still active");
+}
+
+
 bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, Thread* thread) {
   ResourceMark rm;
 
@@ -718,6 +747,9 @@
   aot_class->_classloader = ik->class_loader_data();
   // Set klass's Resolve (second) got cell.
   _klasses_got[klass_data->_got_index] = ik;
+  if (ik->is_initialized()) {
+    _klasses_got[klass_data->_got_index - 1] = ik;
+  }
 
   // Initialize global symbols of the DSO to the corresponding VM symbol values.
   link_global_lib_symbols();
@@ -837,7 +869,7 @@
       f(md);
     } else {
       intptr_t meta = (intptr_t)md;
-      fatal("Invalid value in _metaspace_got[%d] = " INTPTR_FORMAT, i, meta);
+      fatal("Invalid value in _klasses_got[%d] = " INTPTR_FORMAT, i, meta);
     }
   }
 }
@@ -886,6 +918,127 @@
       aot->metadata_do(f);
     }
   }
-  // Scan metaspace_got cells.
+  // Scan klasses_got cells.
   got_metadata_do(f);
 }
+
+bool AOTCodeHeap::reconcile_dynamic_klass(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Klass *dyno_klass, const char *descriptor1, const char *descriptor2) {
+  const char * const descriptors[2] = {descriptor1, descriptor2};
+  JavaThread *thread = JavaThread::current();
+  ResourceMark rm(thread);
+
+  AOTKlassData* holder_data = find_klass(holder);
+  vmassert(holder_data != NULL, "klass %s not found", holder->signature_name());
+  vmassert(is_dependent_method(holder, caller), "sanity");
+
+  AOTKlassData* dyno_data = NULL;
+  bool adapter_failed = false;
+  char buf[64];
+  int descriptor_index = 0;
+  // descriptors[0] specific name ("adapter:<method_id>") for matching
+  // descriptors[1] fall-back name ("adapter") for depdencies
+  while (descriptor_index < 2) {
+    const char *descriptor = descriptors[descriptor_index];
+    if (descriptor == NULL) {
+      break;
+    }
+    jio_snprintf(buf, sizeof buf, "%s<%d:%d>", descriptor, holder_data->_class_id, index);
+    dyno_data = find_klass(buf);
+    if (dyno_data != NULL) {
+      break;
+    }
+    // If match failed then try fall-back for dependencies
+    ++descriptor_index;
+    adapter_failed = true;
+  }
+
+  if (dyno_data == NULL && dyno_klass == NULL) {
+    // all is well, no (appendix) at compile-time, and still none
+    return true;
+  }
+
+  if (dyno_data == NULL) {
+    // no (appendix) at build-time, but now there is
+    sweep_dependent_methods(holder_data);
+    return false;
+  }
+
+  if (adapter_failed) {
+    // adapter method mismatch
+    sweep_dependent_methods(holder_data);
+    sweep_dependent_methods(dyno_data);
+    return false;
+  }
+
+  if (dyno_klass == NULL) {
+    // (appendix) at build-time, none now
+    sweep_dependent_methods(holder_data);
+    sweep_dependent_methods(dyno_data);
+    return false;
+  }
+
+  // TODO: support array appendix object
+  if (!dyno_klass->is_instance_klass()) {
+    sweep_dependent_methods(holder_data);
+    sweep_dependent_methods(dyno_data);
+    return false;
+  }
+
+  InstanceKlass* dyno = InstanceKlass::cast(dyno_klass);
+
+  if (!dyno->is_anonymous()) {
+    if (_klasses_got[dyno_data->_got_index] != dyno) {
+      // compile-time class different from runtime class, fail and deoptimize
+      sweep_dependent_methods(holder_data);
+      sweep_dependent_methods(dyno_data);
+      return false;
+    }
+
+    if (dyno->is_initialized()) {
+      _klasses_got[dyno_data->_got_index - 1] = dyno;
+    }
+    return true;
+  }
+
+  // TODO: support anonymous supers
+  if (!dyno->supers_have_passed_fingerprint_checks() || dyno->get_stored_fingerprint() != dyno_data->_fingerprint) {
+      NOT_PRODUCT( aot_klasses_fp_miss++; )
+      log_trace(aot, class, fingerprint)("class  %s%s  has bad fingerprint in  %s tid=" INTPTR_FORMAT,
+          dyno->internal_name(), dyno->is_shared() ? " (shared)" : "",
+          _lib->name(), p2i(thread));
+    sweep_dependent_methods(holder_data);
+    sweep_dependent_methods(dyno_data);
+    return false;
+  }
+
+  _klasses_got[dyno_data->_got_index] = dyno;
+  if (dyno->is_initialized()) {
+    _klasses_got[dyno_data->_got_index - 1] = dyno;
+  }
+
+  // TODO: hook up any AOT code
+  // load_klass_data(dyno_data, thread);
+  return true;
+}
+
+bool AOTCodeHeap::reconcile_dynamic_method(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Method *adapter_method) {
+    InstanceKlass *adapter_klass = adapter_method->method_holder();
+    char buf[64];
+    jio_snprintf(buf, sizeof buf, "adapter:%d", adapter_method->method_idnum());
+    if (!reconcile_dynamic_klass(caller, holder, index, adapter_klass, buf, "adapter")) {
+      return false;
+    }
+    return true;
+}
+
+bool AOTCodeHeap::reconcile_dynamic_invoke(AOTCompiledMethod* caller, InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass) {
+    if (!reconcile_dynamic_klass(caller, holder, index, appendix_klass, "appendix")) {
+      return false;
+    }
+
+    if (!reconcile_dynamic_method(caller, holder, index, adapter_method)) {
+      return false;
+    }
+
+    return true;
+}
--- a/src/hotspot/share/aot/aotCodeHeap.hpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/aot/aotCodeHeap.hpp	Thu Oct 19 19:23:48 2017 -0700
@@ -241,13 +241,14 @@
   AOTKlassData* find_klass(InstanceKlass* ik);
   bool load_klass_data(InstanceKlass* ik, Thread* thread);
   Klass* get_klass_from_got(const char* klass_name, int klass_len, const Method* method);
-  void sweep_dependent_methods(AOTKlassData* klass_data);
+
   bool is_dependent_method(Klass* dependee, AOTCompiledMethod* aot);
 
   const char* get_name_at(int offset) {
     return _metaspace_names + offset;
   }
 
+
   void oops_do(OopClosure* f);
   void metadata_do(void f(Metadata*));
   void got_metadata_do(void f(Metadata*));
@@ -294,6 +295,21 @@
 
   static void print_statistics();
 #endif
+
+  bool reconcile_dynamic_invoke(AOTCompiledMethod* caller, InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass);
+
+private:
+  AOTKlassData* find_klass(const char* name);
+
+  void sweep_dependent_methods(int* indexes, int methods_cnt);
+  void sweep_dependent_methods(AOTKlassData* klass_data);
+  void sweep_dependent_methods(InstanceKlass* ik);
+  void sweep_method(AOTCompiledMethod* aot);
+
+  bool reconcile_dynamic_klass(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Klass *dyno, const char *descriptor1, const char *descriptor2 = NULL);
+
+  bool reconcile_dynamic_method(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Method *adapter_method);
+
 };
 
 #endif // SHARE_VM_AOT_AOTCODEHEAP_HPP
--- a/src/hotspot/share/aot/aotLoader.cpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/aot/aotLoader.cpp	Thu Oct 19 19:23:48 2017 -0700
@@ -40,6 +40,10 @@
 #define FOR_ALL_AOT_LIBRARIES(lib) for (GrowableArrayIterator<AOTLib*> lib = libraries()->begin(); lib != libraries()->end(); ++lib)
 
 void AOTLoader::load_for_klass(InstanceKlass* ik, Thread* thread) {
+  if (ik->is_anonymous()) {
+    // don't even bother
+    return;
+  }
   if (UseAOT) {
     FOR_ALL_AOT_HEAPS(heap) {
       (*heap)->load_klass_data(ik, thread);
@@ -48,6 +52,10 @@
 }
 
 uint64_t AOTLoader::get_saved_fingerprint(InstanceKlass* ik) {
+  if (ik->is_anonymous()) {
+    // don't even bother
+    return 0;
+  }
   FOR_ALL_AOT_HEAPS(heap) {
     AOTKlassData* klass_data = (*heap)->find_klass(ik);
     if (klass_data != NULL) {
@@ -259,3 +267,34 @@
   }
 }
 #endif
+
+
+bool AOTLoader::reconcile_dynamic_invoke(InstanceKlass* holder, int index, Method* adapter_method, Klass* appendix_klass) {
+  if (!UseAOT) {
+    return true;
+  }
+  JavaThread* thread = JavaThread::current();
+  ResourceMark rm(thread);
+  RegisterMap map(thread, false);
+  frame caller_frame = thread->last_frame().sender(&map); // Skip stub
+  CodeBlob* caller_cb = caller_frame.cb();
+  guarantee(caller_cb != NULL && caller_cb->is_compiled(), "must be called from compiled method");
+  CompiledMethod* cm = caller_cb->as_compiled_method();
+
+  if (!cm->is_aot()) {
+    return true;
+  }
+  AOTCompiledMethod* aot = (AOTCompiledMethod*)cm;
+
+  AOTCodeHeap* caller_heap = NULL;
+  FOR_ALL_AOT_HEAPS(heap) {
+    if ((*heap)->contains_blob(aot)) {
+      caller_heap = *heap;
+      break;
+    }
+  }
+  guarantee(caller_heap != NULL, "CodeHeap not found");
+  bool success = caller_heap->reconcile_dynamic_invoke(aot, holder, index, adapter_method, appendix_klass);
+  vmassert(success || thread->last_frame().sender(&map).is_deoptimized_frame(), "caller not deoptimized on failure");
+  return success;
+}
--- a/src/hotspot/share/aot/aotLoader.hpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/aot/aotLoader.hpp	Thu Oct 19 19:23:48 2017 -0700
@@ -28,6 +28,7 @@
 #include "runtime/handles.hpp"
 
 class AOTCodeHeap;
+class AOTCompiledMethod;
 class AOTLib;
 class CodeBlob;
 template <class T> class GrowableArray;
@@ -71,6 +72,7 @@
   static void flush_evol_dependents_on(InstanceKlass* dependee) NOT_AOT_RETURN;
 #endif // HOTSWAP
 
+  static bool reconcile_dynamic_invoke(InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass) NOT_AOT({ return true; });
 };
 
 #endif // SHARE_VM_AOT_AOTLOADER_HPP
--- a/src/hotspot/share/classfile/klassFactory.cpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/classfile/klassFactory.cpp	Thu Oct 19 19:23:48 2017 -0700
@@ -223,8 +223,8 @@
     result->set_cached_class_file(cached_class_file);
   }
 
-  if (InstanceKlass::should_store_fingerprint()) {
-    result->store_fingerprint(!result->is_anonymous() ? stream->compute_fingerprint() : 0);
+  if (result->should_store_fingerprint()) {
+    result->store_fingerprint(stream->compute_fingerprint());
   }
 
   TRACE_KLASS_CREATION(result, parser, THREAD);
--- a/src/hotspot/share/jvmci/compilerRuntime.cpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/jvmci/compilerRuntime.cpp	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,14 @@
 #include "precompiled.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
+#include "interpreter/linkResolver.hpp"
 #include "jvmci/compilerRuntime.hpp"
+#include "oops/oop.inline.hpp"
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/interfaceSupport.hpp"
+#include "runtime/vframe.hpp"
+#include "aot/aotLoader.hpp"
 
 // Resolve and allocate String
 JRT_BLOCK_ENTRY(void, CompilerRuntime::resolve_string_by_symbol(JavaThread *thread, void* string_result, const char* name))
@@ -119,6 +123,62 @@
   return m;
 }
 
+JRT_BLOCK_ENTRY(void, CompilerRuntime::resolve_dynamic_invoke(JavaThread *thread, oop* appendix_result))
+  JRT_BLOCK
+  {
+    ResourceMark rm(THREAD);
+    vframeStream vfst(thread, true);  // Do not skip and javaCalls
+    assert(!vfst.at_end(), "Java frame must exist");
+    methodHandle caller(THREAD, vfst.method());
+    InstanceKlass* holder = caller->method_holder();
+    int bci = vfst.bci();
+    Bytecode_invoke bytecode(caller, bci);
+    int index = bytecode.index();
+
+    // Make sure it's resolved first
+    CallInfo callInfo;
+    constantPoolHandle cp(holder->constants());
+    ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index, true));
+    Bytecodes::Code invoke_code = bytecode.invoke_code();
+    if (!cp_cache_entry->is_resolved(invoke_code)) {
+        LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, invoke_code, CHECK);
+        if (bytecode.is_invokedynamic()) {
+            cp_cache_entry->set_dynamic_call(cp, callInfo);
+        } else {
+            cp_cache_entry->set_method_handle(cp, callInfo);
+        }
+        vmassert(cp_cache_entry->is_resolved(invoke_code), "sanity");
+    }
+
+    Handle appendix(THREAD, cp_cache_entry->appendix_if_resolved(cp));
+    Klass *appendix_klass = appendix.is_null() ? NULL : appendix->klass();
+
+    methodHandle adapter_method(cp_cache_entry->f1_as_method());
+    InstanceKlass *adapter_klass = adapter_method->method_holder();
+
+    if (appendix_klass != NULL && appendix_klass->is_instance_klass()) {
+        vmassert(InstanceKlass::cast(appendix_klass)->is_initialized(), "sanity");
+    }
+    if (!adapter_klass->is_initialized()) {
+        // Force initialization of adapter class
+        adapter_klass->initialize(CHECK);
+        // Double-check that it was really initialized,
+        // because we could be doing a recursive call
+        // from inside <clinit>.
+    }
+
+    int cpi = cp_cache_entry->constant_pool_index();
+    if (!AOTLoader::reconcile_dynamic_invoke(holder, cpi, adapter_method(),
+      appendix_klass)) {
+      return;
+    }
+
+    *appendix_result = appendix();
+    thread->set_vm_result(appendix());
+  }
+  JRT_BLOCK_END
+JRT_END
+
 JRT_BLOCK_ENTRY(MethodCounters*, CompilerRuntime::resolve_method_by_symbol_and_load_counters(JavaThread *thread, MethodCounters** counters_result, Klass* klass, const char* data))
   MethodCounters* c = *counters_result; // Is it resolved already?
   JRT_BLOCK
--- a/src/hotspot/share/jvmci/compilerRuntime.hpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/jvmci/compilerRuntime.hpp	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,8 @@
                                        const char* signature_name, int signature_name_len);
   // Resolution methods for aot compiled code.
   static void resolve_string_by_symbol(JavaThread *thread, void* string_result, const char* name);
+  static void resolve_dynamic_invoke(JavaThread *thread, oop* appendix_result);
+
   static Klass* resolve_klass_by_symbol(JavaThread *thread, Klass** klass_result, const char* name);
   static Klass* initialize_klass_by_symbol(JavaThread *thread, Klass** klass_result, const char* name);
   static MethodCounters* resolve_method_by_symbol_and_load_counters(JavaThread *thread, MethodCounters** counters_result, Klass* klass_hint, const char* data);
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp	Thu Oct 19 19:23:48 2017 -0700
@@ -174,43 +174,42 @@
 }
 
 AOTOopRecorder::AOTOopRecorder(Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) {
-  _meta_strings = new GrowableArray<const char*>();
+  _meta_refs = new GrowableArray<jobject>();
 }
 
-int AOTOopRecorder::nr_meta_strings() const {
-  return _meta_strings->length();
+int AOTOopRecorder::nr_meta_refs() const {
+  return _meta_refs->length();
 }
 
-const char* AOTOopRecorder::meta_element(int pos) const {
-  return _meta_strings->at(pos);
+jobject AOTOopRecorder::meta_element(int pos) const {
+  return _meta_refs->at(pos);
 }
 
 int AOTOopRecorder::find_index(Metadata* h) {
+  JavaThread* THREAD = JavaThread::current();
+  int oldCount = metadata_count();
   int index =  this->OopRecorder::find_index(h);
+  int newCount = metadata_count();
+
+  if (oldCount == newCount) {
+    // found a match
+    return index;
+  }
+
+  vmassert(index + 1 == newCount, "must be last");
 
   Klass* klass = NULL;
+  oop result = NULL;
   if (h->is_klass()) {
     klass = (Klass*) h;
-    record_meta_string(klass->signature_name(), index);
+    result = CompilerToVM::get_jvmci_type(klass, CATCH);
   } 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);
+    methodHandle mh(method);
+    result = CompilerToVM::get_jvmci_method(method, CATCH);
   }
+  jobject ref = JNIHandles::make_local(THREAD, result);
+  record_meta_ref(ref, index);
 
   return index;
 }
@@ -224,16 +223,12 @@
   return find_index(klass);
 }
 
-void AOTOopRecorder::record_meta_string(const char* name, int index) {
+void AOTOopRecorder::record_meta_ref(jobject o, 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);
-  }
+  assert(index == _meta_refs->length(), "must be last");
+  _meta_refs->append(o);
 }
 
 void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp	Thu Oct 19 19:23:48 2017 -0700
@@ -49,13 +49,13 @@
 
   virtual int find_index(Metadata* h);
   virtual int find_index(jobject h);
-  int nr_meta_strings() const;
-  const char* meta_element(int pos) const;
+  int nr_meta_refs() const;
+  jobject meta_element(int pos) const;
 
 private:
-  void record_meta_string(const char* name, int index);
+  void record_meta_ref(jobject ref, int index);
 
-  GrowableArray<const char*>* _meta_strings;
+  GrowableArray<jobject>* _meta_refs;
 };
 
 class CodeMetadata {
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Thu Oct 19 19:23:48 2017 -0700
@@ -1118,13 +1118,15 @@
 
   AOTOopRecorder* recorder = code_metadata.get_oop_recorder();
 
-  int nr_meta_strings = recorder->nr_meta_strings();
-  objArrayOop metadataArray = oopFactory::new_objectArray(nr_meta_strings, CHECK_(JVMCIEnv::cache_full));
+  int nr_meta_refs = recorder->nr_meta_refs();
+  objArrayOop metadataArray = oopFactory::new_objectArray(nr_meta_refs, CHECK_(JVMCIEnv::cache_full));
   objArrayHandle metadataArrayHandle(THREAD, metadataArray);
-  for (int i = 0; i < nr_meta_strings; ++i) {
-    const char* element = recorder->meta_element(i);
-    Handle java_string = java_lang_String::create_from_str(element, CHECK_(JVMCIEnv::cache_full));
-    metadataArrayHandle->obj_at_put(i, java_string());
+  for (int i = 0; i < nr_meta_refs; ++i) {
+    jobject element = recorder->meta_element(i);
+    if (element == NULL) {
+      return JVMCIEnv::cache_full;
+    }
+    metadataArrayHandle->obj_at_put(i, JNIHandles::resolve(element));
   }
   HotSpotMetaData::set_metadata(metadata_handle, metadataArrayHandle());
 
@@ -1519,6 +1521,48 @@
   }
 C2V_END
 
+C2V_VMENTRY(jint, isResolvedInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+  ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
+  if (cp_cache_entry->is_resolved(Bytecodes::_invokehandle)) {
+    // MethodHandle.invoke* --> LambdaForm?
+    ResourceMark rm;
+
+    LinkInfo link_info(cp, index, CATCH);
+
+    Klass* resolved_klass = link_info.resolved_klass();
+
+    Symbol* name_sym = cp->name_ref_at(index);
+
+    vmassert(MethodHandles::is_method_handle_invoke_name(resolved_klass, name_sym), "!");
+    vmassert(MethodHandles::is_signature_polymorphic_name(resolved_klass, name_sym), "!");
+
+    methodHandle adapter_method(cp_cache_entry->f1_as_method());
+
+    methodHandle resolved_method(adapter_method);
+
+    // Can we treat it as a regular invokevirtual?
+    if (resolved_method->method_holder() == resolved_klass && resolved_method->name() == name_sym) {
+      vmassert(!resolved_method->is_static(),"!");
+      vmassert(MethodHandles::is_signature_polymorphic_method(resolved_method()),"!");
+      vmassert(!MethodHandles::is_signature_polymorphic_static(resolved_method->intrinsic_id()), "!");
+      vmassert(cp_cache_entry->appendix_if_resolved(cp) == NULL, "!");
+      vmassert(cp_cache_entry->method_type_if_resolved(cp) == NULL, "!");
+
+      methodHandle m(LinkResolver::linktime_resolve_virtual_method_or_null(link_info));
+      vmassert(m == resolved_method, "!!");
+      return -1;
+    }
+
+    return Bytecodes::_invokevirtual;
+  }
+  if (cp_cache_entry->is_resolved(Bytecodes::_invokedynamic)) {
+    return Bytecodes::_invokedynamic;
+  }
+  return -1;
+C2V_END
+
+
 C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv*, jobject))
   objArrayHandle holders = oopFactory::new_objArray_handle(SystemDictionary::String_klass(), 2, CHECK_NULL);
   Handle mh = java_lang_String::create_from_str("Ljava/lang/invoke/MethodHandle;", CHECK_NULL);
@@ -1795,6 +1839,7 @@
   {CC "resolveFieldInPool",                           CC "(" HS_CONSTANT_POOL "I" HS_RESOLVED_METHOD "B[I)" HS_RESOLVED_KLASS,              FN_PTR(resolveFieldInPool)},
   {CC "resolveInvokeDynamicInPool",                   CC "(" HS_CONSTANT_POOL "I)V",                                                        FN_PTR(resolveInvokeDynamicInPool)},
   {CC "resolveInvokeHandleInPool",                    CC "(" HS_CONSTANT_POOL "I)V",                                                        FN_PTR(resolveInvokeHandleInPool)},
+  {CC "isResolvedInvokeHandleInPool",                 CC "(" HS_CONSTANT_POOL "I)I",                                                        FN_PTR(isResolvedInvokeHandleInPool)},
   {CC "resolveMethod",                                CC "(" HS_RESOLVED_KLASS HS_RESOLVED_METHOD HS_RESOLVED_KLASS ")" HS_RESOLVED_METHOD, FN_PTR(resolveMethod)},
   {CC "getSignaturePolymorphicHolders",               CC "()[" STRING,                                                                      FN_PTR(getSignaturePolymorphicHolders)},
   {CC "getVtableIndexForInterfaceMethod",             CC "(" HS_RESOLVED_KLASS HS_RESOLVED_METHOD ")I",                                     FN_PTR(getVtableIndexForInterfaceMethod)},
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -299,7 +299,7 @@
     typeArrayOop_field(HotSpotMetaData, relocBytes, "[B")                                                                                                      \
     typeArrayOop_field(HotSpotMetaData, exceptionBytes, "[B")                                                                                                  \
     typeArrayOop_field(HotSpotMetaData, oopMaps, "[B")                                                                                                         \
-    objArrayOop_field(HotSpotMetaData, metadata, "[Ljava/lang/String;")                                                                                        \
+    objArrayOop_field(HotSpotMetaData, metadata, "[Ljava/lang/Object;")                                                                                        \
   end_class                                                                                                                                                    \
   start_class(HotSpotConstantPool)                                                                                                                             \
     long_field(HotSpotConstantPool, metaspaceConstantPool)                                                                                                     \
--- a/src/hotspot/share/jvmci/vmStructs_compiler_runtime.hpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/jvmci/vmStructs_compiler_runtime.hpp	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 #include "jvmci/compilerRuntime.hpp"
 
 #define VM_ADDRESSES_COMPILER_RUNTIME(declare_address, declare_preprocessor_address, declare_function) \
+  declare_function(CompilerRuntime::resolve_dynamic_invoke)                       \
   declare_function(CompilerRuntime::resolve_string_by_symbol)                     \
   declare_function(CompilerRuntime::resolve_klass_by_symbol)                      \
   declare_function(CompilerRuntime::resolve_method_by_symbol_and_load_counters)   \
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Thu Oct 19 19:23:48 2017 -0700
@@ -125,6 +125,7 @@
   nonstatic_field(ConstMethod,                 _code_size,                             u2)                                           \
   nonstatic_field(ConstMethod,                 _name_index,                            u2)                                           \
   nonstatic_field(ConstMethod,                 _signature_index,                       u2)                                           \
+  nonstatic_field(ConstMethod,                 _method_idnum,                          u2)                                           \
   nonstatic_field(ConstMethod,                 _max_stack,                             u2)                                           \
   nonstatic_field(ConstMethod,                 _max_locals,                            u2)                                           \
                                                                                                                                      \
@@ -157,6 +158,7 @@
   nonstatic_field(InstanceKlass,               _constants,                                    ConstantPool*)                         \
   nonstatic_field(InstanceKlass,               _source_file_name_index,                       u2)                                    \
   nonstatic_field(InstanceKlass,               _init_state,                                   u1)                                    \
+  nonstatic_field(InstanceKlass,               _misc_flags,                                   u2)                                    \
                                                                                                                                      \
   volatile_nonstatic_field(JavaFrameAnchor,    _last_Java_sp,                                 intptr_t*)                             \
   volatile_nonstatic_field(JavaFrameAnchor,    _last_Java_pc,                                 address)                               \
@@ -521,6 +523,7 @@
                                                                           \
   declare_constant(InstanceKlass::linked)                                 \
   declare_constant(InstanceKlass::fully_initialized)                      \
+  declare_constant(InstanceKlass::_misc_is_anonymous)                     \
                                                                           \
   declare_constant(JumpData::taken_off_set)                               \
   declare_constant(JumpData::displacement_off_set)                        \
--- a/src/hotspot/share/oops/instanceKlass.cpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Thu Oct 19 19:23:48 2017 -0700
@@ -151,7 +151,7 @@
                                        nonstatic_oop_map_size(parser.total_oop_map_count()),
                                        parser.is_interface(),
                                        parser.is_anonymous(),
-                                       should_store_fingerprint());
+                                       should_store_fingerprint(parser.is_anonymous()));
 
   const Symbol* const class_name = parser.class_name();
   assert(class_name != NULL, "invariant");
@@ -1957,7 +1957,7 @@
   return true;
 }
 
-bool InstanceKlass::should_store_fingerprint() {
+bool InstanceKlass::should_store_fingerprint(bool is_anonymous) {
 #if INCLUDE_AOT
   // We store the fingerprint into the InstanceKlass only in the following 2 cases:
   if (CalculateClassFingerprint) {
@@ -1968,6 +1968,10 @@
     // (2) We are running -Xshare:dump to create a shared archive
     return true;
   }
+  if (UseAOT && is_anonymous) {
+    // (3) We are using AOT code from a shared library and see an anonymous class
+    return true;
+  }
 #endif
 
   // In all other cases we might set the _misc_has_passed_fingerprint_check bit,
--- a/src/hotspot/share/oops/instanceKlass.hpp	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Thu Oct 19 19:23:48 2017 -0700
@@ -731,7 +731,8 @@
   }
   bool supers_have_passed_fingerprint_checks();
 
-  static bool should_store_fingerprint();
+  static bool should_store_fingerprint(bool is_anonymous);
+  bool should_store_fingerprint() const { return should_store_fingerprint(is_anonymous()); }
   bool has_stored_fingerprint() const;
   uint64_t get_stored_fingerprint() const;
   void store_fingerprint(uint64_t fingerprint);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Thu Oct 19 19:23:48 2017 -0700
@@ -144,6 +144,7 @@
         {"SharedRuntime::exception_handler_for_return_address",        "_aot_exception_handler_for_return_address"},
         {"SharedRuntime::register_finalizer",                          "_aot_register_finalizer"},
         {"SharedRuntime::OSR_migration_end",                           "_aot_OSR_migration_end"},
+        {"CompilerRuntime::resolve_dynamic_invoke",                    "_aot_resolve_dynamic_invoke"},
         {"CompilerRuntime::resolve_string_by_symbol",                  "_aot_resolve_string_by_symbol"},
         {"CompilerRuntime::resolve_klass_by_symbol",                   "_aot_resolve_klass_by_symbol"},
         {"CompilerRuntime::resolve_method_by_symbol_and_load_counters","_aot_resolve_method_by_symbol_and_load_counters"},
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java	Thu Oct 19 19:23:48 2017 -0700
@@ -33,6 +33,7 @@
 import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin;
 import org.graalvm.compiler.java.GraphBuilderPhase;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
 import org.graalvm.compiler.lir.phases.LIRSuites;
@@ -63,13 +64,13 @@
     private final PhaseSuite<HighTierContext> graphBuilderSuite;
     private final HighTierContext highTierContext;
 
-    AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend) {
+    AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend, HotSpotInvokeDynamicPlugin inokeDynamicPlugin) {
         this.main = main;
         this.graalOptions = graalOptions;
         this.backend = backend;
         providers = backend.getProviders();
         codeCache = providers.getCodeCache();
-        graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions);
+        graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions, inokeDynamicPlugin);
         highTierContext = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.ALL);
     }
 
@@ -146,13 +147,14 @@
         return null;
     }
 
-    private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions) {
+    private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions, HotSpotInvokeDynamicPlugin inokeDynamicPlugin) {
         PhaseSuite<HighTierContext> graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
         ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
         GraphBuilderConfiguration baseConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
 
         // Use all default plugins.
         Plugins plugins = baseConfig.getPlugins();
+        plugins.setInvokeDynamicPlugin(inokeDynamicPlugin);
         GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withOmitAssertions(!compileWithAssertions);
 
         iterator.next();
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java	Thu Oct 19 19:23:48 2017 -0700
@@ -25,24 +25,35 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Map;
+import java.util.Set;
 
 import jdk.tools.jaotc.binformat.BinaryContainer;
 import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
 import jdk.tools.jaotc.binformat.Symbol.Binding;
 import jdk.tools.jaotc.binformat.Symbol.Kind;
 
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.vm.ci.meta.ResolvedJavaField;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
 
+import jdk.tools.jaotc.AOTDynamicTypeStore.AdapterLocation;
+import jdk.tools.jaotc.AOTDynamicTypeStore.AppendixLocation;
+import jdk.tools.jaotc.AOTDynamicTypeStore.Location;
+
 /**
  * Class encapsulating Graal-compiled output of a Java class. The compilation result of all methods
  * of a class {@code className} are maintained in an array list.
  */
 final class AOTCompiledClass {
 
+    private static AOTDynamicTypeStore dynoStore;
+
+    static void setDynamicTypeStore(AOTDynamicTypeStore s) {
+        dynoStore = s;
+    }
+
     static class AOTKlassData {
         private int gotIndex; // Index (offset/8) to the got in the .metaspace.got section
         private int classId;  // Unique ID
@@ -50,29 +61,64 @@
         private int compiledMethodsOffset;
         // Offset to dependent methods data.
         private int dependentMethodsOffset;
-        private long fingerprint;           // Class fingerprint
 
-        private final String name;
-        private boolean isArray;
+        private final String metadataName;
+        HotSpotResolvedObjectType type;
 
         /**
          * List of dependent compiled methods which have a reference to this class.
          */
         private ArrayList<CompiledMethodInfo> dependentMethods;
 
-        AOTKlassData(BinaryContainer binaryContainer, String name, long fingerprint, int classId) {
+        AOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type, int classId) {
             this.dependentMethods = new ArrayList<>();
             this.classId = classId;
-            this.fingerprint = fingerprint;
-            this.gotIndex = binaryContainer.addTwoSlotKlassSymbol(name);
+            this.type = type;
+            this.metadataName = type.isAnonymous() ? "anon<"+ classId + ">": type.getName();
+            this.gotIndex = binaryContainer.addTwoSlotKlassSymbol(metadataName);
             this.compiledMethodsOffset = -1; // Not compiled classes do not have compiled methods.
             this.dependentMethodsOffset = -1;
-            this.name = name;
-            this.isArray = name.length() > 0 && name.charAt(0) == '[';
         }
 
-        long getFingerprint() {
-            return fingerprint;
+        private String[] getMetaspaceNames() {
+            String name = metadataName;
+            Set<Location> locs = dynoStore.getDynamicClassLocationsForType(type);
+            if (locs == null) {
+                return new String[] {name};
+            } else {
+                ArrayList<String> names = new ArrayList<String>();
+                names.add(name);
+                for (Location l : locs) {
+                    HotSpotResolvedObjectType cpType = l.getHolder();
+                    AOTKlassData data = getAOTKlassData(cpType);
+                    // We collect dynamic types at parse time, but late inlining
+                    // may record types that don't make it into the final graph.
+                    // We can safely ignore those here.
+                    if (data == null) {
+                       // Not a compiled or inlined method
+                       continue;
+                    }
+                    int cpi = l.getCpi();
+                    String location = "<"+ data.classId + ":" + cpi + ">";
+                    if (l instanceof AdapterLocation) {
+                        names.add("adapter" + location);
+                        AdapterLocation a = (AdapterLocation)l;
+                        names.add("adapter:" + a.getMethodId() + location);
+                    } else {
+                        assert l instanceof AppendixLocation;
+                        names.add("appendix" + location);
+                    }
+                }
+                return names.toArray(new String[names.size()]);
+            }
+        }
+
+        HotSpotResolvedObjectType getType() {
+            return type;
+        }
+
+        String getMetadataName() {
+            return metadataName;
         }
 
         /**
@@ -112,6 +158,7 @@
             for (CompiledMethodInfo methodInfo : dependentMethods) {
                 dependenciesContainer.appendInt(methodInfo.getCodeId());
             }
+
             verify();
 
             // @formatter:off
@@ -119,7 +166,9 @@
              * The offsets layout should match AOTKlassData structure in AOT JVM runtime
              */
             int offset = container.getByteStreamSize();
-            container.createSymbol(offset, Kind.OBJECT, Binding.GLOBAL, 0, name);
+            for (String name : getMetaspaceNames()) {
+                container.createSymbol(offset, Kind.OBJECT, Binding.GLOBAL, 0, name);
+            }
                       // Add index (offset/8) to the got in the .metaspace.got section
             container.appendInt(gotIndex).
                       // Add unique ID
@@ -129,13 +178,16 @@
                       // Add the offset to dependent methods data in the .metaspace.offsets section.
                       appendInt(dependentMethodsOffset).
                       // Add fingerprint.
-                      appendLong(fingerprint);
+                      appendLong(type.getFingerprint());
+
             // @formatter:on
         }
 
         private void verify() {
+            String name = type.getName();
             assert gotIndex > 0 : "incorrect gotIndex: " + gotIndex + " for klass: " + name;
-            assert isArray || fingerprint != 0 : "incorrect fingerprint: " + fingerprint + " for klass: " + name;
+            long fingerprint = type.getFingerprint();
+            assert type.isArray() || fingerprint != 0 : "incorrect fingerprint: " + fingerprint + " for klass: " + name;
             assert compiledMethodsOffset >= -1 : "incorrect compiledMethodsOffset: " + compiledMethodsOffset + " for klass: " + name;
             assert dependentMethodsOffset >= -1 : "incorrect dependentMethodsOffset: " + dependentMethodsOffset + " for klass: " + name;
             assert classId >= 0 : "incorrect classId: " + classId + " for klass: " + name;
@@ -148,7 +200,7 @@
     /**
      * List of all collected class data.
      */
-    private static Map<String, AOTKlassData> klassData = new HashMap<>();
+    private static HashMap<String, AOTKlassData> klassData = new HashMap<>();
 
     /**
      * List of all methods to be compiled.
@@ -269,23 +321,25 @@
      */
     synchronized static AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
         String name = type.getName();
-        long fingerprint = type.getFingerprint();
         AOTKlassData data = klassData.get(name);
         if (data != null) {
-            assert data.getFingerprint() == fingerprint : "incorrect fingerprint data for klass: " + name;
+            assert data.getType() == type : "duplicate classes for name " + name;
         } else {
-            data = new AOTKlassData(binaryContainer, name, fingerprint, classesCount++);
+            data = new AOTKlassData(binaryContainer, type, classesCount++);
             klassData.put(name, data);
         }
         return data;
     }
 
-    synchronized static AOTKlassData getAOTKlassData(String name) {
+    private synchronized static AOTKlassData getAOTKlassData(String name) {
         return klassData.get(name);
     }
 
     synchronized static AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
-        return getAOTKlassData(type.getName());
+        String name = type.getName();
+        AOTKlassData data =  getAOTKlassData(name);
+        assert data == null || data.getType() == type : "duplicate classes for name " + name;
+        return data;
     }
 
     void addAOTKlassData(BinaryContainer binaryContainer) {
@@ -354,21 +408,55 @@
             methodInfo.addMethodOffsets(binaryContainer, container);
         }
         String name = resolvedJavaType.getName();
-        AOTKlassData data = klassData.get(name);
+        AOTKlassData data = getAOTKlassData(resolvedJavaType);
         assert data != null : "missing data for klass: " + name;
-        assert data.getFingerprint() == resolvedJavaType.getFingerprint() : "incorrect fingerprint for klass: " + name;
         int cntDepMethods = data.dependentMethods.size();
         assert cntDepMethods > 0 : "no dependent methods for compiled klass: " + name;
         data.setCompiledMethodsOffset(startMethods);
     }
 
     static void putAOTKlassData(BinaryContainer binaryContainer) {
+        // record dynamic types
+        Set<HotSpotResolvedObjectType> dynoTypes = dynoStore.getDynamicTypes();
+        if (dynoTypes != null) {
+            for (HotSpotResolvedObjectType dynoType : dynoTypes) {
+                addFingerprintKlassData(binaryContainer, dynoType);
+            }
+        }
+
         ReadOnlyDataContainer container = binaryContainer.getKlassesOffsetsContainer();
         for (AOTKlassData data : klassData.values()) {
             data.putAOTKlassData(binaryContainer, container);
         }
     }
 
+    static HotSpotResolvedObjectType getType(Object ref) {
+        return (ref instanceof HotSpotResolvedObjectType) ?
+            (HotSpotResolvedObjectType)ref :
+            ((HotSpotResolvedJavaMethod)ref).getDeclaringClass();
+    }
+
+    static String metadataName(HotSpotResolvedObjectType type) {
+        AOTKlassData data = getAOTKlassData(type);
+        assert data != null : "no data for " + type;
+        return getAOTKlassData(type).getMetadataName();
+    }
+
+    private static String metadataName(HotSpotResolvedJavaMethod m) {
+        return metadataName(m.getDeclaringClass()) + "." + m.getName() + m.getSignature().toMethodDescriptor();
+    }
+
+    static String metadataName(Object ref) {
+        if (ref instanceof HotSpotResolvedJavaMethod) {
+            HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod)ref;
+            return metadataName(m);
+        } else {
+            assert ref instanceof HotSpotResolvedObjectType : "unexpected object type " + ref.getClass().getName();
+            HotSpotResolvedObjectType type = (HotSpotResolvedObjectType)ref;
+            return metadataName(type);
+        }
+    }
+
     boolean representsStubs() {
         return representsStubs;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java	Thu Oct 19 19:23:48 2017 -0700
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc;
+
+import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin.DynamicTypeStore;
+import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
+
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
+import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
+import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
+import jdk.vm.ci.hotspot.HotSpotObjectConstant;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+final class AOTDynamicTypeStore implements DynamicTypeStore {
+
+    public static class Location {
+        private HotSpotResolvedObjectType holder;
+        private int cpi;
+
+        Location(HotSpotResolvedObjectType holder, int cpi) {
+            this.holder = holder;
+            this.cpi = cpi;
+        }
+
+        public HotSpotResolvedObjectType getHolder() {
+            return holder;
+        }
+        public int getCpi() {
+            return cpi;
+        }
+        public String toString() {
+            return getHolder().getName() + "@" + cpi;
+        }
+        public int hashCode() {
+            return holder.hashCode() + getClass().hashCode() + cpi;
+        }
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (getClass() != o.getClass()) {
+                return false;
+            }
+            Location l = (Location)o;
+            return cpi == l.cpi && holder.equals(l.holder);
+        }
+    }
+
+    public static class AdapterLocation extends Location {
+        private int methodId;
+
+        AdapterLocation(HotSpotResolvedObjectType holder, int cpi, int methodId) {
+            super(holder, cpi);
+            this.methodId = methodId;
+        }
+        public int getMethodId() {
+            return methodId;
+        }
+        public String toString() {
+            return "adapter:" + methodId + "@" + super.toString();
+        }
+    }
+
+    public static class AppendixLocation extends Location {
+        AppendixLocation(HotSpotResolvedObjectType holder, int cpi) {
+            super(holder, cpi);
+        }
+        public String toString() {
+            return "appendix@" + super.toString();
+        }
+    }
+
+    private HashMap<HotSpotResolvedObjectType, HashSet<Location>> typeMap = new HashMap<>();
+    private HashMap<HotSpotResolvedObjectType, HashSet<HotSpotResolvedObjectType>> holderMap = new HashMap<>();
+
+    public Set<HotSpotResolvedObjectType> getDynamicTypes() {
+        synchronized (typeMap) {
+            return typeMap.keySet();
+        }
+    }
+
+    public Set<HotSpotResolvedObjectType> getDynamicHolders() {
+        synchronized (holderMap) {
+            return holderMap.keySet();
+        }
+    }
+
+    @Override
+    public void recordAdapter(int opcode, HotSpotResolvedObjectType holder, int index, HotSpotResolvedJavaMethod adapter) {
+        int cpi = ((HotSpotConstantPool)holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
+        int methodId = adapter.methodIdnum();
+        HotSpotResolvedObjectType adapterType = adapter.getDeclaringClass();
+        recordDynamicTypeLocation(new AdapterLocation(holder, cpi, methodId), adapterType);
+    }
+
+    @Override
+    public JavaConstant recordAppendix(int opcode, HotSpotResolvedObjectType holder, int index, JavaConstant appendix) {
+        int cpi = ((HotSpotConstantPool)holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
+        HotSpotResolvedObjectType appendixType = ((HotSpotObjectConstant)appendix).getType();
+        recordDynamicTypeLocation(new AppendixLocation(holder, cpi), appendixType);
+        // Make the constant locatable
+        return HotSpotConstantPoolObject.forObject(holder, cpi, appendix);
+    }
+
+    private static <T> void recordDynamicMapValue(HashMap<HotSpotResolvedObjectType, HashSet<T>> map, HotSpotResolvedObjectType type, T v) {
+        synchronized (map) {
+            HashSet<T> set = map.get(type);
+            if (set == null) {
+                set = new HashSet<>();
+                map.put(type, set);
+            }
+            set.add(v);
+        }
+    }
+
+    private void recordDynamicTypeLocation(Location l, HotSpotResolvedObjectType type) {
+        recordDynamicMapValue(typeMap, type, l);
+        HotSpotResolvedObjectType holder = l.getHolder();
+        recordDynamicMapValue(holderMap, holder, type);
+    }
+
+    public Set<Location> getDynamicClassLocationsForType(HotSpotResolvedObjectType type) {
+        synchronized (typeMap) {
+            return typeMap.get(type);
+        }
+    }
+
+    public Set<HotSpotResolvedObjectType> getDynamicTypesForHolder(HotSpotResolvedObjectType holder) {
+        synchronized (holderMap) {
+            return holderMap.get(holder);
+        }
+    }
+
+}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallInfo.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallInfo.java	Thu Oct 19 19:23:48 2017 -0700
@@ -32,9 +32,19 @@
 
 final class CallInfo {
 
+    static boolean isStaticTarget(Call call) {
+        return !((HotSpotResolvedJavaMethod)call.target).hasReceiver();
+    }
+
+    private static boolean isStaticOpcode(Call call) {
+        int opcode = getByteCode(call) & 0xFF;
+        return opcode == Bytecodes.INVOKESTATIC || opcode == Bytecodes.INVOKEDYNAMIC || opcode == Bytecodes.INVOKEVIRTUAL /* invokehandle */;
+    }
+
     static boolean isStaticCall(Call call) {
-        if (isJavaCall(call)) {
-            return ((getByteCode(call) & 0xFF) == Bytecodes.INVOKESTATIC);
+        if (isJavaCall(call) && isStaticTarget(call)) {
+            assert isStaticOpcode(call);
+            return true;
         }
         return false;
     }
@@ -54,7 +64,7 @@
     }
 
     static boolean isVirtualCall(CompiledMethodInfo methodInfo, Call call) {
-        return isInvokeVirtual(call) && !methodInfo.hasMark(call, MarkId.INVOKESPECIAL);
+        return isInvokeVirtual(call) && !methodInfo.hasMark(call, MarkId.INVOKESPECIAL) && !isStaticTarget(call);
     }
 
     static boolean isOptVirtualCall(CompiledMethodInfo methodInfo, Call call) {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java	Thu Oct 19 19:23:48 2017 -0700
@@ -25,7 +25,7 @@
 
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.HashMap;
-import java.util.Map;
+import java.util.HashSet;
 
 import jdk.tools.jaotc.binformat.BinaryContainer;
 import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
@@ -182,12 +182,12 @@
     /**
      * List of stubs (PLT trampoline).
      */
-    private Map<String, StubInformation> stubs = new HashMap<>();
+    private HashMap<String, StubInformation> stubs = new HashMap<>();
 
     /**
      * List of referenced classes.
      */
-    private Map<String, AOTKlassData> dependentKlasses = new HashMap<>();
+    private HashSet<AOTKlassData> dependentKlasses = new HashSet<>();
 
     /**
      * Methods count used to generate unique global method id.
@@ -209,7 +209,7 @@
     void addMethodOffsets(BinaryContainer binaryContainer, ReadOnlyDataContainer container) {
         this.methodOffsets.setNameOffset(binaryContainer.addMetaspaceName(name));
         this.methodOffsets.addMethodOffsets(container, name);
-        for (AOTKlassData data : dependentKlasses.values()) {
+        for (AOTKlassData data : dependentKlasses) {
             data.addDependentMethod(this);
         }
     }
@@ -291,17 +291,15 @@
 
     void addDependentKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
         AOTKlassData klassData = AOTCompiledClass.addFingerprintKlassData(binaryContainer, type);
-        String klassName = type.getName();
-
-        if (dependentKlasses.containsKey(klassName)) {
-            assert dependentKlasses.get(klassName) == klassData : "duplicated data for klass: " + klassName;
-        } else {
-            dependentKlasses.put(klassName, klassData);
-        }
+        dependentKlasses.add(klassData);
     }
 
-    AOTKlassData getDependentKlassData(String klassName) {
-        return dependentKlasses.get(klassName);
+    AOTKlassData getDependentKlassData(HotSpotResolvedObjectType type) {
+        AOTKlassData klassData = AOTCompiledClass.getAOTKlassData(type);
+        if (dependentKlasses.contains(klassData)) {
+            return klassData;
+        }
+        return null;
     }
 
     boolean hasMark(Site call, MarkId id) {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java	Thu Oct 19 19:23:48 2017 -0700
@@ -32,6 +32,7 @@
 import jdk.tools.jaotc.binformat.Symbol;
 import jdk.tools.jaotc.binformat.Symbol.Binding;
 import jdk.tools.jaotc.binformat.Symbol.Kind;
+import jdk.tools.jaotc.AOTCompiledClass;
 import org.graalvm.compiler.code.DataSection;
 import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
 
@@ -40,6 +41,7 @@
 import jdk.vm.ci.code.site.DataPatch;
 import jdk.vm.ci.code.site.DataSectionReference;
 import jdk.vm.ci.code.site.Reference;
+import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
 import jdk.vm.ci.hotspot.HotSpotObjectConstant;
 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
@@ -84,18 +86,24 @@
             HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant;
             if (metaspaceConstant.asResolvedJavaType() != null) {
                 HotSpotResolvedObjectType type = metaspaceConstant.asResolvedJavaType();
-                targetSymbol = type.getName();
+                methodInfo.addDependentKlassData(binaryContainer, type);
+                targetSymbol = AOTCompiledClass.metadataName(type);
                 gotName = ((action == HotSpotConstantLoadAction.INITIALIZE) ? "got.init." : "got.") + targetSymbol;
-                methodInfo.addDependentKlassData(binaryContainer, type);
             } else if (metaspaceConstant.asResolvedJavaMethod() != null && action == HotSpotConstantLoadAction.LOAD_COUNTERS) {
                 targetSymbol = "counters." + JavaMethodInfo.uniqueMethodName(metaspaceConstant.asResolvedJavaMethod());
                 gotName = "got." + targetSymbol;
                 binaryContainer.addCountersSymbol(targetSymbol);
             }
         } else if (constant instanceof HotSpotObjectConstant) {
-            // String constant.
             HotSpotObjectConstant oopConstant = (HotSpotObjectConstant) constant;
-            targetSymbol = "ldc." + oopConstant.toValueString();
+            if (oopConstant instanceof HotSpotConstantPoolObject) {
+                HotSpotConstantPoolObject cpo = (HotSpotConstantPoolObject)oopConstant;
+                // Even if two locations use the same object, resolve separately
+                targetSymbol = "ldc." + cpo.getCpType().getName() + cpo.getCpi();
+            } else {
+                // String constant.
+                targetSymbol = "ldc." + oopConstant.toValueString();
+            }
             Integer offset = binaryContainer.addOopSymbol(targetSymbol);
             gotName = "got.ldc." + offset;
         } else if (constant instanceof HotSpotSentinelConstant) {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java	Thu Oct 19 19:23:48 2017 -0700
@@ -124,6 +124,7 @@
     private static String getResolveSymbolName(CompiledMethodInfo mi, Call call) {
         String resolveSymbolName;
         if (CallInfo.isStaticCall(call)) {
+            assert mi.hasMark(call, MarkId.INVOKESTATIC);
             resolveSymbolName = BinaryContainer.getResolveStaticEntrySymbolName();
         } else if (CallInfo.isSpecialCall(call)) {
             resolveSymbolName = BinaryContainer.getResolveOptVirtualEntrySymbolName();
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Thu Oct 19 19:23:48 2017 -0700
@@ -46,6 +46,7 @@
 import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.hotspot.HotSpotHostBackend;
+import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin;
 import org.graalvm.compiler.java.GraphBuilderPhase;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 import org.graalvm.compiler.options.OptionValues;
@@ -159,7 +160,10 @@
                 System.gc();
             }
 
-            AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend);
+            AOTDynamicTypeStore dynoStore = new AOTDynamicTypeStore();
+            AOTCompiledClass.setDynamicTypeStore(dynoStore);
+
+            AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, new HotSpotInvokeDynamicPlugin(dynoStore));
             SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection();
             AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads);
             classes = compiler.compileClasses(classes);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java	Thu Oct 19 19:23:48 2017 -0700
@@ -33,6 +33,7 @@
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 
+
 import jdk.vm.ci.code.StackSlot;
 import jdk.vm.ci.code.site.DataPatch;
 import jdk.vm.ci.code.site.Infopoint;
@@ -40,6 +41,9 @@
 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
 import jdk.vm.ci.hotspot.HotSpotMetaData;
 
+import static jdk.tools.jaotc.AOTCompiledClass.getType;
+import static jdk.tools.jaotc.AOTCompiledClass.metadataName;
+
 final class MetadataBuilder {
 
     private final DataBuilder dataBuilder;
@@ -168,7 +172,7 @@
     }
 
     private static int addMetadataEntries(BinaryContainer binaryContainer, HotSpotMetaData metaData, CompiledMethodInfo methodInfo) {
-        String[] metaDataEntries = metaData.metadataEntries();
+        Object[] metaDataEntries = metaData.metadataEntries();
 
         if (metaDataEntries.length == 0) {
             return 0;
@@ -177,20 +181,13 @@
         int metadataGotSlotsStart = binaryContainer.getMetadataGotContainer().getByteStreamSize(); // binaryContainer.reserveMetadataGOTSlots(metaDataEntries.length);
 
         for (int index = 0; index < metaDataEntries.length; index++) {
-            String name = metaDataEntries[index];
-            addMetadataEntry(binaryContainer, name);
+            Object ref = metaDataEntries[index];
+            String name = metadataName(ref);
             // Create GOT cells for klasses referenced in metadata
-            String klassName = name;
-            int len = name.length();
-            int parenthesesIndex = name.lastIndexOf('(', len - 1);
-            if (parenthesesIndex > 0) {  // Method name
-                int dotIndex = name.lastIndexOf('.', parenthesesIndex - 1);
-                assert dotIndex > 0 : "method's full name should have '.' : " + name;
-                klassName = name.substring(0, dotIndex);
-            }
+            addMetadataEntry(binaryContainer, name);
             // We should already have added entries for this klass
-            assert AOTCompiledClass.getAOTKlassData(klassName) != null;
-            assert methodInfo.getDependentKlassData(klassName) != null;
+            assert AOTCompiledClass.getAOTKlassData(getType(ref)) != null;
+            assert methodInfo.getDependentKlassData(getType(ref)) != null;
         }
 
         return metadataGotSlotsStart;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -256,6 +256,15 @@
     native void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
 
     /**
+     * If {@code cpi} denotes an entry representing a resolved dynamic adapter
+     * (see {@code resolveInvokeDynamicInPool} and {@code resolveInvokeHandleInPool}),
+     * return the opcode of the instruction for which the resolution was performed
+     * ({@code invokedynamic} or {@code invokevirtual}}, or {@code -1} otherwise.
+     */
+    native int isResolvedInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
+
+
+    /**
      * Gets the list of type names (in the format of {@link JavaType#getName()}) denoting the
      * classes that define signature polymorphic methods.
      */
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
 /**
  * Implementation of {@link ConstantPool} for HotSpot.
  */
-final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject {
+public final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject {
 
     /**
      * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}.
@@ -215,14 +215,14 @@
     }
 
     /**
-     * Converts a raw index from the bytecodes to a constant pool index by adding a
+     * Converts a raw index from the bytecodes to a constant pool cache index by adding a
      * {@link HotSpotVMConfig#constantPoolCpCacheIndexTag constant}.
      *
      * @param rawIndex index from the bytecode
      * @param opcode bytecode to convert the index for
-     * @return constant pool index
+     * @return constant pool cache index
      */
-    private static int rawIndexToConstantPoolIndex(int rawIndex, int opcode) {
+    private static int rawIndexToConstantPoolCacheIndex(int rawIndex, int opcode) {
         int index;
         if (opcode == Bytecodes.INVOKEDYNAMIC) {
             index = rawIndex;
@@ -271,6 +271,7 @@
         return metaspaceConstantPool;
     }
 
+    @Override
     public long getMetaspacePointer() {
         return getMetaspaceConstantPool();
     }
@@ -541,7 +542,7 @@
     @Override
     public JavaConstant lookupAppendix(int cpi, int opcode) {
         assert Bytecodes.isInvoke(opcode);
-        final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+        final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
         Object appendix = compilerToVM().lookupAppendixInPool(this, index);
         if (appendix == null) {
             return null;
@@ -566,7 +567,7 @@
 
     @Override
     public JavaMethod lookupMethod(int cpi, int opcode) {
-        final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+        final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
         final HotSpotResolvedJavaMethod method = compilerToVM().lookupMethodInPool(this, index, (byte) opcode);
         if (method != null) {
             return method;
@@ -603,7 +604,7 @@
 
     @Override
     public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
-        final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+        final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
         final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
         final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
         String typeName = lookupUtf8(typeIndex);
@@ -634,6 +635,25 @@
         }
     }
 
+    /*
+     * Converts a raw index from the bytecodes to a constant pool index
+     * (not a cache index).
+     *
+     * @param rawIndex index from the bytecode
+     * @param opcode bytecode to convert the index for
+     * @return constant pool index
+     */
+    public int rawIndexToConstantPoolIndex(int index, int opcode) {
+        if (isInvokedynamicIndex(index)) {
+            assert opcode == Bytecodes.INVOKEDYNAMIC;
+            index = decodeInvokedynamicIndex(index) + config().constantPoolCpCacheIndexTag;
+        } else {
+            assert opcode != Bytecodes.INVOKEDYNAMIC;
+            index = rawIndexToConstantPoolCacheIndex(index, opcode);
+        }
+        return compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
+    }
+
     @Override
     @SuppressWarnings("fallthrough")
     public void loadReferencedType(int cpi, int opcode) {
@@ -664,7 +684,7 @@
             case Bytecodes.INVOKESTATIC:
             case Bytecodes.INVOKEINTERFACE: {
                 // invoke and field instructions point to a constant pool cache entry.
-                index = rawIndexToConstantPoolIndex(cpi, opcode);
+                index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
                 index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
                 break;
             }
@@ -696,7 +716,7 @@
                 }
                 if (tag == JVM_CONSTANT.MethodRef) {
                     if (Bytecodes.isInvokeHandleAlias(opcode) && isSignaturePolymorphicHolder(type)) {
-                        final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
+                        final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
                         assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
                         compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
                     }
@@ -734,6 +754,25 @@
         return false;
     }
 
+    /**
+     * Check for a resolved dynamic adapter method at the specified index,
+     * resulting from either a resolved invokedynamic or invokevirtual on a signature polymorphic
+     * MethodHandle method (HotSpot invokehandle).
+     *
+     * @param cpi the constant pool index
+     * @param opcode the opcode of the instruction for which the lookup is being performed
+     * @return {@code true} if a signature polymorphic method reference was found, otherwise {@code false}
+     */
+    public boolean isResolvedDynamicInvoke(int cpi, int opcode) {
+        if (Bytecodes.isInvokeHandleAlias(opcode)) {
+            final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
+            assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
+            int op =  compilerToVM().isResolvedInvokeHandleInPool(this, methodRefCacheIndex);
+            return op == opcode;
+        }
+        return false;
+    }
+
     @Override
     public String toString() {
         HotSpotResolvedObjectType holder = getHolder();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java	Thu Oct 19 19:23:48 2017 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Represents a constant that was retrieved from a constant pool.
+ * Used to keep track of the constant pool slot for the constant.
+ */
+public final class HotSpotConstantPoolObject extends HotSpotObjectConstantImpl {
+
+    static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, Object object) {
+        return new HotSpotConstantPoolObject(type, cpi, object);
+    }
+
+    public static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, JavaConstant object) {
+        return forObject(type, cpi, ((HotSpotObjectConstantImpl)object).object());
+    }
+
+    private final HotSpotResolvedObjectType type;
+    private final int cpi;
+
+    public HotSpotResolvedObjectType getCpType() { return type; }
+    public int getCpi()  { return cpi; }
+
+    HotSpotConstantPoolObject(HotSpotResolvedObjectType type, int cpi, Object object) {
+        super(object, false);
+        this.type = type;
+        this.cpi = cpi;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof HotSpotConstantPoolObject) {
+            if (super.equals(o)) {
+                HotSpotConstantPoolObject other = (HotSpotConstantPoolObject) o;
+                return type == other.type && cpi == other.cpi;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toValueString() {
+        return getCpType().getName() + getCpi();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "@" + toValueString();
+    }
+
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
     private byte[] relocBytes;
     private byte[] exceptionBytes;
     private byte[] oopMaps;
-    private String[] metadata;
+    private Object[] metadata;
 
     public HotSpotMetaData(TargetDescription target, HotSpotCompiledCode compiledMethod) {
         // Assign the fields default values...
@@ -66,7 +66,7 @@
         return oopMaps;
     }
 
-    public String[] metadataEntries() {
+    public Object[] metadataEntries() {
         return metadata;
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
  * Represents a constant non-{@code null} object reference, within the compiler and across the
  * compiler/runtime interface.
  */
-final class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
+class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
 
     static JavaConstant forObject(Object object) {
         return forObject(object, false);
@@ -73,7 +73,7 @@
     private final Object object;
     private final boolean compressed;
 
-    private HotSpotObjectConstantImpl(Object object, boolean compressed) {
+    protected HotSpotObjectConstantImpl(Object object, boolean compressed) {
         this.object = object;
         this.compressed = compressed;
         assert object != null;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -122,4 +122,6 @@
     int allocateCompileId(int entryBCI);
 
     boolean hasCodeAtLevel(int entryBCI, int level);
+
+    int methodIdnum();
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Thu Oct 19 19:23:48 2017 -0700
@@ -777,4 +777,8 @@
         }
         return compilerToVM().hasCompiledCodeForOSR(this, entryBCI, level);
     }
+
+    public int methodIdnum() {
+        return UNSAFE.getChar(getConstMethod() + config().constMethodMethodIdnumOffset);
+    }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -108,4 +108,7 @@
     HotSpotResolvedObjectType getEnclosingType();
 
     ResolvedJavaMethod getClassInitializer();
+
+    boolean isAnonymous();
+
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Thu Oct 19 19:23:48 2017 -0700
@@ -934,4 +934,13 @@
     public boolean isCloneableWithAllocation() {
         return (getAccessFlags() & config().jvmAccIsCloneableFast) != 0;
     }
+
+    private int getMiscFlags() {
+        return UNSAFE.getInt(getMetaspaceKlass() + config().instanceKlassMiscFlagsOffset);
+    }
+
+    public boolean isAnonymous() {
+        return (getMiscFlags() & config().instanceKlassMiscIsAnonymous) != 0;
+    }
+
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Thu Oct 19 19:23:48 2017 -0700
@@ -92,11 +92,13 @@
     final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "u1");
     final int instanceKlassConstantsOffset = getFieldOffset("InstanceKlass::_constants", Integer.class, "ConstantPool*");
     final int instanceKlassFieldsOffset = getFieldOffset("InstanceKlass::_fields", Integer.class, "Array<u2>*");
+    final int instanceKlassMiscFlagsOffset = getFieldOffset("InstanceKlass::_misc_flags", Integer.class, "u2");
     final int klassVtableStartOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_start_offset", Integer.class, "int");
     final int klassVtableLengthOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_length_offset", Integer.class, "int");
 
     final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", Integer.class);
     final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
+    final int instanceKlassMiscIsAnonymous = getConstant("InstanceKlass::_misc_is_anonymous", Integer.class);
 
     final int arrayU1LengthOffset = getFieldOffset("Array<int>::_length", Integer.class, "int");
     final int arrayU1DataOffset = getFieldOffset("Array<u1>::_data", Integer.class);
@@ -185,6 +187,7 @@
     final int constMethodCodeSizeOffset = getFieldOffset("ConstMethod::_code_size", Integer.class, "u2");
     final int constMethodNameIndexOffset = getFieldOffset("ConstMethod::_name_index", Integer.class, "u2");
     final int constMethodSignatureIndexOffset = getFieldOffset("ConstMethod::_signature_index", Integer.class, "u2");
+    final int constMethodMethodIdnumOffset = getFieldOffset("ConstMethod::_method_idnum", Integer.class, "u2");
     final int constMethodMaxStackOffset = getFieldOffset("ConstMethod::_max_stack", Integer.class, "u2");
     final int methodMaxLocalsOffset = getFieldOffset("ConstMethod::_max_locals", Integer.class, "u2");
 
--- a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java	Thu Oct 19 19:23:48 2017 -0700
@@ -25,7 +25,6 @@
  * @test
  * @requires vm.aot
  * @library /test/lib /testlibrary /
- * @ignore 8132547
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.misc
  * @build compiler.calls.common.InvokeDynamic
--- a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java	Thu Oct 19 19:23:48 2017 -0700
@@ -25,7 +25,6 @@
  * @test
  * @requires vm.aot
  * @library /test/lib /testlibrary /
- * @ignore 8132547
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.misc
  * @build compiler.calls.common.InvokeDynamic
--- a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java	Thu Oct 19 19:23:48 2017 -0700
@@ -25,7 +25,6 @@
  * @test
  * @requires vm.aot
  * @library /test/lib /testlibrary /
- * @ignore 8132547
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.misc
  * @build compiler.calls.common.InvokeDynamic
--- a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java	Thu Oct 19 19:23:48 2017 -0700
@@ -25,7 +25,6 @@
  * @test
  * @requires vm.aot
  * @library /test/lib /testlibrary /
- * @ignore 8132547
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.misc
  * @build compiler.calls.common.InvokeDynamic
--- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Wed Oct 11 17:11:28 2017 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Thu Oct 19 19:23:48 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -308,10 +308,6 @@
         return CompilerToVM.class;
     }
 
-    public static Class<?> HotSpotConstantPoolClass() {
-        return HotSpotConstantPool.class;
-    }
-
     public static Class<?> getMirror(HotSpotResolvedObjectType type) {
         return ((HotSpotResolvedJavaType) type).mirror();
     }