hotspot/src/share/vm/oops/instanceKlass.cpp
changeset 38937 2bf3c37c4841
parent 38259 b495d1cfe673
child 39216 40c3d66352ae
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Fri Jun 03 01:31:01 2016 +0000
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Jun 02 23:37:09 2016 -0400
@@ -1104,21 +1104,21 @@
 
 void InstanceKlass::mask_for(const methodHandle& method, int bci,
   InterpreterOopMap* entry_for) {
-  // Dirty read, then double-check under a lock.
-  if (_oop_map_cache == NULL) {
-    // Otherwise, allocate a new one.
+  // Lazily create the _oop_map_cache at first request
+  // Lock-free access requires load_ptr_acquire.
+  OopMapCache* oop_map_cache =
+      static_cast<OopMapCache*>(OrderAccess::load_ptr_acquire(&_oop_map_cache));
+  if (oop_map_cache == NULL) {
     MutexLocker x(OopMapCacheAlloc_lock);
-    // First time use. Allocate a cache in C heap
-    if (_oop_map_cache == NULL) {
-      // Release stores from OopMapCache constructor before assignment
-      // to _oop_map_cache. C++ compilers on ppc do not emit the
-      // required memory barrier only because of the volatile
-      // qualifier of _oop_map_cache.
-      OrderAccess::release_store_ptr(&_oop_map_cache, new OopMapCache());
+    // Check if _oop_map_cache was allocated while we were waiting for this lock
+    if ((oop_map_cache = _oop_map_cache) == NULL) {
+      oop_map_cache = new OopMapCache();
+      // Ensure _oop_map_cache is stable, since it is examined without a lock
+      OrderAccess::release_store_ptr(&_oop_map_cache, oop_map_cache);
     }
   }
-  // _oop_map_cache is constant after init; lookup below does is own locking.
-  _oop_map_cache->lookup(method, bci, entry_for);
+  // _oop_map_cache is constant after init; lookup below does its own locking.
+  oop_map_cache->lookup(method, bci, entry_for);
 }