--- a/src/hotspot/share/runtime/deoptimization.cpp Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/runtime/deoptimization.cpp Thu Oct 17 20:53:35 2019 +0100
@@ -31,6 +31,7 @@
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "code/scopeDesc.hpp"
+#include "compiler/compilationPolicy.hpp"
#include "interpreter/bytecode.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/oopMapCache.hpp"
@@ -48,9 +49,11 @@
#include "oops/verifyOopClosure.hpp"
#include "prims/jvmtiThreadState.hpp"
#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"
@@ -154,6 +157,92 @@
return fetch_unroll_info_helper(thread, exec_mode);
JRT_END
+#if COMPILER2_OR_JVMCI
+static bool eliminate_allocations(JavaThread* thread, int exec_mode, CompiledMethod* compiled_method,
+ frame& deoptee, RegisterMap& map, GrowableArray<compiledVFrame*>* chunk) {
+ bool realloc_failures = false;
+ assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames");
+
+ GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
+
+ // The flag return_oop() indicates call sites which return oop
+ // in compiled code. Such sites include java method calls,
+ // runtime calls (for example, used to allocate new objects/arrays
+ // on slow code path) and any other calls generated in compiled code.
+ // It is not guaranteed that we can get such information here only
+ // by analyzing bytecode in deoptimized frames. This is why this flag
+ // is set during method compilation (see Compile::Process_OopMap_Node()).
+ // If the previous frame was popped or if we are dispatching an exception,
+ // we don't have an oop result.
+ bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution() && (exec_mode == Deoptimization::Unpack_deopt);
+ Handle return_value;
+ if (save_oop_result) {
+ // Reallocation may trigger GC. If deoptimization happened on return from
+ // call which returns oop we need to save it since it is not in oopmap.
+ oop result = deoptee.saved_oop_result(&map);
+ assert(oopDesc::is_oop_or_null(result), "must be oop");
+ return_value = Handle(thread, result);
+ assert(Universe::heap()->is_in_or_null(result), "must be heap pointer");
+ if (TraceDeoptimization) {
+ ttyLocker ttyl;
+ tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, p2i(result), p2i(thread));
+ }
+ }
+ if (objects != NULL) {
+ JRT_BLOCK
+ realloc_failures = Deoptimization::realloc_objects(thread, &deoptee, &map, objects, THREAD);
+ JRT_END
+ bool skip_internal = (compiled_method != NULL) && !compiled_method->is_compiled_by_jvmci();
+ Deoptimization::reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal);
+#ifndef PRODUCT
+ if (TraceDeoptimization) {
+ ttyLocker ttyl;
+ tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, p2i(thread));
+ Deoptimization::print_objects(objects, realloc_failures);
+ }
+#endif
+ }
+ if (save_oop_result) {
+ // Restore result.
+ deoptee.set_saved_oop_result(&map, return_value());
+ }
+ return realloc_failures;
+}
+
+static void eliminate_locks(JavaThread* thread, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
+#ifndef PRODUCT
+ bool first = true;
+#endif
+ for (int i = 0; i < chunk->length(); i++) {
+ compiledVFrame* cvf = chunk->at(i);
+ assert (cvf->scope() != NULL,"expect only compiled java frames");
+ GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
+ if (monitors->is_nonempty()) {
+ Deoptimization::relock_objects(monitors, thread, realloc_failures);
+#ifndef PRODUCT
+ if (PrintDeoptimizationDetails) {
+ ttyLocker ttyl;
+ for (int j = 0; j < monitors->length(); j++) {
+ MonitorInfo* mi = monitors->at(j);
+ if (mi->eliminated()) {
+ if (first) {
+ first = false;
+ tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, p2i(thread));
+ }
+ if (mi->owner_is_scalar_replaced()) {
+ Klass* k = java_lang_Class::as_Klass(mi->owner_klass());
+ tty->print_cr(" failed reallocation for klass %s", k->external_name());
+ } else {
+ tty->print_cr(" object <" INTPTR_FORMAT "> locked", p2i(mi->owner()));
+ }
+ }
+ }
+ }
+#endif // !PRODUCT
+ }
+ }
+}
+#endif // COMPILER2_OR_JVMCI
// This is factored, since it is both called from a JRT_LEAF (deoptimization) and a JRT_ENTRY (uncommon_trap)
Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread* thread, int exec_mode) {
@@ -198,95 +287,33 @@
bool realloc_failures = false;
#if COMPILER2_OR_JVMCI
+#if INCLUDE_JVMCI
+ bool jvmci_enabled = true;
+#else
+ bool jvmci_enabled = false;
+#endif
+
// Reallocate the non-escaping objects and restore their fields. Then
// relock objects if synchronization on them was eliminated.
-#if !INCLUDE_JVMCI
- if (DoEscapeAnalysis || EliminateNestedLocks) {
- if (EliminateAllocations) {
-#endif // INCLUDE_JVMCI
- assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames");
- GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
+ if (jvmci_enabled || (DoEscapeAnalysis && EliminateAllocations)) {
+ realloc_failures = eliminate_allocations(thread, exec_mode, cm, deoptee, map, chunk);
+ }
+#endif // COMPILER2_OR_JVMCI
+
+ // Revoke biases, done with in java state.
+ // No safepoints allowed after this
+ revoke_from_deopt_handler(thread, deoptee, &map);
- // The flag return_oop() indicates call sites which return oop
- // in compiled code. Such sites include java method calls,
- // runtime calls (for example, used to allocate new objects/arrays
- // on slow code path) and any other calls generated in compiled code.
- // It is not guaranteed that we can get such information here only
- // by analyzing bytecode in deoptimized frames. This is why this flag
- // is set during method compilation (see Compile::Process_OopMap_Node()).
- // If the previous frame was popped or if we are dispatching an exception,
- // we don't have an oop result.
- bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution() && (exec_mode == Unpack_deopt);
- Handle return_value;
- if (save_oop_result) {
- // Reallocation may trigger GC. If deoptimization happened on return from
- // call which returns oop we need to save it since it is not in oopmap.
- oop result = deoptee.saved_oop_result(&map);
- assert(oopDesc::is_oop_or_null(result), "must be oop");
- return_value = Handle(thread, result);
- assert(Universe::heap()->is_in_or_null(result), "must be heap pointer");
- if (TraceDeoptimization) {
- ttyLocker ttyl;
- tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, p2i(result), p2i(thread));
- }
- }
- if (objects != NULL) {
- JRT_BLOCK
- realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD);
- JRT_END
- bool skip_internal = (cm != NULL) && !cm->is_compiled_by_jvmci();
- reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal);
-#ifndef PRODUCT
- if (TraceDeoptimization) {
- ttyLocker ttyl;
- tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, p2i(thread));
- print_objects(objects, realloc_failures);
- }
-#endif
- }
- if (save_oop_result) {
- // Restore result.
- deoptee.set_saved_oop_result(&map, return_value());
- }
-#if !INCLUDE_JVMCI
- }
- if (EliminateLocks) {
-#endif // INCLUDE_JVMCI
-#ifndef PRODUCT
- bool first = true;
-#endif
- for (int i = 0; i < chunk->length(); i++) {
- compiledVFrame* cvf = chunk->at(i);
- assert (cvf->scope() != NULL,"expect only compiled java frames");
- GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
- if (monitors->is_nonempty()) {
- relock_objects(monitors, thread, realloc_failures);
-#ifndef PRODUCT
- if (PrintDeoptimizationDetails) {
- ttyLocker ttyl;
- for (int j = 0; j < monitors->length(); j++) {
- MonitorInfo* mi = monitors->at(j);
- if (mi->eliminated()) {
- if (first) {
- first = false;
- tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, p2i(thread));
- }
- if (mi->owner_is_scalar_replaced()) {
- Klass* k = java_lang_Class::as_Klass(mi->owner_klass());
- tty->print_cr(" failed reallocation for klass %s", k->external_name());
- } else {
- tty->print_cr(" object <" INTPTR_FORMAT "> locked", p2i(mi->owner()));
- }
- }
- }
- }
-#endif // !PRODUCT
- }
- }
-#if !INCLUDE_JVMCI
- }
+ // Ensure that no safepoint is taken after pointers have been stored
+ // in fields of rematerialized objects. If a safepoint occurs from here on
+ // out the java state residing in the vframeArray will be missed.
+ // Locks may be rebaised in a safepoint.
+ NoSafepointVerifier no_safepoint;
+
+#if COMPILER2_OR_JVMCI
+ if (jvmci_enabled || ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateLocks)) {
+ eliminate_locks(thread, chunk, realloc_failures);
}
-#endif // INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
ScopeDesc* trap_scope = chunk->at(0)->scope();
@@ -302,11 +329,6 @@
guarantee(exceptionObject() != NULL, "exception oop can not be null");
}
- // Ensure that no safepoint is taken after pointers have been stored
- // in fields of rematerialized objects. If a safepoint occurs from here on
- // out the java state residing in the vframeArray will be missed.
- NoSafepointVerifier no_safepoint;
-
vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures);
#if COMPILER2_OR_JVMCI
if (realloc_failures) {
@@ -629,7 +651,7 @@
p2i(thread), p2i(array), exec_mode);
}
#endif
- Events::log(thread, "DEOPT UNPACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT " mode %d",
+ Events::log_deopt_message(thread, "DEOPT UNPACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT " mode %d",
p2i(stub_frame.pc()), p2i(stub_frame.sp()), exec_mode);
UnrollBlock* info = array->unroll_block();
@@ -777,13 +799,11 @@
JRT_END
class DeoptimizeMarkedTC : public ThreadClosure {
- bool _in_handshake;
public:
- DeoptimizeMarkedTC(bool in_handshake) : _in_handshake(in_handshake) {}
virtual void do_thread(Thread* thread) {
assert(thread->is_Java_thread(), "must be");
JavaThread* jt = (JavaThread*)thread;
- jt->deoptimize_marked_methods(_in_handshake);
+ jt->deoptimize_marked_methods();
}
};
@@ -792,7 +812,7 @@
DeoptimizationMarker dm;
if (SafepointSynchronize::is_at_safepoint()) {
- DeoptimizeMarkedTC deopt(false);
+ DeoptimizeMarkedTC deopt;
// Make the dependent methods not entrant
CodeCache::make_marked_nmethods_not_entrant();
Threads::java_threads_do(&deopt);
@@ -802,7 +822,7 @@
MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
CodeCache::make_marked_nmethods_not_entrant();
}
- DeoptimizeMarkedTC deopt(true);
+ DeoptimizeMarkedTC deopt;
Handshake::execute(&deopt);
}
}
@@ -810,8 +830,141 @@
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;
+ }
+ oop lookup_raw(intptr_t raw_value) {
+ // Have to cast to avoid little/big-endian problems.
+ if (sizeof(PrimitiveType) > sizeof(jint)) {
+ jlong value = (jlong)raw_value;
+ return lookup(value);
+ }
+ PrimitiveType value = (PrimitiveType)*((jint*)&raw_value);
+ return lookup(value);
+ }
+};
+
+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_raw(intptr_t raw_value) {
+ // Have to cast to avoid little/big-endian problems.
+ jboolean value = (jboolean)*((jint*)&raw_value);
+ return lookup(value);
+ }
+ 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(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());
+ 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 +980,21 @@
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 +1267,12 @@
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);
@@ -1123,19 +1294,19 @@
assert(!mon_info->owner_is_scalar_replaced() || realloc_failures, "reallocation was missed");
if (!mon_info->owner_is_scalar_replaced()) {
Handle obj(thread, mon_info->owner());
- markOop mark = obj->mark();
- if (UseBiasedLocking && mark->has_bias_pattern()) {
+ markWord mark = obj->mark();
+ if (UseBiasedLocking && mark.has_bias_pattern()) {
// New allocated objects may have the mark set to anonymously biased.
// Also the deoptimized method may called methods with synchronization
// where the thread-local object is bias locked to the current thread.
- assert(mark->is_biased_anonymously() ||
- mark->biased_locker() == thread, "should be locked to current thread");
+ assert(mark.is_biased_anonymously() ||
+ mark.biased_locker() == thread, "should be locked to current thread");
// Reset mark word to unbiased prototype.
- markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
+ markWord unbiased_prototype = markWord::prototype().set_age(mark.age());
obj->set_mark(unbiased_prototype);
}
BasicLock* lock = mon_info->lock();
- ObjectSynchronizer::slow_enter(obj, lock, thread);
+ ObjectSynchronizer::enter(obj, lock, thread);
assert(mon_info->owner()->is_locked(), "object must be locked now");
}
}
@@ -1172,7 +1343,7 @@
#endif // COMPILER2_OR_JVMCI
vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
- Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, p2i(fr.pc()), p2i(fr.sp()));
+ Events::log_deopt_message(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, p2i(fr.pc()), p2i(fr.sp()));
#ifndef PRODUCT
if (PrintDeoptimizationDetails) {
@@ -1245,7 +1416,7 @@
for (int j = 0; j < monitors->number_of_monitors(); j++) {
BasicObjectLock* src = monitors->at(j);
if (src->obj() != NULL) {
- ObjectSynchronizer::fast_exit(src->obj(), src->lock(), thread);
+ ObjectSynchronizer::exit(src->obj(), src->lock(), thread);
}
}
array->element(i)->free_monitors(thread);
@@ -1294,21 +1465,7 @@
collect_monitors(cvf, objects_to_revoke);
}
-void Deoptimization::revoke_using_safepoint(JavaThread* thread, frame fr, RegisterMap* map) {
- if (!UseBiasedLocking) {
- return;
- }
- GrowableArray<Handle>* objects_to_revoke = new GrowableArray<Handle>();
- get_monitors_from_stack(objects_to_revoke, thread, fr, map);
-
- if (SafepointSynchronize::is_at_safepoint()) {
- BiasedLocking::revoke_at_safepoint(objects_to_revoke);
- } else {
- BiasedLocking::revoke(objects_to_revoke);
- }
-}
-
-void Deoptimization::revoke_using_handshake(JavaThread* thread, frame fr, RegisterMap* map) {
+void Deoptimization::revoke_from_deopt_handler(JavaThread* thread, frame fr, RegisterMap* map) {
if (!UseBiasedLocking) {
return;
}
@@ -1318,8 +1475,8 @@
int len = objects_to_revoke->length();
for (int i = 0; i < len; i++) {
oop obj = (objects_to_revoke->at(i))();
- BiasedLocking::revoke_own_locks_in_handshake(objects_to_revoke->at(i), thread);
- assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+ BiasedLocking::revoke_own_lock(objects_to_revoke->at(i), thread);
+ assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
}
@@ -1351,16 +1508,7 @@
fr.deoptimize(thread);
}
-void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map, bool in_handshake) {
- deopt_thread(in_handshake, thread, fr, map, Reason_constraint);
-}
-
void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map, DeoptReason reason) {
- deopt_thread(false, thread, fr, map, reason);
-}
-
-void Deoptimization::deopt_thread(bool in_handshake, JavaThread* thread,
- frame fr, RegisterMap *map, DeoptReason reason) {
// Deoptimize only if the frame comes from compile code.
// Do not deoptimize the frame which is already patched
// during the execution of the loops below.
@@ -1369,15 +1517,7 @@
}
ResourceMark rm;
DeoptimizationMarker dm;
- if (UseBiasedLocking) {
- if (in_handshake) {
- revoke_using_handshake(thread, fr, map);
- } else {
- revoke_using_safepoint(thread, fr, map);
- }
- }
deoptimize_single_frame(thread, fr, reason);
-
}
#if INCLUDE_JVMCI
@@ -1532,15 +1672,12 @@
nmethodLocker nl(fr.pc());
// Log a message
- Events::log(thread, "Uncommon trap: trap_request=" PTR32_FORMAT " fr.pc=" INTPTR_FORMAT " relative=" INTPTR_FORMAT,
+ Events::log_deopt_message(thread, "Uncommon trap: trap_request=" PTR32_FORMAT " fr.pc=" INTPTR_FORMAT " relative=" INTPTR_FORMAT,
trap_request, p2i(fr.pc()), fr.pc() - fr.cb()->code_begin());
{
ResourceMark rm;
- // Revoke biases of any monitors in the frame to ensure we can migrate them
- revoke_biases_of_monitors(thread, fr, ®_map);
-
DeoptReason reason = trap_request_reason(trap_request);
DeoptAction action = trap_request_action(trap_request);
#if INCLUDE_JVMCI
@@ -1932,7 +2069,7 @@
if (trap_method() == nm->method()) {
make_not_compilable = true;
} else {
- trap_method->set_not_compilable(CompLevel_full_optimization, true, "overflow_recompile_count > PerBytecodeRecompilationCutoff");
+ trap_method->set_not_compilable("overflow_recompile_count > PerBytecodeRecompilationCutoff", CompLevel_full_optimization);
// But give grace to the enclosing nm->method().
}
}
@@ -1946,7 +2083,7 @@
// Give up compiling
if (make_not_compilable && !nm->method()->is_not_compilable(CompLevel_full_optimization)) {
assert(make_not_entrant, "consistent");
- nm->method()->set_not_compilable(CompLevel_full_optimization);
+ nm->method()->set_not_compilable("give up compiling", CompLevel_full_optimization);
}
} // Free marked resources
@@ -2176,6 +2313,7 @@
"profile_predicate",
"unloaded",
"uninitialized",
+ "initialized",
"unreached",
"unhandled",
"constraint",