mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8357175: Failure to generate or load AOT code should be handled gracefully
Reviewed-by: iveresov, asmehra
This commit is contained in:
parent
470ffeedda
commit
e3eb089d47
@ -125,6 +125,8 @@ uint AOTCodeCache::max_aot_code_size() {
|
||||
return _max_aot_code_size;
|
||||
}
|
||||
|
||||
// This method is called during universe_init()
|
||||
// and does final AOT state and flags settings.
|
||||
void AOTCodeCache::initialize() {
|
||||
#if defined(ZERO) || !(defined(AMD64) || defined(AARCH64))
|
||||
log_info(aot, codecache, init)("AOT Code Cache is not supported on this platform.");
|
||||
@ -197,31 +199,40 @@ void AOTCodeCache::initialize() {
|
||||
#endif // defined(AMD64) || defined(AARCH64)
|
||||
}
|
||||
|
||||
static AOTCodeCache* opened_cache = nullptr; // Use this until we verify the cache
|
||||
AOTCodeCache* AOTCodeCache::_cache = nullptr;
|
||||
|
||||
// This method is called after universe_init()
|
||||
// when all GC settings are finalized.
|
||||
void AOTCodeCache::init2() {
|
||||
if (!is_on()) {
|
||||
if (opened_cache == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (!verify_vm_config()) {
|
||||
close();
|
||||
if (!opened_cache->verify_config()) {
|
||||
delete opened_cache;
|
||||
opened_cache = nullptr;
|
||||
report_load_failure();
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize the table of external routines so we can save
|
||||
// generated code blobs that reference them
|
||||
init_extrs_table();
|
||||
init_early_stubs_table();
|
||||
AOTCodeAddressTable* table = opened_cache->_table;
|
||||
assert(table != nullptr, "should be initialized already");
|
||||
table->init_extrs();
|
||||
table->init_early_stubs();
|
||||
|
||||
// Now cache and address table are ready for AOT code generation
|
||||
_cache = opened_cache;
|
||||
}
|
||||
|
||||
AOTCodeCache* AOTCodeCache::_cache = nullptr;
|
||||
|
||||
bool AOTCodeCache::open_cache(bool is_dumping, bool is_using) {
|
||||
AOTCodeCache* cache = new AOTCodeCache(is_dumping, is_using);
|
||||
if (cache->failed()) {
|
||||
delete cache;
|
||||
_cache = nullptr;
|
||||
opened_cache = new AOTCodeCache(is_dumping, is_using);
|
||||
if (opened_cache->failed()) {
|
||||
delete opened_cache;
|
||||
opened_cache = nullptr;
|
||||
return false;
|
||||
}
|
||||
_cache = cache;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -229,6 +240,7 @@ void AOTCodeCache::close() {
|
||||
if (is_on()) {
|
||||
delete _cache; // Free memory
|
||||
_cache = nullptr;
|
||||
opened_cache = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,7 +288,7 @@ AOTCodeCache::AOTCodeCache(bool is_dumping, bool is_using) :
|
||||
log_debug(aot, codecache, init)("Mapped %u bytes at address " INTPTR_FORMAT " at AOT Code Cache", _load_size, p2i(_load_buffer));
|
||||
|
||||
_load_header = (Header*)addr(0);
|
||||
if (!_load_header->verify_config(_load_size)) {
|
||||
if (!_load_header->verify(_load_size)) {
|
||||
set_failed();
|
||||
return;
|
||||
}
|
||||
@ -300,20 +312,6 @@ AOTCodeCache::AOTCodeCache(bool is_dumping, bool is_using) :
|
||||
_table = new AOTCodeAddressTable();
|
||||
}
|
||||
|
||||
void AOTCodeCache::init_extrs_table() {
|
||||
AOTCodeAddressTable* table = addr_table();
|
||||
if (table != nullptr) {
|
||||
table->init_extrs();
|
||||
}
|
||||
}
|
||||
|
||||
void AOTCodeCache::init_early_stubs_table() {
|
||||
AOTCodeAddressTable* table = addr_table();
|
||||
if (table != nullptr) {
|
||||
table->init_early_stubs();
|
||||
}
|
||||
}
|
||||
|
||||
void AOTCodeCache::init_shared_blobs_table() {
|
||||
AOTCodeAddressTable* table = addr_table();
|
||||
if (table != nullptr) {
|
||||
@ -381,11 +379,11 @@ void AOTCodeCache::Config::record() {
|
||||
_compressedOopBase = CompressedOops::base();
|
||||
_compressedKlassShift = CompressedKlassPointers::shift();
|
||||
_contendedPaddingWidth = ContendedPaddingWidth;
|
||||
_objectAlignment = ObjectAlignmentInBytes;
|
||||
_gc = (uint)Universe::heap()->kind();
|
||||
}
|
||||
|
||||
bool AOTCodeCache::Config::verify() const {
|
||||
// First checks affect all cached AOT code
|
||||
#ifdef ASSERT
|
||||
if ((_flags & debugVM) == 0) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created by product VM, it can't be used by debug VM");
|
||||
@ -404,47 +402,24 @@ bool AOTCodeCache::Config::verify() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((_flags & compressedOops) != 0) != UseCompressedOops) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseCompressedOops = %s", UseCompressedOops ? "false" : "true");
|
||||
return false;
|
||||
}
|
||||
if (((_flags & compressedClassPointers) != 0) != UseCompressedClassPointers) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseCompressedClassPointers = %s", UseCompressedClassPointers ? "false" : "true");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((_flags & systemClassAssertions) != 0) != JavaAssertions::systemClassDefault()) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with JavaAssertions::systemClassDefault() = %s", JavaAssertions::systemClassDefault() ? "disabled" : "enabled");
|
||||
return false;
|
||||
}
|
||||
if (((_flags & userClassAssertions) != 0) != JavaAssertions::userClassDefault()) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with JavaAssertions::userClassDefault() = %s", JavaAssertions::userClassDefault() ? "disabled" : "enabled");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((_flags & enableContendedPadding) != 0) != EnableContended) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with EnableContended = %s", EnableContended ? "false" : "true");
|
||||
return false;
|
||||
}
|
||||
if (((_flags & restrictContendedPadding) != 0) != RestrictContended) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with RestrictContended = %s", RestrictContended ? "false" : "true");
|
||||
return false;
|
||||
}
|
||||
if (_compressedOopShift != (uint)CompressedOops::shift()) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with different CompressedOops::shift(): %d vs current %d", _compressedOopShift, CompressedOops::shift());
|
||||
return false;
|
||||
}
|
||||
if (_compressedKlassShift != (uint)CompressedKlassPointers::shift()) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with CompressedKlassPointers::shift() = %d vs current %d", _compressedKlassShift, CompressedKlassPointers::shift());
|
||||
return false;
|
||||
}
|
||||
if (_contendedPaddingWidth != (uint)ContendedPaddingWidth) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with ContendedPaddingWidth = %d vs current %d", _contendedPaddingWidth, ContendedPaddingWidth);
|
||||
return false;
|
||||
|
||||
// The following checks do not affect AOT adapters caching
|
||||
|
||||
if (((_flags & compressedOops) != 0) != UseCompressedOops) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseCompressedOops = %s", UseCompressedOops ? "false" : "true");
|
||||
AOTStubCaching = false;
|
||||
}
|
||||
if (_objectAlignment != (uint)ObjectAlignmentInBytes) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with ObjectAlignmentInBytes = %d vs current %d", _objectAlignment, ObjectAlignmentInBytes);
|
||||
return false;
|
||||
if (_compressedOopShift != (uint)CompressedOops::shift()) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with different CompressedOops::shift(): %d vs current %d", _compressedOopShift, CompressedOops::shift());
|
||||
AOTStubCaching = false;
|
||||
}
|
||||
|
||||
// This should be the last check as it only disables AOTStubCaching
|
||||
@ -456,7 +431,7 @@ bool AOTCodeCache::Config::verify() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AOTCodeCache::Header::verify_config(uint load_size) const {
|
||||
bool AOTCodeCache::Header::verify(uint load_size) const {
|
||||
if (_version != AOT_CODE_VERSION) {
|
||||
log_debug(aot, codecache, init)("AOT Code Cache disabled: different AOT Code version %d vs %d recorded in AOT Code header", AOT_CODE_VERSION, _version);
|
||||
return false;
|
||||
@ -857,6 +832,10 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind
|
||||
#endif /* PRODUCT */
|
||||
|
||||
if (!cache->write_relocations(blob)) {
|
||||
if (!cache->failed()) {
|
||||
// We may miss an address in AOT table - skip this code blob.
|
||||
cache->set_write_position(entry_position);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -985,6 +964,10 @@ CodeBlob* AOTCodeReader::compile_code_blob(const char* name, int entry_offset_co
|
||||
|
||||
// ------------ process code and data --------------
|
||||
|
||||
// Can't use -1. It is valid value for jump to iteself destination
|
||||
// used by static call stub: see NativeJump::jump_destination().
|
||||
#define BAD_ADDRESS_ID -2
|
||||
|
||||
bool AOTCodeCache::write_relocations(CodeBlob& code_blob) {
|
||||
GrowableArray<uint> reloc_data;
|
||||
RelocIterator iter(&code_blob);
|
||||
@ -1001,16 +984,24 @@ bool AOTCodeCache::write_relocations(CodeBlob& code_blob) {
|
||||
if (dest == r->addr()) { // possible call via trampoline on Aarch64
|
||||
dest = (address)-1; // do nothing in this case when loading this relocation
|
||||
}
|
||||
reloc_data.at_put(idx, _table->id_for_address(dest, iter, &code_blob));
|
||||
int id = _table->id_for_address(dest, iter, &code_blob);
|
||||
if (id == BAD_ADDRESS_ID) {
|
||||
return false;
|
||||
}
|
||||
reloc_data.at_put(idx, id);
|
||||
break;
|
||||
}
|
||||
case relocInfo::runtime_call_w_cp_type:
|
||||
fatal("runtime_call_w_cp_type unimplemented");
|
||||
break;
|
||||
log_debug(aot, codecache, reloc)("runtime_call_w_cp_type relocation is not implemented");
|
||||
return false;
|
||||
case relocInfo::external_word_type: {
|
||||
// Record offset of runtime target
|
||||
address target = ((external_word_Relocation*)iter.reloc())->target();
|
||||
reloc_data.at_put(idx, _table->id_for_address(target, iter, &code_blob));
|
||||
int id = _table->id_for_address(target, iter, &code_blob);
|
||||
if (id == BAD_ADDRESS_ID) {
|
||||
return false;
|
||||
}
|
||||
reloc_data.at_put(idx, id);
|
||||
break;
|
||||
}
|
||||
case relocInfo::internal_word_type:
|
||||
@ -1020,7 +1011,8 @@ bool AOTCodeCache::write_relocations(CodeBlob& code_blob) {
|
||||
case relocInfo::post_call_nop_type:
|
||||
break;
|
||||
default:
|
||||
fatal("relocation %d unimplemented", (int)iter.type());
|
||||
log_debug(aot, codecache, reloc)("relocation %d unimplemented", (int)iter.type());
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
if (log.is_enabled()) {
|
||||
@ -1069,7 +1061,8 @@ void AOTCodeReader::fix_relocations(CodeBlob* code_blob) {
|
||||
break;
|
||||
}
|
||||
case relocInfo::runtime_call_w_cp_type:
|
||||
fatal("runtime_call_w_cp_type unimplemented");
|
||||
// this relocation should not be in cache (see write_relocations)
|
||||
assert(false, "runtime_call_w_cp_type relocation is not implemented");
|
||||
break;
|
||||
case relocInfo::external_word_type: {
|
||||
address target = _cache->address_for_id(reloc_data[j]);
|
||||
@ -1095,7 +1088,7 @@ void AOTCodeReader::fix_relocations(CodeBlob* code_blob) {
|
||||
case relocInfo::post_call_nop_type:
|
||||
break;
|
||||
default:
|
||||
fatal("relocation %d unimplemented", (int)iter.type());
|
||||
assert(false,"relocation %d unimplemented", (int)iter.type());
|
||||
break;
|
||||
}
|
||||
if (log.is_enabled()) {
|
||||
@ -1397,9 +1390,13 @@ void AOTCodeAddressTable::init_shared_blobs() {
|
||||
if (_complete || initializing_shared_blobs) return; // Done already
|
||||
initializing_shared_blobs = true;
|
||||
address* blobs_addr = NEW_C_HEAP_ARRAY(address, _blobs_max, mtCode);
|
||||
|
||||
// Divide _shared_blobs_addr array to chunks because they could be initialized in parrallel
|
||||
_shared_blobs_addr = blobs_addr;
|
||||
_C1_blobs_addr = _shared_blobs_addr + _shared_blobs_max;
|
||||
_shared_blobs_length = _C1_blobs_length = 0;
|
||||
|
||||
_shared_blobs_length = 0;
|
||||
_C1_blobs_length = 0;
|
||||
|
||||
// clear the address table
|
||||
memset(blobs_addr, 0, sizeof(address)* _blobs_max);
|
||||
@ -1556,7 +1553,7 @@ const char* AOTCodeAddressTable::add_C_string(const char* str) {
|
||||
}
|
||||
return dup;
|
||||
} else {
|
||||
fatal("Number of C strings >= MAX_STR_COUNT");
|
||||
assert(false, "Number of C strings >= MAX_STR_COUNT");
|
||||
}
|
||||
}
|
||||
return str;
|
||||
@ -1595,13 +1592,11 @@ static int search_address(address addr, address* table, uint length) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return BAD_ADDRESS_ID;
|
||||
}
|
||||
|
||||
address AOTCodeAddressTable::address_for_id(int idx) {
|
||||
if (!_extrs_complete) {
|
||||
fatal("AOT Code Cache VM runtime addresses table is not complete");
|
||||
}
|
||||
assert(_extrs_complete, "AOT Code Cache VM runtime addresses table is not complete");
|
||||
if (idx == -1) {
|
||||
return (address)-1;
|
||||
}
|
||||
@ -1612,6 +1607,7 @@ address AOTCodeAddressTable::address_for_id(int idx) {
|
||||
}
|
||||
if (idx < 0) {
|
||||
fatal("Incorrect id %d for AOT Code Cache addresses table", id);
|
||||
return nullptr;
|
||||
}
|
||||
// no need to compare unsigned id against 0
|
||||
if (/* id >= _extrs_base && */ id < _extrs_length) {
|
||||
@ -1634,9 +1630,7 @@ address AOTCodeAddressTable::address_for_id(int idx) {
|
||||
}
|
||||
|
||||
int AOTCodeAddressTable::id_for_address(address addr, RelocIterator reloc, CodeBlob* code_blob) {
|
||||
if (!_extrs_complete) {
|
||||
fatal("AOT Code Cache VM runtime addresses table is not complete");
|
||||
}
|
||||
assert(_extrs_complete, "AOT Code Cache VM runtime addresses table is not complete");
|
||||
int id = -1;
|
||||
if (addr == (address)-1) { // Static call stub has jump to itself
|
||||
return id;
|
||||
@ -1655,7 +1649,7 @@ int AOTCodeAddressTable::id_for_address(address addr, RelocIterator reloc, CodeB
|
||||
desc = StubCodeDesc::desc_for(addr + frame::pc_return_offset);
|
||||
}
|
||||
const char* sub_name = (desc != nullptr) ? desc->name() : "<unknown>";
|
||||
fatal("Address " INTPTR_FORMAT " for Stub:%s is missing in AOT Code Cache addresses table", p2i(addr), sub_name);
|
||||
assert(false, "Address " INTPTR_FORMAT " for Stub:%s is missing in AOT Code Cache addresses table", p2i(addr), sub_name);
|
||||
} else {
|
||||
return id + _stubs_base;
|
||||
}
|
||||
@ -1666,7 +1660,7 @@ int AOTCodeAddressTable::id_for_address(address addr, RelocIterator reloc, CodeB
|
||||
int id_base = _shared_blobs_base;
|
||||
id = search_address(addr, _shared_blobs_addr, _blobs_max);
|
||||
if (id < 0) {
|
||||
fatal("Address " INTPTR_FORMAT " for Blob:%s is missing in AOT Code Cache addresses table", p2i(addr), cb->name());
|
||||
assert(false, "Address " INTPTR_FORMAT " for Blob:%s is missing in AOT Code Cache addresses table", p2i(addr), cb->name());
|
||||
} else {
|
||||
return id_base + id;
|
||||
}
|
||||
@ -1687,16 +1681,20 @@ int AOTCodeAddressTable::id_for_address(address addr, RelocIterator reloc, CodeB
|
||||
assert(dist > (uint)(_all_max + MAX_STR_COUNT), "change encoding of distance");
|
||||
return dist;
|
||||
}
|
||||
#ifdef ASSERT
|
||||
reloc.print_current_on(tty);
|
||||
code_blob->print_on(tty);
|
||||
code_blob->print_code_on(tty);
|
||||
fatal("Address " INTPTR_FORMAT " for runtime target '%s+%d' is missing in AOT Code Cache addresses table", p2i(addr), func_name, offset);
|
||||
assert(false, "Address " INTPTR_FORMAT " for runtime target '%s+%d' is missing in AOT Code Cache addresses table", p2i(addr), func_name, offset);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ASSERT
|
||||
reloc.print_current_on(tty);
|
||||
code_blob->print_on(tty);
|
||||
code_blob->print_code_on(tty);
|
||||
os::find(addr, tty);
|
||||
fatal("Address " INTPTR_FORMAT " for <unknown>/('%s') is missing in AOT Code Cache addresses table", p2i(addr), (const char*)addr);
|
||||
assert(false, "Address " INTPTR_FORMAT " for <unknown>/('%s') is missing in AOT Code Cache addresses table", p2i(addr), (const char*)addr);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
return _extrs_base + id;
|
||||
|
||||
@ -169,7 +169,6 @@ protected:
|
||||
uint _compressedOopShift;
|
||||
uint _compressedKlassShift;
|
||||
uint _contendedPaddingWidth;
|
||||
uint _objectAlignment;
|
||||
uint _gc;
|
||||
enum Flags {
|
||||
none = 0,
|
||||
@ -206,7 +205,7 @@ protected:
|
||||
uint _C2_blobs_count;
|
||||
Config _config;
|
||||
|
||||
public:
|
||||
public:
|
||||
void init(uint cache_size,
|
||||
uint strings_count, uint strings_offset,
|
||||
uint entries_count, uint entries_offset,
|
||||
@ -236,8 +235,8 @@ public:
|
||||
uint C1_blobs_count() const { return _C1_blobs_count; }
|
||||
uint C2_blobs_count() const { return _C2_blobs_count; }
|
||||
|
||||
bool verify_config(uint load_size) const;
|
||||
bool verify_vm_config() const { // Called after Universe initialized
|
||||
bool verify(uint load_size) const;
|
||||
bool verify_config() const { // Called after Universe initialized
|
||||
return _config.verify();
|
||||
}
|
||||
};
|
||||
@ -298,8 +297,6 @@ public:
|
||||
void load_strings();
|
||||
int store_strings();
|
||||
|
||||
static void init_extrs_table() NOT_CDS_RETURN;
|
||||
static void init_early_stubs_table() NOT_CDS_RETURN;
|
||||
static void init_shared_blobs_table() NOT_CDS_RETURN;
|
||||
static void init_early_c1_table() NOT_CDS_RETURN;
|
||||
|
||||
@ -352,9 +349,9 @@ private:
|
||||
static AOTCodeCache* _cache;
|
||||
|
||||
static bool open_cache(bool is_dumping, bool is_using);
|
||||
static bool verify_vm_config() {
|
||||
if (is_on_for_use()) {
|
||||
return _cache->_load_header->verify_vm_config();
|
||||
bool verify_config() {
|
||||
if (for_use()) {
|
||||
return _load_header->verify_config();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user