mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 10:34:38 +02:00
8223320: [AOT] jck test api/javax_script/ScriptEngine/PutGet.html fails when test classes are AOTed
Materialization of primitive boxes should use caches Reviewed-by: kvn, never
This commit is contained in:
parent
7d63888ac8
commit
e47daab7b4
18 changed files with 666 additions and 26 deletions
|
@ -50,7 +50,10 @@
|
|||
#include "runtime/biasedLocking.hpp"
|
||||
#include "runtime/compilationPolicy.hpp"
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/fieldDescriptor.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "runtime/frame.inline.hpp"
|
||||
#include "runtime/jniHandles.inline.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
|
@ -232,7 +235,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
|||
}
|
||||
if (objects != NULL) {
|
||||
JRT_BLOCK
|
||||
realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD);
|
||||
realloc_failures = realloc_objects(thread, &deoptee, &map, objects, THREAD);
|
||||
JRT_END
|
||||
bool skip_internal = (cm != NULL) && !cm->is_compiled_by_jvmci();
|
||||
reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal);
|
||||
|
@ -810,8 +813,131 @@ void Deoptimization::deoptimize_all_marked() {
|
|||
Deoptimization::DeoptAction Deoptimization::_unloaded_action
|
||||
= Deoptimization::Action_reinterpret;
|
||||
|
||||
|
||||
|
||||
#if INCLUDE_JVMCI || INCLUDE_AOT
|
||||
template<typename CacheType>
|
||||
class BoxCacheBase : public CHeapObj<mtCompiler> {
|
||||
protected:
|
||||
static InstanceKlass* find_cache_klass(Symbol* klass_name, TRAPS) {
|
||||
ResourceMark rm;
|
||||
char* klass_name_str = klass_name->as_C_string();
|
||||
Klass* k = SystemDictionary::find(klass_name, Handle(), Handle(), THREAD);
|
||||
guarantee(k != NULL, "%s must be loaded", klass_name_str);
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
guarantee(ik->is_initialized(), "%s must be initialized", klass_name_str);
|
||||
CacheType::compute_offsets(ik);
|
||||
return ik;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PrimitiveType, typename CacheType, typename BoxType> class BoxCache : public BoxCacheBase<CacheType> {
|
||||
PrimitiveType _low;
|
||||
PrimitiveType _high;
|
||||
jobject _cache;
|
||||
protected:
|
||||
static BoxCache<PrimitiveType, CacheType, BoxType> *_singleton;
|
||||
BoxCache(Thread* thread) {
|
||||
InstanceKlass* ik = BoxCacheBase<CacheType>::find_cache_klass(CacheType::symbol(), thread);
|
||||
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);
|
||||
}
|
||||
public:
|
||||
static BoxCache<PrimitiveType, CacheType, BoxType>* singleton(Thread* thread) {
|
||||
if (_singleton == NULL) {
|
||||
BoxCache<PrimitiveType, CacheType, BoxType>* s = new BoxCache<PrimitiveType, CacheType, BoxType>(thread);
|
||||
if (!Atomic::replace_if_null(s, &_singleton)) {
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
return _singleton;
|
||||
}
|
||||
oop lookup(PrimitiveType value) {
|
||||
if (_low <= value && value <= _high) {
|
||||
int offset = value - _low;
|
||||
return objArrayOop(JNIHandles::resolve_non_null(_cache))->obj_at(offset);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
typedef BoxCache<jint, java_lang_Integer_IntegerCache, java_lang_Integer> IntegerBoxCache;
|
||||
typedef BoxCache<jlong, java_lang_Long_LongCache, java_lang_Long> LongBoxCache;
|
||||
typedef BoxCache<jchar, java_lang_Character_CharacterCache, java_lang_Character> CharacterBoxCache;
|
||||
typedef BoxCache<jshort, java_lang_Short_ShortCache, java_lang_Short> ShortBoxCache;
|
||||
typedef BoxCache<jbyte, java_lang_Byte_ByteCache, java_lang_Byte> ByteBoxCache;
|
||||
|
||||
template<> BoxCache<jint, java_lang_Integer_IntegerCache, java_lang_Integer>* BoxCache<jint, java_lang_Integer_IntegerCache, java_lang_Integer>::_singleton = NULL;
|
||||
template<> BoxCache<jlong, java_lang_Long_LongCache, java_lang_Long>* BoxCache<jlong, java_lang_Long_LongCache, java_lang_Long>::_singleton = NULL;
|
||||
template<> BoxCache<jchar, java_lang_Character_CharacterCache, java_lang_Character>* BoxCache<jchar, java_lang_Character_CharacterCache, java_lang_Character>::_singleton = NULL;
|
||||
template<> BoxCache<jshort, java_lang_Short_ShortCache, java_lang_Short>* BoxCache<jshort, java_lang_Short_ShortCache, java_lang_Short>::_singleton = NULL;
|
||||
template<> BoxCache<jbyte, java_lang_Byte_ByteCache, java_lang_Byte>* BoxCache<jbyte, java_lang_Byte_ByteCache, java_lang_Byte>::_singleton = NULL;
|
||||
|
||||
class BooleanBoxCache : public BoxCacheBase<java_lang_Boolean> {
|
||||
jobject _true_cache;
|
||||
jobject _false_cache;
|
||||
protected:
|
||||
static BooleanBoxCache *_singleton;
|
||||
BooleanBoxCache(Thread *thread) {
|
||||
InstanceKlass* ik = find_cache_klass(java_lang_Boolean::symbol(), thread);
|
||||
_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);
|
||||
JNIHandles::destroy_global(_false_cache);
|
||||
}
|
||||
public:
|
||||
static BooleanBoxCache* singleton(Thread* thread) {
|
||||
if (_singleton == NULL) {
|
||||
BooleanBoxCache* s = new BooleanBoxCache(thread);
|
||||
if (!Atomic::replace_if_null(s, &_singleton)) {
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
return _singleton;
|
||||
}
|
||||
oop lookup(jboolean value) {
|
||||
if (value != 0) {
|
||||
return JNIHandles::resolve_non_null(_true_cache);
|
||||
}
|
||||
return JNIHandles::resolve_non_null(_false_cache);
|
||||
}
|
||||
};
|
||||
|
||||
BooleanBoxCache* BooleanBoxCache::_singleton = NULL;
|
||||
|
||||
oop Deoptimization::get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMap* reg_map, TRAPS) {
|
||||
Klass* k = java_lang_Class::as_Klass(bv->klass()->as_ConstantOopReadValue()->value()());
|
||||
BasicType box_type = SystemDictionary::box_klass_type(k);
|
||||
if (box_type != T_OBJECT) {
|
||||
StackValue* value = StackValue::create_stack_value(fr, reg_map, bv->field_at(0));
|
||||
switch(box_type) {
|
||||
case T_INT: return IntegerBoxCache::singleton(THREAD)->lookup(value->get_int());
|
||||
case T_LONG: {
|
||||
StackValue* low = StackValue::create_stack_value(fr, reg_map, bv->field_at(1));
|
||||
jlong res = (jlong)low->get_int();
|
||||
return LongBoxCache::singleton(THREAD)->lookup(res);
|
||||
}
|
||||
case T_CHAR: return CharacterBoxCache::singleton(THREAD)->lookup(value->get_int());
|
||||
case T_SHORT: return ShortBoxCache::singleton(THREAD)->lookup(value->get_int());
|
||||
case T_BYTE: return ByteBoxCache::singleton(THREAD)->lookup(value->get_int());
|
||||
case T_BOOLEAN: return BooleanBoxCache::singleton(THREAD)->lookup(value->get_int());
|
||||
default:;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif // INCLUDE_JVMCI || INCLUDE_AOT
|
||||
|
||||
#if COMPILER2_OR_JVMCI
|
||||
bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS) {
|
||||
bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, TRAPS) {
|
||||
Handle pending_exception(THREAD, thread->pending_exception());
|
||||
const char* exception_file = thread->exception_file();
|
||||
int exception_line = thread->exception_line();
|
||||
|
@ -827,8 +953,21 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArra
|
|||
oop obj = NULL;
|
||||
|
||||
if (k->is_instance_klass()) {
|
||||
#if INCLUDE_JVMCI || INCLUDE_AOT
|
||||
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);
|
||||
if (obj != NULL) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_JVMCI || INCLUDE_AOT
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
obj = ik->allocate_instance(THREAD);
|
||||
if (obj == NULL) {
|
||||
obj = ik->allocate_instance(THREAD);
|
||||
}
|
||||
} else if (k->is_typeArray_klass()) {
|
||||
TypeArrayKlass* ak = TypeArrayKlass::cast(k);
|
||||
assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length");
|
||||
|
@ -1101,7 +1240,12 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr
|
|||
if (obj.is_null()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMCI || INCLUDE_AOT
|
||||
// Don't reassign fields of boxes that came from a cache. Caches may be in CDS.
|
||||
if (sv->is_auto_box() && ((AutoBoxObjectValue*) sv)->is_cached()) {
|
||||
continue;
|
||||
}
|
||||
#endif // INCLUDE_JVMCI || INCLUDE_AOT
|
||||
if (k->is_instance_klass()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), skip_internal);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue