6681646: Relocking of a scalar replaced object during deoptimization is broken

Tue, 01 Apr 2008 16:14:18 -0700

author
kvn
date
Tue, 01 Apr 2008 16:14:18 -0700
changeset 518
d3cd40645d0d
parent 517
de93acbb64fc
child 519
6e085831cad7
child 525
cf4e16e9ca60
child 531
2acabb781f53
child 537
f96100ac3d12
child 587
c70a245cad3a

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

src/share/vm/runtime/deoptimization.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/deoptimization.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/vframe.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/vframe.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/vframe_hp.cpp file | annotate | diff | comparison | revisions
     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  }

mercurial