changeset 58160:d02b937ae15b lworld

8225638: [lworld] Store inline classes in CDS archive
author iklam
date Mon, 16 Dec 2019 22:20:28 -0800
parents 1711231a9e7e
children c3824206b8c3
files src/hotspot/share/classfile/javaClasses.cpp src/hotspot/share/memory/dynamicArchive.cpp src/hotspot/share/memory/metaspaceClosure.hpp src/hotspot/share/memory/metaspaceShared.cpp src/hotspot/share/oops/instanceKlass.cpp src/hotspot/share/oops/method.cpp src/hotspot/share/oops/method.hpp src/hotspot/share/oops/method.inline.hpp src/hotspot/share/oops/valueKlass.cpp src/hotspot/share/oops/valueKlass.hpp src/hotspot/share/runtime/arguments.cpp src/hotspot/share/runtime/globals.hpp src/hotspot/share/runtime/sharedRuntime.cpp src/hotspot/share/runtime/sharedRuntime.hpp test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java test/hotspot/jtreg/runtime/cds/appcds/HelloInlineClassTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicInlineClass.java test/hotspot/jtreg/runtime/cds/appcds/test-classes/HelloInlineClassApp.java test/hotspot/jtreg/runtime/cds/appcds/test-classes/HelloRelocation.java test/jtreg-ext/requires/VMProps.java
diffstat 21 files changed, 460 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/classfile/javaClasses.cpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Mon Dec 16 22:20:28 2019 -0800
@@ -44,7 +44,7 @@
 #include "memory/universe.hpp"
 #include "oops/fieldStreams.inline.hpp"
 #include "oops/instanceKlass.hpp"
-#include "oops/instanceMirrorKlass.hpp"
+#include "oops/instanceMirrorKlass.inline.hpp"
 #include "oops/klass.hpp"
 #include "oops/method.inline.hpp"
 #include "oops/objArrayOop.inline.hpp"
@@ -1197,6 +1197,12 @@
     }
   }
 
+  if (k->is_value()) {
+    // Values have a mirror and an indirect mirror. Don't handle this for now. TODO:CDS
+    k->set_java_mirror_handle(NULL);
+    return NULL;
+  }
+
   // Now start archiving the mirror object
   oop archived_mirror = HeapShared::archive_heap_object(mirror, THREAD);
   if (archived_mirror == NULL) {
--- a/src/hotspot/share/memory/dynamicArchive.cpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/memory/dynamicArchive.cpp	Mon Dec 16 22:20:28 2019 -0800
@@ -261,12 +261,26 @@
     }
 
     virtual void push_special(SpecialRef type, Ref* ref, intptr_t* p) {
-      assert(type == _method_entry_ref, "only special type allowed for now");
+      // TODO:CDS - JDK-8234693 will consolidate this with an almost identical method in metaspaceShared.cpp
+      assert_valid(type);
       address obj = ref->obj();
       address new_obj = _builder->get_new_loc(ref);
       size_t offset = pointer_delta(p, obj,  sizeof(u1));
       intptr_t* new_p = (intptr_t*)(new_obj + offset);
-      assert(*p == *new_p, "must be a copy");
+      switch (type) {
+      case _method_entry_ref:
+        assert(*p == *new_p, "must be a copy");
+        break;
+      case _internal_pointer_ref:
+        {
+          size_t off = pointer_delta(*((address*)p), obj, sizeof(u1));
+          assert(0 <= intx(off) && intx(off) < ref->size() * BytesPerWord, "must point to internal address");
+          *((address*)new_p) = new_obj + off;
+        }
+        break;
+      default:
+        ShouldNotReachHere();
+      }
       ArchivePtrMarker::mark_pointer((address*)new_p);
     }
   };
@@ -785,7 +799,7 @@
 size_t DynamicArchiveBuilder::estimate_trampoline_size() {
   size_t total = 0;
   size_t each_method_bytes =
-    align_up(SharedRuntime::trampoline_size(), BytesPerWord) +
+    align_up(SharedRuntime::trampoline_size(), BytesPerWord) * 3 +
     align_up(sizeof(AdapterHandlerEntry*), BytesPerWord);
 
   for (int i = 0; i < _klasses->length(); i++) {
@@ -806,9 +820,20 @@
     Array<Method*>* methods = ik->methods();
     for (int j = 0; j < methods->length(); j++) {
       Method* m = methods->at(j);
+
+      // TODO:CDS - JDK-8234693 will consolidate this with Method::unlink()
       address c2i_entry_trampoline =
         (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size());
       m->set_from_compiled_entry(to_target(c2i_entry_trampoline));
+
+      address c2i_value_ro_entry_trampoline =
+        (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size());
+      m->set_from_compiled_value_ro_entry(to_target(c2i_value_ro_entry_trampoline));
+
+      address c2i_value_entry_trampoline =
+        (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size());
+      m->set_from_compiled_value_entry(to_target(c2i_value_entry_trampoline));
+
       AdapterHandlerEntry** adapter_trampoline =
         (AdapterHandlerEntry**)MetaspaceShared::misc_code_space_alloc(sizeof(AdapterHandlerEntry*));
       *adapter_trampoline = NULL;
--- a/src/hotspot/share/memory/metaspaceClosure.hpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/memory/metaspaceClosure.hpp	Mon Dec 16 22:20:28 2019 -0800
@@ -77,7 +77,11 @@
   };
 
   enum SpecialRef {
-    _method_entry_ref
+    // A field that points to a method entry. E.g., Method::_i2i_entry
+    _method_entry_ref,
+
+    // A field that points to a location inside the current object.
+    _internal_pointer_ref,
   };
 
   // class MetaspaceClosure::Ref --
@@ -284,13 +288,21 @@
   }
 
   template <class T> void push_method_entry(T** mpp, intptr_t* p) {
-    push_special(_method_entry_ref, new ObjectRef<T>(mpp, _default), (intptr_t*)p);
+    push_special(_method_entry_ref, new ObjectRef<T>(mpp, _default), p);
+  }
+
+  template <class T> void push_internal_pointer(T** mpp, intptr_t* p) {
+    push_special(_internal_pointer_ref, new ObjectRef<T>(mpp, _default), p);
   }
 
   // This is for tagging special pointers that are not a reference to MetaspaceObj. It's currently
   // used to mark the method entry points in Method/ConstMethod.
   virtual void push_special(SpecialRef type, Ref* obj, intptr_t* p) {
-    assert(type == _method_entry_ref, "only special type allowed for now");
+    assert_valid(type);
+  }
+
+  static void assert_valid(SpecialRef type) {
+    assert(type == _method_entry_ref || type == _internal_pointer_ref, "only special types allowed for now");
   }
 };
 
--- a/src/hotspot/share/memory/metaspaceShared.cpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/memory/metaspaceShared.cpp	Mon Dec 16 22:20:28 2019 -0800
@@ -59,6 +59,8 @@
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/typeArrayKlass.hpp"
+#include "oops/valueArrayKlass.hpp"
+#include "oops/valueKlass.hpp"
 #include "prims/jvmtiRedefineClasses.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/os.hpp"
@@ -641,13 +643,15 @@
 // Currently, the archive contain ONLY the following types of objects that have C++ vtables.
 #define CPP_VTABLE_PATCH_TYPES_DO(f) \
   f(ConstantPool) \
+  f(InstanceClassLoaderKlass) \
   f(InstanceKlass) \
-  f(InstanceClassLoaderKlass) \
   f(InstanceMirrorKlass) \
   f(InstanceRefKlass) \
   f(Method) \
   f(ObjArrayKlass) \
-  f(TypeArrayKlass)
+  f(TypeArrayKlass) \
+  f(ValueArrayKlass) \
+  f(ValueKlass)
 
 class CppVtableInfo {
   intptr_t _vtable_size;
@@ -829,7 +833,9 @@
     {
       Klass* k = (Klass*)obj;
       assert(k->is_klass(), "must be");
-      if (k->is_instance_klass()) {
+      if (k->is_value()) {
+        kind = ValueKlass_Kind;
+      } else if (k->is_instance_klass()) {
         kind = InstanceKlass_Kind;
       } else {
         assert(k->is_objArray_klass(),
@@ -913,6 +919,8 @@
         CppVtableCloner<InstanceRefKlass>::patch(ik);
       } else if (ik->is_mirror_instance_klass()) {
         CppVtableCloner<InstanceMirrorKlass>::patch(ik);
+      } else if (ik->is_value()) {
+        CppVtableCloner<ValueKlass>::patch(ik);
       } else {
         CppVtableCloner<InstanceKlass>::patch(ik);
       }
@@ -1269,12 +1277,26 @@
       return true; // recurse into ref.obj()
     }
     virtual void push_special(SpecialRef type, Ref* ref, intptr_t* p) {
-      assert(type == _method_entry_ref, "only special type allowed for now");
+      assert_valid(type);
+
       address obj = ref->obj();
       address new_obj = get_new_loc(ref);
       size_t offset = pointer_delta(p, obj,  sizeof(u1));
       intptr_t* new_p = (intptr_t*)(new_obj + offset);
-      assert(*p == *new_p, "must be a copy");
+      switch (type) {
+      case _method_entry_ref:
+        assert(*p == *new_p, "must be a copy");
+        break;
+      case _internal_pointer_ref:
+        {
+          size_t off = pointer_delta(*((address*)p), obj, sizeof(u1));
+          assert(0 <= intx(off) && intx(off) < ref->size() * BytesPerWord, "must point to internal address");
+          *((address*)new_p) = new_obj + off;
+        }
+        break;
+      default:
+        ShouldNotReachHere();
+      }
       ArchivePtrMarker::mark_pointer((address*)new_p);
     }
   };
--- a/src/hotspot/share/oops/instanceKlass.cpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Mon Dec 16 22:20:28 2019 -0800
@@ -2550,6 +2550,10 @@
   set_package(loader_data, CHECK);
   Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
 
+  if (is_value()) {
+    ValueKlass::cast(this)->initialize_calling_convention(CHECK);
+  }
+
   Array<Method*>* methods = this->methods();
   int num_methods = methods->length();
   for (int index = 0; index < num_methods; ++index) {
@@ -2575,7 +2579,7 @@
   }
 
   // Initialize current biased locking state.
-  if (UseBiasedLocking && BiasedLocking::enabled()) {
+  if (UseBiasedLocking && BiasedLocking::enabled() && !is_value()) {
     set_prototype_header(markWord::biased_locking_prototype());
   }
 }
--- a/src/hotspot/share/oops/method.cpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/oops/method.cpp	Mon Dec 16 22:20:28 2019 -0800
@@ -357,6 +357,8 @@
   Method* this_ptr = this;
   it->push_method_entry(&this_ptr, (intptr_t*)&_i2i_entry);
   it->push_method_entry(&this_ptr, (intptr_t*)&_from_compiled_entry);
+  it->push_method_entry(&this_ptr, (intptr_t*)&_from_compiled_value_ro_entry);
+  it->push_method_entry(&this_ptr, (intptr_t*)&_from_compiled_value_entry);
   it->push_method_entry(&this_ptr, (intptr_t*)&_from_interpreted_entry);
 }
 
@@ -1108,16 +1110,18 @@
     //       Remove the use of CDSAdapterHandlerEntry.
     CDSAdapterHandlerEntry* cds_adapter = (CDSAdapterHandlerEntry*)adapter();
     constMethod()->set_adapter_trampoline(cds_adapter->get_adapter_trampoline());
+
     _from_compiled_entry = cds_adapter->get_c2i_entry_trampoline();
     assert(*((int*)_from_compiled_entry) == 0,
-           "must be NULL during dump time, to be initialized at run time");
-    _from_compiled_value_ro_entry = cds_adapter->get_c2i_entry_trampoline(); // FIXME - doesn't work if you have value args!
+           "instructions must be zeros during dump time, to be initialized at run time");
+
+    _from_compiled_value_ro_entry = cds_adapter->get_c2i_value_ro_entry_trampoline();
     assert(*((int*)_from_compiled_value_ro_entry) == 0,
-           "must be NULL during dump time, to be initialized at run time");
-    _from_compiled_value_entry  = cds_adapter->get_c2i_entry_trampoline(); // FIXME - doesn't work if you have value args (or this is value type)!
+           "instructions must be zeros during dump time, to be initialized at run time");
+
+    _from_compiled_value_entry = cds_adapter->get_c2i_value_entry_trampoline();
     assert(*((int*)_from_compiled_value_entry) == 0,
-           "must be NULL during dump time, to be initialized at run time");
-    assert(!method_holder()->is_value(), "FIXME: valuetype not supported by CDS");
+           "instructions must be zeros during dump time, to be initialized at run time");
   }
 
   if (is_native()) {
@@ -1286,12 +1290,25 @@
 void Method::restore_unshareable_info(TRAPS) {
   assert(is_method() && is_valid_method(this), "ensure C++ vtable is restored");
 
+#if 0
+  /*
+   * CDS:TODO --
+   * "Q" classes in the method signature must be resolved during link_method.
+   * However, at this point we are still inside method_holder()->restore_unshareable_info.
+   * If we try to resolve method_holder(), or multually dependent classes, it will
+   * cause deadlock and other ill effects.
+   *
+   * For now, lets do method linking inside InstanceKlass::link_class(). Optimization
+   * may be possible if we know that resolution will never happen.
+   */
+
   // Since restore_unshareable_info can be called more than once for a method, don't
   // redo any work.
   if (adapter() == NULL) {
     methodHandle mh(THREAD, this);
     link_method(mh, CHECK);
   }
+#endif
 }
 
 address Method::from_compiled_entry_no_trampoline(bool caller_is_c1) const {
--- a/src/hotspot/share/oops/method.hpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/oops/method.hpp	Mon Dec 16 22:20:28 2019 -0800
@@ -149,6 +149,8 @@
 
   static address make_adapters(const methodHandle& mh, TRAPS);
   address from_compiled_entry() const;
+  address from_compiled_value_ro_entry() const;
+  address from_compiled_value_entry() const;
   address from_compiled_entry_no_trampoline(bool caller_is_c1) const;
   address from_interpreted_entry() const;
 
@@ -499,7 +501,13 @@
     constMethod()->update_adapter_trampoline(adapter);
   }
   void set_from_compiled_entry(address entry) {
-    _from_compiled_entry =  entry;
+    _from_compiled_entry = entry;
+  }
+  void set_from_compiled_value_ro_entry(address entry) {
+    _from_compiled_value_ro_entry = entry;
+  }
+  void set_from_compiled_value_entry(address entry) {
+    _from_compiled_value_entry = entry;
   }
 
   address get_i2c_entry();
--- a/src/hotspot/share/oops/method.inline.hpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/oops/method.inline.hpp	Mon Dec 16 22:20:28 2019 -0800
@@ -32,6 +32,14 @@
   return Atomic::load_acquire(&_from_compiled_entry);
 }
 
+inline address Method::from_compiled_value_ro_entry() const {
+  return Atomic::load_acquire(&_from_compiled_value_ro_entry);
+}
+
+inline address Method::from_compiled_value_entry() const {
+  return Atomic::load_acquire(&_from_compiled_value_entry);
+}
+
 inline address Method::from_interpreted_entry() const {
   return Atomic::load_acquire(&_from_interpreted_entry);
 }
--- a/src/hotspot/share/oops/valueKlass.cpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/oops/valueKlass.cpp	Mon Dec 16 22:20:28 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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 "gc/shared/gcLocker.inline.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
+#include "memory/metaspaceClosure.hpp"
 #include "memory/metadataFactory.hpp"
 #include "oops/access.hpp"
 #include "oops/compressedOops.inline.hpp"
@@ -197,6 +198,24 @@
   return true;
 }
 
+void ValueKlass::remove_unshareable_info() {
+  InstanceKlass::remove_unshareable_info();
+
+  *((Array<SigEntry>**)adr_extended_sig()) = NULL;
+  *((Array<VMRegPair>**)adr_return_regs()) = NULL;
+  *((address*)adr_pack_handler()) = NULL;
+  *((address*)adr_pack_handler_jobject()) = NULL;
+  *((address*)adr_unpack_handler()) = NULL;
+  assert(pack_handler() == NULL, "pack handler not null");
+  *((Klass**)adr_value_array_klass()) = NULL;
+}
+
+void ValueKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
+  InstanceKlass::restore_unshareable_info(loader_data, protection_domain, CHECK);
+  oop val = allocate_instance(CHECK);
+  set_default_value(val);
+}
+
 
 Klass* ValueKlass::array_klass_impl(ArrayStorageProperties storage_props, bool or_null, int n, TRAPS) {
   if (storage_props.is_null_free()) {
@@ -541,3 +560,10 @@
   InstanceKlass::oop_verify_on(obj, st);
   guarantee(obj->mark().is_always_locked(), "Header is not always locked");
 }
+
+void ValueKlass::metaspace_pointers_do(MetaspaceClosure* it) {
+  InstanceKlass::metaspace_pointers_do(it);
+
+  ValueKlass* this_ptr = this;
+  it->push_internal_pointer(&this_ptr, (intptr_t*)&_adr_valueklass_fixed_block);
+}
--- a/src/hotspot/share/oops/valueKlass.hpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/oops/valueKlass.hpp	Mon Dec 16 22:20:28 2019 -0800
@@ -37,6 +37,9 @@
   friend class VMStructs;
   friend class InstanceKlass;
 
+ public:
+  ValueKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
+
  private:
 
   // Constructor
@@ -156,6 +159,10 @@
 
   int first_field_offset_old();
 
+  virtual void remove_unshareable_info();
+  virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS);
+  virtual void metaspace_pointers_do(MetaspaceClosure* it);
+
  private:
   int collect_fields(GrowableArray<SigEntry>* sig, int base_off = 0);
 
--- a/src/hotspot/share/runtime/arguments.cpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/runtime/arguments.cpp	Mon Dec 16 22:20:28 2019 -0800
@@ -4189,7 +4189,7 @@
     log_info(verification)("Turning on remote verification because local verification is on");
     FLAG_SET_DEFAULT(BytecodeVerificationRemote, true);
   }
-  if (!EnableValhalla || is_interpreter_only()) {
+  if (!EnableValhalla || (is_interpreter_only() && !is_dumping_archive())) {
     // Disable calling convention optimizations if value types are not supported
     ValueTypePassFieldsAsArgs = false;
     ValueTypeReturnedAsFields = false;
--- a/src/hotspot/share/runtime/globals.hpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/runtime/globals.hpp	Mon Dec 16 22:20:28 2019 -0800
@@ -2307,8 +2307,7 @@
                                                                             \
   /* Shared spaces */                                                       \
                                                                             \
-  /* Disabled UseSharedSpaces for Valhalla, just for now */                 \
-  product(bool, UseSharedSpaces, false,                                     \
+  product(bool, UseSharedSpaces, true,                                      \
           "Use shared spaces for metadata")                                 \
                                                                             \
   product(bool, VerifySharedSpaces, false,                                  \
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Mon Dec 16 22:20:28 2019 -0800
@@ -2727,6 +2727,20 @@
                               c2i_unverified_value_entry, c2i_no_clinit_check_entry);
 }
 
+static void generate_trampoline(address trampoline, address destination) {
+  if (*(int*)trampoline == 0) {
+    CodeBuffer buffer(trampoline, (int)SharedRuntime::trampoline_size());
+    MacroAssembler _masm(&buffer);
+    SharedRuntime::generate_trampoline(&_masm, destination);
+    assert(*(int*)trampoline != 0, "Instruction(s) for trampoline must not be encoded as zeros.");
+      _masm.flush();
+
+    if (PrintInterpreter) {
+      Disassembler::decode(buffer.insts_begin(), buffer.insts_end());
+    }
+  }
+}
+
 AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) {
   AdapterHandlerEntry* entry = get_adapter0(method);
   if (entry != NULL && method->is_shared()) {
@@ -2735,23 +2749,15 @@
     if (method->adapter() == NULL) {
       method->update_adapter_trampoline(entry);
     }
-    address trampoline = method->from_compiled_entry();
-    if (*(int*)trampoline == 0) {
-      CodeBuffer buffer(trampoline, (int)SharedRuntime::trampoline_size());
-      MacroAssembler _masm(&buffer);
-      SharedRuntime::generate_trampoline(&_masm, entry->get_c2i_entry());
-      assert(*(int*)trampoline != 0, "Instruction(s) for trampoline must not be encoded as zeros.");
-      _masm.flush();
-
-      if (PrintInterpreter) {
-        Disassembler::decode(buffer.insts_begin(), buffer.insts_end());
-      }
-    }
+    generate_trampoline(method->from_compiled_entry(),          entry->get_c2i_entry());
+    generate_trampoline(method->from_compiled_value_ro_entry(), entry->get_c2i_value_ro_entry());
+    generate_trampoline(method->from_compiled_value_entry(),    entry->get_c2i_value_entry());
   }
 
   return entry;
 }
 
+
 CompiledEntrySignature::CompiledEntrySignature(Method* method) :
   _method(method), _num_value_args(0), _has_value_recv(false),
   _sig_cc(NULL), _sig_cc_ro(NULL), _regs(NULL), _regs_cc(NULL), _regs_cc_ro(NULL),
@@ -3536,6 +3542,8 @@
 void CDSAdapterHandlerEntry::init() {
   assert(DumpSharedSpaces, "used during dump time only");
   _c2i_entry_trampoline = (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size());
+  _c2i_value_ro_entry_trampoline = (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size());
+  _c2i_value_entry_trampoline = (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size());
   _adapter_trampoline = (AdapterHandlerEntry**)MetaspaceShared::misc_code_space_alloc(sizeof(AdapterHandlerEntry*));
 };
 
--- a/src/hotspot/share/runtime/sharedRuntime.hpp	Mon Dec 16 16:07:29 2019 +0100
+++ b/src/hotspot/share/runtime/sharedRuntime.hpp	Mon Dec 16 22:20:28 2019 -0800
@@ -740,11 +740,15 @@
 // that's used only during CDS dump time.
 // For details, see comments around Method::link_method()
 class CDSAdapterHandlerEntry: public AdapterHandlerEntry {
-  address               _c2i_entry_trampoline;   // allocated from shared spaces "MC" region
-  AdapterHandlerEntry** _adapter_trampoline;     // allocated from shared spaces "MD" region
+  address               _c2i_entry_trampoline;           // allocated from shared spaces "MC" region
+  address               _c2i_value_ro_entry_trampoline;  // allocated from shared spaces "MC" region
+  address               _c2i_value_entry_trampoline;     // allocated from shared spaces "MC" region
+  AdapterHandlerEntry** _adapter_trampoline;             // allocated from shared spaces "MD" region
 
 public:
   address get_c2i_entry_trampoline()             const { return _c2i_entry_trampoline; }
+  address get_c2i_value_ro_entry_trampoline()    const { return _c2i_value_ro_entry_trampoline; }
+  address get_c2i_value_entry_trampoline()       const { return _c2i_value_entry_trampoline; }
   AdapterHandlerEntry** get_adapter_trampoline() const { return _adapter_trampoline; }
   void init() NOT_CDS_RETURN;
 };
--- a/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java	Mon Dec 16 16:07:29 2019 +0100
+++ b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java	Mon Dec 16 22:20:28 2019 -0800
@@ -29,8 +29,8 @@
  * @comment JDK-8231610 Relocate the CDS archive if it cannot be mapped to the requested address
  * @bug 8231610
  * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @build Hello
- * @run driver ClassFileInstaller -jar hello.jar Hello
+ * @build HelloRelocation
+ * @run driver ClassFileInstaller -jar hello.jar HelloRelocation HelloInlineClassApp HelloInlineClassApp$Point
  * @run driver ArchiveRelocationTest
  */
 
@@ -62,7 +62,7 @@
 
 
         String appJar = ClassFileInstaller.getJarPath("hello.jar");
-        String mainClass = "Hello";
+        String mainClass = "HelloRelocation";
         String forceRelocation = "-XX:ArchiveRelocationMode=1";
         String dumpRelocArg = dump_reloc ? forceRelocation : "-showversion";
         String runRelocArg  = run_reloc  ? forceRelocation : "-showversion";
@@ -70,7 +70,9 @@
         String unlockArg = "-XX:+UnlockDiagnosticVMOptions";
 
         OutputAnalyzer out = TestCommon.dump(appJar,
-                                             TestCommon.list(mainClass),
+                                             TestCommon.list(mainClass,
+                                                             "HelloInlineClassApp",
+                                                             "HelloInlineClassApp$Point"),
                                              unlockArg, dumpRelocArg, logArg);
         if (dump_reloc) {
             out.shouldContain("ArchiveRelocationMode == 1: always allocate class space at an alternative address");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/HelloInlineClassTest.java	Mon Dec 16 22:20:28 2019 -0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+/*
+ * @test
+ * @summary Hello World test for using inline classes with CDS
+ * @requires vm.cds
+ * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
+ * @build HelloInlineClassApp
+ * @run driver ClassFileInstaller -jar hello_inline.jar HelloInlineClassApp HelloInlineClassApp$Point
+ * @run driver HelloInlineClassTest
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class HelloInlineClassTest {
+    public static void main(String[] args) throws Exception {
+        String appJar = ClassFileInstaller.getJarPath("hello_inline.jar");
+        String mainClass = "HelloInlineClassApp";
+        OutputAnalyzer output =
+            TestCommon.dump(appJar, TestCommon.list(mainClass,
+                                                    "HelloInlineClassApp$Point"));
+        output.shouldHaveExitValue(0);
+
+        TestCommon.run("-Xint", "-cp", appJar,  mainClass)
+            .assertNormalExit();
+
+        TestCommon.run("-cp", appJar,  mainClass)
+            .assertNormalExit();
+
+        String compFlag = "-XX:CompileCommand=compileonly,HelloInlineClassApp*::*";
+
+        TestCommon.run("-Xcomp", compFlag,
+                       "-cp", appJar,  mainClass)
+            .assertNormalExit();
+
+        TestCommon.run("-Xcomp", compFlag,
+                       "-XX:TieredStopAtLevel=1",
+                       "-XX:+TieredCompilation",
+                       "-XX:-Inline",
+                       "-cp", appJar,  mainClass)
+            .assertNormalExit();
+
+        TestCommon.run("-Xcomp", compFlag,
+                       "-XX:TieredStopAtLevel=4",
+                       "-XX:-TieredCompilation",
+                       "-XX:-Inline",
+                       "-cp", appJar,  mainClass)
+            .assertNormalExit();
+    }
+}
--- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java	Mon Dec 16 16:07:29 2019 +0100
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java	Mon Dec 16 22:20:28 2019 -0800
@@ -30,8 +30,8 @@
  * @comment JDK-8231610 Relocate the CDS archive if it cannot be mapped to the requested address
  * @bug 8231610
  * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @build Hello
- * @run driver ClassFileInstaller -jar hello.jar Hello
+ * @build HelloRelocation
+ * @run driver ClassFileInstaller -jar hello.jar HelloRelocation HelloInlineClassApp HelloInlineClassApp$Point
  * @run driver DynamicArchiveRelocationTest
  */
 
@@ -78,7 +78,7 @@
         System.out.println("============================================================");
 
         String appJar = ClassFileInstaller.getJarPath("hello.jar");
-        String mainClass = "Hello";
+        String mainClass = "HelloRelocation";
         String forceRelocation = "-XX:ArchiveRelocationMode=1";
         String dumpBaseRelocArg = dump_base_reloc ? forceRelocation : "-showversion";
         String dumpTopRelocArg  = dump_top_reloc  ? forceRelocation : "-showversion";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicInlineClass.java	Mon Dec 16 22:20:28 2019 -0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+/*
+ * @test
+ * @summary Hello World test for dynamic archive
+ * @requires vm.cds
+ * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
+ * @build HelloInlineClassApp
+ * @run driver ClassFileInstaller -jar hello_inline.jar HelloInlineClassApp HelloInlineClassApp$Point
+ * @run driver HelloDynamicInlineClass
+ */
+
+public class HelloDynamicInlineClass extends DynamicArchiveTestBase {
+    public static void main(String[] args) throws Exception {
+        runTest(HelloDynamicInlineClass::testDefaultBase);
+        runTest(HelloDynamicInlineClass::testCustomBase);
+    }
+
+    // (1) Test with default base archive + top archive
+    static void testDefaultBase() throws Exception {
+        String topArchiveName = getNewArchiveName("top");
+        doTest(null, topArchiveName);
+    }
+
+    // (2) Test with custom base archive + top archive
+    static void testCustomBase() throws Exception {
+        String topArchiveName = getNewArchiveName("top2");
+        String baseArchiveName = getNewArchiveName("base");
+        dumpBaseArchive(baseArchiveName);
+        doTest(baseArchiveName, topArchiveName);
+    }
+
+    private static void doTest(String baseArchiveName, String topArchiveName) throws Exception {
+        String appJar = ClassFileInstaller.getJarPath("hello_inline.jar");
+        String mainClass = "HelloInlineClassApp";
+        dump2(baseArchiveName, topArchiveName,
+             "-Xlog:cds",
+             "-Xlog:cds+dynamic=debug",
+             "-cp", appJar, mainClass)
+            .assertNormalExit(output -> {
+                    output.shouldContain("Buffer-space to target-space delta")
+                           .shouldContain("Written dynamic archive 0x");
+                });
+        run2(baseArchiveName, topArchiveName,
+            "-Xlog:class+load",
+            "-Xlog:cds+dynamic=debug,cds=debug",
+            "-cp", appJar, mainClass)
+            .assertNormalExit(output -> {
+                    output.shouldContain("HelloInlineClassApp$Point source: shared objects file")
+                          .shouldHaveExitValue(0);
+              });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/HelloInlineClassApp.java	Mon Dec 16 22:20:28 2019 -0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+public class HelloInlineClassApp {
+    static inline class Point {
+        int x, y;
+
+        public String toString() {
+            return "(" + x + ", " + y + ")";
+        }
+
+        public Point(int x, int y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        Point add(Point p1) {
+            return new Point(x + p1.x, y + p1.y);
+        }
+
+        Point add(Point p1, Point p2) {
+            return new Point(x + p1.x + p2.x, y + p1.y + p2.y);
+        }
+
+        Point add(Point p1, int x2, int y2, Point p3) {
+            return new Point(x + p1.x + x2 + p3.x, y + p1.y + y2 + p3.y);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Point p = new Point(0, 123);
+        System.out.println("Point = " + p);
+        String req = "(0, 123)";
+        if (!p.toString().equals(req)) {
+            throw new RuntimeException("Expected " + req + " but got " + p);
+        }
+
+        Point p1 = new Point(1, 1);
+        Point p2 = new Point(2, 2);
+        Point p3 = new Point(3, 3);
+        int x2 = 200;
+        int y2 = 200;
+
+        int loops = 100000;
+        for (int i=0; i<loops; i++) {
+            p = p.add(p1);
+            p = p.add(p1, p2);
+            p = p.add(p1, x2, y2, p3);
+        }
+
+        int expectedX = 0 +
+            loops * p1.x +
+            loops * (p1.x + p2.x) +
+            loops * (p1.x + x2 + p3.x);
+
+        int expectedY = 123 +
+            loops * p1.y +
+            loops * (p1.y + p2.y) +
+            loops * (p1.y + y2 + p3.y);
+
+        System.out.println("Point (2) = " + p);
+
+        if (p.x != expectedX || p.y != expectedY) {
+            throw new RuntimeException("Expected (" + expectedX + ", " + expectedY + " but got " + p);
+        }
+
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/HelloRelocation.java	Mon Dec 16 22:20:28 2019 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+public class HelloRelocation {
+    public static void main(String args[]) throws Exception {
+        System.out.println("Hello World");
+        HelloInlineClassApp.main(args);
+    }
+}
--- a/test/jtreg-ext/requires/VMProps.java	Mon Dec 16 16:07:29 2019 +0100
+++ b/test/jtreg-ext/requires/VMProps.java	Mon Dec 16 22:20:28 2019 -0800
@@ -409,8 +409,7 @@
      * @return true if CDS is supported by the VM to be tested.
      */
     protected String vmCDS() {
-        //return "" + WB.isCDSIncludedInVmBuild();
-        return "false";
+        return "" + WB.isCDSIncludedInVmBuild();
     }
 
     /**