Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8305066: [JVMCI] guarantee(ik->is_initialized()) failed: java/lang/Lo…
…ng$LongCache must be initialized

Reviewed-by: never, iveresov
  • Loading branch information
Doug Simon committed Mar 31, 2023
1 parent fe42312 commit e012685
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 32 deletions.
68 changes: 47 additions & 21 deletions src/hotspot/share/runtime/deoptimization.cpp
Expand Up @@ -1056,8 +1056,10 @@ class BoxCacheBase : public CHeapObj<mtCompiler> {
char* klass_name_str = klass_name->as_C_string();
InstanceKlass* ik = SystemDictionary::find_instance_klass(thread, klass_name, Handle(), Handle());
guarantee(ik != nullptr, "%s must be loaded", klass_name_str);
guarantee(ik->is_initialized(), "%s must be initialized", klass_name_str);
CacheType::compute_offsets(ik);
if (!ik->is_in_error_state()) {
guarantee(ik->is_initialized(), "%s must be initialized", klass_name_str);
CacheType::compute_offsets(ik);
}
return ik;
}
};
Expand All @@ -1070,11 +1072,17 @@ template<typename PrimitiveType, typename CacheType, typename BoxType> class Box
static BoxCache<PrimitiveType, CacheType, BoxType> *_singleton;
BoxCache(Thread* thread) {
InstanceKlass* ik = BoxCacheBase<CacheType>::find_cache_klass(thread, CacheType::symbol());
objArrayOop cache = CacheType::cache(ik);
assert(cache->length() > 0, "Empty cache");
_low = BoxType::value(cache->obj_at(0));
_high = _low + cache->length() - 1;
_cache = JNIHandles::make_global(Handle(thread, cache));
if (ik->is_in_error_state()) {
_low = 1;
_high = 0;
_cache = nullptr;
} else {
objArrayOop cache = CacheType::cache(ik);
assert(cache->length() > 0, "Empty cache");
_low = BoxType::value(cache->obj_at(0));
_high = _low + cache->length() - 1;
_cache = JNIHandles::make_global(Handle(thread, cache));
}
}
~BoxCache() {
JNIHandles::destroy_global(_cache);
Expand All @@ -1096,7 +1104,11 @@ template<typename PrimitiveType, typename CacheType, typename BoxType> class Box
}
return nullptr;
}
oop lookup_raw(intptr_t raw_value) {
oop lookup_raw(intptr_t raw_value, bool& cache_init_error) {
if (_cache == nullptr) {
cache_init_error = true;
return nullptr;
}
// Have to cast to avoid little/big-endian problems.
if (sizeof(PrimitiveType) > sizeof(jint)) {
jlong value = (jlong)raw_value;
Expand Down Expand Up @@ -1126,8 +1138,13 @@ class BooleanBoxCache : public BoxCacheBase<java_lang_Boolean> {
static BooleanBoxCache *_singleton;
BooleanBoxCache(Thread *thread) {
InstanceKlass* ik = find_cache_klass(thread, java_lang_Boolean::symbol());
_true_cache = JNIHandles::make_global(Handle(thread, java_lang_Boolean::get_TRUE(ik)));
_false_cache = JNIHandles::make_global(Handle(thread, java_lang_Boolean::get_FALSE(ik)));
if (ik->is_in_error_state()) {
_true_cache = nullptr;
_false_cache = nullptr;
} else {
_true_cache = JNIHandles::make_global(Handle(thread, java_lang_Boolean::get_TRUE(ik)));
_false_cache = JNIHandles::make_global(Handle(thread, java_lang_Boolean::get_FALSE(ik)));
}
}
~BooleanBoxCache() {
JNIHandles::destroy_global(_true_cache);
Expand All @@ -1143,7 +1160,11 @@ class BooleanBoxCache : public BoxCacheBase<java_lang_Boolean> {
}
return _singleton;
}
oop lookup_raw(intptr_t raw_value) {
oop lookup_raw(intptr_t raw_value, bool& cache_in_error) {
if (_true_cache == nullptr) {
cache_in_error = true;
return nullptr;
}
// Have to cast to avoid little/big-endian problems.
jboolean value = (jboolean)*((jint*)&raw_value);
return lookup(value);
Expand All @@ -1158,18 +1179,18 @@ class BooleanBoxCache : public BoxCacheBase<java_lang_Boolean> {

BooleanBoxCache* BooleanBoxCache::_singleton = nullptr;

oop Deoptimization::get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMap* reg_map, TRAPS) {
oop Deoptimization::get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMap* reg_map, bool& cache_init_error, TRAPS) {
Klass* k = java_lang_Class::as_Klass(bv->klass()->as_ConstantOopReadValue()->value()());
BasicType box_type = vmClasses::box_klass_type(k);
if (box_type != T_OBJECT) {
StackValue* value = StackValue::create_stack_value(fr, reg_map, bv->field_at(box_type == T_LONG ? 1 : 0));
switch(box_type) {
case T_INT: return IntegerBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
case T_CHAR: return CharacterBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
case T_SHORT: return ShortBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
case T_BYTE: return ByteBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
case T_BOOLEAN: return BooleanBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
case T_LONG: return LongBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
case T_INT: return IntegerBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_CHAR: return CharacterBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_SHORT: return ShortBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_BYTE: return ByteBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_BOOLEAN: return BooleanBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_LONG: return LongBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
default:;
}
}
Expand All @@ -1193,21 +1214,26 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap*
Klass* k = java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()());
oop obj = nullptr;

bool cache_init_error = false;
if (k->is_instance_klass()) {
#if INCLUDE_JVMCI
CompiledMethod* cm = fr->cb()->as_compiled_method_or_null();
if (cm->is_compiled_by_jvmci() && sv->is_auto_box()) {
AutoBoxObjectValue* abv = (AutoBoxObjectValue*) sv;
obj = get_cached_box(abv, fr, reg_map, THREAD);
obj = get_cached_box(abv, fr, reg_map, cache_init_error, THREAD);
if (obj != nullptr) {
// Set the flag to indicate the box came from a cache, so that we can skip the field reassignment for it.
abv->set_cached(true);
} else if (cache_init_error) {
// Results in an OOME which is valid (as opposed to a class initialization error)
// and is fine for the rare case a cache initialization failing.
failures = true;
}
}
#endif // INCLUDE_JVMCI

InstanceKlass* ik = InstanceKlass::cast(k);
if (obj == nullptr) {
if (obj == nullptr && !cache_init_error) {
#ifdef COMPILER2
if (EnableVectorSupport && VectorSupport::is_vector(ik)) {
obj = VectorSupport::allocate_vector(ik, fr, reg_map, sv, THREAD);
Expand All @@ -1233,7 +1259,7 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap*
}

assert(sv->value().is_null(), "redundant reallocation");
assert(obj != nullptr || HAS_PENDING_EXCEPTION, "allocation should succeed or we should get an exception");
assert(obj != nullptr || HAS_PENDING_EXCEPTION || cache_init_error, "allocation should succeed or we should get an exception");
CLEAR_PENDING_EXCEPTION;
sv->set_value(obj);
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/runtime/deoptimization.hpp
Expand Up @@ -185,7 +185,7 @@ class Deoptimization : AllStatic {

#if INCLUDE_JVMCI
static address deoptimize_for_missing_exception_handler(CompiledMethod* cm);
static oop get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMap* reg_map, TRAPS);
static oop get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMap* reg_map, bool& cache_init_error, TRAPS);
#endif

private:
Expand Down
Expand Up @@ -74,7 +74,7 @@ public static VirtualObject get(ResolvedJavaType type, int id) {
* @param id a unique id that identifies the object within the debug information for one
* position in the compiled code.
* @param isAutoBox a flag that tells the runtime that the object may be a boxed primitive and
* that it possibly needs to be obtained for the box cache instead of creating a new
* that it possibly needs to be obtained from the box cache instead of creating a new
* instance.
* @return a new {@link VirtualObject} instance.
*/
Expand Down
Expand Up @@ -192,15 +192,6 @@ public static HotSpotJVMCIRuntime runtime() {
// initialized.
JVMCI.getRuntime();
}
// Make sure all the primitive box caches are populated (required to properly
// materialize boxed primitives
// during deoptimization).
Boolean.valueOf(false);
Byte.valueOf((byte) 0);
Short.valueOf((short) 0);
Character.valueOf((char) 0);
Integer.valueOf(0);
Long.valueOf(0);
}
}
return result;
Expand Down

1 comment on commit e012685

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.