< prev index next >

src/hotspot/share/runtime/synchronizer.cpp

Print this page
*** 239,10 ***
--- 239,24 ---
  bool volatile ObjectSynchronizer::_is_async_deflation_requested = false;
  bool volatile ObjectSynchronizer::_is_final_audit = false;
  jlong ObjectSynchronizer::_last_async_deflation_time_ns = 0;
  static uintx _no_progress_cnt = 0;
  
+ #define CHECK_THROW_NOSYNC_IMSE(obj)  \
+   if (EnableValhalla && (obj)->mark().is_inline_type()) {  \
+     JavaThread* THREAD = current;           \
+     ResourceMark rm(THREAD);                \
+     THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), obj->klass()->external_name()); \
+   }
+ 
+ #define CHECK_THROW_NOSYNC_IMSE_0(obj)  \
+   if (EnableValhalla && (obj)->mark().is_inline_type()) {  \
+     JavaThread* THREAD = current;             \
+     ResourceMark rm(THREAD);                  \
+     THROW_MSG_0(vmSymbols::java_lang_IllegalMonitorStateException(), obj->klass()->external_name()); \
+   }
+ 
  // =====================> Quick functions
  
  // The quick_* forms are special fast-path variants used to improve
  // performance.  In the simplest case, a "quick_*" implementation could
  // simply return false, in which case the caller will perform the necessary

*** 265,10 ***
--- 279,11 ---
  
  bool ObjectSynchronizer::quick_notify(oopDesc* obj, JavaThread* current, bool all) {
    assert(current->thread_state() == _thread_in_Java, "invariant");
    NoSafepointVerifier nsv;
    if (obj == NULL) return false;  // slow-path for invalid obj
+   assert(!EnableValhalla || !obj->klass()->is_inline_klass(), "monitor op on inline type");
    const markWord mark = obj->mark();
  
    if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) {
      // Degenerate notify
      // stack-locked by caller so by definition the implied waitset is empty.

*** 313,10 ***
--- 328,11 ---
  bool ObjectSynchronizer::quick_enter(oop obj, JavaThread* current,
                                       BasicLock * lock) {
    assert(current->thread_state() == _thread_in_Java, "invariant");
    NoSafepointVerifier nsv;
    if (obj == NULL) return false;       // Need to throw NPE
+   assert(!EnableValhalla || !obj->klass()->is_inline_klass(), "monitor op on inline type");
  
    if (obj->klass()->is_value_based()) {
      return false;
    }
  

*** 422,10 ***
--- 438,11 ---
  // The interpreter and compiler assembly code tries to lock using the fast path
  // of this algorithm. Make sure to update that code if the following function is
  // changed. The implementation is extremely sensitive to race condition. Be careful.
  
  void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current) {
+   CHECK_THROW_NOSYNC_IMSE(obj);
    if (obj->klass()->is_value_based()) {
      handle_sync_on_value_based_class(obj, current);
    }
  
    markWord mark = obj->mark();

*** 461,10 ***
--- 478,14 ---
    }
  }
  
  void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) {
    markWord mark = object->mark();
+   if (EnableValhalla && mark.is_inline_type()) {
+     return;
+   }
+   assert(!EnableValhalla || !object->klass()->is_inline_klass(), "monitor op on inline type");
  
    markWord dhw = lock->displaced_header();
    if (dhw.value() == 0) {
      // If the displaced header is NULL, then this exit matches up with
      // a recursive enter. No real work to do here except for diagnostics.

*** 521,19 ***
--- 542,23 ---
  //  3) when notified on lock2, unlock lock2
  //  4) reenter lock1 with original recursion count
  //  5) lock lock2
  // NOTE: must use heavy weight monitor to handle complete_exit/reenter()
  intx ObjectSynchronizer::complete_exit(Handle obj, JavaThread* current) {
+   assert(!EnableValhalla || !obj->klass()->is_inline_klass(), "monitor op on inline type");
+ 
    // The ObjectMonitor* can't be async deflated until ownership is
    // dropped inside exit() and the ObjectMonitor* must be !is_busy().
    ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_vm_internal);
    intptr_t ret_code = monitor->complete_exit(current);
    return ret_code;
  }
  
  // NOTE: must use heavy weight monitor to handle complete_exit/reenter()
  void ObjectSynchronizer::reenter(Handle obj, intx recursions, JavaThread* current) {
+   assert(!EnableValhalla || !obj->klass()->is_inline_klass(), "monitor op on inline type");
+ 
    // An async deflation can race after the inflate() call and before
    // reenter() -> enter() can make the ObjectMonitor busy. reenter() ->
    // enter() returns false if we have lost the race to async deflation
    // and we simply try again.
    while (true) {

*** 549,10 ***
--- 574,11 ---
  // NOTE: must use heavy weight monitor to handle jni monitor enter
  void ObjectSynchronizer::jni_enter(Handle obj, JavaThread* current) {
    if (obj->klass()->is_value_based()) {
      handle_sync_on_value_based_class(obj, current);
    }
+   CHECK_THROW_NOSYNC_IMSE(obj);
  
    // the current locking is from JNI instead of Java code
    current->set_current_pending_monitor_is_from_java(false);
    // An async deflation can race after the inflate() call and before
    // enter() can make the ObjectMonitor busy. enter() returns false if

*** 567,10 ***
--- 593,11 ---
  }
  
  // NOTE: must use heavy weight monitor to handle jni monitor exit
  void ObjectSynchronizer::jni_exit(oop obj, TRAPS) {
    JavaThread* current = THREAD;
+   CHECK_THROW_NOSYNC_IMSE(obj);
  
    // The ObjectMonitor* can't be async deflated until ownership is
    // dropped inside exit() and the ObjectMonitor* must be !is_busy().
    ObjectMonitor* monitor = inflate(current, obj, inflate_cause_jni_exit);
    // If this thread has locked the object, exit the monitor. We

*** 604,10 ***
--- 631,11 ---
  // -----------------------------------------------------------------------------
  //  Wait/Notify/NotifyAll
  // NOTE: must use heavy weight monitor to handle wait()
  int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
    JavaThread* current = THREAD;
+   CHECK_THROW_NOSYNC_IMSE_0(obj);
    if (millis < 0) {
      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
    }
    // The ObjectMonitor* can't be async deflated because the _waiters
    // field is incremented before ownership is dropped and decremented

*** 626,19 ***
--- 654,21 ---
  }
  
  // No exception are possible in this case as we only use this internally when locking is
  // correct and we have to wait until notified - so no interrupts or timeouts.
  void ObjectSynchronizer::wait_uninterruptibly(Handle obj, JavaThread* current) {
+   CHECK_THROW_NOSYNC_IMSE(obj);
    // The ObjectMonitor* can't be async deflated because the _waiters
    // field is incremented before ownership is dropped and decremented
    // after ownership is regained.
    ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_wait);
    monitor->wait(0 /* wait-forever */, false /* not interruptible */, current);
  }
  
  void ObjectSynchronizer::notify(Handle obj, TRAPS) {
    JavaThread* current = THREAD;
+   CHECK_THROW_NOSYNC_IMSE(obj);
  
    markWord mark = obj->mark();
    if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) {
      // Not inflated so there can't be any waiters to notify.
      return;

*** 650,10 ***
--- 680,11 ---
  }
  
  // NOTE: see comment of notify()
  void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
    JavaThread* current = THREAD;
+   CHECK_THROW_NOSYNC_IMSE(obj);
  
    markWord mark = obj->mark();
    if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) {
      // Not inflated so there can't be any waiters to notify.
      return;

*** 796,10 ***
--- 827,14 ---
    assert(value != markWord::no_hash, "invariant");
    return value;
  }
  
  intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) {
+   if (EnableValhalla && obj->klass()->is_inline_klass()) {
+     // VM should be calling bootstrap method
+     ShouldNotReachHere();
+   }
  
    while (true) {
      ObjectMonitor* monitor = NULL;
      markWord temp, test;
      intptr_t hash;

*** 904,19 ***
      // We finally get the hash.
      return hash;
    }
  }
  
- // Deprecated -- use FastHashCode() instead.
- 
- intptr_t ObjectSynchronizer::identity_hash_value_for(Handle obj) {
-   return FastHashCode(Thread::current(), obj());
- }
- 
  
  bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current,
                                                     Handle h_obj) {
    assert(current == JavaThread::current(), "Can only be called on current thread");
    oop obj = h_obj();
  
    markWord mark = read_stable_mark(obj);
  
--- 939,16 ---
      // We finally get the hash.
      return hash;
    }
  }
  
  
  bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current,
                                                     Handle h_obj) {
+   if (EnableValhalla && h_obj->mark().is_inline_type()) {
+     return false;
+   }
    assert(current == JavaThread::current(), "Can only be called on current thread");
    oop obj = h_obj();
  
    markWord mark = read_stable_mark(obj);
  

*** 1115,10 ***
--- 1147,14 ---
    (void)inflate(Thread::current(), obj, inflate_cause_vm_internal);
  }
  
  ObjectMonitor* ObjectSynchronizer::inflate(Thread* current, oop object,
                                             const InflateCause cause) {
+   if (EnableValhalla) {
+     guarantee(!object->klass()->is_inline_klass(), "Attempt to inflate inline type");
+   }
+ 
    EventJavaMonitorInflate event;
  
    for (;;) {
      const markWord mark = object->mark_acquire();
  
< prev index next >