--- old/src/share/vm/oops/instanceKlass.cpp 2016-06-01 21:28:08.357813687 -0400 +++ new/src/share/vm/oops/instanceKlass.cpp 2016-06-01 21:28:06.277695757 -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(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); }