8186088: ConstantPoolCache::_resolved_references is not a JNIHandle

Make an OopHandle type to replace jobject to encapsulate these oop pointers in metadata and module entry.

Reviewed-by: sspitsyn, dholmes, jiangli, twisti
This commit is contained in:
Coleen Phillimore 2017-08-23 12:00:39 -04:00
parent c1f2527986
commit 111116dd5b
31 changed files with 142 additions and 48 deletions

View File

@ -272,8 +272,7 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
// load pointer for resolved_references[] objArray
ldr(result, Address(result, ConstantPool::cache_offset_in_bytes()));
ldr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
// JNIHandles::resolve(obj);
ldr(result, Address(result, 0));
resolve_oop_handle(result);
// Add in the index
add(result, result, tmp);
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));

View File

@ -3279,6 +3279,12 @@ void MacroAssembler::load_klass(Register dst, Register src) {
}
}
// ((OopHandle)result).resolve();
void MacroAssembler::resolve_oop_handle(Register result) {
// OopHandle::resolve is an indirection.
ldr(result, Address(result, 0));
}
void MacroAssembler::load_mirror(Register dst, Register method) {
const int mirror_offset = in_bytes(Klass::java_mirror_offset());
ldr(dst, Address(rmethod, Method::const_offset()));

View File

@ -790,6 +790,7 @@ public:
void store_klass(Register dst, Register src);
void cmp_klass(Register oop, Register trial_klass, Register tmp);
void resolve_oop_handle(Register result);
void load_mirror(Register dst, Register method);
void load_heap_oop(Register dst, Address src);

View File

@ -300,8 +300,7 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
// load pointer for resolved_references[] objArray
ldr(cache, Address(result, ConstantPool::cache_offset_in_bytes()));
ldr(cache, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
// JNIHandles::resolve(result)
ldr(cache, Address(cache, 0));
resolve_oop_handle(cache);
// Add in the index
// convert from field index to resolved_references() index and from
// word index to byte offset. Since this is a java object, it can be compressed

View File

@ -2887,6 +2887,11 @@ int MacroAssembler::patchable_call(address target, RelocationHolder const& rspec
return offset();
}
// ((OopHandle)result).resolve();
void MacroAssembler::resolve_oop_handle(Register result) {
// OopHandle::resolve is an indirection.
ldr(result, Address(result, 0));
}
void MacroAssembler::load_mirror(Register mirror, Register method, Register tmp) {
const int mirror_offset = in_bytes(Klass::java_mirror_offset());
@ -2896,6 +2901,7 @@ void MacroAssembler::load_mirror(Register mirror, Register method, Register tmp)
ldr(mirror, Address(tmp, mirror_offset));
}
///////////////////////////////////////////////////////////////////////////////
// Compressed pointers

View File

@ -687,6 +687,7 @@ public:
AbstractAssembler::emit_address((address)L.data());
}
void resolve_oop_handle(Register result);
void load_mirror(Register mirror, Register method, Register tmp);
// Porting layer between 32-bit ARM and AArch64

View File

@ -464,8 +464,7 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result
// Load pointer for resolved_references[] objArray.
ld(result, ConstantPool::cache_offset_in_bytes(), result);
ld(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
// JNIHandles::resolve(result)
ld(result, 0, result);
resolve_oop_handle(result);
#ifdef ASSERT
Label index_ok;
lwa(R0, arrayOopDesc::length_offset_in_bytes(), result);

View File

@ -3372,6 +3372,12 @@ void MacroAssembler::load_klass(Register dst, Register src) {
}
}
// ((OopHandle)result).resolve();
void MacroAssembler::resolve_oop_handle(Register result) {
// OopHandle::resolve is an indirection.
ld(result, 0, result);
}
void MacroAssembler::load_mirror_from_const_method(Register mirror, Register const_method) {
ld(mirror, in_bytes(ConstMethod::constants_offset()), const_method);
ld(mirror, ConstantPool::pool_holder_offset_in_bytes(), mirror);

View File

@ -725,6 +725,7 @@ class MacroAssembler: public Assembler {
void store_klass(Register dst_oop, Register klass, Register tmp = R0);
void store_klass_gap(Register dst_oop, Register val = noreg); // Will store 0 if val not specified.
void resolve_oop_handle(Register result);
void load_mirror_from_const_method(Register mirror, Register const_method);
static int instr_size_for_decode_klass_not_null();

View File

@ -364,8 +364,7 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result
// Load pointer for resolved_references[] objArray.
z_lg(result, ConstantPool::cache_offset_in_bytes(), result);
z_lg(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
// JNIHandles::resolve(result)
z_lg(result, 0, result); // Load resolved references array itself.
resolve_oop_handle(result); // Load resolved references array itself.
#ifdef ASSERT
NearLabel index_ok;
z_lgf(Z_R0, Address(result, arrayOopDesc::length_offset_in_bytes()));

View File

@ -4660,6 +4660,12 @@ void MacroAssembler::oop_decoder(Register Rdst, Register Rsrc, bool maybeNULL, R
}
}
// ((OopHandle)result).resolve();
void MacroAssembler::resolve_oop_handle(Register result) {
// OopHandle::resolve is an indirection.
z_lg(result, 0, result);
}
void MacroAssembler::load_mirror(Register mirror, Register method) {
mem2reg_opt(mirror, Address(method, Method::const_offset()));
mem2reg_opt(mirror, Address(mirror, ConstMethod::constants_offset()));

View File

@ -832,6 +832,7 @@ class MacroAssembler: public Assembler {
void oop_decoder(Register Rdst, Register Rsrc, bool maybeNULL,
Register Rbase = Z_R1, int pow2_offset = -1);
void resolve_oop_handle(Register result);
void load_mirror(Register mirror, Register method);
//--------------------------

View File

@ -730,8 +730,7 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
// load pointer for resolved_references[] objArray
ld_ptr(result, ConstantPool::cache_offset_in_bytes(), result);
ld_ptr(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
// JNIHandles::resolve(result)
ld_ptr(result, 0, result);
resolve_oop_handle(result);
// Add in the index
add(result, tmp, result);
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);

View File

@ -3822,6 +3822,12 @@ void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_v
card_table_write(bs->byte_map_base, tmp, store_addr);
}
// ((OopHandle)result).resolve();
void MacroAssembler::resolve_oop_handle(Register result) {
// OopHandle::resolve is an indirection.
ld_ptr(result, 0, result);
}
void MacroAssembler::load_mirror(Register mirror, Register method) {
const int mirror_offset = in_bytes(Klass::java_mirror_offset());
ld_ptr(method, in_bytes(Method::const_offset()), mirror);

View File

@ -995,6 +995,7 @@ public:
inline void ldbool(const Address& a, Register d);
inline void movbool( bool boolconst, Register d);
void resolve_oop_handle(Register result);
void load_mirror(Register mirror, Register method);
// klass oop manipulations if compressed

View File

@ -511,8 +511,7 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
// load pointer for resolved_references[] objArray
movptr(result, Address(result, ConstantPool::cache_offset_in_bytes()));
movptr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
// JNIHandles::resolve(obj);
movptr(result, Address(result, 0));
resolve_oop_handle(result);
// Add in the index
addptr(result, tmp);
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));

View File

@ -6604,6 +6604,12 @@ void MacroAssembler::restore_cpu_control_state_after_jni() {
#endif // _LP64
}
// ((OopHandle)result).resolve();
void MacroAssembler::resolve_oop_handle(Register result) {
// OopHandle::resolve is an indirection.
movptr(result, Address(result, 0));
}
void MacroAssembler::load_mirror(Register mirror, Register method) {
// get mirror
const int mirror_offset = in_bytes(Klass::java_mirror_offset());
@ -7030,7 +7036,6 @@ void MacroAssembler::reinit_heapbase() {
#endif // _LP64
// C2 compiled method's prolog code.
void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b) {

View File

@ -327,6 +327,7 @@ class MacroAssembler: public Assembler {
void movbool(Address dst, Register src);
void testbool(Register dst);
void resolve_oop_handle(Register result);
void load_mirror(Register mirror, Register method);
// oop manipulations

View File

@ -759,14 +759,18 @@ Metaspace* ClassLoaderData::metaspace_non_null() {
return metaspace;
}
jobject ClassLoaderData::add_handle(Handle h) {
OopHandle ClassLoaderData::add_handle(Handle h) {
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
return (jobject) _handles.add(h());
return OopHandle(_handles.add(h()));
}
void ClassLoaderData::remove_handle_unsafe(jobject h) {
assert(_handles.contains((oop*) h), "Got unexpected handle " PTR_FORMAT, p2i((oop*) h));
*((oop*) h) = NULL;
void ClassLoaderData::init_handle_locked(OopHandle& dest, Handle h) {
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
if (dest.resolve() != NULL) {
return;
} else {
dest = _handles.add(h());
}
}
// Add this metadata pointer to be freed when it's safe. This is only during

View File

@ -29,6 +29,7 @@
#include "memory/memRegion.hpp"
#include "memory/metaspace.hpp"
#include "memory/metaspaceCounters.hpp"
#include "oops/oopHandle.hpp"
#include "runtime/mutex.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/growableArray.hpp"
@ -362,8 +363,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
void verify();
const char* loader_name();
jobject add_handle(Handle h);
void remove_handle_unsafe(jobject h);
OopHandle add_handle(Handle h);
void init_handle_locked(OopHandle& pd, Handle h); // used for concurrent access to ModuleEntry::_pd field
void add_class(Klass* k, bool publicize = true);
void remove_class(Klass* k);
bool contains_klass(Klass* k);

View File

@ -799,7 +799,7 @@ void java_lang_Class::set_mirror_module_field(Klass* k, Handle mirror, Handle mo
// If java.base was already defined then patch this particular class with java.base.
if (javabase_was_defined) {
ModuleEntry *javabase_entry = ModuleEntryTable::javabase_moduleEntry();
assert(javabase_entry != NULL && javabase_entry->module_handle() != NULL,
assert(javabase_entry != NULL && javabase_entry->module() != NULL,
"Setting class module field, " JAVA_BASE_NAME " should be defined");
Handle javabase_handle(THREAD, javabase_entry->module());
set_module(mirror(), javabase_handle());

View File

@ -80,19 +80,16 @@ void ModuleEntry::set_version(Symbol* version) {
}
// Returns the shared ProtectionDomain
Handle ModuleEntry::shared_protection_domain() {
return Handle(Thread::current(), JNIHandles::resolve(_pd));
oop ModuleEntry::shared_protection_domain() {
return _pd.resolve();
}
// Set the shared ProtectionDomain atomically
void ModuleEntry::set_shared_protection_domain(ClassLoaderData *loader_data,
Handle pd_h) {
// Create a handle for the shared ProtectionDomain and save it atomically.
// If someone beats us setting the _pd cache, the created handle is destroyed.
jobject obj = loader_data->add_handle(pd_h);
if (Atomic::cmpxchg_ptr(obj, &_pd, NULL) != NULL) {
loader_data->remove_handle_unsafe(obj);
}
// init_handle_locked checks if someone beats us setting the _pd cache.
loader_data->init_handle_locked(_pd, pd_h);
}
// Returns true if this module can read module m

View File

@ -27,6 +27,7 @@
#include "classfile/classLoaderData.hpp"
#include "classfile/vmSymbols.hpp"
#include "oops/oopHandle.hpp"
#include "oops/symbol.hpp"
#include "prims/jni.h"
#include "runtime/jniHandles.hpp"
@ -56,8 +57,8 @@ class ModuleClosure;
// data structure.
class ModuleEntry : public HashtableEntry<Symbol*, mtModule> {
private:
jobject _module; // java.lang.Module
jobject _pd; // java.security.ProtectionDomain, cached
OopHandle _module; // java.lang.Module
OopHandle _pd; // java.security.ProtectionDomain, cached
// for shared classes from this module
ClassLoaderData* _loader_data;
GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
@ -89,16 +90,16 @@ public:
Symbol* name() const { return literal(); }
void set_name(Symbol* n) { set_literal(n); }
oop module() const { return JNIHandles::resolve(_module); }
jobject module_handle() const { return _module; }
void set_module(jobject j) { _module = j; }
oop module() const { return _module.resolve(); }
OopHandle module_handle() const { return _module; }
void set_module(OopHandle j) { _module = j; }
// The shared ProtectionDomain reference is set once the VM loads a shared class
// originated from the current Module. The referenced ProtectionDomain object is
// created by the ClassLoader when loading a class (shared or non-shared) from the
// Module for the first time. This ProtectionDomain object is used for all
// classes from the Module loaded by the same ClassLoader.
Handle shared_protection_domain();
oop shared_protection_domain();
void set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd);
ClassLoaderData* loader_data() const { return _loader_data; }
@ -246,7 +247,7 @@ public:
static void set_javabase_moduleEntry(ModuleEntry* java_base) { _javabase_module = java_base; }
static bool javabase_defined() { return ((_javabase_module != NULL) &&
(_javabase_module->module_handle() != NULL)); }
(_javabase_module->module() != NULL)); }
static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location);
static void patch_javabase_entries(Handle module_handle);

View File

@ -134,7 +134,7 @@ void ConstantPool::metaspace_pointers_do(MetaspaceClosure* it) {
}
objArrayOop ConstantPool::resolved_references() const {
return (objArrayOop)JNIHandles::resolve(_cache->resolved_references());
return (objArrayOop)_cache->resolved_references();
}
// Create resolved_references array and mapping array for original cp indexes

View File

@ -28,6 +28,7 @@
#include "oops/arrayOop.hpp"
#include "oops/cpCache.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oopHandle.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayOop.hpp"
#include "runtime/handles.hpp"
@ -821,7 +822,7 @@ class ConstantPool : public Metadata {
private:
void set_resolved_references(jobject s) { _cache->set_resolved_references(s); }
void set_resolved_references(OopHandle s) { _cache->set_resolved_references(s); }
Array<u2>* reference_map() const { return (_cache == NULL) ? NULL : _cache->reference_map(); }
void set_reference_map(Array<u2>* o) { _cache->set_reference_map(o); }

View File

@ -28,6 +28,7 @@
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.hpp"
#include "oops/array.hpp"
#include "oops/oopHandle.hpp"
#include "runtime/orderAccess.hpp"
#include "utilities/align.hpp"
@ -413,7 +414,7 @@ class ConstantPoolCache: public MetaspaceObj {
// stored in the ConstantPool, which is read-only.
// Array of resolved objects from the constant pool and map from resolved
// object index to original constant pool index
jobject _resolved_references;
OopHandle _resolved_references;
Array<u2>* _reference_map;
// The narrowOop pointer to the archived resolved_references. Set at CDS dump
// time when caching java heap object is supported.
@ -455,8 +456,8 @@ class ConstantPoolCache: public MetaspaceObj {
oop archived_references() NOT_CDS_JAVA_HEAP_RETURN_(NULL);
void set_archived_references(oop o) NOT_CDS_JAVA_HEAP_RETURN;
jobject resolved_references() { return _resolved_references; }
void set_resolved_references(jobject s) { _resolved_references = s; }
oop resolved_references() { return _resolved_references.resolve(); }
void set_resolved_references(OopHandle s) { _resolved_references = s; }
Array<u2>* reference_map() const { return _reference_map; }
void set_reference_map(Array<u2>* o) { _reference_map = o; }

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_OOPS_OOPHANDLE_HPP
#define SHARE_VM_OOPS_OOPHANDLE_HPP
#include "oops/oop.hpp"
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
// Simple class for encapsulating oop pointers stored in metadata.
// These are different from Handle. The Handle class stores pointers
// to oops on the stack, and manages the allocation from a thread local
// area in the constructor.
// This assumes that the caller will allocate the handle in the appropriate
// area. The reason for the encapsulation is to help with naming and to allow
// future uses for read barriers.
class OopHandle {
private:
oop* _obj;
public:
OopHandle() : _obj(NULL) {}
OopHandle(oop* w) : _obj(w) {}
oop resolve() const { return (_obj == NULL) ? (oop)NULL : *_obj; }
};
#endif // SHARE_VM_OOPS_OOPHANDLE_HPP

View File

@ -1490,14 +1490,14 @@ JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) {
}
}
GrowableArray<jobject>* JvmtiModuleClosure::_tbl = NULL;
GrowableArray<OopHandle>* JvmtiModuleClosure::_tbl = NULL;
jvmtiError
JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr) {
ResourceMark rm;
MutexLocker ml(Module_lock);
_tbl = new GrowableArray<jobject>(77);
_tbl = new GrowableArray<OopHandle>(77);
if (_tbl == NULL) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
@ -1513,7 +1513,7 @@ JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobje
return JVMTI_ERROR_OUT_OF_MEMORY;
}
for (jint idx = 0; idx < len; idx++) {
array[idx] = _tbl->at(idx);
array[idx] = JNIHandles::make_local(Thread::current(), _tbl->at(idx).resolve());
}
_tbl = NULL;
*modules_ptr = array;

View File

@ -30,6 +30,7 @@
#include "prims/jvmtiEventController.hpp"
#include "prims/jvmtiThreadState.hpp"
#include "prims/jvmtiThreadState.inline.hpp"
#include "oops/oopHandle.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/frame.hpp"
#include "runtime/handles.inline.hpp"
@ -704,12 +705,12 @@ class JvmtiMonitorClosure: public MonitorClosure {
// Jvmti module closure to collect all modules loaded to the system.
class JvmtiModuleClosure : public StackObj {
private:
static GrowableArray<jobject> *_tbl; // Protected with Module_lock
static GrowableArray<OopHandle> *_tbl; // Protected with Module_lock
static void do_module(ModuleEntry* entry) {
assert_locked_or_safepoint(Module_lock);
jobject module = entry->module_handle();
guarantee(module != NULL, "module object is NULL");
OopHandle module = entry->module_handle();
guarantee(module.resolve() != NULL, "module object is NULL");
_tbl->push(module);
}

View File

@ -764,7 +764,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
ModuleEntry* module_entry = InstanceKlass::cast(klass)->module();
assert(module_entry != NULL, "module_entry should always be set");
if (module_entry->is_named() &&
module_entry->module_handle() != NULL &&
module_entry->module() != NULL &&
!module_entry->has_default_read_edges()) {
if (!module_entry->set_has_default_read_edges()) {
// We won a potential race.

View File

@ -83,6 +83,7 @@
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oopHandle.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
#include "oops/typeArrayOop.hpp"
@ -235,7 +236,7 @@ typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
nonstatic_field(ConstantPool, _operands, Array<u2>*) \
nonstatic_field(ConstantPool, _resolved_klasses, Array<Klass*>*) \
nonstatic_field(ConstantPool, _length, int) \
nonstatic_field(ConstantPoolCache, _resolved_references, jobject) \
nonstatic_field(ConstantPoolCache, _resolved_references, OopHandle) \
nonstatic_field(ConstantPoolCache, _reference_map, Array<u2>*) \
nonstatic_field(ConstantPoolCache, _length, int) \
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
@ -1438,6 +1439,7 @@ typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
declare_oop_type(oop) \
declare_oop_type(narrowOop) \
declare_oop_type(typeArrayOop) \
declare_oop_type(OopHandle) \
\
/*************************************/ \
/* MethodOop-related data structures */ \