6681646: Relocking of a scalar replaced object during deoptimization is broken
Summary: Relocking of a thread-local object during deoptimization is broken
Reviewed-by: kbr, jrose, never
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Mon Mar 31 18:37:36 2008 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Tue Apr 01 16:14:18 2008 -0700
@@ -143,6 +143,7 @@
// relock objects if synchronization on them was eliminated.
if (DoEscapeAnalysis) {
if (EliminateAllocations) {
+ assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames");
GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
bool reallocated = false;
if (objects != NULL) {
@@ -162,19 +163,26 @@
}
}
if (EliminateLocks) {
+#ifndef PRODUCT
+ bool first = true;
+#endif
for (int i = 0; i < chunk->length(); i++) {
- GrowableArray<MonitorValue*>* monitors = chunk->at(i)->scope()->monitors();
- if (monitors != NULL) {
- relock_objects(&deoptee, &map, monitors);
+ 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);
#ifndef PRODUCT
if (TraceDeoptimization) {
ttyLocker ttyl;
- tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread);
for (int j = 0; j < monitors->length(); j++) {
- MonitorValue* mv = monitors->at(j);
- if (mv->eliminated()) {
- StackValue* owner = StackValue::create_stack_value(&deoptee, &map, mv->owner());
- tty->print_cr(" object <" INTPTR_FORMAT "> locked", owner->get_obj()());
+ MonitorInfo* mi = monitors->at(j);
+ if (mi->eliminated()) {
+ if (first) {
+ first = false;
+ tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread);
+ }
+ tty->print_cr(" object <" INTPTR_FORMAT "> locked", mi->owner());
}
}
}
@@ -799,18 +807,27 @@
// relock objects for which synchronization was eliminated
-void Deoptimization::relock_objects(frame* fr, RegisterMap* reg_map, GrowableArray<MonitorValue*>* monitors) {
+void Deoptimization::relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread) {
for (int i = 0; i < monitors->length(); i++) {
- MonitorValue* mv = monitors->at(i);
- StackValue* owner = StackValue::create_stack_value(fr, reg_map, mv->owner());
- if (mv->eliminated()) {
- Handle obj = owner->get_obj();
- assert(obj.not_null(), "reallocation was missed");
- BasicLock* lock = StackValue::resolve_monitor_lock(fr, mv->basic_lock());
- lock->set_displaced_header(obj->mark());
- obj->set_mark((markOop) lock);
+ MonitorInfo* mon_info = monitors->at(i);
+ if (mon_info->eliminated()) {
+ assert(mon_info->owner() != NULL, "reallocation was missed");
+ Handle obj = Handle(mon_info->owner());
+ markOop 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");
+ // Reset mark word to unbiased prototype.
+ markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
+ obj->set_mark(unbiased_prototype);
+ }
+ BasicLock* lock = mon_info->lock();
+ ObjectSynchronizer::slow_enter(obj, lock, thread);
}
- assert(owner->get_obj()->is_locked(), "object must be locked now");
+ assert(mon_info->owner()->is_locked(), "object must be locked now");
}
}
@@ -916,7 +933,7 @@
GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
for (int i = 0; i < monitors->length(); i++) {
MonitorInfo* mon_info = monitors->at(i);
- if (mon_info->owner() != NULL) {
+ if (mon_info->owner() != NULL && !mon_info->eliminated()) {
objects_to_revoke->append(Handle(mon_info->owner()));
}
}
--- a/hotspot/src/share/vm/runtime/deoptimization.hpp Mon Mar 31 18:37:36 2008 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.hpp Tue Apr 01 16:14:18 2008 -0700
@@ -105,7 +105,7 @@
static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
static void reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj);
static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects);
- static void relock_objects(frame* fr, RegisterMap* reg_map, GrowableArray<MonitorValue*>* monitors);
+ static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread);
NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects);)
#endif // COMPILER2
--- a/hotspot/src/share/vm/runtime/vframe.cpp Mon Mar 31 18:37:36 2008 -0700
+++ b/hotspot/src/share/vm/runtime/vframe.cpp Tue Apr 01 16:14:18 2008 -0700
@@ -206,7 +206,7 @@
for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin()));
current >= fr().interpreter_frame_monitor_end();
current = fr().previous_monitor_in_interpreter_frame(current)) {
- result->push(new MonitorInfo(current->obj(), current->lock()));
+ result->push(new MonitorInfo(current->obj(), current->lock(), false));
}
return result;
}
--- a/hotspot/src/share/vm/runtime/vframe.hpp Mon Mar 31 18:37:36 2008 -0700
+++ b/hotspot/src/share/vm/runtime/vframe.hpp Tue Apr 01 16:14:18 2008 -0700
@@ -230,15 +230,18 @@
private:
oop _owner; // the object owning the monitor
BasicLock* _lock;
+ bool _eliminated;
public:
// Constructor
- MonitorInfo(oop owner, BasicLock* lock) {
+ MonitorInfo(oop owner, BasicLock* lock, bool eliminated) {
_owner = owner;
_lock = lock;
+ _eliminated = eliminated;
}
// Accessors
oop owner() const { return _owner; }
BasicLock* lock() const { return _lock; }
+ bool eliminated() const { return _eliminated; }
};
class vframeStreamCommon : StackObj {
--- a/hotspot/src/share/vm/runtime/vframe_hp.cpp Mon Mar 31 18:37:36 2008 -0700
+++ b/hotspot/src/share/vm/runtime/vframe_hp.cpp Tue Apr 01 16:14:18 2008 -0700
@@ -190,7 +190,7 @@
// Casting away const
frame& fr = (frame&) _fr;
MonitorInfo* info = new MonitorInfo(fr.compiled_synchronized_native_monitor_owner(nm),
- fr.compiled_synchronized_native_monitor(nm));
+ fr.compiled_synchronized_native_monitor(nm), false);
monitors->push(info);
return monitors;
}
@@ -202,7 +202,7 @@
for (int index = 0; index < monitors->length(); index++) {
MonitorValue* mv = monitors->at(index);
StackValue *owner_sv = create_stack_value(mv->owner()); // it is an oop
- result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock())));
+ result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()), mv->eliminated()));
}
return result;
}