Tue, 01 Apr 2008 16:14:18 -0700
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
1.1 --- a/src/share/vm/runtime/deoptimization.cpp Mon Mar 31 18:37:36 2008 -0700 1.2 +++ b/src/share/vm/runtime/deoptimization.cpp Tue Apr 01 16:14:18 2008 -0700 1.3 @@ -143,6 +143,7 @@ 1.4 // relock objects if synchronization on them was eliminated. 1.5 if (DoEscapeAnalysis) { 1.6 if (EliminateAllocations) { 1.7 + assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames"); 1.8 GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects(); 1.9 bool reallocated = false; 1.10 if (objects != NULL) { 1.11 @@ -162,19 +163,26 @@ 1.12 } 1.13 } 1.14 if (EliminateLocks) { 1.15 +#ifndef PRODUCT 1.16 + bool first = true; 1.17 +#endif 1.18 for (int i = 0; i < chunk->length(); i++) { 1.19 - GrowableArray<MonitorValue*>* monitors = chunk->at(i)->scope()->monitors(); 1.20 - if (monitors != NULL) { 1.21 - relock_objects(&deoptee, &map, monitors); 1.22 + compiledVFrame* cvf = chunk->at(i); 1.23 + assert (cvf->scope() != NULL,"expect only compiled java frames"); 1.24 + GrowableArray<MonitorInfo*>* monitors = cvf->monitors(); 1.25 + if (monitors->is_nonempty()) { 1.26 + relock_objects(monitors, thread); 1.27 #ifndef PRODUCT 1.28 if (TraceDeoptimization) { 1.29 ttyLocker ttyl; 1.30 - tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread); 1.31 for (int j = 0; j < monitors->length(); j++) { 1.32 - MonitorValue* mv = monitors->at(j); 1.33 - if (mv->eliminated()) { 1.34 - StackValue* owner = StackValue::create_stack_value(&deoptee, &map, mv->owner()); 1.35 - tty->print_cr(" object <" INTPTR_FORMAT "> locked", owner->get_obj()()); 1.36 + MonitorInfo* mi = monitors->at(j); 1.37 + if (mi->eliminated()) { 1.38 + if (first) { 1.39 + first = false; 1.40 + tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread); 1.41 + } 1.42 + tty->print_cr(" object <" INTPTR_FORMAT "> locked", mi->owner()); 1.43 } 1.44 } 1.45 } 1.46 @@ -799,18 +807,27 @@ 1.47 1.48 1.49 // relock objects for which synchronization was eliminated 1.50 -void Deoptimization::relock_objects(frame* fr, RegisterMap* reg_map, GrowableArray<MonitorValue*>* monitors) { 1.51 +void Deoptimization::relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread) { 1.52 for (int i = 0; i < monitors->length(); i++) { 1.53 - MonitorValue* mv = monitors->at(i); 1.54 - StackValue* owner = StackValue::create_stack_value(fr, reg_map, mv->owner()); 1.55 - if (mv->eliminated()) { 1.56 - Handle obj = owner->get_obj(); 1.57 - assert(obj.not_null(), "reallocation was missed"); 1.58 - BasicLock* lock = StackValue::resolve_monitor_lock(fr, mv->basic_lock()); 1.59 - lock->set_displaced_header(obj->mark()); 1.60 - obj->set_mark((markOop) lock); 1.61 + MonitorInfo* mon_info = monitors->at(i); 1.62 + if (mon_info->eliminated()) { 1.63 + assert(mon_info->owner() != NULL, "reallocation was missed"); 1.64 + Handle obj = Handle(mon_info->owner()); 1.65 + markOop mark = obj->mark(); 1.66 + if (UseBiasedLocking && mark->has_bias_pattern()) { 1.67 + // New allocated objects may have the mark set to anonymously biased. 1.68 + // Also the deoptimized method may called methods with synchronization 1.69 + // where the thread-local object is bias locked to the current thread. 1.70 + assert(mark->is_biased_anonymously() || 1.71 + mark->biased_locker() == thread, "should be locked to current thread"); 1.72 + // Reset mark word to unbiased prototype. 1.73 + markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age()); 1.74 + obj->set_mark(unbiased_prototype); 1.75 + } 1.76 + BasicLock* lock = mon_info->lock(); 1.77 + ObjectSynchronizer::slow_enter(obj, lock, thread); 1.78 } 1.79 - assert(owner->get_obj()->is_locked(), "object must be locked now"); 1.80 + assert(mon_info->owner()->is_locked(), "object must be locked now"); 1.81 } 1.82 } 1.83 1.84 @@ -916,7 +933,7 @@ 1.85 GrowableArray<MonitorInfo*>* monitors = cvf->monitors(); 1.86 for (int i = 0; i < monitors->length(); i++) { 1.87 MonitorInfo* mon_info = monitors->at(i); 1.88 - if (mon_info->owner() != NULL) { 1.89 + if (mon_info->owner() != NULL && !mon_info->eliminated()) { 1.90 objects_to_revoke->append(Handle(mon_info->owner())); 1.91 } 1.92 }
2.1 --- a/src/share/vm/runtime/deoptimization.hpp Mon Mar 31 18:37:36 2008 -0700 2.2 +++ b/src/share/vm/runtime/deoptimization.hpp Tue Apr 01 16:14:18 2008 -0700 2.3 @@ -105,7 +105,7 @@ 2.4 static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type); 2.5 static void reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj); 2.6 static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects); 2.7 - static void relock_objects(frame* fr, RegisterMap* reg_map, GrowableArray<MonitorValue*>* monitors); 2.8 + static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread); 2.9 NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects);) 2.10 #endif // COMPILER2 2.11
3.1 --- a/src/share/vm/runtime/vframe.cpp Mon Mar 31 18:37:36 2008 -0700 3.2 +++ b/src/share/vm/runtime/vframe.cpp Tue Apr 01 16:14:18 2008 -0700 3.3 @@ -206,7 +206,7 @@ 3.4 for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin())); 3.5 current >= fr().interpreter_frame_monitor_end(); 3.6 current = fr().previous_monitor_in_interpreter_frame(current)) { 3.7 - result->push(new MonitorInfo(current->obj(), current->lock())); 3.8 + result->push(new MonitorInfo(current->obj(), current->lock(), false)); 3.9 } 3.10 return result; 3.11 }
4.1 --- a/src/share/vm/runtime/vframe.hpp Mon Mar 31 18:37:36 2008 -0700 4.2 +++ b/src/share/vm/runtime/vframe.hpp Tue Apr 01 16:14:18 2008 -0700 4.3 @@ -230,15 +230,18 @@ 4.4 private: 4.5 oop _owner; // the object owning the monitor 4.6 BasicLock* _lock; 4.7 + bool _eliminated; 4.8 public: 4.9 // Constructor 4.10 - MonitorInfo(oop owner, BasicLock* lock) { 4.11 + MonitorInfo(oop owner, BasicLock* lock, bool eliminated) { 4.12 _owner = owner; 4.13 _lock = lock; 4.14 + _eliminated = eliminated; 4.15 } 4.16 // Accessors 4.17 oop owner() const { return _owner; } 4.18 BasicLock* lock() const { return _lock; } 4.19 + bool eliminated() const { return _eliminated; } 4.20 }; 4.21 4.22 class vframeStreamCommon : StackObj {
5.1 --- a/src/share/vm/runtime/vframe_hp.cpp Mon Mar 31 18:37:36 2008 -0700 5.2 +++ b/src/share/vm/runtime/vframe_hp.cpp Tue Apr 01 16:14:18 2008 -0700 5.3 @@ -190,7 +190,7 @@ 5.4 // Casting away const 5.5 frame& fr = (frame&) _fr; 5.6 MonitorInfo* info = new MonitorInfo(fr.compiled_synchronized_native_monitor_owner(nm), 5.7 - fr.compiled_synchronized_native_monitor(nm)); 5.8 + fr.compiled_synchronized_native_monitor(nm), false); 5.9 monitors->push(info); 5.10 return monitors; 5.11 } 5.12 @@ -202,7 +202,7 @@ 5.13 for (int index = 0; index < monitors->length(); index++) { 5.14 MonitorValue* mv = monitors->at(index); 5.15 StackValue *owner_sv = create_stack_value(mv->owner()); // it is an oop 5.16 - result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()))); 5.17 + result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()), mv->eliminated())); 5.18 } 5.19 return result; 5.20 }