Skip to content
Permalink
Browse files
8241071: Generation of classes.jsa with -Xshare:dump is not determini…
…stic

Reviewed-by: dholmes, stuefe
  • Loading branch information
iklam committed May 5, 2020
1 parent 957eb27 commit eadcb08c3cc41dbb05b083bf3e83eaf1d2670cfe
@@ -1,5 +1,5 @@
#
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2016, 2020, 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,6 +122,7 @@ JVM_GetNestMembers
JVM_GetPrimitiveArrayElement
JVM_GetProperties
JVM_GetProtectionDomain
JVM_GetRandomSeedForCDSDump
JVM_GetRecordComponents
JVM_GetSimpleBinaryName
JVM_GetStackAccessControlContext
@@ -176,6 +176,11 @@ void SymbolTable::create_table () {
}

void SymbolTable::delete_symbol(Symbol* sym) {
if (Arguments::is_dumping_archive()) {
// Do not delete symbols as we may be in the middle of preparing the
// symbols for dumping.
return;
}
if (sym->is_permanent()) {
MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
// Deleting permanent symbol should not occur very often (insert race condition),
@@ -221,12 +226,18 @@ Symbol* SymbolTable::allocate_symbol(const char* name, int len, bool c_heap) {

Symbol* sym;
if (Arguments::is_dumping_archive()) {
// Need to make all symbols permanent -- or else some symbols may be GC'ed
// during the archive dumping code that's executed outside of a safepoint.
c_heap = false;
}
if (c_heap) {
// refcount starts as 1
sym = new (len) Symbol((const u1*)name, len, 1);
assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
} else if (DumpSharedSpaces) {
// See comments inside Symbol::operator new(size_t, int)
sym = new (len) Symbol((const u1*)name, len, PERM_REFCOUNT);
assert(sym != NULL, "new should call vm_exit_out_of_memory if failed to allocate symbol during DumpSharedSpaces");
} else {
// Allocate to global arena
MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
@@ -174,10 +174,22 @@ class DumpTimeSharedClassInfo: public CHeapObj<mtClass> {
}
};

inline unsigned DumpTimeSharedClassTable_hash(InstanceKlass* const& k) {
if (DumpSharedSpaces) {
// Deterministic archive contents
uintx delta = k->name() - MetaspaceShared::symbol_rs_base();
return primitive_hash<uintx>(delta);
} else {
// Deterministic archive is not possible because classes can be loaded
// in multiple threads.
return primitive_hash<InstanceKlass*>(k);
}
}

class DumpTimeSharedClassTable: public ResourceHashtable<
InstanceKlass*,
DumpTimeSharedClassInfo,
primitive_hash<InstanceKlass*>,
&DumpTimeSharedClassTable_hash,
primitive_equals<InstanceKlass*>,
15889, // prime number
ResourceObj::C_HEAP>
@@ -176,6 +176,9 @@ JVM_GetVmArguments(JNIEnv *env);
JNIEXPORT void JNICALL
JVM_InitializeFromArchive(JNIEnv* env, jclass cls);

JNIEXPORT jlong JNICALL
JVM_GetRandomSeedForCDSDump();

/*
* java.lang.Throwable
*/
@@ -503,14 +503,13 @@ class DynamicArchiveBuilder : ResourceObj {
void write_archive(char* serialized_data);

void init_first_dump_space(address reserved_bottom) {
address first_space_base = reserved_bottom;
DumpRegion* mc_space = MetaspaceShared::misc_code_dump_space();
DumpRegion* rw_space = MetaspaceShared::read_write_dump_space();

// Use the same MC->RW->RO ordering as in the base archive.
MetaspaceShared::init_shared_dump_space(mc_space, first_space_base);
MetaspaceShared::init_shared_dump_space(mc_space);
_current_dump_space = mc_space;
_last_verified_top = first_space_base;
_last_verified_top = reserved_bottom;
_num_dump_regions_used = 1;
}

@@ -1177,13 +1177,20 @@ void FileMapRegion::init(int region_index, char* base, size_t size, bool read_on
_mapped_base = NULL;
}

static const char* region_names[] = {
"mc", "rw", "ro", "bm", "ca0", "ca1", "oa0", "oa1"
};

void FileMapInfo::write_region(int region, char* base, size_t size,
bool read_only, bool allow_exec) {
Arguments::assert_is_dumping_archive();

FileMapRegion* si = space_at(region);
char* target_base;

const int num_regions = sizeof(region_names)/sizeof(region_names[0]);
assert(0 <= region && region < num_regions, "sanity");

if (region == MetaspaceShared::bm) {
target_base = NULL; // always NULL for bm region.
} else {
@@ -1197,11 +1204,13 @@ void FileMapInfo::write_region(int region, char* base, size_t size,

si->set_file_offset(_file_offset);
char* requested_base = (target_base == NULL) ? NULL : target_base + MetaspaceShared::final_delta();
log_debug(cds)("Shared file region %d: " SIZE_FORMAT_HEX_W(08)
" bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08),
region, size, p2i(requested_base), _file_offset);

int crc = ClassLoader::crc32(0, base, (jint)size);
if (size > 0) {
log_debug(cds)("Shared file region (%-3s) %d: " SIZE_FORMAT_W(8)
" bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08)
" crc 0x%08x",
region_names[region], region, size, p2i(requested_base), _file_offset, crc);
}
si->init(region, target_base, size, read_only, allow_exec, crc);

if (base != NULL) {
@@ -1246,8 +1255,6 @@ void FileMapInfo::write_bitmap_region(const CHeapBitMap* ptrmap,
write_oopmaps(open_oopmaps, curr_offset, buffer);
}

log_debug(cds)("ptrmap = " INTPTR_FORMAT " (" SIZE_FORMAT " bytes)",
p2i(buffer), size_in_bytes);
write_region(MetaspaceShared::bm, (char*)buffer, size_in_bytes, /*read_only=*/true, /*allow_exec=*/false);
}

@@ -1297,23 +1304,20 @@ size_t FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *heap_me
}

size_t total_size = 0;
for (int i = first_region_id, arr_idx = 0;
i < first_region_id + max_num_regions;
i++, arr_idx++) {
for (int i = 0; i < max_num_regions; i++) {
char* start = NULL;
size_t size = 0;
if (arr_idx < arr_len) {
start = (char*)heap_mem->at(arr_idx).start();
size = heap_mem->at(arr_idx).byte_size();
if (i < arr_len) {
start = (char*)heap_mem->at(i).start();
size = heap_mem->at(i).byte_size();
total_size += size;
}

log_debug(cds)("Archive heap region %d: " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes",
i, p2i(start), p2i(start + size), size);
write_region(i, start, size, false, false);
int region_idx = i + first_region_id;
write_region(region_idx, start, size, false, false);
if (size > 0) {
space_at(i)->init_oopmap(oopmaps->at(arr_idx)._offset,
oopmaps->at(arr_idx)._oopmap_size_in_bits);
space_at(region_idx)->init_oopmap(oopmaps->at(i)._offset,
oopmaps->at(i)._oopmap_size_in_bits);
}
}
return total_size;
@@ -142,6 +142,10 @@ oop HeapShared::archive_heap_object(oop obj, Thread* THREAD) {
if (archived_oop != NULL) {
Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(obj), cast_from_oop<HeapWord*>(archived_oop), len);
MetaspaceShared::relocate_klass_ptr(archived_oop);
// Clear age -- it might have been set if a GC happened during -Xshare:dump
markWord mark = archived_oop->mark_raw();
mark = mark.set_age(0);
archived_oop->set_mark_raw(mark);
ArchivedObjectCache* cache = archived_object_cache();
cache->put(obj, archived_oop);
log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT,

0 comments on commit eadcb08

Please sign in to comment.