diff -r 057f21a10f5f -r 7dad333205cd hotspot/src/share/vm/oops/constantPool.cpp --- a/hotspot/src/share/vm/oops/constantPool.cpp Mon Aug 14 16:48:44 2017 +0200 +++ b/hotspot/src/share/vm/oops/constantPool.cpp Mon Aug 14 14:32:17 2017 -0400 @@ -33,6 +33,7 @@ #include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "oops/constantPool.hpp" @@ -47,6 +48,9 @@ #include "runtime/signature.hpp" #include "runtime/vframe.hpp" #include "utilities/copy.hpp" +#if INCLUDE_ALL_GCS +#include "gc/g1/g1SATBCardTableModRefBS.hpp" +#endif // INCLUDE_ALL_GCS ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) { Array* tags = MetadataFactory::new_array(loader_data, length, 0, CHECK_NULL); @@ -238,11 +242,53 @@ release_tag_at_put(class_index, JVM_CONSTANT_Class); } +#if INCLUDE_CDS_JAVA_HEAP +// Archive the resolved references +void ConstantPool::archive_resolved_references(Thread* THREAD) { + if (_cache == NULL) { + return; // nothing to do + } + + InstanceKlass *ik = pool_holder(); + if (!(ik->is_shared_boot_class() || ik->is_shared_platform_class() || + ik->is_shared_app_class())) { + // Archiving resolved references for classes from non-builtin loaders + // is not yet supported. + set_resolved_references(NULL); + return; + } + + objArrayOop rr = resolved_references(); + if (rr != NULL) { + for (int i = 0; i < rr->length(); i++) { + oop p = rr->obj_at(i); + if (p != NULL) { + int index = object_to_cp_index(i); + if (tag_at(index).is_string()) { + oop op = StringTable::create_archived_string(p, THREAD); + // If the String object is not archived (possibly too large), + // NULL is returned. Also set it in the array, so we won't + // have a 'bad' reference in the archived resolved_reference + // array. + rr->obj_at_put(i, op); + } else { + rr->obj_at_put(i, NULL); + } + } + } + oop archived = MetaspaceShared::archive_heap_object(rr, THREAD); + _cache->set_archived_references(archived); + set_resolved_references(NULL); + } +} +#endif + // CDS support. Create a new resolved_references array. void ConstantPool::restore_unshareable_info(TRAPS) { assert(is_constantPool(), "ensure C++ vtable is restored"); assert(on_stack(), "should always be set for shared constant pools"); assert(is_shared(), "should always be set for shared constant pools"); + assert(_cache != NULL, "constant pool _cache should not be NULL"); // Only create the new resolved references array if it hasn't been attempted before if (resolved_references() != NULL) return; @@ -251,14 +297,30 @@ restore_vtable(); if (SystemDictionary::Object_klass_loaded()) { - // Recreate the object array and add to ClassLoaderData. - int map_length = resolved_reference_length(); - if (map_length > 0) { - objArrayOop stom = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK); - Handle refs_handle (THREAD, (oop)stom); // must handleize. - - ClassLoaderData* loader_data = pool_holder()->class_loader_data(); + ClassLoaderData* loader_data = pool_holder()->class_loader_data(); +#if INCLUDE_CDS_JAVA_HEAP + if (MetaspaceShared::open_archive_heap_region_mapped() && + _cache->archived_references() != NULL) { + oop archived = _cache->archived_references(); + // Make sure GC knows the cached object is now live. This is necessary after + // initial GC marking and during concurrent marking as strong roots are only + // scanned during initial marking (at the start of the GC marking). + assert(UseG1GC, "Requires G1 GC"); + G1SATBCardTableModRefBS::enqueue(archived); + // Create handle for the archived resolved reference array object + Handle refs_handle(THREAD, (oop)archived); set_resolved_references(loader_data->add_handle(refs_handle)); + } else +#endif + { + // No mapped archived resolved reference array + // Recreate the object array and add to ClassLoaderData. + int map_length = resolved_reference_length(); + if (map_length > 0) { + objArrayOop stom = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK); + Handle refs_handle(THREAD, (oop)stom); // must handleize. + set_resolved_references(loader_data->add_handle(refs_handle)); + } } } } @@ -266,10 +328,18 @@ void ConstantPool::remove_unshareable_info() { // Resolved references are not in the shared archive. // Save the length for restoration. It is not necessarily the same length - // as reference_map.length() if invokedynamic is saved. + // as reference_map.length() if invokedynamic is saved. It is needed when + // re-creating the resolved reference array if archived heap data cannot be map + // at runtime. set_resolved_reference_length( resolved_references() != NULL ? resolved_references()->length() : 0); - set_resolved_references(NULL); + + // If archiving heap objects is not allowed, clear the resolved references. + // Otherwise, it is cleared after the resolved references array is cached + // (see archive_resolved_references()). + if (!MetaspaceShared::is_heap_object_archiving_allowed()) { + set_resolved_references(NULL); + } // Shared ConstantPools are in the RO region, so the _flags cannot be modified. // The _on_stack flag is used to prevent ConstantPools from deallocation during @@ -619,19 +689,19 @@ } } -// Resolve all the classes in the constant pool. If they are all resolved, -// the constant pool is read-only. Enhancement: allocate cp entries to -// another metaspace, and copy to read-only or read-write space if this -// bit is set. bool ConstantPool::resolve_class_constants(TRAPS) { constantPoolHandle cp(THREAD, this); for (int index = 1; index < length(); index++) { // Index 0 is unused - if (tag_at(index).is_unresolved_klass() && - klass_at_if_loaded(cp, index) == NULL) { - return false; + if (tag_at(index).is_string()) { + Symbol* sym = cp->unresolved_string_at(index); + // Look up only. Only resolve references to already interned strings. + oop str = StringTable::lookup(sym); + if (str != NULL) { + int cache_index = cp->cp_to_object_index(index); + cp->string_at_put(index, cache_index, str); + } + } } - } - // set_preresolution(); or some bit for future use return true; }