changeset 9762:081cf5f88897

Big cleanup, part 2: revisit, fix & cleanup all runtime barriers.
author rkennke
date Sat, 03 Oct 2015 13:51:17 +0200
parents 0d5b3847ab03
children 29693376eaec
files src/share/vm/c1/c1_Runtime1.cpp src/share/vm/ci/ciObject.hpp src/share/vm/ci/ciObjectFactory.hpp src/share/vm/classfile/classLoaderData.cpp src/share/vm/classfile/dictionary.cpp src/share/vm/classfile/dictionary.hpp src/share/vm/classfile/javaClasses.cpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/code/nmethod.cpp src/share/vm/code/relocInfo.cpp src/share/vm/gc/shared/barrierSet.hpp src/share/vm/gc/shared/referenceProcessor.cpp src/share/vm/gc/shared/space.inline.hpp src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp src/share/vm/gc/shenandoah/shenandoahMarkCompact.cpp src/share/vm/interpreter/interpreterRuntime.cpp src/share/vm/memory/oopFactory.cpp src/share/vm/memory/universe.cpp src/share/vm/memory/universe.hpp src/share/vm/memory/universe.inline.hpp src/share/vm/oops/cpCache.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceRefKlass.cpp src/share/vm/oops/klass.cpp src/share/vm/oops/klass.hpp src/share/vm/oops/objArrayKlass.cpp src/share/vm/oops/objArrayOop.hpp src/share/vm/oops/objArrayOop.inline.hpp src/share/vm/oops/oop.cpp src/share/vm/oops/oop.inline.hpp src/share/vm/oops/typeArrayKlass.cpp src/share/vm/oops/typeArrayOop.hpp src/share/vm/opto/runtime.cpp src/share/vm/prims/jni.cpp src/share/vm/prims/jvm.cpp src/share/vm/prims/jvmtiEnv.cpp src/share/vm/prims/unsafe.cpp src/share/vm/runtime/basicLock.hpp src/share/vm/runtime/biasedLocking.cpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/handles.hpp src/share/vm/runtime/jniHandles.hpp src/share/vm/runtime/objectMonitor.inline.hpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/synchronizer.cpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/thread.hpp src/share/vm/runtime/vframe.hpp src/share/vm/services/lowMemoryDetector.cpp src/share/vm/services/memoryManager.hpp src/share/vm/services/memoryPool.cpp src/share/vm/services/threadService.cpp src/share/vm/services/threadService.hpp src/share/vm/utilities/exceptions.cpp src/share/vm/utilities/exceptions.hpp
diffstat 56 files changed, 444 insertions(+), 353 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/c1/c1_Runtime1.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -674,7 +674,7 @@
   if (PrintBiasedLockingStatistics) {
     Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
   }
-  Handle h_obj(thread, obj);
+Handle h_obj(thread, oopDesc::bs()->resolve_and_maybe_copy_oop(obj));
   assert(h_obj()->is_oop(), "must be NULL or an object");
   if (UseBiasedLocking) {
     // Retry fast entry if bias is revoked to avoid unnecessary inflation
@@ -699,7 +699,7 @@
   // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown
   EXCEPTION_MARK;
 
-  oop obj = lock->obj();
+  oop obj = oopDesc::bs()->resolve_and_maybe_copy_oop(lock->obj());
   assert(obj->is_oop(), "must be NULL or an object");
   if (UseFastLocking) {
     // When using fast locking, the compiled code has already tried the fast case
--- a/src/share/vm/ci/ciObject.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/ci/ciObject.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -27,6 +27,7 @@
 
 #include "ci/ciBaseObject.hpp"
 #include "ci/ciClassList.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/jniHandles.hpp"
@@ -69,7 +70,9 @@
   // Get the VM oop that this object holds.
   oop get_oop() const {
     assert(_handle != NULL, "null oop");
-    return JNIHandles::resolve_non_null(_handle);
+    oop obj = JNIHandles::resolve_non_null(_handle);
+    assert(obj == oopDesc::bs()->resolve_and_maybe_copy_oop(obj), "expect to-space copy");
+    return obj;
   }
 
   void init_flags_from(oop x);
--- a/src/share/vm/ci/ciObjectFactory.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/ci/ciObjectFactory.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -27,6 +27,7 @@
 
 #include "ci/ciClassList.hpp"
 #include "ci/ciObject.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "utilities/growableArray.hpp"
 
 // ciObjectFactory
@@ -79,7 +80,11 @@
 
   static bool is_equal(NonPermObject* p, oop key) {
     // Shenandoah: We already force-forwarded the key earlier.
-    return oopDesc::bs()->resolve_oop(p->object()->get_oop()) == key;
+    // The oop in the object should always point to to-space.
+    assert(key == oopDesc::bs()->resolve_oop(key), "should be forwarded");
+    assert(p->object()->get_oop() == oopDesc::bs()->resolve_oop(p->object()->get_oop()),
+	   "should be forwarded");
+    return p->object()->get_oop() == key;
   }
 
   NonPermObject* &find_non_perm(oop key);
--- a/src/share/vm/classfile/classLoaderData.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/classfile/classLoaderData.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -242,7 +242,7 @@
   // Have to lock and put the new dependency on the end of the dependency
   // array so the card mark for CMS sees that this dependency is new.
   // Can probably do this lock free with some effort.
-  ObjectLocker ol(Handle(THREAD, _list_head), THREAD);
+  ObjectLocker ol(Handle(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(_list_head)), THREAD);
 
   oop loader_or_mirror = new_dependency->obj_at(0);
 
--- a/src/share/vm/classfile/dictionary.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/classfile/dictionary.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -80,13 +80,14 @@
 
 bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
 #ifdef ASSERT
-  if (protection_domain == InstanceKlass::cast(klass())->protection_domain()) {
+  protection_domain = oopDesc::bs()->resolve_and_maybe_copy_oop(protection_domain);
+  if (protection_domain == oopDesc::bs()->resolve_and_maybe_copy_oop(InstanceKlass::cast(klass())->protection_domain())) {
     // Ensure this doesn't show up in the pd_set (invariant)
     bool in_pd_set = false;
     for (ProtectionDomainEntry* current = _pd_set;
                                 current != NULL;
                                 current = current->next()) {
-      if (current->protection_domain() == protection_domain) {
+      if (oopDesc::bs()->resolve_and_maybe_copy_oop(current->protection_domain()) == protection_domain) {
         in_pd_set = true;
         break;
       }
@@ -98,7 +99,7 @@
   }
 #endif /* ASSERT */
 
-  if (protection_domain == InstanceKlass::cast(klass())->protection_domain()) {
+  if (protection_domain == oopDesc::bs()->resolve_and_maybe_copy_oop(InstanceKlass::cast(klass())->protection_domain())) {
     // Succeeds trivially
     return true;
   }
@@ -106,7 +107,7 @@
   for (ProtectionDomainEntry* current = _pd_set;
                               current != NULL;
                               current = current->next()) {
-    if (current->protection_domain() == protection_domain) return true;
+    if (oopDesc::bs()->resolve_and_maybe_copy_oop(current->protection_domain()) == protection_domain) return true;
   }
   return false;
 }
--- a/src/share/vm/classfile/dictionary.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/classfile/dictionary.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -141,7 +141,7 @@
   // to be updated.
   bool _strongly_reachable;
  public:
-  oop protection_domain() { return oopDesc::bs()->resolve_oop(literal()); }
+  oop protection_domain() { return literal(); }
 
   void init() {
     _strongly_reachable = false;
@@ -356,7 +356,7 @@
   Method*        method() const     { return _method; }
   void set_method(Method* p)        { _method = p; }
 
-  oop      method_type() const      { return oopDesc::bs()->resolve_oop(_method_type); }
+  oop      method_type() const      { return _method_type; }
   oop*     method_type_addr()       { return &_method_type; }
   void set_method_type(oop p)       { _method_type = p; }
 
--- a/src/share/vm/classfile/javaClasses.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/classfile/javaClasses.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -212,7 +212,9 @@
   int length = UTF8::unicode_length(utf8_str);
   Handle h_obj = basic_create(length, CHECK_NH);
   if (length > 0) {
-    UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length);
+    typeArrayOop buffer = value(h_obj());
+    buffer = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(buffer));
+    UTF8::convert_to_unicode(utf8_str, buffer->char_at_addr(0), length);
   }
   return h_obj;
 }
@@ -226,7 +228,9 @@
   int length = UTF8::unicode_length((char*)symbol->bytes(), symbol->utf8_length());
   Handle h_obj = basic_create(length, CHECK_NH);
   if (length > 0) {
-    UTF8::convert_to_unicode((char*)symbol->bytes(), value(h_obj())->char_at_addr(0), length);
+    typeArrayOop buffer = value(h_obj());
+    buffer = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(buffer));
+    UTF8::convert_to_unicode((char*)symbol->bytes(), buffer->char_at_addr(0), length);
   }
   return h_obj;
 }
@@ -347,6 +351,7 @@
 
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   return java_lang_String::hash_code(value->char_at_addr(offset), length);
 }
 
@@ -355,6 +360,7 @@
   int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
 
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
   if (base == NULL) return NULL;
 
@@ -375,6 +381,7 @@
 
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   return StringTable::hash_string(value->char_at_addr(offset), length);
 }
 
@@ -383,6 +390,7 @@
   typeArrayOop value  = java_lang_String::value(obj);
   int          offset = java_lang_String::offset(obj);
   int          length = java_lang_String::length(obj);
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
   Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD);
   return sym;
@@ -392,6 +400,7 @@
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
   return SymbolTable::probe_unicode(base, length);
 }
@@ -401,6 +410,7 @@
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
   return UNICODE::utf8_length(position, length);
 }
@@ -409,6 +419,7 @@
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
   return UNICODE::as_utf8(position, length);
 }
@@ -417,6 +428,7 @@
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
   return UNICODE::as_utf8(position, length, buf, buflen);
 }
@@ -426,6 +438,7 @@
   int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
   assert(start + len <= length, "just checking");
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   jchar* position = value->char_at_addr(offset + start);
   return UNICODE::as_utf8(position, len);
 }
@@ -435,6 +448,7 @@
   int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
   assert(start + len <= length, "just checking");
+  value = typeArrayOop(oopDesc::bs()->resolve_oop(value));
   jchar* position = value->char_at_addr(offset + start);
   return UNICODE::as_utf8(position, len, buf, buflen);
 }
@@ -684,7 +698,7 @@
 
 oop java_lang_Class::protection_domain(oop java_class) {
   assert(_protection_domain_offset != 0, "must be set");
-  return oopDesc::bs()->resolve_oop(java_class->obj_field(_protection_domain_offset));
+  return java_class->obj_field(_protection_domain_offset);
 }
 void java_lang_Class::set_protection_domain(oop java_class, oop pd) {
   assert(_protection_domain_offset != 0, "must be set");
@@ -702,7 +716,7 @@
 
 oop java_lang_Class::init_lock(oop java_class) {
   assert(_init_lock_offset != 0, "must be set");
-  return oopDesc::bs()->resolve_oop(java_class->obj_field(_init_lock_offset));
+  return java_class->obj_field(_init_lock_offset);
 }
 void java_lang_Class::set_init_lock(oop java_class, oop init_lock) {
   assert(_init_lock_offset != 0, "must be set");
@@ -711,7 +725,7 @@
 
 objArrayOop java_lang_Class::signers(oop java_class) {
   assert(_signers_offset != 0, "must be set");
-  return (objArrayOop) oopDesc::bs()->resolve_oop(java_class->obj_field(_signers_offset));
+  return (objArrayOop)java_class->obj_field(_signers_offset);
 }
 void java_lang_Class::set_signers(oop java_class, objArrayOop signers) {
   assert(_signers_offset != 0, "must be set");
@@ -868,9 +882,7 @@
   } else {
     assert(oopDesc::bs()->resolve_and_maybe_copy_oop(java_class) == oopDesc::bs()->resolve_and_maybe_copy_oop(Universe::void_mirror()), "only valid non-array primitive");
   }
-
   assert(oopDesc::bs()->resolve_and_maybe_copy_oop(Universe::java_mirror(type)) == oopDesc::bs()->resolve_and_maybe_copy_oop(java_class), "must be consistent");
-
   return type;
 }
 
@@ -1116,7 +1128,7 @@
          _park_blocker_offset != 0, "Must support parkBlocker field");
 
   if (_park_blocker_offset > 0) {
-    return oopDesc::bs()->resolve_oop(java_thread->obj_field(_park_blocker_offset));
+    return java_thread->obj_field(_park_blocker_offset);
   }
 
   return NULL;
--- a/src/share/vm/classfile/systemDictionary.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/classfile/systemDictionary.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -103,7 +103,7 @@
 // Java-level SystemLoader
 
 oop SystemDictionary::java_system_loader() {
-  return oopDesc::bs()->resolve_oop(_java_system_loader);
+  return _java_system_loader;
 }
 
 void SystemDictionary::compute_java_system_loader(TRAPS) {
@@ -498,7 +498,7 @@
   bool calledholdinglock
       = ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, lockObject);
   assert(calledholdinglock,"must hold lock for notify");
-  assert((!(lockObject() == oopDesc::bs()->resolve_oop(_system_loader_lock_obj)) && !is_parallelCapable(lockObject)), "unexpected double_lock_wait");
+  assert((!(oopDesc::bs()->resolve_and_maybe_copy_oop(lockObject()) == oopDesc::bs()->resolve_and_maybe_copy_oop(_system_loader_lock_obj)) && !is_parallelCapable(lockObject)), "unexpected double_lock_wait");
   ObjectSynchronizer::notifyall(lockObject, THREAD);
   intptr_t recursions =  ObjectSynchronizer::complete_exit(lockObject, THREAD);
   SystemDictionary_lock->wait();
@@ -1531,9 +1531,9 @@
 Handle SystemDictionary::compute_loader_lock_object(Handle class_loader, TRAPS) {
   // If class_loader is NULL we synchronize on _system_loader_lock_obj
   if (class_loader.is_null()) {
-    return Handle(THREAD, oopDesc::bs()->resolve_oop(_system_loader_lock_obj));
+    return Handle(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(_system_loader_lock_obj));
   } else {
-    return class_loader;
+    return Handle(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(class_loader()));
   }
 }
 
@@ -1552,7 +1552,7 @@
       == ObjectSynchronizer::owner_other) {
     // contention will likely happen, so increment the corresponding
     // contention counter.
-    if (loader_lock() == oopDesc::bs()->resolve_oop(_system_loader_lock_obj)) {
+    if (oopDesc::bs()->resolve_and_maybe_copy_oop(loader_lock()) == oopDesc::bs()->resolve_and_maybe_copy_oop(_system_loader_lock_obj)) {
       ClassLoader::sync_systemLoaderLockContentionRate()->inc();
     } else {
       ClassLoader::sync_nonSystemLoaderLockContentionRate()->inc();
--- a/src/share/vm/code/nmethod.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/code/nmethod.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -900,7 +900,9 @@
       handle == (jobject) Universe::non_oop_word()) {
     (*dest) = (oop) handle;
   } else {
-    (*dest) = JNIHandles::resolve_non_null(handle);
+    oop obj = JNIHandles::resolve_non_null(handle);
+    assert(obj == oopDesc::bs()->resolve_and_maybe_copy_oop(obj), "expect to-space copy");
+    (*dest) = obj;
   }
 }
 
--- a/src/share/vm/code/relocInfo.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/code/relocInfo.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -709,7 +709,7 @@
   oop v = *oop_addr();
   // clean inline caches store a special pseudo-null
   if (v == (oop)Universe::non_oop_word())  v = NULL;
-  return oopDesc::bs()->resolve_oop(v);
+  return v;
 }
 
 
--- a/src/share/vm/gc/shared/barrierSet.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/gc/shared/barrierSet.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -221,9 +221,6 @@
   virtual oop resolve_oop(oop src) {
     return src;
   }
-  virtual oop maybe_resolve_oop(oop src) {
-    return src;
-  }
   virtual oop resolve_and_maybe_copy_oop(oop src) {
     return src;
   }
--- a/src/share/vm/gc/shared/referenceProcessor.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/gc/shared/referenceProcessor.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -446,7 +446,6 @@
   _next = discovered;
   _referent_addr = java_lang_ref_Reference::referent_addr(_ref);
   _referent = java_lang_ref_Reference::referent(_ref);
-  // _referent = oopDesc::bs()->resolve_oop(_referent);
   assert(_referent == oopDesc::bs()->resolve_oop(_referent), "expect forwarded referent");
   assert(Universe::heap()->is_in_reserved_or_null(_referent),
          "Wrong oop found in java.lang.Reference object");
@@ -645,14 +644,11 @@
 
 void
 ReferenceProcessor::clear_discovered_references(DiscoveredList& refs_list) {
-  BarrierSet* bs = oopDesc::bs();
   oop obj = NULL;
-  // oop next = bs->resolve_and_maybe_copy_oop(refs_list.head());
   oop next = refs_list.head();
   while (next != obj) {
     obj = next;
     assert(obj == oopDesc::bs()->resolve_oop(obj), "expect forwarded obj");
-    // next = bs->resolve_and_maybe_copy_oop(java_lang_ref_Reference::discovered(obj));
     next = java_lang_ref_Reference::discovered(obj);
     java_lang_ref_Reference::set_discovered_raw(obj, NULL);
   }
@@ -1038,7 +1034,6 @@
 //     and complexity in processing these references.
 //     We call this choice the "RefeferentBasedDiscovery" policy.
 bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) {
-
   // Make sure we are discovering refs (rather than processing discovered refs).
   if (!_discovering_refs || !RegisterReferences) {
     return false;
--- a/src/share/vm/gc/shared/space.inline.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/gc/shared/space.inline.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -124,7 +124,9 @@
            space->make_oop(q)->mark()->is_marked() ||
 	   oopDesc::bs()->resolve_oop(space->make_oop(q))->mark()->is_marked() ||
 	   space->make_oop(q)->mark()->is_unlocked() ||
-           space->make_oop(q)->mark()->has_bias_pattern(),
+	   oopDesc::bs()->resolve_oop(space->make_oop(q))->mark()->is_unlocked() ||
+           space->make_oop(q)->mark()->has_bias_pattern() ||
+           oopDesc::bs()->resolve_oop(space->make_oop(q))->mark()->has_bias_pattern(),
            "these are the only valid states during a mark sweep");
     if (space->scanned_block_is_obj(q) && space->make_oop(q)->is_gc_marked()) {
       // prefetch beyond q
--- a/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -255,14 +255,6 @@
   return ShenandoahBarrierSet::resolve_oop_static(src);
 }
 
-oop ShenandoahBarrierSet::maybe_resolve_oop(oop src) {
-  if (Universe::heap()->is_in(src)) {
-    return resolve_oop_static(src);
-  } else {
-    return src;
-  }
-}
-
 oop ShenandoahBarrierSet::resolve_and_maybe_copy_oop_work(oop src) {
   ShenandoahHeap *sh = (ShenandoahHeap*) Universe::heap();
   assert(src != NULL, "only evacuated non NULL oops");
--- a/src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -149,7 +149,6 @@
   }
 
 
-  virtual oop maybe_resolve_oop(oop src);
   oop resolve_and_maybe_copy_oopHelper(oop src);
   oop resolve_and_maybe_copy_oop_work(oop src);
   oop resolve_and_maybe_copy_oop_work2(oop src);
--- a/src/share/vm/gc/shenandoah/shenandoahMarkCompact.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/gc/shenandoah/shenandoahMarkCompact.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -55,13 +55,15 @@
   }
   _heap->clear_cset_fast_test();
 
+  /*
   if (ShenandoahVerify) {
     // Full GC should only be called between regular concurrent cycles, therefore
     // those verifications should be valid.
     _heap->verify_heap_after_evacuation();
     _heap->verify_heap_after_update_refs();
   }
- 
+  */
+
   if (ShenandoahTraceFullGC) {
     gclog_or_tty->print_cr("Shenandoah-full-gc: start with heap used: "SIZE_FORMAT" MB", _heap->used() / M);
     gclog_or_tty->print_cr("Shenandoah-full-gc: phase 1: marking the heap");
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -615,7 +615,7 @@
   if (PrintBiasedLockingStatistics) {
     Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
   }
-  Handle h_obj(thread, elem->obj());
+  Handle h_obj(thread, oopDesc::bs()->resolve_and_maybe_copy_oop(elem->obj()));
   assert(Universe::heap()->is_in_reserved_or_null(h_obj()),
          "must be NULL or an object");
   if (UseBiasedLocking) {
@@ -637,7 +637,7 @@
 #ifdef ASSERT
   thread->last_frame().interpreter_frame_verify_monitor(elem);
 #endif
-  Handle h_obj(thread, elem->obj());
+  Handle h_obj(thread, oopDesc::bs()->resolve_and_maybe_copy_oop(elem->obj()));
   assert(Universe::heap()->is_in_reserved_or_null(h_obj()),
          "must be NULL or an object");
   if (elem == NULL || h_obj()->is_unlocked()) {
--- a/src/share/vm/memory/oopFactory.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/memory/oopFactory.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -40,6 +40,7 @@
 typeArrayOop oopFactory::new_charArray(const char* utf8_str, TRAPS) {
   int length = utf8_str == NULL ? 0 : UTF8::unicode_length(utf8_str);
   typeArrayOop result = new_charArray(length, CHECK_NULL);
+  result = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(result));
   if (length > 0) {
     UTF8::convert_to_unicode(utf8_str, result->char_at_addr(0), length);
   }
--- a/src/share/vm/memory/universe.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/memory/universe.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -592,9 +592,6 @@
   //   a filled in stack trace.
   // - if there are no preallocated errors with backtrace available then return
   //   an error without backtrace.
-
-  default_err = resolve_oop(default_err);
-
   int next;
   if (_preallocated_out_of_memory_error_avail_count > 0) {
     next = (int)Atomic::add(-1, &_preallocated_out_of_memory_error_avail_count);
--- a/src/share/vm/memory/universe.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/memory/universe.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -25,7 +25,6 @@
 #ifndef SHARE_VM_MEMORY_UNIVERSE_HPP
 #define SHARE_VM_MEMORY_UNIVERSE_HPP
 
-#include "gc/shared/barrierSet.hpp"
 #include "runtime/handles.hpp"
 #include "utilities/array.hpp"
 #include "utilities/growableArray.hpp"
@@ -204,12 +203,8 @@
   static bool _bootstrapping;                         // true during genesis
   static bool _fully_initialized;                     // true after universe_init and initialize_vtables called
 
-  static oop resolve_oop(oop o) {
-    return (oop) oopDesc::bs()->resolve_oop(o);
-  }
-
   // the array of preallocated errors with backtraces
-  static objArrayOop  preallocated_out_of_memory_errors()     { return (objArrayOop) resolve_oop((oop) _preallocated_out_of_memory_error_array); }
+  static objArrayOop  preallocated_out_of_memory_errors()     { return _preallocated_out_of_memory_error_array; }
 
   // generate an out of memory error; if possible using an error with preallocated backtrace;
   // otherwise return the given default error.
@@ -235,7 +230,7 @@
   // Mirrors for primitive classes (created eagerly)
   static oop check_mirror(oop m) {
     assert(m != NULL, "mirror not initialized");
-    return resolve_oop(m);
+    return m;
   }
 
   static void     set_narrow_oop_base(address base) {
@@ -295,19 +290,18 @@
 
   static oop java_mirror(BasicType t) {
     assert((uint)t < T_VOID+1, "range check");
-    oop mirror = check_mirror(_mirrors[t]);
-    return mirror;
+    return check_mirror(_mirrors[t]);
   }
-  static oop      main_thread_group()                 { return resolve_oop(_main_thread_group); }
+  static oop      main_thread_group()                 { return _main_thread_group; }
   static void set_main_thread_group(oop group)        { _main_thread_group = group;}
 
-  static oop      system_thread_group()               { return resolve_oop(_system_thread_group); }
+  static oop      system_thread_group()               { return _system_thread_group; }
   static void set_system_thread_group(oop group)      { _system_thread_group = group;}
 
-  static objArrayOop  the_empty_class_klass_array ()  { return (objArrayOop) resolve_oop((oop) _the_empty_class_klass_array);   }
+  static objArrayOop  the_empty_class_klass_array ()  { return _the_empty_class_klass_array;   }
   static Array<Klass*>* the_array_interfaces_array() { return _the_array_interfaces_array;   }
-  static oop          the_null_string()               { return resolve_oop(_the_null_string);               }
-  static oop          the_min_jint_string()          { return resolve_oop(_the_min_jint_string);          }
+  static oop          the_null_string()               { return _the_null_string;               }
+  static oop          the_min_jint_string()          { return _the_min_jint_string;          }
 
   static Method*      finalizer_register_method()     { return _finalizer_register_cache->get_method(); }
   static Method*      loader_addClass_method()        { return _loader_addClass_cache->get_method(); }
@@ -315,10 +309,10 @@
   static Method*      protection_domain_implies_method() { return _pd_implies_cache->get_method(); }
   static Method*      throw_illegal_access_error()    { return _throw_illegal_access_error_cache->get_method(); }
 
-  static oop          null_ptr_exception_instance()   { return resolve_oop(_null_ptr_exception_instance);   }
-  static oop          arithmetic_exception_instance() { return resolve_oop(_arithmetic_exception_instance); }
-  static oop          virtual_machine_error_instance() { return resolve_oop(_virtual_machine_error_instance); }
-  static oop          vm_exception()                  { return resolve_oop(_vm_exception); }
+  static oop          null_ptr_exception_instance()   { return _null_ptr_exception_instance;   }
+  static oop          arithmetic_exception_instance() { return _arithmetic_exception_instance; }
+  static oop          virtual_machine_error_instance() { return _virtual_machine_error_instance; }
+  static oop          vm_exception()                  { return _vm_exception; }
 
   static inline oop   allocation_context_notification_obj();
   static inline void  set_allocation_context_notification_obj(oop obj);
--- a/src/share/vm/memory/universe.inline.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/memory/universe.inline.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -42,7 +42,7 @@
 }
 
 inline oop Universe::allocation_context_notification_obj() {
-  return resolve_oop(_allocation_context_notification_obj);
+  return _allocation_context_notification_obj;
 }
 
 inline void Universe::set_allocation_context_notification_obj(oop obj) {
--- a/src/share/vm/oops/cpCache.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/cpCache.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -283,7 +283,7 @@
   // the lock, so that when the losing writer returns, he can use the linked
   // cache entry.
 
-  objArrayHandle resolved_references = cpool->resolved_references();
+  objArrayHandle resolved_references = objArrayHandle(objArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(cpool->resolved_references())));
   // Use the resolved_references() lock for this cpCache entry.
   // resolved_references are created for all classes with Invokedynamic, MethodHandle
   // or MethodType constant pool cache entries.
--- a/src/share/vm/oops/instanceKlass.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/instanceKlass.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -471,6 +471,7 @@
 void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_k) {
   EXCEPTION_MARK;
   oop init_lock = this_k->init_lock();
+  init_lock = oopDesc::bs()->resolve_and_maybe_copy_oop(init_lock);
   ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
 
   // abort if someone beat us to the initialization
@@ -617,6 +618,7 @@
   // verification & rewriting
   {
     oop init_lock = this_k->init_lock();
+    init_lock = oopDesc::bs()->resolve_and_maybe_copy_oop(init_lock);
     ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
     // rewritten will have been set if loader constraint error found
     // on an earlier link attempt
@@ -750,6 +752,7 @@
   // Step 1
   {
     oop init_lock = this_k->init_lock();
+    init_lock = oopDesc::bs()->resolve_and_maybe_copy_oop(init_lock);
     ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
 
     Thread *self = THREAD; // it's passed the current thread
@@ -882,6 +885,7 @@
 
 void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_k, ClassState state, TRAPS) {
   oop init_lock = this_k->init_lock();
+  init_lock = oopDesc::bs()->resolve_and_maybe_copy_oop(init_lock);
   ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
   this_k->set_init_state(state);
   this_k->fence_and_clear_init_lock();
--- a/src/share/vm/oops/instanceRefKlass.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/instanceRefKlass.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -91,7 +91,7 @@
 
 bool InstanceRefKlass::owns_pending_list_lock(JavaThread* thread) {
   if (java_lang_ref_Reference::pending_list_lock() == NULL) return false;
-  Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock());
+  Handle h_lock(thread, oopDesc::bs()->resolve_and_maybe_copy_oop(java_lang_ref_Reference::pending_list_lock()));
   return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock);
 }
 
@@ -104,7 +104,7 @@
   // to hold the pending list lock. We want to free this handle.
   HandleMark hm;
 
-  Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
+  Handle h_lock(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(java_lang_ref_Reference::pending_list_lock()));
   ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD);
   assert(ObjectSynchronizer::current_thread_holds_lock(
            JavaThread::current(), h_lock),
@@ -122,7 +122,7 @@
   // to hold the pending list lock. We want to free this handle.
   HandleMark hm;
 
-  Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
+  Handle h_lock(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(java_lang_ref_Reference::pending_list_lock()));
   assert(ObjectSynchronizer::current_thread_holds_lock(
            JavaThread::current(), h_lock),
          "Lock should be held");
--- a/src/share/vm/oops/klass.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/klass.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -556,7 +556,7 @@
   return NULL;
 }
 
-oop Klass::class_loader() const { return oopDesc::bs()->resolve_oop(class_loader_data()->class_loader()); }
+oop Klass::class_loader() const { return class_loader_data()->class_loader(); }
 
 const char* Klass::external_name() const {
   if (oop_is_instance()) {
--- a/src/share/vm/oops/klass.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/klass.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -25,7 +25,6 @@
 #ifndef SHARE_VM_OOPS_KLASS_HPP
 #define SHARE_VM_OOPS_KLASS_HPP
 
-#include "gc/shared/barrierSet.hpp"
 #include "gc/shared/specialized_oop_closures.hpp"
 #include "memory/iterator.hpp"
 #include "memory/memRegion.hpp"
@@ -224,7 +223,7 @@
   void klass_oop_store(volatile oop* p, oop v);
 
   // java mirror
-  oop java_mirror() const              { return oopDesc::bs()->resolve_oop(_java_mirror); }
+  oop java_mirror() const              { return _java_mirror; }
   void set_java_mirror(oop m) { klass_oop_store(&_java_mirror, m); }
 
   // modifier flags
--- a/src/share/vm/oops/objArrayKlass.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/objArrayKlass.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -200,7 +200,6 @@
       for (int index = 0; index < length; index++) {
         ArrayKlass* ak = ArrayKlass::cast(h_lower_dimension());
         oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
-	h_array = objArrayHandle(THREAD, (objArrayOop)oopDesc::bs()->resolve_and_maybe_copy_oop(h_array()));
         h_array->obj_at_put(index, sub_array);
       }
     } else {
@@ -299,6 +298,10 @@
   if (length==0) {
     return;
   }
+
+  s = arrayOop(oopDesc::bs()->resolve_oop(s));
+  d = arrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(d));
+
   if (UseCompressedOops) {
     narrowOop* const src = objArrayOop(s)->obj_at_addr<narrowOop>(src_pos);
     narrowOop* const dst = objArrayOop(d)->obj_at_addr<narrowOop>(dst_pos);
--- a/src/share/vm/oops/objArrayOop.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/objArrayOop.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_OOPS_OBJARRAYOOP_HPP
 #define SHARE_VM_OOPS_OBJARRAYOOP_HPP
 
+#include "gc/shared/barrierSet.hpp"
 #include "gc/shared/specialized_oop_closures.hpp"
 #include "oops/arrayOop.hpp"
 
@@ -82,15 +83,11 @@
   oop obj_at(int index) const;
 
   void obj_at_put(int index, oop value) {
-    objArrayOop forwarded_copy = 
-      (objArrayOop) oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-    if ((oopDesc*) forwarded_copy != this)
-      return forwarded_copy->obj_at_put(index, value);
-
+    objArrayOop p = (objArrayOop) oopDesc::bs()->resolve_and_maybe_copy_oop(this);
     if (UseCompressedOops) {
-      oop_store(obj_at_addr<narrowOop>(index), value);
+      oop_store(p->obj_at_addr<narrowOop>(index), value);
     } else {
-      oop_store(obj_at_addr<oop>(index), value);
+      oop_store(p->obj_at_addr<oop>(index), value);
     }
   }
 
--- a/src/share/vm/oops/objArrayOop.inline.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/objArrayOop.inline.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -30,12 +30,13 @@
 #include "runtime/globals.hpp"
 
 inline oop objArrayOopDesc::obj_at(int index) const {
+  objArrayOop p = (objArrayOop) oopDesc::bs()->resolve_oop((oop) this);
   // With UseCompressedOops decode the narrow oop in the objArray to an
   // uncompressed oop.  Otherwise this is simply a "*" operator.
   if (UseCompressedOops) {
-    return load_decode_heap_oop(obj_at_addr<narrowOop>(index));
+    return load_decode_heap_oop(p->obj_at_addr<narrowOop>(index));
   } else {
-    return load_decode_heap_oop(obj_at_addr<oop>(index));
+    return load_decode_heap_oop(p->obj_at_addr<oop>(index));
   }
 }
 
--- a/src/share/vm/oops/oop.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/oop.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -100,7 +100,7 @@
   // slow case; we have to acquire the micro lock in order to locate the header
   ResetNoHandleMark rnm; // Might be called from LEAF/QUICK ENTRY
   HandleMark hm;
-  Handle object(this);
+  Handle object(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
   return ObjectSynchronizer::identity_hash_value_for(object);
 }
 
--- a/src/share/vm/oops/oop.inline.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/oop.inline.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -134,7 +134,7 @@
 inline bool oopDesc::is_objArray()            const { return klass()->oop_is_objArray(); }
 inline bool oopDesc::is_typeArray()           const { return klass()->oop_is_typeArray(); }
 
-inline void*     oopDesc::field_base(int offset)        const { return (void*)&((char*)(oopDesc*)bs()->resolve_oop((oop) this))[offset]; }
+inline void*     oopDesc::field_base(int offset)        const { return (void*)&((char*)this)[offset]; }
 
 template <class T> inline T* oopDesc::obj_field_addr(int offset) const { return (T*)field_base(offset); }
 inline Metadata** oopDesc::metadata_field_addr(int offset) const { return (Metadata**)field_base(offset); }
@@ -280,43 +280,35 @@
 // In order to put or get a field out of an instance, must first check
 // if the field has been compressed and uncompress it.
 inline oop oopDesc::obj_field(int offset) const {
+  oop p = bs()->resolve_oop((oop) this);
   return UseCompressedOops ?
-    load_decode_heap_oop(obj_field_addr<narrowOop>(offset)) :
-    load_decode_heap_oop(obj_field_addr<oop>(offset));
+    load_decode_heap_oop(p->obj_field_addr<narrowOop>(offset)) :
+    load_decode_heap_oop(p->obj_field_addr<oop>(offset));
 }
 
 inline void oopDesc::obj_field_put(int offset, oop value) {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this)
-    return forwarded_copy->obj_field_put(offset, value);
-
-  value = oopDesc::bs()->resolve_oop(value);
-
-  UseCompressedOops ? oop_store(obj_field_addr<narrowOop>(offset), value) :
-                      oop_store(obj_field_addr<oop>(offset),       value);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  value = bs()->resolve_oop(value);
+  UseCompressedOops ? oop_store(p->obj_field_addr<narrowOop>(offset), value) :
+                      oop_store(p->obj_field_addr<oop>(offset),       value);
 }
 
 inline Metadata* oopDesc::metadata_field(int offset) const {
-  return *metadata_field_addr(offset);
+  oop p = bs()->resolve_oop((oop) this);
+  return *p->metadata_field_addr(offset);
 }
 
 inline void oopDesc::metadata_field_put(int offset, Metadata* value) {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->metadata_field_put(offset, value);
-  }
-  *metadata_field_addr(offset) = value;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->metadata_field_addr(offset) = value;
 }
 
 inline void oopDesc::obj_field_put_raw(int offset, oop value) {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->obj_field_put_raw(offset, value);
-  }
-  value = oopDesc::bs()->resolve_oop(value);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  value = bs()->resolve_oop(value);
   UseCompressedOops ?
-    encode_store_heap_oop(obj_field_addr<narrowOop>(offset), value) :
-    encode_store_heap_oop(obj_field_addr<oop>(offset),       value);
+    encode_store_heap_oop(p->obj_field_addr<narrowOop>(offset), value) :
+    encode_store_heap_oop(p->obj_field_addr<oop>(offset),       value);
 }
 inline void oopDesc::obj_field_put_volatile(int offset, oop value) {
   OrderAccess::release();
@@ -324,187 +316,182 @@
   OrderAccess::fence();
 }
 
-inline jbyte oopDesc::byte_field(int offset) const                  { return (jbyte) *byte_field_addr(offset);    }
+inline jbyte oopDesc::byte_field(int offset) const                  {
+  oop p = bs()->resolve_oop((oop) this);
+  return (jbyte) *p->byte_field_addr(offset);
+}
 inline void oopDesc::byte_field_put(int offset, jbyte contents)     {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->byte_field_put(offset, contents);
-  }
- *byte_field_addr(offset) = (jint) contents;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->byte_field_addr(offset) = (jint) contents;
 }
 
-inline jboolean oopDesc::bool_field(int offset) const               { return (jboolean) *bool_field_addr(offset); }
+inline jboolean oopDesc::bool_field(int offset) const               {
+  oop p = bs()->resolve_oop((oop) this);
+  return (jboolean) *p->bool_field_addr(offset);
+}
 inline void oopDesc::bool_field_put(int offset, jboolean contents)  {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->bool_field_put(offset, contents);
-  }
- *bool_field_addr(offset) = (jint) contents;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->bool_field_addr(offset) = (jint) contents;
 }
 
-inline jchar oopDesc::char_field(int offset) const                  { return (jchar) *char_field_addr(offset);    }
+inline jchar oopDesc::char_field(int offset) const                  {
+  oop p = bs()->resolve_oop((oop) this);
+  return (jchar) *p->char_field_addr(offset);
+}
 inline void oopDesc::char_field_put(int offset, jchar contents)     {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->char_field_put(offset, contents);
-  }
- *char_field_addr(offset) = (jint) contents;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->char_field_addr(offset) = (jint) contents;
 }
 
-inline jint oopDesc::int_field(int offset) const                    { return *int_field_addr(offset);        }
+inline jint oopDesc::int_field(int offset) const                    {
+  oop p = bs()->resolve_oop((oop) this);
+  return *p->int_field_addr(offset);
+}
 inline void oopDesc::int_field_put(int offset, jint contents)       {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->int_field_put(offset, contents);
-  }
- *int_field_addr(offset) = contents;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->int_field_addr(offset) = contents;
 }
 
-inline jshort oopDesc::short_field(int offset) const                { return (jshort) *short_field_addr(offset);  }
+inline jshort oopDesc::short_field(int offset) const                {
+  oop p = bs()->resolve_oop((oop) this);
+  return (jshort) *p->short_field_addr(offset);
+}
 inline void oopDesc::short_field_put(int offset, jshort contents)   {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->short_field_put(offset, contents);
-  }
- *short_field_addr(offset) = (jint) contents;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->short_field_addr(offset) = (jint) contents;
 }
 
-inline jlong oopDesc::long_field(int offset) const                  { return *long_field_addr(offset);       }
+inline jlong oopDesc::long_field(int offset) const                  {
+  oop p = bs()->resolve_oop((oop) this);
+  return *p->long_field_addr(offset);
+}
 inline void oopDesc::long_field_put(int offset, jlong contents)     {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->long_field_put(offset, contents);
-  }
- *long_field_addr(offset) = contents;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->long_field_addr(offset) = contents;
 }
 
-inline jfloat oopDesc::float_field(int offset) const                { return *float_field_addr(offset);      }
+inline jfloat oopDesc::float_field(int offset) const                {
+  oop p = bs()->resolve_oop((oop) this);
+  return *p->float_field_addr(offset);
+}
 inline void oopDesc::float_field_put(int offset, jfloat contents)   {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->float_field_put(offset, contents);
-  }
- *float_field_addr(offset) = contents;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->float_field_addr(offset) = contents;
 }
 
-inline jdouble oopDesc::double_field(int offset) const              { return *double_field_addr(offset);     }
+inline jdouble oopDesc::double_field(int offset) const              {
+  oop p = bs()->resolve_oop((oop) this);
+  return *p->double_field_addr(offset);
+}
 inline void oopDesc::double_field_put(int offset, jdouble contents) {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->double_field_put(offset, contents);
-  }
- *double_field_addr(offset) = contents;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->double_field_addr(offset) = contents;
 }
 
-inline address oopDesc::address_field(int offset) const              { return *address_field_addr(offset);     }
+inline address oopDesc::address_field(int offset) const              {
+  oop p = bs()->resolve_oop((oop) this);
+  return *p->address_field_addr(offset);
+}
 inline void oopDesc::address_field_put(int offset, address contents) {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->address_field_put(offset, contents);
-  }
- *address_field_addr(offset) = contents;
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  *p->address_field_addr(offset) = contents;
 }
 
 inline oop oopDesc::obj_field_acquire(int offset) const {
+  oop p = bs()->resolve_oop((oop) this);
   return UseCompressedOops ?
              decode_heap_oop((narrowOop)
-               OrderAccess::load_acquire(obj_field_addr<narrowOop>(offset)))
+               OrderAccess::load_acquire(p->obj_field_addr<narrowOop>(offset)))
            : decode_heap_oop((oop)
-               OrderAccess::load_ptr_acquire(obj_field_addr<oop>(offset)));
+               OrderAccess::load_ptr_acquire(p->obj_field_addr<oop>(offset)));
 }
 inline void oopDesc::release_obj_field_put(int offset, oop value) {
-  oopDesc* forwarded_copy =
-    (oopDesc*) oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-
-  value = oopDesc::bs()->resolve_oop(value);
-
-  if (forwarded_copy != this)
-    return forwarded_copy->release_obj_field_put(offset, value);
-
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  value = bs()->resolve_oop(value);
   UseCompressedOops ?
-    oop_store((volatile narrowOop*)obj_field_addr<narrowOop>(offset), value) :
-    oop_store((volatile oop*)      obj_field_addr<oop>(offset),       value);
+    oop_store((volatile narrowOop*)p->obj_field_addr<narrowOop>(offset), value) :
+    oop_store((volatile oop*)      p->obj_field_addr<oop>(offset),       value);
 }
 
-inline jbyte oopDesc::byte_field_acquire(int offset) const                  { return OrderAccess::load_acquire(byte_field_addr(offset));     }
+inline jbyte oopDesc::byte_field_acquire(int offset) const                  {
+  oop p = bs()->resolve_oop((oop) this);
+  return OrderAccess::load_acquire(p->byte_field_addr(offset));
+}
 inline void oopDesc::release_byte_field_put(int offset, jbyte contents)     {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->release_bool_field_put(offset, contents);
-  }
- OrderAccess::release_store(byte_field_addr(offset), contents);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  OrderAccess::release_store(p->byte_field_addr(offset), contents);
 }
 
-inline jboolean oopDesc::bool_field_acquire(int offset) const               { return OrderAccess::load_acquire(bool_field_addr(offset));     }
+inline jboolean oopDesc::bool_field_acquire(int offset) const               {
+  oop p = bs()->resolve_oop((oop) this);
+  return OrderAccess::load_acquire(p->bool_field_addr(offset));
+}
 inline void oopDesc::release_bool_field_put(int offset, jboolean contents)  {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->release_bool_field_put(offset, contents);
-  }
- OrderAccess::release_store(bool_field_addr(offset), contents);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  OrderAccess::release_store(p->bool_field_addr(offset), contents);
 }
 
-inline jchar oopDesc::char_field_acquire(int offset) const                  { return OrderAccess::load_acquire(char_field_addr(offset));     }
+inline jchar oopDesc::char_field_acquire(int offset) const                  {
+  oop p = bs()->resolve_oop((oop) this);
+  return OrderAccess::load_acquire(p->char_field_addr(offset));
+}
 inline void oopDesc::release_char_field_put(int offset, jchar contents)     {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->release_char_field_put(offset, contents);
-  }
- OrderAccess::release_store(char_field_addr(offset), contents);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  OrderAccess::release_store(p->char_field_addr(offset), contents);
 }
 
-inline jint oopDesc::int_field_acquire(int offset) const                    { return OrderAccess::load_acquire(int_field_addr(offset));      }
+inline jint oopDesc::int_field_acquire(int offset) const                    {
+  oop p = bs()->resolve_oop((oop) this);
+  return OrderAccess::load_acquire(p->int_field_addr(offset));
+}
 inline void oopDesc::release_int_field_put(int offset, jint contents)       {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->release_int_field_put(offset, contents);
-  }
- OrderAccess::release_store(int_field_addr(offset), contents);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  OrderAccess::release_store(p->int_field_addr(offset), contents);
 }
 
-inline jshort oopDesc::short_field_acquire(int offset) const                { return (jshort)OrderAccess::load_acquire(short_field_addr(offset)); }
+inline jshort oopDesc::short_field_acquire(int offset) const                {
+  oop p = bs()->resolve_oop((oop) this);
+  return (jshort)OrderAccess::load_acquire(p->short_field_addr(offset));
+}
 inline void oopDesc::release_short_field_put(int offset, jshort contents)   {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->release_short_field_put(offset, contents);
-  }
- OrderAccess::release_store(short_field_addr(offset), contents);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  OrderAccess::release_store(p->short_field_addr(offset), contents);
 }
 
-inline jlong oopDesc::long_field_acquire(int offset) const                  { return OrderAccess::load_acquire(long_field_addr(offset));       }
+inline jlong oopDesc::long_field_acquire(int offset) const                  {
+  oop p = bs()->resolve_oop((oop) this);
+  return OrderAccess::load_acquire(p->long_field_addr(offset));
+}
 inline void oopDesc::release_long_field_put(int offset, jlong contents)     {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->release_long_field_put(offset, contents);
-  }
- OrderAccess::release_store(long_field_addr(offset), contents);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  OrderAccess::release_store(p->long_field_addr(offset), contents);
 }
 
-inline jfloat oopDesc::float_field_acquire(int offset) const                { return OrderAccess::load_acquire(float_field_addr(offset));      }
+inline jfloat oopDesc::float_field_acquire(int offset) const                {
+  oop p = bs()->resolve_oop((oop) this);
+  return OrderAccess::load_acquire(p->float_field_addr(offset));
+}
 inline void oopDesc::release_float_field_put(int offset, jfloat contents)   {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->release_float_field_put(offset, contents);
-  }
- OrderAccess::release_store(float_field_addr(offset), contents);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  OrderAccess::release_store(p->float_field_addr(offset), contents);
 }
 
-inline jdouble oopDesc::double_field_acquire(int offset) const              { return OrderAccess::load_acquire(double_field_addr(offset));     }
+inline jdouble oopDesc::double_field_acquire(int offset) const              {
+  oop p = bs()->resolve_oop((oop) this);
+  return OrderAccess::load_acquire(p->double_field_addr(offset));
+}
 inline void oopDesc::release_double_field_put(int offset, jdouble contents) {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->release_double_field_put(offset, contents);
-  }
- OrderAccess::release_store(double_field_addr(offset), contents);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  OrderAccess::release_store(p->double_field_addr(offset), contents);
 }
 
-inline address oopDesc::address_field_acquire(int offset) const             { return (address) OrderAccess::load_ptr_acquire(address_field_addr(offset)); }
+inline address oopDesc::address_field_acquire(int offset) const             {
+  oop p = bs()->resolve_oop((oop) this);
+  return (address) OrderAccess::load_ptr_acquire(p->address_field_addr(offset));
+}
 inline void oopDesc::release_address_field_put(int offset, address contents) {
-  oopDesc* forwarded_copy = oopDesc::bs()->resolve_and_maybe_copy_oop(this);
-  if (forwarded_copy != this) {
-    return forwarded_copy->release_address_field_put(offset, contents);
-  }
- OrderAccess::release_store_ptr(address_field_addr(offset), contents);
+  oop p = bs()->resolve_and_maybe_copy_oop(this);
+  OrderAccess::release_store_ptr(p->address_field_addr(offset), contents);
 }
 
 inline int oopDesc::size_given_klass(Klass* klass)  {
--- a/src/share/vm/oops/typeArrayKlass.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/typeArrayKlass.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -148,6 +148,9 @@
   if (length == 0)
     return;
 
+  s = arrayOop(oopDesc::bs()->resolve_oop(s));
+  d = arrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(d));
+
   // This is an attempt to make the copy_array fast.
   int l2es = log2_element_size();
   int ihs = array_header_in_bytes() / wordSize;
--- a/src/share/vm/oops/typeArrayOop.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/oops/typeArrayOop.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_OOPS_TYPEARRAYOOP_HPP
 #define SHARE_VM_OOPS_TYPEARRAYOOP_HPP
 
+#include "gc/shared/barrierSet.hpp"
 #include "oops/arrayOop.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "runtime/orderAccess.inline.hpp"
@@ -92,50 +93,116 @@
     return &double_base()[which];
   }
 
-  jbyte byte_at(int which) const                  { return *byte_at_addr(which); }
-  void byte_at_put(int which, jbyte contents)     { *byte_at_addr(which) = contents; }
+  jbyte byte_at(int which) const                  {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return *p->byte_at_addr(which);
+  }
+  void byte_at_put(int which, jbyte contents)     {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->byte_at_addr(which) = contents;
+  }
 
-  jboolean bool_at(int which) const               { return *bool_at_addr(which); }
-  void bool_at_put(int which, jboolean contents)  { *bool_at_addr(which) = contents; }
+  jboolean bool_at(int which) const               {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return *p->bool_at_addr(which);
+  }
+  void bool_at_put(int which, jboolean contents)  {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->bool_at_addr(which) = contents;
+  }
 
-  jchar char_at(int which) const                  { return *char_at_addr(which); }
-  void char_at_put(int which, jchar contents)     { *char_at_addr(which) = contents; }
+  jchar char_at(int which) const                  {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return *p->char_at_addr(which);
+  }
+  void char_at_put(int which, jchar contents)     {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->char_at_addr(which) = contents;
+  }
 
-  jint int_at(int which) const                    { return *int_at_addr(which); }
-  void int_at_put(int which, jint contents)       { *int_at_addr(which) = contents; }
+  jint int_at(int which) const                    {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return *p->int_at_addr(which);
+  }
+  void int_at_put(int which, jint contents)       {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->int_at_addr(which) = contents;
+  }
 
-  jshort short_at(int which) const                { return *short_at_addr(which); }
-  void short_at_put(int which, jshort contents)   { *short_at_addr(which) = contents; }
+  jshort short_at(int which) const                {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return *p->short_at_addr(which);
+  }
+  void short_at_put(int which, jshort contents)   {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->short_at_addr(which) = contents;
+  }
 
-  jushort ushort_at(int which) const              { return *ushort_at_addr(which); }
-  void ushort_at_put(int which, jushort contents) { *ushort_at_addr(which) = contents; }
+  jushort ushort_at(int which) const              {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return *p->ushort_at_addr(which);
+  }
+  void ushort_at_put(int which, jushort contents) {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->ushort_at_addr(which) = contents;
+  }
 
-  jlong long_at(int which) const                  { return *long_at_addr(which); }
-  void long_at_put(int which, jlong contents)     { *long_at_addr(which) = contents; }
+  jlong long_at(int which) const                  {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return *p->long_at_addr(which);
+  }
+  void long_at_put(int which, jlong contents)     {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->long_at_addr(which) = contents;
+  }
 
-  jfloat float_at(int which) const                { return *float_at_addr(which); }
-  void float_at_put(int which, jfloat contents)   { *float_at_addr(which) = contents; }
+  jfloat float_at(int which) const                {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return *p->float_at_addr(which);
+  }
+  void float_at_put(int which, jfloat contents)   {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->float_at_addr(which) = contents;
+  }
 
-  jdouble double_at(int which) const              { return *double_at_addr(which); }
-  void double_at_put(int which, jdouble contents) { *double_at_addr(which) = contents; }
+  jdouble double_at(int which) const              {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return *p->double_at_addr(which);
+  }
+  void double_at_put(int which, jdouble contents) {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->double_at_addr(which) = contents;
+  }
 
-  jbyte byte_at_acquire(int which) const              { return OrderAccess::load_acquire(byte_at_addr(which)); }
-  void release_byte_at_put(int which, jbyte contents) { OrderAccess::release_store(byte_at_addr(which), contents); }
+  jbyte byte_at_acquire(int which) const              {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return OrderAccess::load_acquire(p->byte_at_addr(which));
+  }
+  void release_byte_at_put(int which, jbyte contents) {
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    OrderAccess::release_store(p->byte_at_addr(which), contents);
+  }
 
   // Java thinks metadata arrays are just arrays of either long or int, since
   // there doesn't seem to be T_ADDRESS, so this is a bit of unfortunate
   // casting
 #ifdef _LP64
   Metadata* metadata_at(int which) const {
-    return (Metadata*)*long_at_addr(which); }
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return (Metadata*)*p->long_at_addr(which);
+  }
   void metadata_at_put(int which, Metadata* contents) {
-    *long_at_addr(which) = (long)contents;
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->long_at_addr(which) = (long)contents;
   }
 #else
   Metadata* metadata_at(int which) const {
-    return (Metadata*)*int_at_addr(which); }
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_oop((oop) this));
+    return (Metadata*)*p->int_at_addr(which);
+  }
   void metadata_at_put(int which, Metadata* contents) {
-    *int_at_addr(which) = (int)contents;
+    typeArrayOop p = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(this));
+    *p->int_at_addr(which) = (int)contents;
   }
 #endif // _LP64
 
--- a/src/share/vm/opto/runtime.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/opto/runtime.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -423,7 +423,7 @@
   ResourceMark rm;
   jint len = dims->length();
   assert(len > 0, "Dimensions array should contain data");
-  jint *j_dims = typeArrayOop(dims)->int_at_addr(0);
+  jint *j_dims = typeArrayOop(oopDesc::bs()->resolve_oop(dims))->int_at_addr(0);
   jint *c_dims = NEW_RESOURCE_ARRAY(jint, len);
   Copy::conjoint_jints_atomic(j_dims, c_dims, len);
 
@@ -438,6 +438,7 @@
   // the dominant fast-path is to simply return.
   // Relatedly, it's critical that notify/notifyAll be fast in order to
   // reduce lock hold times.
+  obj = oopDesc::bs()->resolve_and_maybe_copy_oop(obj);
   if (!SafepointSynchronize::is_synchronizing()) {
     if (ObjectSynchronizer::quick_notify(obj, thread, false)) {
       return;
@@ -456,6 +457,7 @@
 
 JRT_BLOCK_ENTRY(void, OptoRuntime::monitor_notifyAll_C(oopDesc* obj, JavaThread *thread))
 
+  obj = oopDesc::bs()->resolve_and_maybe_copy_oop(obj);
   if (!SafepointSynchronize::is_synchronizing() ) {
     if (ObjectSynchronizer::quick_notify(obj, thread, true)) {
       return;
--- a/src/share/vm/prims/jni.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/prims/jni.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -336,7 +336,7 @@
   }
   ResourceMark rm(THREAD);
   ClassFileStream st((u1*) buf, bufLen, NULL);
-  Handle class_loader (THREAD, JNIHandles::resolve(loaderRef));
+  Handle class_loader (THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve(loaderRef)));
 
   if (UsePerfData && !class_loader.is_null()) {
     // check whether the current caller thread holds the lock or not.
@@ -823,6 +823,7 @@
   oop a = JNIHandles::resolve(r1);
   a = oopDesc::bs()->resolve_and_maybe_copy_oop(a);
   oop b = JNIHandles::resolve(r2);
+  b = oopDesc::bs()->resolve_and_maybe_copy_oop(b);
   jboolean ret = (a == b) ? JNI_TRUE : JNI_FALSE;
 
   HOTSPOT_JNI_ISSAMEOBJECT_RETURN(ret);
@@ -2170,7 +2171,6 @@
   JNIWrapper("SetObjectField");
   HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
   oop o = JNIHandles::resolve_non_null(obj);
-  o = oopDesc::bs()->resolve_and_maybe_copy_oop(o);
   Klass* k = o->klass();
   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
   // Keep JVMTI addition small and only check enabled flag here.
@@ -2195,7 +2195,6 @@
   EntryProbe; \
 \
   oop o = JNIHandles::resolve_non_null(obj); \
-  o = oopDesc::bs()->resolve_and_maybe_copy_oop(o); \
   Klass* k = o->klass(); \
   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);  \
   /* Keep JVMTI addition small and only check enabled flag here.       */ \
@@ -2405,9 +2404,7 @@
     field_value.unionType = value; \
     JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \
   } \
-  oop o = id->holder()->java_mirror(); \
-  o = oopDesc::bs()->resolve_and_maybe_copy_oop(o); \
-  o-> Fieldname##_field_put (id->offset(), value); \
+  id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \
   ReturnProbe;\
 JNI_END
 
@@ -2476,7 +2473,7 @@
  HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(env, string, (uintptr_t *) isCopy);
   jchar* buf = NULL;
   oop s = JNIHandles::resolve_non_null(string);
-  typeArrayOop s_value = java_lang_String::value(s);
+  typeArrayOop s_value = typeArrayOop(oopDesc::bs()->resolve_oop(java_lang_String::value(s)));
   if (s_value != NULL) {
     int s_len = java_lang_String::length(s);
     int s_offset = java_lang_String::offset(s);
@@ -2575,7 +2572,7 @@
 JNI_QUICK_ENTRY(jsize, jni_GetArrayLength(JNIEnv *env, jarray array))
   JNIWrapper("GetArrayLength");
  HOTSPOT_JNI_GETARRAYLENGTH_ENTRY(env, array);
-  arrayOop a = arrayOop(JNIHandles::resolve_non_null(array));
+  arrayOop a = arrayOop(oopDesc::bs()->resolve_oop(JNIHandles::resolve_non_null(array)));
   assert(a->is_array(), "must be array");
   jsize ret = a->length();
  HOTSPOT_JNI_GETARRAYLENGTH_RETURN(ret);
@@ -2638,7 +2635,6 @@
   DT_VOID_RETURN_MARK(SetObjectArrayElement);
 
   objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
-  a = objArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(a));
   oop v = JNIHandles::resolve(value);
   if (a->is_within_bounds(index)) {
     if (v == NULL || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
@@ -2725,6 +2721,7 @@
   EntryProbe; \
   /* allocate an chunk of memory in c land */ \
   typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
+  a = typeArrayOop(oopDesc::bs()->resolve_oop(a)); \
   ElementType* result; \
   int len = a->length(); \
   if (len == 0) { \
@@ -2834,6 +2831,7 @@
   EntryProbe; \
   DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \
   typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \
+  src = typeArrayOop(oopDesc::bs()->resolve_oop(src)); \
   if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \
     THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \
   } else { \
@@ -3083,7 +3081,7 @@
     THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
   }
 
-  Handle obj(thread, JNIHandles::resolve_non_null(jobj));
+  Handle obj(thread, oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve_non_null(jobj)));
   ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR));
   ret = JNI_OK;
   return ret;
@@ -3102,7 +3100,7 @@
     THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
   }
 
-  Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
+  Handle obj(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve_non_null(jobj)));
   ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
 
   ret = JNI_OK;
@@ -3121,6 +3119,7 @@
  HOTSPOT_JNI_GETSTRINGREGION_ENTRY(env, string, start, len, buf);
   DT_VOID_RETURN_MARK(GetStringRegion);
   oop s = JNIHandles::resolve_non_null(string);
+  s = oopDesc::bs()->resolve_oop(s);
   int s_len = java_lang_String::length(s);
   if (start < 0 || len < 0 || start + len > s_len) {
     THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
@@ -3128,6 +3127,7 @@
     if (len > 0) {
       int s_offset = java_lang_String::offset(s);
       typeArrayOop s_value = java_lang_String::value(s);
+      s_value = typeArrayOop(oopDesc::bs()->resolve_oop(s_value));
       memcpy(buf, s_value->char_at_addr(s_offset+start), sizeof(jchar)*len);
     }
   }
@@ -3201,6 +3201,7 @@
   oop s = JNIHandles::resolve_non_null(string);
   int s_len = java_lang_String::length(s);
   typeArrayOop s_value = java_lang_String::value(s);
+  s_value = typeArrayOop(oopDesc::bs()->resolve_oop(s_value));
   int s_offset = java_lang_String::offset(s);
   const jchar* ret;
   if (s_len > 0) {
--- a/src/share/vm/prims/jvm.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/prims/jvm.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -357,10 +357,7 @@
   assert(s->is_oop(), "JVM_ArrayCopy: src not an oop");
   assert(d->is_oop(), "JVM_ArrayCopy: dst not an oop");
   // Do copy
-  s->klass()->copy_array(s, src_pos, 
-			 (arrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(d))), 
-			  dst_pos,
-			 length, thread);
+  s->klass()->copy_array(s, src_pos, d, dst_pos, length, thread);
 JVM_END
 
 
@@ -554,13 +551,15 @@
 JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
   JVMWrapper("JVM_IHashCode");
   // as implemented in the classic virtual machine; return 0 if object is NULL
-  return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ;
+  return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve_non_null(handle))) ;
 JVM_END
 
 
 JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
   JVMWrapper("JVM_MonitorWait");
-  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
+  oop o = JNIHandles::resolve_non_null(handle);
+  o = oopDesc::bs()->resolve_and_maybe_copy_oop(o);
+  Handle obj(THREAD, o);
   JavaThreadInObjectWaitState jtiows(thread, ms != 0);
   if (JvmtiExport::should_post_monitor_wait()) {
     JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);
@@ -577,14 +576,14 @@
 
 JVM_ENTRY(void, JVM_MonitorNotify(JNIEnv* env, jobject handle))
   JVMWrapper("JVM_MonitorNotify");
-  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
+  Handle obj(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve_non_null(handle)));
   ObjectSynchronizer::notify(obj, CHECK);
 JVM_END
 
 
 JVM_ENTRY(void, JVM_MonitorNotifyAll(JNIEnv* env, jobject handle))
   JVMWrapper("JVM_MonitorNotifyAll");
-  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
+  Handle obj(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve_non_null(handle)));
   ObjectSynchronizer::notifyall(obj, CHECK);
 JVM_END
 
@@ -898,7 +897,7 @@
 
   ResourceMark rm(THREAD);
   ClassFileStream st((u1*) buf, len, (char *)source);
-  Handle class_loader (THREAD, JNIHandles::resolve(loader));
+  Handle class_loader (THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve(loader)));
   if (UsePerfData) {
     is_lock_held_by_thread(class_loader,
                            ClassLoader::sync_JVMDefineClassLockFreeCounter(),
@@ -962,7 +961,7 @@
   // Security Note:
   //   The Java level wrapper will perform the necessary security check allowing
   //   us to pass the NULL as the initiating class loader.
-  Handle h_loader(THREAD, JNIHandles::resolve(loader));
+  Handle h_loader(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve(loader)));
   if (UsePerfData) {
     is_lock_held_by_thread(h_loader,
                            ClassLoader::sync_JVMFindLoadedClassLockFreeCounter(),
@@ -3031,7 +3030,7 @@
   if (obj == NULL) {
     THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
   }
-  Handle h_obj(THREAD, JNIHandles::resolve(obj));
+  Handle h_obj(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve(obj)));
   return ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, h_obj);
 JVM_END
 
@@ -3321,7 +3320,6 @@
 JVM_ENTRY(void, JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val))
   JVMWrapper("JVM_SetArrayElement");
   arrayOop a = check_array(env, arr, false, CHECK);
-  a = arrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(a));
   oop box = JNIHandles::resolve(val);
   jvalue value;
   value.i = 0; // to initialize value before getting used in CHECK
@@ -3339,7 +3337,6 @@
 JVM_ENTRY(void, JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v, unsigned char vCode))
   JVMWrapper("JVM_SetPrimitiveArrayElement");
   arrayOop a = check_array(env, arr, true, CHECK);
-  a = arrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(a));
   assert(a->is_typeArray(), "just checking");
   BasicType value_type = (BasicType) vCode;
   Reflection::array_set(&v, a, index, value_type, CHECK);
--- a/src/share/vm/prims/jvmtiEnv.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/prims/jvmtiEnv.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -467,7 +467,7 @@
     // lock the loader
     Thread* thread = Thread::current();
     HandleMark hm;
-    Handle loader_lock = Handle(thread, SystemDictionary::system_loader_lock());
+    Handle loader_lock = Handle(thread, oopDesc::bs()->resolve_and_maybe_copy_oop(SystemDictionary::system_loader_lock()));
 
     ObjectLocker ol(loader_lock, thread);
 
@@ -513,7 +513,7 @@
 
     // lock the loader
     Thread* THREAD = Thread::current();
-    Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
+    Handle loader = Handle(THREAD, oopDesc::bs()->resolve_and_maybe_copy_oop(SystemDictionary::java_system_loader()));
 
     ObjectLocker ol(loader, THREAD);
 
--- a/src/share/vm/prims/unsafe.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/prims/unsafe.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -126,8 +126,7 @@
       // gets moved by concurrent threads while executing this code.
       p = oopDesc::bs()->resolve_and_maybe_copy_oop(p);
       void* ptr_plus_disp = (address)p + byte_offset;
-      void* obj_field_addr = (void*)p->obj_field_addr<oop>((jint)byte_offset); 
-      assert(obj_field_addr == ptr_plus_disp,
+      assert((void*)p->obj_field_addr<oop>((jint)byte_offset) == ptr_plus_disp,
              "raw [ptr+disp] must be consistent with oop::field_base");
     }
     jlong p_size = HeapWordSize * (jlong)(p->size());
@@ -160,6 +159,7 @@
 
 #define GET_FIELD(obj, offset, type_name, v) \
   oop p = JNIHandles::resolve(obj); \
+  p = oopDesc::bs()->resolve_oop(p); \
   type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset)
 
 #define SET_FIELD(obj, offset, type_name, x) \
@@ -169,6 +169,7 @@
 
 #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
   oop p = JNIHandles::resolve(obj); \
+  p = oopDesc::bs()->resolve_oop(p); \
   if (support_IRIW_for_not_multiple_copy_atomic_cpu) { \
     OrderAccess::fence(); \
   } \
@@ -188,6 +189,7 @@
 UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
   UnsafeWrapper("Unsafe_GetObject");
   oop p = JNIHandles::resolve(obj);
+  p = oopDesc::bs()->resolve_oop(p);
   oop v;
   if (UseCompressedOops) {
     narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset);
@@ -225,7 +227,7 @@
 
 UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
   UnsafeWrapper("Unsafe_SetObject");
-  oop x = JNIHandles::resolve(x_h);
+  oop x = oopDesc::bs()->resolve_oop(JNIHandles::resolve(x_h));
   oop p = oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve(obj));
   if (UseCompressedOops) {
     oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
@@ -237,6 +239,7 @@
 UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
   UnsafeWrapper("Unsafe_GetObjectVolatile");
   oop p = JNIHandles::resolve(obj);
+  p = oopDesc::bs()->resolve_oop(p);
   void* addr = index_oop_from_field_offset_long(p, offset);
   volatile oop v;
   if (UseCompressedOops) {
@@ -253,6 +256,7 @@
   UnsafeWrapper("Unsafe_SetObjectVolatile");
   oop x = JNIHandles::resolve(x_h);
   oop p = JNIHandles::resolve(obj);
+  x = oopDesc::bs()->resolve_oop(x);
   p = oopDesc::bs()->resolve_and_maybe_copy_oop(p);
   void* addr = index_oop_from_field_offset_long(p, offset);
   OrderAccess::release();
@@ -320,7 +324,7 @@
       return v;
     }
     else {
-      Handle p (THREAD, JNIHandles::resolve(obj));
+      Handle p (THREAD, oopDesc::bs()->resolve_oop(JNIHandles::resolve(obj)));
       jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
       MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
       jlong value = Atomic::load(addr);
@@ -443,6 +447,7 @@
   UnsafeWrapper("Unsafe_SetOrderedObject");
   oop x = JNIHandles::resolve(x_h);
   oop p = JNIHandles::resolve(obj);
+  x = oopDesc::bs()->resolve_oop(x);
   p = oopDesc::bs()->resolve_and_maybe_copy_oop(p);
   void* addr = index_oop_from_field_offset_long(p, offset);
   OrderAccess::release();
@@ -660,6 +665,7 @@
   }
   oop srcp = JNIHandles::resolve(srcObj);
   oop dstp = JNIHandles::resolve(dstObj);
+  srcp = oopDesc::bs()->resolve_oop(srcp);
   dstp = oopDesc::bs()->resolve_and_maybe_copy_oop(dstp);
   if (dstp != NULL && !dstp->is_typeArray()) {
     // NYI:  This works only for non-oop arrays at present.
@@ -1097,6 +1103,7 @@
   oop p = oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve(obj));
   HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
   oop x = JNIHandles::resolve(x_h);
+  x = oopDesc::bs()->resolve_oop(x);
   oop old = JNIHandles::resolve(e_h);
   jboolean success;
   if (UseShenandoahGC) {
@@ -1199,7 +1206,7 @@
   double la[max_nelem];
   jint ret;
 
-  typeArrayOop a = typeArrayOop(oopDesc::bs()->resolve_and_maybe_copy_oop(JNIHandles::resolve_non_null(loadavg)));
+  typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(loadavg));
   assert(a->is_typeArray(), "must be type array");
 
   if (nelem < 0 || nelem > max_nelem || a->length() < nelem) {
--- a/src/share/vm/runtime/basicLock.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/basicLock.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -62,8 +62,14 @@
 
  public:
   // Manipulation
-  oop      obj() const                                { return oopDesc::bs()->resolve_oop(_obj);  }
-  void set_obj(oop obj)                               { _obj = obj; }
+  oop      obj() const                                {
+    assert(_obj == oopDesc::bs()->resolve_and_maybe_copy_oop(_obj), "expect to-space copy");
+    return _obj;
+  }
+  void set_obj(oop obj)                               {
+    _obj = obj;
+    assert(_obj == oopDesc::bs()->resolve_and_maybe_copy_oop(_obj), "expect to-space copy");
+  }
   BasicLock* lock()                                   { return &_lock; }
 
   // Note: Use frame::interpreter_frame_monitor_size() for the size of BasicObjectLocks
--- a/src/share/vm/runtime/biasedLocking.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/biasedLocking.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -146,6 +146,7 @@
 
 
 static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) {
+  assert(obj == oopDesc::bs()->resolve_oop(obj), "expect to-space copy");
   markOop mark = obj->mark();
   if (!mark->has_bias_pattern()) {
     if (TraceBiasedLocking) {
@@ -325,7 +326,7 @@
                                                                    bool attempt_rebias_of_object,
                                                                    JavaThread* requesting_thread) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint");
-
+  assert(o == oopDesc::bs()->resolve_oop(o), "expect to-space copy");
   if (TraceBiasedLocking) {
     tty->print_cr("* Beginning bulk revocation (kind == %s) because of object "
                   INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
@@ -367,6 +368,7 @@
           if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
             // We might have encountered this object already in the case of recursive locking
             assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment");
+	    assert(owner == oopDesc::bs()->resolve_oop(owner), "expect to-space copy");
             owner->set_mark(mark->set_bias_epoch(cur_epoch));
           }
         }
@@ -531,14 +533,13 @@
 BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) {
   assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint");
 
-  Handle n_obj(THREAD,
-	       oopDesc::bs()->resolve_and_maybe_copy_oop(obj()));
+  assert(obj() == oopDesc::bs()->resolve_oop(obj()), "must be to-space copy");
 
   // We can revoke the biases of anonymously-biased objects
   // efficiently enough that we should not cause these revocations to
   // update the heuristics because doing so may cause unwanted bulk
   // revocations (which are expensive) to occur.
-  markOop mark = n_obj->mark();
+  markOop mark = obj->mark();
   if (mark->is_biased_anonymously() && !attempt_rebias) {
     // We are probably trying to revoke the bias of this object due to
     // an identity hash code computation. Try to revoke the bias
@@ -548,12 +549,12 @@
     // the bias of the object.
     markOop biased_value       = mark;
     markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
-    markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, n_obj->mark_addr(), mark);
+    markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark);
     if (res_mark == biased_value) {
       return BIAS_REVOKED;
     }
   } else if (mark->has_bias_pattern()) {
-    Klass* k = n_obj->klass();
+    Klass* k = obj->klass();
     markOop prototype_header = k->prototype_header();
     if (!prototype_header->has_bias_pattern()) {
       // This object has a stale bias from before the bulk revocation
@@ -563,8 +564,8 @@
       // by another thread so we simply return and let the caller deal
       // with it.
       markOop biased_value       = mark;
-      markOop res_mark = (markOop) Atomic::cmpxchg_ptr(prototype_header, n_obj->mark_addr(), mark);
-      assert(!(*(n_obj->mark_addr()))->has_bias_pattern(), "even if we raced, should still be revoked");
+      markOop res_mark = (markOop) Atomic::cmpxchg_ptr(prototype_header, obj->mark_addr(), mark);
+      assert(!(*(obj->mark_addr()))->has_bias_pattern(), "even if we raced, should still be revoked");
       return BIAS_REVOKED;
     } else if (prototype_header->bias_epoch() != mark->bias_epoch()) {
       // The epoch of this biasing has expired indicating that the
@@ -578,14 +579,14 @@
         assert(THREAD->is_Java_thread(), "");
         markOop biased_value       = mark;
         markOop rebiased_prototype = markOopDesc::encode((JavaThread*) THREAD, mark->age(), prototype_header->bias_epoch());
-        markOop res_mark = (markOop) Atomic::cmpxchg_ptr(rebiased_prototype, n_obj->mark_addr(), mark);
+        markOop res_mark = (markOop) Atomic::cmpxchg_ptr(rebiased_prototype, obj->mark_addr(), mark);
         if (res_mark == biased_value) {
           return BIAS_REVOKED_AND_REBIASED;
         }
       } else {
         markOop biased_value       = mark;
         markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
-        markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, n_obj->mark_addr(), mark);
+        markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark);
         if (res_mark == biased_value) {
           return BIAS_REVOKED;
         }
@@ -593,11 +594,11 @@
     }
   }
 
-  HeuristicsResult heuristics = update_heuristics(n_obj(), attempt_rebias);
+  HeuristicsResult heuristics = update_heuristics(obj(), attempt_rebias);
   if (heuristics == HR_NOT_BIASED) {
     return NOT_BIASED;
   } else if (heuristics == HR_SINGLE_REVOKE) {
-    Klass *k = n_obj->klass();
+    Klass *k = obj->klass();
     markOop prototype_header = k->prototype_header();
     if (mark->biased_locker() == THREAD &&
         prototype_header->bias_epoch() == mark->bias_epoch()) {
@@ -614,12 +615,12 @@
       if (TraceBiasedLocking) {
         tty->print_cr("Revoking bias by walking my own stack:");
       }
-      BiasedLocking::Condition cond = revoke_bias(n_obj(), false, false, (JavaThread*) THREAD);
+      BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD);
       ((JavaThread*) THREAD)->set_cached_monitor_info(NULL);
       assert(cond == BIAS_REVOKED, "why not?");
       return cond;
     } else {
-      VM_RevokeBias revoke(&n_obj, (JavaThread*) THREAD);
+      VM_RevokeBias revoke(&obj, (JavaThread*) THREAD);
       VMThread::execute(&revoke);
       return revoke.status_code();
     }
@@ -627,7 +628,7 @@
 
   assert((heuristics == HR_BULK_REVOKE) ||
          (heuristics == HR_BULK_REBIAS), "?");
-  VM_BulkRevokeBias bulk_revoke(&n_obj, (JavaThread*) THREAD,
+  VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*) THREAD,
                                 (heuristics == HR_BULK_REBIAS),
                                 attempt_rebias);
   VMThread::execute(&bulk_revoke);
@@ -648,6 +649,7 @@
 void BiasedLocking::revoke_at_safepoint(Handle h_obj) {
   assert(SafepointSynchronize::is_at_safepoint(), "must only be called while at safepoint");
   oop obj = h_obj();
+  assert(obj == oopDesc::bs()->resolve_oop(obj), "expect to-space copy");
   HeuristicsResult heuristics = update_heuristics(obj, false);
   if (heuristics == HR_SINGLE_REVOKE) {
     revoke_bias(obj, false, false, NULL);
@@ -711,6 +713,7 @@
             MonitorInfo* mon_info = monitors->at(i);
             if (mon_info->owner_is_scalar_replaced()) continue;
             oop owner = mon_info->owner();
+	    assert(owner == oopDesc::bs()->resolve_oop(owner), "expect to-space copy");
             if (owner != NULL) {
               markOop mark = owner->mark();
               if (mark->has_bias_pattern()) {
--- a/src/share/vm/runtime/deoptimization.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -935,7 +935,7 @@
     if (mon_info->eliminated()) {
       assert(!mon_info->owner_is_scalar_replaced() || realloc_failures, "reallocation was missed");
       if (!mon_info->owner_is_scalar_replaced()) {
-        Handle obj = Handle(mon_info->owner());
+        Handle obj = Handle(oopDesc::bs()->resolve_and_maybe_copy_oop(mon_info->owner()));
         markOop mark = obj->mark();
         if (UseBiasedLocking && mark->has_bias_pattern()) {
           // New allocated objects may have the mark set to anonymously biased.
@@ -1058,7 +1058,7 @@
       for (int j = 0; j < monitors->number_of_monitors(); j++) {
         BasicObjectLock* src = monitors->at(j);
         if (src->obj() != NULL) {
-          ObjectSynchronizer::fast_exit(src->obj(), src->lock(), thread);
+          ObjectSynchronizer::fast_exit(oopDesc::bs()->resolve_and_maybe_copy_oop(src->obj()), src->lock(), thread);
         }
       }
       array->element(i)->free_monitors(thread);
--- a/src/share/vm/runtime/handles.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/handles.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -25,7 +25,6 @@
 #ifndef SHARE_VM_RUNTIME_HANDLES_HPP
 #define SHARE_VM_RUNTIME_HANDLES_HPP
 
-#include "gc/shared/barrierSet.hpp"
 #include "oops/oop.hpp"
 #include "oops/oopsHierarchy.hpp"
 
@@ -71,8 +70,8 @@
   oop* _handle;
 
  protected:
-  oop     obj() const                            { return _handle == NULL ? (oop)NULL : oopDesc::bs()->resolve_oop(*_handle); }
-  oop     non_null_obj() const                   { assert(_handle != NULL, "resolving NULL handle"); return oopDesc::bs()->resolve_oop(*_handle);}
+  oop     obj() const                            { return _handle == NULL ? (oop)NULL : *_handle; }
+  oop     non_null_obj() const                   { assert(_handle != NULL, "resolving NULL handle"); return *_handle; }
 
  public:
   // Constructors
@@ -83,7 +82,7 @@
   // General access
   oop     operator () () const                   { return obj(); }
   oop     operator -> () const                   { return non_null_obj(); }
-  bool    operator == (oop o) const              { return obj() == oopDesc::bs()->resolve_oop(o); }
+  bool    operator == (oop o) const              { return obj() == o; }
   bool    operator == (const Handle& h) const          { return obj() == h.obj(); }
 
   // Null checks
--- a/src/share/vm/runtime/jniHandles.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/jniHandles.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -66,7 +66,7 @@
   // Sentinel marking deleted handles in block. Note that we cannot store NULL as
   // the sentinel, since clearing weak global JNI refs are done by storing NULL in
   // the handle. The handle may not be reused before destroy_weak_global is called.
-  static oop deleted_handle()   { return oopDesc::bs()->resolve_oop(_deleted_handle); }
+  static oop deleted_handle()   { return _deleted_handle; }
 
   // Initialization
   static void initialize();
@@ -175,7 +175,6 @@
 
 inline oop JNIHandles::resolve(jobject handle) {
   oop result = (handle == NULL ? (oop)NULL : *(oop*)handle);
-  result = oopDesc::bs()->resolve_oop(result);
   assert(result != NULL || (handle == NULL || !CheckJNICalls || is_weak_global_handle(handle)), "Invalid value read from jni handle");
   assert(result != badJNIHandle, "Pointing to zapped jni handle area");
   return result;
@@ -185,7 +184,6 @@
 inline oop JNIHandles::resolve_external_guard(jobject handle) {
   if (handle == NULL) return NULL;
   oop result = *(oop*)handle;
-  result = oopDesc::bs()->resolve_oop(result);
   if (result == NULL || result == badJNIHandle) return NULL;
   return result;
 };
@@ -194,7 +192,6 @@
 inline oop JNIHandles::resolve_non_null(jobject handle) {
   assert(handle != NULL, "JNI handle should not be null");
   oop result = *(oop*)handle;
-  result = oopDesc::bs()->resolve_oop(result);
   assert(result != NULL, "Invalid value read from jni handle");
   assert(result != badJNIHandle, "Pointing to zapped jni handle area");
   // Don't let that private _deleted_handle object escape into the wild.
--- a/src/share/vm/runtime/objectMonitor.inline.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/objectMonitor.inline.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -66,7 +66,12 @@
 
 
 inline void* ObjectMonitor::object() const {
-  return oopDesc::bs()->maybe_resolve_oop(oop(_object));
+  /*
+  if (_object != (cast_to_oop<intptr_t>(-1))) {
+    assert(oop(_object) == oopDesc::bs()->resolve_and_maybe_copy_oop(oop(_object)), "expect to-space copy");
+  }
+  */
+  return _object;
 }
 
 inline void* ObjectMonitor::object_addr() {
@@ -75,6 +80,9 @@
 
 inline void ObjectMonitor::set_object(void* obj) {
   _object = obj;
+  if (_object != (cast_to_oop<intptr_t>(-1))) {
+    assert(oop(_object) == oopDesc::bs()->resolve_and_maybe_copy_oop(oop(_object)), "expect to-space copy");
+  }
 }
 
 inline bool ObjectMonitor::check(TRAPS) {
--- a/src/share/vm/runtime/sharedRuntime.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -1755,10 +1755,6 @@
   if (src == NULL || dest == NULL) {
     THROW(vmSymbols::java_lang_NullPointerException());
   }
-
-  src = oopDesc::bs()->resolve_oop(src);
-  dest = oopDesc::bs()->resolve_and_maybe_copy_oop(dest);
-
   // Do the copy.  The casts to arrayOop are necessary to the copy_array API,
   // even though the copy_array API also performs dynamic checks to ensure
   // that src and dest are truly arrays (and are conformable).
@@ -1804,6 +1800,7 @@
 
 // Handles the uncommon case in locking, i.e., contention or an inflated lock.
 JRT_BLOCK_ENTRY(void, SharedRuntime::complete_monitor_locking_C(oopDesc* _obj, BasicLock* lock, JavaThread* thread))
+  _obj = oopDesc::bs()->resolve_and_maybe_copy_oop(_obj);
   // Disable ObjectSynchronizer::quick_enter() in default config
   // until JDK-8077392 is resolved.
   if ((SyncFlags & 256) != 0 && !SafepointSynchronize::is_synchronizing()) {
@@ -1833,8 +1830,8 @@
 
 // Handles the uncommon cases of monitor unlocking in compiled code
 JRT_LEAF(void, SharedRuntime::complete_monitor_unlocking_C(oopDesc* _obj, BasicLock* lock, JavaThread * THREAD))
+  _obj = oopDesc::bs()->resolve_and_maybe_copy_oop(_obj);
    oop obj(_obj);
-  obj = oopDesc::bs()->resolve_oop(obj);
   assert(JavaThread::current() == THREAD, "invariant");
   // I'm not convinced we need the code contained by MIGHT_HAVE_PENDING anymore
   // testing was unable to ever fire the assert that guarded it so I have removed it.
--- a/src/share/vm/runtime/synchronizer.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/synchronizer.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -160,6 +160,7 @@
   assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
   assert(self->is_Java_thread(), "invariant");
   assert(((JavaThread *) self)->thread_state() == _thread_in_Java, "invariant");
+  assert(obj == oopDesc::bs()->resolve_and_maybe_copy_oop(obj), "expect to-space copy");
   No_Safepoint_Verifier nsv;
   if (obj == NULL) return false;  // slow-path for invalid obj
   const markOop mark = obj->mark();
@@ -210,6 +211,7 @@
   assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
   assert(Self->is_Java_thread(), "invariant");
   assert(((JavaThread *) Self)->thread_state() == _thread_in_Java, "invariant");
+  assert(obj == oopDesc::bs()->resolve_and_maybe_copy_oop(obj), "expect to-space copy");
   No_Safepoint_Verifier nsv;
   if (obj == NULL) return false;       // Need to throw NPE
   const markOop mark = obj->mark();
@@ -256,6 +258,7 @@
 
 void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock,
                                     bool attempt_rebias, TRAPS) {
+  assert(obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     if (!SafepointSynchronize::is_at_safepoint()) {
       BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD);
@@ -275,7 +278,7 @@
 void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
   assert(!object->mark()->has_bias_pattern(), "should not see bias pattern here");
   // if displaced header is null, the previous enter is recursive enter, no-op
-  object = oopDesc::bs()->resolve_and_maybe_copy_oop(object);
+  assert(object == oopDesc::bs()->resolve_and_maybe_copy_oop(object), "expect to-space copy");
 
   markOop dhw = lock->displaced_header();
   markOop mark;
@@ -316,16 +319,15 @@
 // We don't need to use fast path here, because it must have been
 // failed in the interpreter/compiler code.
 void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
-  Handle n_obj(THREAD,
-	       oopDesc::bs()->resolve_and_maybe_copy_oop(obj()));
-  markOop mark = n_obj->mark();
+  assert(obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(obj()), "expect to-space copy");
+  markOop mark = obj->mark();
   assert(!mark->has_bias_pattern(), "should not see bias pattern here");
 
   if (mark->is_neutral()) {
     // Anticipate successful CAS -- the ST of the displaced mark must
     // be visible <= the ST performed by the CAS.
     lock->set_displaced_header(mark);
-    if (mark == (markOop) Atomic::cmpxchg_ptr(lock, n_obj()->mark_addr(), mark)) {
+    if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) {
       TEVENT(slow_enter: release stacklock);
       return;
     }
@@ -333,7 +335,7 @@
   } else if (mark->has_locker() &&
              THREAD->is_lock_owned((address)mark->locker())) {
     assert(lock != mark->locker(), "must not re-lock the same lock");
-    assert(lock != (BasicLock*)n_obj->mark(), "don't relock with same BasicLock");
+    assert(lock != (BasicLock*)obj->mark(), "don't relock with same BasicLock");
     lock->set_displaced_header(NULL);
     return;
   }
@@ -343,7 +345,7 @@
   // must be non-zero to avoid looking like a re-entrant lock,
   // and must not look locked either.
   lock->set_displaced_header(markOopDesc::unused_mark());
-  ObjectSynchronizer::inflate(THREAD, n_obj())->enter(THREAD);
+  ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
 }
 
 // This routine is used to handle interpreter/compiler slow case
@@ -368,6 +370,7 @@
 // NOTE: must use heavy weight monitor to handle complete_exit/reenter()
 intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
   TEVENT(complete_exit);
+  assert(obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     BiasedLocking::revoke_and_rebias(obj, false, THREAD);
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
@@ -381,6 +384,7 @@
 // NOTE: must use heavy weight monitor to handle complete_exit/reenter()
 void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
   TEVENT(reenter);
+  assert(obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     BiasedLocking::revoke_and_rebias(obj, false, THREAD);
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
@@ -396,6 +400,7 @@
 void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) {
   // the current locking is from JNI instead of Java code
   TEVENT(jni_enter);
+  assert(obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     BiasedLocking::revoke_and_rebias(obj, false, THREAD);
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
@@ -408,6 +413,7 @@
 // NOTE: must use heavy weight monitor to handle jni monitor exit
 void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
   TEVENT(jni_exit);
+  assert(obj == oopDesc::bs()->resolve_and_maybe_copy_oop(obj), "expect to-space copy");
   if (UseBiasedLocking) {
     Handle h_obj(THREAD, obj);
     BiasedLocking::revoke_and_rebias(h_obj, false, THREAD);
@@ -450,6 +456,7 @@
 //  Wait/Notify/NotifyAll
 // NOTE: must use heavy weight monitor to handle wait()
 int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
+  assert(obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     BiasedLocking::revoke_and_rebias(obj, false, THREAD);
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
@@ -470,6 +477,7 @@
 }
 
 void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) {
+  assert(obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     BiasedLocking::revoke_and_rebias(obj, false, THREAD);
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
@@ -482,6 +490,7 @@
 }
 
 void ObjectSynchronizer::notify(Handle obj, TRAPS) {
+  assert(obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     BiasedLocking::revoke_and_rebias(obj, false, THREAD);
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
@@ -496,6 +505,7 @@
 
 // NOTE: see comment of notify()
 void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
+  assert(obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     BiasedLocking::revoke_and_rebias(obj, false, THREAD);
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
@@ -673,7 +683,7 @@
 }
 
 intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
-  obj = oopDesc::bs()->resolve_and_maybe_copy_oop(obj);
+  assert(obj == oopDesc::bs()->resolve_and_maybe_copy_oop(obj), "expect to-space copy");
   if (UseBiasedLocking) {
     // NOTE: many places throughout the JVM do not expect a safepoint
     // to be taken here, in particular most operations on perm gen
@@ -691,7 +701,6 @@
              "biases should not be seen by VM thread here");
       BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
       obj = hobj();
-      obj = oopDesc::bs()->resolve_and_maybe_copy_oop(obj);
       assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
     }
   }
@@ -788,6 +797,7 @@
 
 bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
                                                    Handle h_obj) {
+  assert(h_obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(h_obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     BiasedLocking::revoke_and_rebias(h_obj, false, thread);
     assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
@@ -860,6 +870,7 @@
 
 // FIXME: jvmti should call this
 JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) {
+  assert(h_obj() == oopDesc::bs()->resolve_and_maybe_copy_oop(h_obj()), "expect to-space copy");
   if (UseBiasedLocking) {
     if (SafepointSynchronize::is_at_safepoint()) {
       BiasedLocking::revoke_at_safepoint(h_obj);
@@ -908,7 +919,6 @@
     for (int i = _BLOCKSIZE - 1; i > 0; i--) {
       mid = (ObjectMonitor *)(block + i);
       oop object = (oop) mid->object();
-      object = oopDesc::bs()->resolve_oop(object);
       if (object != NULL) {
         closure->do_monitor(mid);
       }
@@ -1282,6 +1292,7 @@
 
 // Fast path code shared by multiple functions
 ObjectMonitor* ObjectSynchronizer::inflate_helper(oop obj) {
+  assert(obj == oopDesc::bs()->resolve_and_maybe_copy_oop(obj), "expect to-space copy");
   markOop mark = obj->mark();
   if (mark->has_monitor()) {
     assert(ObjectSynchronizer::verify_objmon_isinpool(mark->monitor()), "monitor is invalid");
@@ -1296,7 +1307,7 @@
                                                      oop object) {
   // Inflate mutates the heap ...
   // Relaxing assertion for bug 6320749.
-  object = oopDesc::bs()->resolve_and_maybe_copy_oop(object);
+  assert(object == oopDesc::bs()->resolve_and_maybe_copy_oop(object), "expect to-space copy");
   assert(Universe::verify_in_progress() ||
          !SafepointSynchronize::is_at_safepoint(), "invariant");
 
@@ -1315,7 +1326,7 @@
     if (mark->has_monitor()) {
       ObjectMonitor * inf = mark->monitor();
       assert(inf->header()->is_neutral(), "invariant");
-      assert(oopDesc::bs()->resolve_oop((oop) inf->object()) == object, "invariant");
+      assert((oop) inf->object() == object, "invariant");
       assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
       return inf;
     }
@@ -1521,6 +1532,7 @@
                                          ObjectMonitor** freeTailp) {
   bool deflated;
   // Normal case ... The monitor is associated with obj.
+  assert(obj == oopDesc::bs()->resolve_and_maybe_copy_oop(obj), "expect to-space copy");
   guarantee(obj->mark() == markOopDesc::encode(mid), "invariant");
   guarantee(mid == obj->mark()->monitor(), "invariant");
   guarantee(mid->header()->is_neutral(), "invariant");
@@ -1640,7 +1652,6 @@
     for (int i = 1; i < _BLOCKSIZE; i++) {
       ObjectMonitor* mid = (ObjectMonitor*)&block[i];
       oop obj = (oop) mid->object();
-      obj = oopDesc::bs()->resolve_oop(obj);
 
       if (obj == NULL) {
         // The monitor is not associated with an object.
@@ -1807,7 +1818,6 @@
     for (int i = 1; i < _BLOCKSIZE; i++) {
       mid = (ObjectMonitor *)(block + i);
       oop object = (oop) mid->object();
-      object = oopDesc::bs()->resolve_oop(object);
 
       if (object != NULL) {
         mid->verify();
--- a/src/share/vm/runtime/thread.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/thread.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -1677,7 +1677,7 @@
 
 static void ensure_join(JavaThread* thread) {
   // We do not need to grap the Threads_lock, since we are operating on ourself.
-  Handle threadObj(thread, thread->threadObj());
+  Handle threadObj(thread, oopDesc::bs()->resolve_and_maybe_copy_oop(thread->threadObj()));
   assert(threadObj.not_null(), "java thread object must exist");
   ObjectLocker lock(threadObj, thread);
   // Ignore pending exception (ThreadDeath), since we are exiting anyway
--- a/src/share/vm/runtime/thread.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/thread.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -1035,7 +1035,7 @@
 
   // Thread oop. threadObj() can be NULL for initial JavaThread
   // (or for threads attached via JNI)
-  oop threadObj() const                          { return oopDesc::bs()->resolve_oop(_threadObj); }
+  oop threadObj() const                          { return _threadObj; }
   void set_threadObj(oop p)                      { _threadObj = p; }
 
   ThreadPriority java_priority() const;          // Read from threadObj()
@@ -1277,7 +1277,7 @@
   void set_callee_target  (Method* x)          { _callee_target   = x; }
 
   // Oop results of vm runtime calls
-  oop  vm_result() const                         { return oopDesc::bs()->resolve_oop(_vm_result); }
+  oop  vm_result() const                         { return _vm_result; }
   void set_vm_result  (oop x)                    { _vm_result   = x; }
 
   Metadata*    vm_result_2() const               { return _vm_result_2; }
@@ -1287,7 +1287,7 @@
   void set_deferred_card_mark(MemRegion mr)      { _deferred_card_mark = mr;   }
 
   // Exception handling for compiled methods
-  oop      exception_oop() const                 { return oopDesc::bs()->resolve_oop(_exception_oop); }
+  oop      exception_oop() const                 { return _exception_oop; }
   address  exception_pc() const                  { return _exception_pc; }
   address  exception_handler_pc() const          { return _exception_handler_pc; }
   bool     is_method_handle_return() const       { return _is_method_handle_return == 1; }
--- a/src/share/vm/runtime/vframe.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/runtime/vframe.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -250,6 +250,7 @@
  public:
   // Constructor
   MonitorInfo(oop owner, BasicLock* lock, bool eliminated, bool owner_is_scalar_replaced) {
+    assert(owner == oopDesc::bs()->resolve_and_maybe_copy_oop(owner), "expect to-space copy");
     if (!owner_is_scalar_replaced) {
       _owner = owner;
       _owner_klass = NULL;
@@ -265,11 +266,12 @@
   // Accessors
   oop        owner() const {
     assert(!_owner_is_scalar_replaced, "should not be called for scalar replaced object");
-    return oopDesc::bs()->resolve_oop(_owner);
+    assert(_owner == oopDesc::bs()->resolve_and_maybe_copy_oop(_owner), "expect to-space copy");
+    return _owner;
   }
   oop   owner_klass() const {
     assert(_owner_is_scalar_replaced, "should not be called for not scalar replaced object");
-    return oopDesc::bs()->resolve_oop(_owner_klass);
+    return _owner_klass;
   }
   BasicLock* lock()  const { return _lock;  }
   bool eliminated()  const { return _eliminated; }
--- a/src/share/vm/services/lowMemoryDetector.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/services/lowMemoryDetector.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -297,7 +297,7 @@
   if (_sensor_obj != NULL) {
     Klass* k = Management::sun_management_Sensor_klass(CHECK);
     instanceKlassHandle sensorKlass (THREAD, k);
-    Handle sensor_h(THREAD, oopDesc::bs()->resolve_oop(_sensor_obj));
+    Handle sensor_h(THREAD, _sensor_obj);
     Handle usage_h = MemoryService::create_MemoryUsage_obj(_usage, CHECK);
 
     JavaValue result(T_VOID);
@@ -326,7 +326,7 @@
   if (_sensor_obj != NULL) {
     Klass* k = Management::sun_management_Sensor_klass(CHECK);
     instanceKlassHandle sensorKlass (THREAD, k);
-    Handle sensor(THREAD, oopDesc::bs()->resolve_oop(_sensor_obj));
+    Handle sensor(THREAD, _sensor_obj);
 
     JavaValue result(T_VOID);
     JavaCallArguments args(sensor);
--- a/src/share/vm/services/memoryManager.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/services/memoryManager.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -63,7 +63,7 @@
 
   void add_pool(MemoryPool* pool);
 
-  bool is_manager(instanceHandle mh)     { return mh() == oopDesc::bs()->resolve_oop(_memory_mgr_obj); }
+  bool is_manager(instanceHandle mh)     { return oopDesc::bs()->resolve_and_maybe_copy_oop(mh()) == oopDesc::bs()->resolve_and_maybe_copy_oop(_memory_mgr_obj); }
 
   virtual instanceOop get_memory_manager_instance(TRAPS);
   virtual bool is_gc_memory_manager()    { return false; }
--- a/src/share/vm/services/memoryPool.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/services/memoryPool.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -140,7 +140,7 @@
     }
   }
 
-  return (instanceOop) oopDesc::bs()->resolve_oop((oop) pool_obj);
+  return pool_obj;
 }
 
 inline static size_t get_max_value(size_t val1, size_t val2) {
--- a/src/share/vm/services/threadService.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/services/threadService.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -166,6 +166,7 @@
     // If obj == NULL, then ObjectMonitor is raw which doesn't count.
   }
 
+  obj = oopDesc::bs()->resolve_and_maybe_copy_oop(obj);
   Handle h(obj);
   return h;
 }
@@ -507,7 +508,6 @@
   int len = (_locked_monitors != NULL ? _locked_monitors->length() : 0);
   for (int i = 0; i < len; i++) {
     oop o = _locked_monitors->at(i);
-    o = oopDesc::bs()->resolve_oop(o);
     InstanceKlass* ik = InstanceKlass::cast(o->klass());
     st->print_cr("\t- locked <" INTPTR_FORMAT "> (a %s)", (address)o, ik->external_name());
   }
@@ -590,6 +590,8 @@
 bool ThreadStackTrace::is_owned_monitor_on_stack(oop object) {
   assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped");
 
+  object = oopDesc::bs()->resolve_and_maybe_copy_oop(object);
+
   bool found = false;
   int num_frames = get_stack_depth();
   for (int depth = 0; depth < num_frames; depth++) {
@@ -598,6 +600,7 @@
     GrowableArray<oop>* locked_monitors = frame->locked_monitors();
     for (int j = 0; j < len; j++) {
       oop monitor = locked_monitors->at(j);
+      monitor = oopDesc::bs()->resolve_and_maybe_copy_oop(monitor);
       assert(monitor != NULL, "must be a Java object");
       if (monitor == object) {
         found = true;
--- a/src/share/vm/services/threadService.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/services/threadService.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -218,7 +218,7 @@
 
   java_lang_Thread::ThreadStatus thread_status() { return _thread_status; }
 
-  oop         threadObj() const           { return oopDesc::bs()->resolve_oop(_threadObj); }
+  oop         threadObj() const           { return _threadObj; }
 
   void        set_next(ThreadSnapshot* n) { _next = n; }
 
@@ -233,8 +233,8 @@
   jlong       sleep_ticks()               { return _sleep_ticks; }
 
 
-  oop         blocker_object()            { return oopDesc::bs()->resolve_oop(_blocker_object); }
-  oop         blocker_object_owner()      { return oopDesc::bs()->resolve_oop(_blocker_object_owner); }
+  oop         blocker_object()            { return _blocker_object; }
+  oop         blocker_object_owner()      { return _blocker_object_owner; }
 
   ThreadSnapshot*   next() const          { return _next; }
   ThreadStackTrace* get_stack_trace()     { return _stack_trace; }
--- a/src/share/vm/utilities/exceptions.cpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/utilities/exceptions.cpp	Sat Oct 03 13:51:17 2015 +0200
@@ -52,10 +52,6 @@
   _exception_line    = line;
 }
 
-oop ThreadShadow::pending_exception() const {
-  return Universe::heap()->barrier_set()->resolve_oop(_pending_exception);
-}
-
 void ThreadShadow::clear_pending_exception() {
   if (TraceClearedExceptions) {
     if (_pending_exception != NULL) {
--- a/src/share/vm/utilities/exceptions.hpp	Thu Oct 01 18:39:20 2015 +0200
+++ b/src/share/vm/utilities/exceptions.hpp	Sat Oct 03 13:51:17 2015 +0200
@@ -75,7 +75,7 @@
   virtual void unused_initial_virtual() { }
 
  public:
-  oop  pending_exception() const;
+  oop  pending_exception() const                 { return _pending_exception; }
   bool has_pending_exception() const             { return _pending_exception != NULL; }
   const char* exception_file() const             { return _exception_file; }
   int  exception_line() const                    { return _exception_line; }