6681646: Relocking of a scalar replaced object during deoptimization is broken
authorkvn
Tue, 01 Apr 2008 16:14:18 -0700
changeset 256 70fdc3927a4e
parent 255 5734cddd944b
child 257 229330365385
child 337 7e7f474103fe
child 343 8ea45f69cebb
child 349 94856a2bae83
child 578 862a85ed20db
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
hotspot/src/share/vm/runtime/deoptimization.cpp
hotspot/src/share/vm/runtime/deoptimization.hpp
hotspot/src/share/vm/runtime/vframe.cpp
hotspot/src/share/vm/runtime/vframe.hpp
hotspot/src/share/vm/runtime/vframe_hp.cpp
--- 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;
 }