# HG changeset patch # User rkennke # Date 1521651124 -3600 # Wed Mar 21 17:52:04 2018 +0100 # Node ID 7ea4aea05c92bc289067a9f82f5f8604292dbc2f # Parent 26958d06b585396746a003f667d9b9aa30ef601d [mq]: JDK-8199781.patch diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -540,7 +540,7 @@ // Calculate accessibility the hard way. if (!k->is_loaded()) { is_accessible = false; - } else if (k->loader() != accessor->loader() && + } else if (!oopDesc::equals(k->loader(), accessor->loader()) && get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) { // Loaded only remotely. Not linked yet. is_accessible = false; @@ -591,7 +591,7 @@ index = cpool->object_to_cp_index(cache_index); oop obj = cpool->resolved_references()->obj_at(cache_index); if (obj != NULL) { - if (obj == Universe::the_null_sentinel()) { + if (oopDesc::equals(obj, Universe::the_null_sentinel())) { return ciConstant(T_OBJECT, get_object(NULL)); } BasicType bt = T_OBJECT; diff --git a/src/hotspot/share/ci/ciObjectFactory.cpp b/src/hotspot/share/ci/ciObjectFactory.cpp --- a/src/hotspot/share/ci/ciObjectFactory.cpp +++ b/src/hotspot/share/ci/ciObjectFactory.cpp @@ -249,7 +249,7 @@ // into the cache. Handle keyHandle(Thread::current(), key); ciObject* new_object = create_new_object(keyHandle()); - assert(keyHandle() == new_object->get_oop(), "must be properly recorded"); + assert(oopDesc::equals(keyHandle(), new_object->get_oop()), "must be properly recorded"); init_ident_of(new_object); assert(Universe::heap()->is_in_reserved(new_object->get_oop()), "must be"); @@ -450,8 +450,8 @@ for (int i=0; i<_unloaded_klasses->length(); i++) { ciKlass* entry = _unloaded_klasses->at(i); if (entry->name()->equals(name) && - entry->loader() == loader && - entry->protection_domain() == domain) { + oopDesc::equals(entry->loader(), loader) && + oopDesc::equals(entry->protection_domain(), domain)) { // We've found a match. return entry; } diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -201,7 +201,7 @@ VerifyContainsOopClosure(oop target) : _target(target), _found(false) {} void do_oop(oop* p) { - if (p != NULL && *p == _target) { + if (p != NULL && oopDesc::equals(oopDesc::load_heap_oop(p), _target)) { _found = true; } } @@ -380,7 +380,7 @@ // Just return if this dependency is to a class with the same or a parent // class_loader. - if (from == to || java_lang_ClassLoader::isAncestor(from, to)) { + if (oopDesc::equals(from, to) || java_lang_ClassLoader::isAncestor(from, to)) { return; // this class loader is in the parent list, no need to add it. } } diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp --- a/src/hotspot/share/classfile/dictionary.cpp +++ b/src/hotspot/share/classfile/dictionary.cpp @@ -161,13 +161,13 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const { #ifdef ASSERT - if (protection_domain == instance_klass()->protection_domain()) { + if (oopDesc::equals(protection_domain, instance_klass()->protection_domain())) { // Ensure this doesn't show up in the pd_set (invariant) bool in_pd_set = false; for (ProtectionDomainEntry* current = pd_set_acquire(); current != NULL; current = current->next()) { - if (current->object_no_keepalive() == protection_domain) { + if (oopDesc::equals(current->object_no_keepalive(), protection_domain)) { in_pd_set = true; break; } @@ -179,7 +179,7 @@ } #endif /* ASSERT */ - if (protection_domain == instance_klass()->protection_domain()) { + if (oopDesc::equals(protection_domain, instance_klass()->protection_domain())) { // Succeeds trivially return true; } @@ -187,7 +187,7 @@ for (ProtectionDomainEntry* current = pd_set_acquire(); current != NULL; current = current->next()) { - if (current->object_no_keepalive() == protection_domain) return true; + if (oopDesc::equals(current->object_no_keepalive(), protection_domain)) return true; } return false; } diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -869,7 +869,7 @@ } else { assert(Universe::is_module_initialized() || (ModuleEntryTable::javabase_defined() && - (module() == ModuleEntryTable::javabase_moduleEntry()->module())), + (oopDesc::equals(module(), ModuleEntryTable::javabase_moduleEntry()->module()))), "Incorrect java.lang.Module specification while creating mirror"); set_module(mirror(), module()); } @@ -946,7 +946,7 @@ } // set the classLoader field in the java_lang_Class instance - assert(class_loader() == k->class_loader(), "should be same"); + assert(oopDesc::equals(class_loader(), k->class_loader()), "should be same"); set_class_loader(mirror(), class_loader()); // Setup indirection from klass->mirror @@ -1460,9 +1460,9 @@ // Note: create_basic_type_mirror above initializes ak to a non-null value. type = ArrayKlass::cast(ak)->element_type(); } else { - assert(java_class == Universe::void_mirror(), "only valid non-array primitive"); + assert(oopDesc::equals(java_class, Universe::void_mirror()), "only valid non-array primitive"); } - assert(Universe::java_mirror(type) == java_class, "must be consistent"); + assert(oopDesc::equals(Universe::java_mirror(type), java_class), "must be consistent"); return type; } @@ -3835,14 +3835,14 @@ } bool java_lang_invoke_MethodType::equals(oop mt1, oop mt2) { - if (mt1 == mt2) + if (oopDesc::equals(mt1, mt2)) return true; - if (rtype(mt1) != rtype(mt2)) + if (!oopDesc::equals(rtype(mt1), rtype(mt2))) return false; if (ptype_count(mt1) != ptype_count(mt2)) return false; for (int i = ptype_count(mt1) - 1; i >= 0; i--) { - if (ptype(mt1, i) != ptype(mt2, i)) + if (!oopDesc::equals(ptype(mt1, i), ptype(mt2, i))) return false; } return true; @@ -4040,7 +4040,7 @@ // This loop taken verbatim from ClassLoader.java: do { acl = parent(acl); - if (cl == acl) { + if (oopDesc::equals(cl, acl)) { return true; } assert(++loop_count > 0, "loop_count overflow"); @@ -4070,7 +4070,7 @@ oop cl = SystemDictionary::java_system_loader(); while(cl != NULL) { - if (cl == loader) return true; + if (oopDesc::equals(cl, loader)) return true; cl = parent(cl); } return false; diff --git a/src/hotspot/share/classfile/protectionDomainCache.cpp b/src/hotspot/share/classfile/protectionDomainCache.cpp --- a/src/hotspot/share/classfile/protectionDomainCache.cpp +++ b/src/hotspot/share/classfile/protectionDomainCache.cpp @@ -132,7 +132,7 @@ ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, Handle protection_domain) { for (ProtectionDomainCacheEntry* e = bucket(index); e != NULL; e = e->next()) { - if (e->object_no_keepalive() == protection_domain()) { + if (oopDesc::equals(e->object_no_keepalive(), protection_domain())) { return e; } } diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -181,7 +181,7 @@ return false; } return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_AppClassLoader_klass() || - class_loader == _java_system_loader); + oopDesc::equals(class_loader, _java_system_loader)); } // Returns true if the passed class loader is the platform class loader. @@ -390,7 +390,7 @@ ((quicksuperk = childk->super()) != NULL) && ((quicksuperk->name() == class_name) && - (quicksuperk->class_loader() == class_loader()))) { + (oopDesc::equals(quicksuperk->class_loader(), class_loader())))) { return quicksuperk; } else { PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, child_name, loader_data); @@ -524,7 +524,7 @@ bool calledholdinglock = ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, lockObject); assert(calledholdinglock,"must hold lock for notify"); - assert((!(lockObject() == _system_loader_lock_obj) && !is_parallelCapable(lockObject)), "unexpected double_lock_wait"); + assert((!oopDesc::equals(lockObject(), _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(); @@ -842,7 +842,7 @@ // If everything was OK (no exceptions, no null return value), and // class_loader is NOT the defining loader, do a little more bookkeeping. if (!HAS_PENDING_EXCEPTION && k != NULL && - k->class_loader() != class_loader()) { + !oopDesc::equals(k->class_loader(), class_loader())) { check_constraints(d_hash, k, class_loader, false, THREAD); @@ -988,7 +988,7 @@ if (host_klass != NULL) { // Create a new CLD for anonymous class, that uses the same class loader // as the host_klass - guarantee(host_klass->class_loader() == class_loader(), "should be the same"); + guarantee(oopDesc::equals(host_klass->class_loader(), class_loader()), "should be the same"); loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader); } else { loader_data = ClassLoaderData::class_loader_data(class_loader()); @@ -1746,7 +1746,7 @@ == ObjectSynchronizer::owner_other) { // contention will likely happen, so increment the corresponding // contention counter. - if (loader_lock() == _system_loader_lock_obj) { + if (oopDesc::equals(loader_lock(), _system_loader_lock_obj)) { ClassLoader::sync_systemLoaderLockContentionRate()->inc(); } else { ClassLoader::sync_nonSystemLoaderLockContentionRate()->inc(); @@ -2228,7 +2228,7 @@ // cleared if revocation occurs too often for this type // NOTE that we must only do this when the class is initally // defined, not each time it is referenced from a new class loader - if (k->class_loader() == class_loader()) { + if (oopDesc::equals(k->class_loader(), class_loader())) { k->set_prototype_header(markOopDesc::biased_locking_prototype()); } } @@ -2420,7 +2420,7 @@ Handle loader1, Handle loader2, bool is_method, TRAPS) { // Nothing to do if loaders are the same. - if (loader1() == loader2()) { + if (oopDesc::equals(loader1(), loader2())) { return NULL; } diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp --- a/src/hotspot/share/code/dependencies.cpp +++ b/src/hotspot/share/code/dependencies.cpp @@ -1818,12 +1818,12 @@ if (changes == NULL) { // Validate all CallSites - if (java_lang_invoke_CallSite::target(call_site) != method_handle) + if (!oopDesc::equals(java_lang_invoke_CallSite::target(call_site), method_handle)) return call_site->klass(); // assertion failed } else { // Validate the given CallSite - if (call_site == changes->call_site() && java_lang_invoke_CallSite::target(call_site) != changes->method_handle()) { - assert(method_handle != changes->method_handle(), "must be"); + if (oopDesc::equals(call_site, changes->call_site()) && !oopDesc::equals(java_lang_invoke_CallSite::target(call_site), changes->method_handle())) { + assert(!oopDesc::equals(method_handle, changes->method_handle()), "must be"); return call_site->klass(); // assertion failed } } diff --git a/src/hotspot/share/gc/shared/barrierSet.hpp b/src/hotspot/share/gc/shared/barrierSet.hpp --- a/src/hotspot/share/gc/shared/barrierSet.hpp +++ b/src/hotspot/share/gc/shared/barrierSet.hpp @@ -268,6 +268,10 @@ static oop resolve(oop obj) { return Raw::resolve(obj); } + + static bool equals(oop o1, oop o2) { + return Raw::equals(o1, o2); + } }; }; diff --git a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp --- a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp +++ b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp @@ -2434,7 +2434,7 @@ handle_exception); result = THREAD->vm_result(); } - if (result == Universe::the_null_sentinel()) + if (oopDesc::equals(result, Universe::the_null_sentinel())) result = NULL; VERIFY_OOP(result); diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -154,7 +154,7 @@ if (rindex >= 0) { oop coop = m->constants()->resolved_references()->obj_at(rindex); oop roop = (result == NULL ? Universe::the_null_sentinel() : result); - assert(roop == coop, "expected result for assembly code"); + assert(oopDesc::equals(roop, coop), "expected result for assembly code"); } } #endif diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -601,12 +601,12 @@ // preallocated errors with backtrace have been consumed. Also need to avoid // a potential loop which could happen if an out of memory occurs when attempting // to allocate the backtrace. - return ((throwable() != Universe::_out_of_memory_error_java_heap) && - (throwable() != Universe::_out_of_memory_error_metaspace) && - (throwable() != Universe::_out_of_memory_error_class_metaspace) && - (throwable() != Universe::_out_of_memory_error_array_size) && - (throwable() != Universe::_out_of_memory_error_gc_overhead_limit) && - (throwable() != Universe::_out_of_memory_error_realloc_objects)); + return ((!oopDesc::equals(throwable(), Universe::_out_of_memory_error_java_heap)) && + (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_metaspace)) && + (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_class_metaspace)) && + (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_array_size)) && + (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_gc_overhead_limit)) && + (!oopDesc::equals(throwable(), Universe::_out_of_memory_error_realloc_objects))); } diff --git a/src/hotspot/share/oops/access.hpp b/src/hotspot/share/oops/access.hpp --- a/src/hotspot/share/oops/access.hpp +++ b/src/hotspot/share/oops/access.hpp @@ -56,7 +56,7 @@ // * arraycopy: Copy data from one heap array to another heap array. // * clone: Clone the contents of an object to a newly allocated object. // * resolve: Resolve a stable to-space invariant oop that is guaranteed not to relocate its payload until a subsequent thread transition. - +// * equals: Object equality, e.g. when different copies of the same objects are in use (from-space vs. to-space) typedef uint64_t DecoratorSet; // == Internal Decorators - do not use == @@ -304,6 +304,9 @@ template oop resolve(oop src); + template + bool equals(oop o1, oop o2); + // Infer the type that should be returned from a load. template class LoadProxy: public StackObj { @@ -512,6 +515,11 @@ verify_decorators(); return AccessInternal::resolve(obj); } + + static bool equals(oop o1, oop o2) { + verify_decorators(); + return AccessInternal::equals(o1, o2); + } }; // Helper for performing raw accesses (knows only of memory ordering diff --git a/src/hotspot/share/oops/access.inline.hpp b/src/hotspot/share/oops/access.inline.hpp --- a/src/hotspot/share/oops/access.inline.hpp +++ b/src/hotspot/share/oops/access.inline.hpp @@ -214,6 +214,13 @@ } }; + template + struct PostRuntimeDispatch: public AllStatic { + static bool access_barrier(oop o1, oop o2) { + return GCBarrierType::equals(o1, o2); + } + }; + // Resolving accessors with barriers from the barrier set happens in two steps. // 1. Expand paths with runtime-decorators, e.g. is UseCompressedOops on or off. // 2. Expand paths for each BarrierSet available in the system. @@ -467,6 +474,22 @@ } }; + template + struct RuntimeDispatch: AllStatic { + typedef typename AccessFunction::type func_t; + static func_t _equals_func; + + static bool equals_init(oop o1, oop o2) { + func_t function = BarrierResolver::resolve_barrier(); + _equals_func = function; + return function(o1, o2); + } + + static inline bool equals(oop o1, oop o2) { + return _equals_func(o1, o2); + } + }; + // Initialize the function pointers to point to the resolving function. template typename AccessFunction::type @@ -512,6 +535,10 @@ typename AccessFunction::type RuntimeDispatch::_resolve_func = &resolve_init; + template + typename AccessFunction::type + RuntimeDispatch::_equals_func = &equals_init; + // Step 3: Pre-runtime dispatching. // The PreRuntimeDispatch class is responsible for filtering the barrier strength // decorators. That is, for AS_RAW, it hardwires the accesses without a runtime @@ -824,6 +851,21 @@ resolve(oop obj) { return RuntimeDispatch::resolve(obj); } + + template + inline static typename EnableIf< + HasDecorator::value, bool>::type + equals(oop o1, oop o2) { + typedef RawAccessBarrier Raw; + return Raw::equals(o1, o2); + } + + template + inline static typename EnableIf< + !HasDecorator::value, bool>::type + equals(oop o1, oop o2) { + return RuntimeDispatch::equals(o1, o2); + } }; // This class adds implied decorators that follow according to decorator rules. @@ -1133,6 +1175,12 @@ const DecoratorSet expanded_decorators = DecoratorFixup::value; return PreRuntimeDispatch::resolve(obj); } + + template + inline bool equals(oop o1, oop o2) { + const DecoratorSet expanded_decorators = DecoratorFixup::value; + return PreRuntimeDispatch::equals(o1, o2); + } } template diff --git a/src/hotspot/share/oops/accessBackend.hpp b/src/hotspot/share/oops/accessBackend.hpp --- a/src/hotspot/share/oops/accessBackend.hpp +++ b/src/hotspot/share/oops/accessBackend.hpp @@ -53,7 +53,8 @@ BARRIER_ATOMIC_XCHG_AT, BARRIER_ARRAYCOPY, BARRIER_CLONE, - BARRIER_RESOLVE + BARRIER_RESOLVE, + BARRIER_EQUALS }; template @@ -102,6 +103,7 @@ typedef bool (*arraycopy_func_t)(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length); typedef void (*clone_func_t)(oop src, oop dst, size_t size); typedef oop (*resolve_func_t)(oop obj); + typedef bool (*equals_func_t)(oop o1, oop o2); }; template @@ -127,6 +129,7 @@ ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ARRAYCOPY, arraycopy_func_t); ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_CLONE, clone_func_t); ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_RESOLVE, resolve_func_t); + ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_EQUALS, equals_func_t); #undef ACCESS_GENERATE_ACCESS_FUNCTION template @@ -388,6 +391,8 @@ static void clone(oop src, oop dst, size_t size); static oop resolve(oop obj) { return obj; } + + static bool equals(oop o1, oop o2) { return o1 == o2; } }; #endif // SHARE_VM_RUNTIME_ACCESSBACKEND_HPP diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -841,7 +841,7 @@ if (cache_index >= 0) { result_oop = this_cp->resolved_references()->obj_at(cache_index); if (result_oop != NULL) { - if (result_oop == Universe::the_null_sentinel()) { + if (oopDesc::equals(result_oop, Universe::the_null_sentinel())) { DEBUG_ONLY(int temp_index = (index >= 0 ? index : this_cp->object_to_cp_index(cache_index))); assert(this_cp->tag_at(temp_index).is_dynamic_constant(), "only condy uses the null sentinel"); result_oop = NULL; @@ -1074,12 +1074,12 @@ } else { // Return the winning thread's result. This can be different than // the result here for MethodHandles. - if (old_result == Universe::the_null_sentinel()) + if (oopDesc::equals(old_result, Universe::the_null_sentinel())) old_result = NULL; return old_result; } } else { - assert(result_oop != Universe::the_null_sentinel(), ""); + assert(!oopDesc::equals(result_oop, Universe::the_null_sentinel()), ""); return result_oop; } } @@ -1245,7 +1245,7 @@ oop ConstantPool::string_at_impl(const constantPoolHandle& this_cp, int which, int obj_index, TRAPS) { // If the string has already been interned, this entry will be non-null oop str = this_cp->resolved_references()->obj_at(obj_index); - assert(str != Universe::the_null_sentinel(), ""); + assert(!oopDesc::equals(str, Universe::the_null_sentinel()), ""); if (str != NULL) return str; Symbol* sym = this_cp->unresolved_string_at(which); str = StringTable::intern(sym, CHECK_(NULL)); diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -2401,7 +2401,7 @@ // and package entries. Both must be the same. This rule // applies even to classes that are defined in the unnamed // package, they still must have the same class loader. - if ((classloader1 == classloader2) && (classpkg1 == classpkg2)) { + if (oopDesc::equals(classloader1, classloader2) && (classpkg1 == classpkg2)) { return true; } @@ -2412,7 +2412,7 @@ // and classname information is enough to determine a class's package bool InstanceKlass::is_same_class_package(oop other_class_loader, const Symbol* other_class_name) const { - if (class_loader() != other_class_loader) { + if (!oopDesc::equals(class_loader(), other_class_loader)) { return false; } if (name()->fast_compare(other_class_name) == 0) { diff --git a/src/hotspot/share/oops/klassVtable.cpp b/src/hotspot/share/oops/klassVtable.cpp --- a/src/hotspot/share/oops/klassVtable.cpp +++ b/src/hotspot/share/oops/klassVtable.cpp @@ -496,7 +496,7 @@ // to link to the first super, and we get all the others. Handle super_loader(THREAD, super_klass->class_loader()); - if (target_loader() != super_loader()) { + if (!oopDesc::equals(target_loader(), super_loader())) { ResourceMark rm(THREAD); Symbol* failed_type_symbol = SystemDictionary::check_signature_loaders(signature, target_loader, @@ -1225,7 +1225,7 @@ // if checkconstraints requested if (checkconstraints) { Handle method_holder_loader (THREAD, target->method_holder()->class_loader()); - if (method_holder_loader() != interface_loader()) { + if (!oopDesc::equals(method_holder_loader(), interface_loader())) { ResourceMark rm(THREAD); Symbol* failed_type_symbol = SystemDictionary::check_signature_loaders(m->signature(), diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp --- a/src/hotspot/share/oops/objArrayKlass.cpp +++ b/src/hotspot/share/oops/objArrayKlass.cpp @@ -220,7 +220,7 @@ // Either oop or narrowOop depending on UseCompressedOops. template void ObjArrayKlass::do_copy(arrayOop s, T* src, arrayOop d, T* dst, int length, TRAPS) { - if (s == d) { + if (oopDesc::equals(s, d)) { // since source and destination are equal we do not need conversion checks. assert(length > 0, "sanity check"); HeapAccess<>::oop_arraycopy(s, d, src, dst, length); diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -37,6 +37,10 @@ bool always_do_update_barrier = false; +bool oopDesc::equals(oop o1, oop o2) { + return Access<>::equals(o1, o2); +} + void oopDesc::print_on(outputStream* st) const { if (this == NULL) { st->print_cr("NULL"); diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -145,6 +145,8 @@ } } + static bool equals(oop o1, oop o2); + // Decode an oop pointer from a narrowOop if compressed. // These are overloaded for oop and narrowOop as are the other functions // below so that they can be called in template functions. diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -582,7 +582,7 @@ oop super_mirror = JNIHandles::resolve_non_null(super); if (java_lang_Class::is_primitive(sub_mirror) || java_lang_Class::is_primitive(super_mirror)) { - jboolean ret = (sub_mirror == super_mirror); + jboolean ret = oopDesc::equals(sub_mirror, super_mirror); HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret); return ret; @@ -822,7 +822,7 @@ oop a = JNIHandles::resolve(r1); oop b = JNIHandles::resolve(r2); - jboolean ret = (a == b) ? JNI_TRUE : JNI_FALSE; + jboolean ret = oopDesc::equals(a, b) ? JNI_TRUE : JNI_FALSE; HOTSPOT_JNI_ISSAMEOBJECT_RETURN(ret); return ret; diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -1364,7 +1364,7 @@ protection_domain = method->method_holder()->protection_domain(); } - if ((previous_protection_domain != protection_domain) && (protection_domain != NULL)) { + if ((!oopDesc::equals(previous_protection_domain, protection_domain)) && (protection_domain != NULL)) { local_array->push(protection_domain); previous_protection_domain = protection_domain; } diff --git a/src/hotspot/share/prims/methodHandles.cpp b/src/hotspot/share/prims/methodHandles.cpp --- a/src/hotspot/share/prims/methodHandles.cpp +++ b/src/hotspot/share/prims/methodHandles.cpp @@ -961,7 +961,7 @@ if (!java_lang_invoke_MemberName::is_instance(result())) return -99; // caller bug! oop saved = MethodHandles::init_field_MemberName(result, st.field_descriptor()); - if (saved != result()) + if (!oopDesc::equals(saved, result())) results->obj_at_put(rfill-1, saved); // show saved instance to user } else if (++overflow >= overflow_limit) { match_flags = 0; break; // got tired of looking at overflow @@ -1013,7 +1013,7 @@ return -99; // caller bug! CallInfo info(m, NULL, CHECK_0); oop saved = MethodHandles::init_method_MemberName(result, info); - if (saved != result()) + if (!oopDesc::equals(saved, result())) results->obj_at_put(rfill-1, saved); // show saved instance to user } else if (++overflow >= overflow_limit) { match_flags = 0; break; // got tired of looking at overflow diff --git a/src/hotspot/share/prims/stackwalk.cpp b/src/hotspot/share/prims/stackwalk.cpp --- a/src/hotspot/share/prims/stackwalk.cpp +++ b/src/hotspot/share/prims/stackwalk.cpp @@ -48,7 +48,7 @@ bool BaseFrameStream::check_magic(objArrayHandle frames_array) { oop m1 = frames_array->obj_at(magic_pos); jlong m2 = _anchor; - if (m1 == _thread->threadObj() && m2 == address_value()) return true; + if (oopDesc::equals(m1, _thread->threadObj()) && m2 == address_value()) return true; return false; } @@ -77,7 +77,7 @@ { assert(thread != NULL && thread->is_Java_thread(), ""); oop m1 = frames_array->obj_at(magic_pos); - if (m1 != thread->threadObj()) return NULL; + if (!oopDesc::equals(m1, thread->threadObj())) return NULL; if (magic == 0L) return NULL; BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic; if (!stream->is_valid_in(thread, frames_array)) return NULL; diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp --- a/src/hotspot/share/prims/unsafe.cpp +++ b/src/hotspot/share/prims/unsafe.cpp @@ -897,7 +897,7 @@ oop p = JNIHandles::resolve(obj); assert_field_offset_sane(p, offset); oop ret = HeapAccess::oop_atomic_cmpxchg_at(x, p, (ptrdiff_t)offset, e); - return ret == e; + return oopDesc::equals(ret, e); } UNSAFE_END UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) { diff --git a/src/hotspot/share/runtime/biasedLocking.cpp b/src/hotspot/share/runtime/biasedLocking.cpp --- a/src/hotspot/share/runtime/biasedLocking.cpp +++ b/src/hotspot/share/runtime/biasedLocking.cpp @@ -254,7 +254,7 @@ BasicLock* highest_lock = NULL; for (int i = 0; i < cached_monitor_info->length(); i++) { MonitorInfo* mon_info = cached_monitor_info->at(i); - if (mon_info->owner() == obj) { + if (oopDesc::equals(mon_info->owner(), obj)) { log_trace(biasedlocking)(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")", p2i((void *) mon_info->owner()), p2i((void *) obj)); diff --git a/src/hotspot/share/runtime/handles.cpp b/src/hotspot/share/runtime/handles.cpp --- a/src/hotspot/share/runtime/handles.cpp +++ b/src/hotspot/share/runtime/handles.cpp @@ -30,6 +30,14 @@ #include "runtime/handles.inline.hpp" #include "runtime/thread.inline.hpp" +bool Handle::operator == (oop o) const { + return oopDesc::equals(obj(), o); +} + +bool Handle::operator == (const Handle& h) const { + return oopDesc::equals(obj(), h.obj()); +} + #ifdef ASSERT oop* HandleArea::allocate_handle(oop obj) { assert(_handle_mark_nesting > 1, "memory leak: allocating handle outside HandleMark"); diff --git a/src/hotspot/share/runtime/handles.hpp b/src/hotspot/share/runtime/handles.hpp --- a/src/hotspot/share/runtime/handles.hpp +++ b/src/hotspot/share/runtime/handles.hpp @@ -77,8 +77,9 @@ // General access oop operator () () const { return obj(); } oop operator -> () const { return non_null_obj(); } - bool operator == (oop o) const { return obj() == o; } - bool operator == (const Handle& h) const { return obj() == h.obj(); } + + bool operator == (oop o) const; + bool operator == (const Handle& h) const; // Null checks bool is_null() const { return _handle == NULL; } diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp --- a/src/hotspot/share/runtime/reflection.cpp +++ b/src/hotspot/share/runtime/reflection.cpp @@ -418,7 +418,7 @@ assert(lower_dim->is_array_klass(), "just checking"); result2 = lower_dim->java_mirror(); } - assert(result == result2, "results must be consistent"); + assert(oopDesc::equals(result, result2), "results must be consistent"); #endif //ASSERT return result; } diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -170,7 +170,7 @@ if (mark->has_monitor()) { ObjectMonitor * const mon = mark->monitor(); - assert(mon->object() == obj, "invariant"); + assert(oopDesc::equals((oop) mon->object(), obj), "invariant"); if (mon->owner() != self) return false; // slow-path for IMS exception if (mon->first_waiter() != NULL) { @@ -214,7 +214,7 @@ if (mark->has_monitor()) { ObjectMonitor * const m = mark->monitor(); - assert(m->object() == obj, "invariant"); + assert(oopDesc::equals((oop) m->object(), obj), "invariant"); Thread * const owner = (Thread *) m->_owner; // Lock contention and Transactional Lock Elision (TLE) diagnostics @@ -1401,7 +1401,7 @@ if (mark->has_monitor()) { ObjectMonitor * inf = mark->monitor(); assert(inf->header()->is_neutral(), "invariant"); - assert(inf->object() == object, "invariant"); + assert(oopDesc::equals((oop) inf->object(), object), "invariant"); assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid"); return inf; } diff --git a/src/hotspot/share/services/memoryManager.hpp b/src/hotspot/share/services/memoryManager.hpp --- a/src/hotspot/share/services/memoryManager.hpp +++ b/src/hotspot/share/services/memoryManager.hpp @@ -68,7 +68,7 @@ void add_pool(MemoryPool* pool); - bool is_manager(instanceHandle mh) { return mh() == _memory_mgr_obj; } + bool is_manager(instanceHandle mh) { return oopDesc::equals(mh(), _memory_mgr_obj); } virtual instanceOop get_memory_manager_instance(TRAPS); virtual bool is_gc_memory_manager() { return false; } diff --git a/src/hotspot/share/services/memoryPool.hpp b/src/hotspot/share/services/memoryPool.hpp --- a/src/hotspot/share/services/memoryPool.hpp +++ b/src/hotspot/share/services/memoryPool.hpp @@ -92,7 +92,7 @@ // max size could be changed virtual size_t max_size() const { return _max_size; } - bool is_pool(instanceHandle pool) { return (pool() == _memory_pool_obj); } + bool is_pool(instanceHandle pool) { return oopDesc::equals(pool(), _memory_pool_obj); } bool available_for_allocation() { return _available_for_allocation; } bool set_available_for_allocation(bool value) { diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp --- a/src/hotspot/share/services/threadService.cpp +++ b/src/hotspot/share/services/threadService.cpp @@ -606,7 +606,7 @@ for (int j = 0; j < len; j++) { oop monitor = locked_monitors->at(j); assert(monitor != NULL, "must be a Java object"); - if (monitor == object) { + if (oopDesc::equals(monitor, object)) { found = true; break; } diff --git a/src/hotspot/share/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp --- a/src/hotspot/share/utilities/exceptions.cpp +++ b/src/hotspot/share/utilities/exceptions.cpp @@ -442,9 +442,9 @@ volatile int Exceptions::_out_of_memory_error_class_metaspace_errors = 0; void Exceptions::count_out_of_memory_exceptions(Handle exception) { - if (exception() == Universe::out_of_memory_error_metaspace()) { + if (oopDesc::equals(exception(), Universe::out_of_memory_error_metaspace())) { Atomic::inc(&_out_of_memory_error_metaspace_errors); - } else if (exception() == Universe::out_of_memory_error_class_metaspace()) { + } else if (oopDesc::equals(exception(), Universe::out_of_memory_error_class_metaspace())) { Atomic::inc(&_out_of_memory_error_class_metaspace_errors); } else { // everything else reported as java heap OOM diff --git a/src/hotspot/share/utilities/growableArray.hpp b/src/hotspot/share/utilities/growableArray.hpp --- a/src/hotspot/share/utilities/growableArray.hpp +++ b/src/hotspot/share/utilities/growableArray.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_UTILITIES_GROWABLEARRAY_HPP #include "memory/allocation.hpp" +#include "oops/oop.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/ostream.hpp" @@ -211,6 +212,15 @@ void print(); + inline static bool safe_equals(oop obj1, oop obj2) { + return oopDesc::equals(obj1, obj2); + } + + template + inline static bool safe_equals(X i1, X i2) { + return i1 == i2; + } + int append(const E& elem) { check_nesting(); if (_len == _max) grow(_len); @@ -295,7 +305,7 @@ bool contains(const E& elem) const { for (int i = 0; i < _len; i++) { - if (_data[i] == elem) return true; + if (safe_equals(_data[i], elem)) return true; } return false; }