mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8026977: NPG: Remove ConstantPool::lock
Write klass and resolved_references constant pool fields lock free. Reviewed-by: jrose, twisti
This commit is contained in:
parent
c1c9f333d5
commit
243d697d71
@ -512,24 +512,9 @@ ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool,
|
||||
} else {
|
||||
// Check if it's resolved if it's not a symbol constant pool entry.
|
||||
klass = KlassHandle(THREAD, ConstantPool::klass_at_if_loaded(cpool, index));
|
||||
|
||||
if (klass.is_null()) {
|
||||
// The klass has not been inserted into the constant pool.
|
||||
// Try to look it up by name.
|
||||
{
|
||||
// We have to lock the cpool to keep the oop from being resolved
|
||||
// while we are accessing it.
|
||||
MonitorLockerEx ml(cpool->lock());
|
||||
constantTag tag = cpool->tag_at(index);
|
||||
if (tag.is_klass()) {
|
||||
// The klass has been inserted into the constant pool
|
||||
// very recently.
|
||||
klass = KlassHandle(THREAD, cpool->resolved_klass_at(index));
|
||||
} else {
|
||||
assert(cpool->tag_at(index).is_unresolved_klass(), "wrong tag");
|
||||
klass_name = cpool->unresolved_klass_at(index);
|
||||
}
|
||||
}
|
||||
if (klass.is_null()) {
|
||||
klass_name = cpool->klass_name_at(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
/* Copyright (c) 2013, 2014, 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
|
||||
@ -686,7 +686,7 @@ class CompileReplay : public StackObj {
|
||||
switch (cp->tag_at(i).value()) {
|
||||
case JVM_CONSTANT_UnresolvedClass: {
|
||||
if (tag == JVM_CONSTANT_Class) {
|
||||
tty->print_cr("Resolving klass %s at %d", cp->unresolved_klass_at(i)->as_utf8(), i);
|
||||
tty->print_cr("Resolving klass %s at %d", cp->klass_name_at(i)->as_utf8(), i);
|
||||
Klass* k = cp->klass_at(i, CHECK);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -510,7 +510,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
|
||||
jbyte tag = cp->tag_at(index).value();
|
||||
switch (tag) {
|
||||
case JVM_CONSTANT_UnresolvedClass: {
|
||||
Symbol* class_name = cp->unresolved_klass_at(index);
|
||||
Symbol* class_name = cp->klass_name_at(index);
|
||||
// check the name, even if _cp_patches will overwrite it
|
||||
verify_legal_class_name(class_name, CHECK_(nullHandle));
|
||||
break;
|
||||
@ -3161,7 +3161,7 @@ instanceKlassHandle ClassFileParser::parse_super_class(int super_class_index,
|
||||
if (_need_verify)
|
||||
is_array = super_klass->oop_is_array();
|
||||
} else if (_need_verify) {
|
||||
is_array = (_cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY);
|
||||
is_array = (_cp->klass_name_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY);
|
||||
}
|
||||
if (_need_verify) {
|
||||
guarantee_property(!is_array,
|
||||
@ -3855,7 +3855,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
"Invalid this class index %u in constant pool in class file %s",
|
||||
this_class_index, CHECK_(nullHandle));
|
||||
|
||||
Symbol* class_name = cp->unresolved_klass_at(this_class_index);
|
||||
Symbol* class_name = cp->klass_name_at(this_class_index);
|
||||
assert(class_name != NULL, "class_name can't be null");
|
||||
|
||||
// It's important to set parsed_name *before* resolving the super class.
|
||||
|
||||
@ -187,8 +187,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
JNIHandleBlock* handles() const;
|
||||
void set_handles(JNIHandleBlock* handles);
|
||||
|
||||
Mutex* metaspace_lock() const { return _metaspace_lock; }
|
||||
|
||||
// GC interface.
|
||||
void clear_claimed() { _claimed = 0; }
|
||||
bool claimed() const { return _claimed == 1; }
|
||||
@ -216,6 +214,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
return _the_null_class_loader_data;
|
||||
}
|
||||
|
||||
Mutex* metaspace_lock() const { return _metaspace_lock; }
|
||||
|
||||
bool is_anonymous() const { return _is_anonymous; }
|
||||
|
||||
static void init_null_class_loader_data() {
|
||||
|
||||
@ -71,7 +71,6 @@ ConstantPool::ConstantPool(Array<u1>* tags) {
|
||||
|
||||
// only set to non-zero if constant pool is merged by RedefineClasses
|
||||
set_version(0);
|
||||
set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock"));
|
||||
|
||||
// initialize tag array
|
||||
int length = tags->length();
|
||||
@ -100,9 +99,6 @@ void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) {
|
||||
void ConstantPool::release_C_heap_structures() {
|
||||
// walk constant pool and decrement symbol reference counts
|
||||
unreference_symbols();
|
||||
|
||||
delete _lock;
|
||||
set_lock(NULL);
|
||||
}
|
||||
|
||||
objArrayOop ConstantPool::resolved_references() const {
|
||||
@ -146,8 +142,7 @@ void ConstantPool::initialize_resolved_references(ClassLoaderData* loader_data,
|
||||
// CDS support. Create a new resolved_references array.
|
||||
void ConstantPool::restore_unshareable_info(TRAPS) {
|
||||
|
||||
// Only create the new resolved references array and lock if it hasn't been
|
||||
// attempted before
|
||||
// Only create the new resolved references array if it hasn't been attempted before
|
||||
if (resolved_references() != NULL) return;
|
||||
|
||||
// restore the C++ vtable from the shared archive
|
||||
@ -163,9 +158,6 @@ void ConstantPool::restore_unshareable_info(TRAPS) {
|
||||
ClassLoaderData* loader_data = pool_holder()->class_loader_data();
|
||||
set_resolved_references(loader_data->add_handle(refs_handle));
|
||||
}
|
||||
|
||||
// Also need to recreate the mutex. Make sure this matches the constructor
|
||||
set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,7 +168,6 @@ void ConstantPool::remove_unshareable_info() {
|
||||
set_resolved_reference_length(
|
||||
resolved_references() != NULL ? resolved_references()->length() : 0);
|
||||
set_resolved_references(NULL);
|
||||
set_lock(NULL);
|
||||
}
|
||||
|
||||
int ConstantPool::cp_to_object_index(int cp_index) {
|
||||
@ -186,11 +177,41 @@ int ConstantPool::cp_to_object_index(int cp_index) {
|
||||
return (i < 0) ? _no_index_sentinel : i;
|
||||
}
|
||||
|
||||
Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, TRAPS) {
|
||||
// A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
|
||||
// It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
|
||||
// tag is not updated atomicly.
|
||||
void ConstantPool::trace_class_resolution(constantPoolHandle this_cp, KlassHandle k) {
|
||||
ResourceMark rm;
|
||||
int line_number = -1;
|
||||
const char * source_file = NULL;
|
||||
if (JavaThread::current()->has_last_Java_frame()) {
|
||||
// try to identify the method which called this function.
|
||||
vframeStream vfst(JavaThread::current());
|
||||
if (!vfst.at_end()) {
|
||||
line_number = vfst.method()->line_number_from_bci(vfst.bci());
|
||||
Symbol* s = vfst.method()->method_holder()->source_file_name();
|
||||
if (s != NULL) {
|
||||
source_file = s->as_C_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (k() != this_cp->pool_holder()) {
|
||||
// only print something if the classes are different
|
||||
if (source_file != NULL) {
|
||||
tty->print("RESOLVE %s %s %s:%d\n",
|
||||
this_cp->pool_holder()->external_name(),
|
||||
InstanceKlass::cast(k())->external_name(), source_file, line_number);
|
||||
} else {
|
||||
tty->print("RESOLVE %s %s\n",
|
||||
this_cp->pool_holder()->external_name(),
|
||||
InstanceKlass::cast(k())->external_name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, TRAPS) {
|
||||
assert(THREAD->is_Java_thread(), "must be a Java thread");
|
||||
|
||||
// A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
|
||||
// It is not safe to rely on the tag bit's here, since we don't have a lock, and
|
||||
// the entry and tag is not updated atomicly.
|
||||
CPSlot entry = this_cp->slot_at(which);
|
||||
if (entry.is_resolved()) {
|
||||
assert(entry.get_klass()->is_klass(), "must be");
|
||||
@ -198,115 +219,51 @@ Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, TRAPS)
|
||||
return entry.get_klass();
|
||||
}
|
||||
|
||||
// Acquire lock on constant oop while doing update. After we get the lock, we check if another object
|
||||
// already has updated the object
|
||||
assert(THREAD->is_Java_thread(), "must be a Java thread");
|
||||
bool do_resolve = false;
|
||||
bool in_error = false;
|
||||
|
||||
// Create a handle for the mirror. This will preserve the resolved class
|
||||
// until the loader_data is registered.
|
||||
Handle mirror_handle;
|
||||
|
||||
Symbol* name = NULL;
|
||||
Handle loader;
|
||||
{ MonitorLockerEx ml(this_cp->lock());
|
||||
|
||||
if (this_cp->tag_at(which).is_unresolved_klass()) {
|
||||
if (this_cp->tag_at(which).is_unresolved_klass_in_error()) {
|
||||
in_error = true;
|
||||
} else {
|
||||
do_resolve = true;
|
||||
name = this_cp->unresolved_klass_at(which);
|
||||
loader = Handle(THREAD, this_cp->pool_holder()->class_loader());
|
||||
}
|
||||
}
|
||||
} // unlocking constantPool
|
||||
|
||||
|
||||
// The original attempt to resolve this constant pool entry failed so find the
|
||||
// class of the original error and throw another error of the same class (JVMS 5.4.3).
|
||||
// If there is a detail message, pass that detail message to the error constructor.
|
||||
// The JVMS does not strictly require us to duplicate the same detail message,
|
||||
// or any internal exception fields such as cause or stacktrace. But since the
|
||||
// detail message is often a class name or other literal string, we will repeat it if
|
||||
// we can find it in the symbol table.
|
||||
if (in_error) {
|
||||
// This tag doesn't change back to unresolved class unless at a safepoint.
|
||||
if (this_cp->tag_at(which).is_unresolved_klass_in_error()) {
|
||||
// The original attempt to resolve this constant pool entry failed so find the
|
||||
// class of the original error and throw another error of the same class
|
||||
// (JVMS 5.4.3).
|
||||
// If there is a detail message, pass that detail message to the error.
|
||||
// The JVMS does not strictly require us to duplicate the same detail message,
|
||||
// or any internal exception fields such as cause or stacktrace. But since the
|
||||
// detail message is often a class name or other literal string, we will repeat it
|
||||
// if we can find it in the symbol table.
|
||||
throw_resolution_error(this_cp, which, CHECK_0);
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
if (do_resolve) {
|
||||
// this_cp must be unlocked during resolve_or_fail
|
||||
oop protection_domain = this_cp->pool_holder()->protection_domain();
|
||||
Handle h_prot (THREAD, protection_domain);
|
||||
Klass* kk = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
|
||||
KlassHandle k;
|
||||
if (!HAS_PENDING_EXCEPTION) {
|
||||
k = KlassHandle(THREAD, kk);
|
||||
// preserve the resolved klass.
|
||||
mirror_handle = Handle(THREAD, kk->java_mirror());
|
||||
// Do access check for klasses
|
||||
verify_constant_pool_resolve(this_cp, k, THREAD);
|
||||
}
|
||||
Handle mirror_handle;
|
||||
Symbol* name = entry.get_symbol();
|
||||
Handle loader (THREAD, this_cp->pool_holder()->class_loader());
|
||||
Handle protection_domain (THREAD, this_cp->pool_holder()->protection_domain());
|
||||
Klass* kk = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD);
|
||||
KlassHandle k (THREAD, kk);
|
||||
if (!HAS_PENDING_EXCEPTION) {
|
||||
// preserve the resolved klass from unloading
|
||||
mirror_handle = Handle(THREAD, kk->java_mirror());
|
||||
// Do access check for klasses
|
||||
verify_constant_pool_resolve(this_cp, k, THREAD);
|
||||
}
|
||||
|
||||
// Failed to resolve class. We must record the errors so that subsequent attempts
|
||||
// to resolve this constant pool entry fail with the same error (JVMS 5.4.3).
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
MonitorLockerEx ml(this_cp->lock());
|
||||
// Failed to resolve class. We must record the errors so that subsequent attempts
|
||||
// to resolve this constant pool entry fail with the same error (JVMS 5.4.3).
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
save_and_throw_exception(this_cp, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_0);
|
||||
}
|
||||
|
||||
// some other thread has beaten us and has resolved the class.
|
||||
if (this_cp->tag_at(which).is_klass()) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
entry = this_cp->resolved_klass_at(which);
|
||||
return entry.get_klass();
|
||||
}
|
||||
// Make this class loader depend upon the class loader owning the class reference
|
||||
ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data();
|
||||
this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
|
||||
|
||||
// The tag could have changed to in-error before the lock but we have to
|
||||
// handle that here for the class case.
|
||||
save_and_throw_exception(this_cp, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_0);
|
||||
}
|
||||
|
||||
if (TraceClassResolution && !k()->oop_is_array()) {
|
||||
// skip resolving the constant pool so that this code get's
|
||||
// called the next time some bytecodes refer to this class.
|
||||
ResourceMark rm;
|
||||
int line_number = -1;
|
||||
const char * source_file = NULL;
|
||||
if (JavaThread::current()->has_last_Java_frame()) {
|
||||
// try to identify the method which called this function.
|
||||
vframeStream vfst(JavaThread::current());
|
||||
if (!vfst.at_end()) {
|
||||
line_number = vfst.method()->line_number_from_bci(vfst.bci());
|
||||
Symbol* s = vfst.method()->method_holder()->source_file_name();
|
||||
if (s != NULL) {
|
||||
source_file = s->as_C_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (k() != this_cp->pool_holder()) {
|
||||
// only print something if the classes are different
|
||||
if (source_file != NULL) {
|
||||
tty->print("RESOLVE %s %s %s:%d\n",
|
||||
this_cp->pool_holder()->external_name(),
|
||||
InstanceKlass::cast(k())->external_name(), source_file, line_number);
|
||||
} else {
|
||||
tty->print("RESOLVE %s %s\n",
|
||||
this_cp->pool_holder()->external_name(),
|
||||
InstanceKlass::cast(k())->external_name());
|
||||
}
|
||||
}
|
||||
if (TraceClassResolution && !k->oop_is_array()) {
|
||||
// skip resolving the constant pool so that this code gets
|
||||
// called the next time some bytecodes refer to this class.
|
||||
trace_class_resolution(this_cp, k);
|
||||
return k();
|
||||
} else {
|
||||
MonitorLockerEx ml(this_cp->lock());
|
||||
// Only updated constant pool - if it is resolved.
|
||||
do_resolve = this_cp->tag_at(which).is_unresolved_klass();
|
||||
if (do_resolve) {
|
||||
ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data();
|
||||
this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
|
||||
this_cp->klass_at_put(which, k());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entry = this_cp->resolved_klass_at(which);
|
||||
assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point");
|
||||
@ -576,7 +533,7 @@ Symbol* ConstantPool::exception_message(constantPoolHandle this_cp, int which, c
|
||||
switch (tag.value()) {
|
||||
case JVM_CONSTANT_UnresolvedClass:
|
||||
// return the class name in the error message
|
||||
message = this_cp->unresolved_klass_at(which);
|
||||
message = this_cp->klass_name_at(which);
|
||||
break;
|
||||
case JVM_CONSTANT_MethodHandle:
|
||||
// return the method handle name in the error message
|
||||
@ -606,7 +563,6 @@ void ConstantPool::throw_resolution_error(constantPoolHandle this_cp, int which,
|
||||
// in the resolution error table, so that the same exception is thrown again.
|
||||
void ConstantPool::save_and_throw_exception(constantPoolHandle this_cp, int which,
|
||||
constantTag tag, TRAPS) {
|
||||
assert(this_cp->lock()->is_locked(), "constant pool lock should be held");
|
||||
Symbol* error = PENDING_EXCEPTION->klass()->name();
|
||||
|
||||
int error_tag = tag.error_value();
|
||||
@ -620,7 +576,14 @@ void ConstantPool::save_and_throw_exception(constantPoolHandle this_cp, int whic
|
||||
} else if (this_cp->tag_at(which).value() != error_tag) {
|
||||
Symbol* message = exception_message(this_cp, which, tag, PENDING_EXCEPTION);
|
||||
SystemDictionary::add_resolution_error(this_cp, which, error, message);
|
||||
this_cp->tag_at_put(which, error_tag);
|
||||
// CAS in the tag. If a thread beat us to registering this error that's fine.
|
||||
// If another thread resolved the reference, this is an error. The resolution
|
||||
// must deterministically get an error. So why do we save this?
|
||||
// We save this because jvmti can add classes to the bootclass path after this
|
||||
// error, so it needs to get the same error if the error is first.
|
||||
jbyte old_tag = Atomic::cmpxchg((jbyte)error_tag,
|
||||
(jbyte*)this_cp->tag_addr_at(which), (jbyte)tag.value());
|
||||
assert(old_tag == error_tag || old_tag == tag.value(), "should not be resolved otherwise");
|
||||
} else {
|
||||
// some other thread put this in error state
|
||||
throw_resolution_error(this_cp, which, CHECK);
|
||||
@ -710,7 +673,6 @@ oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_cp, int index
|
||||
THREAD);
|
||||
result_oop = value();
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
MonitorLockerEx ml(this_cp->lock()); // lock cpool to change tag.
|
||||
save_and_throw_exception(this_cp, index, tag, CHECK_NULL);
|
||||
}
|
||||
break;
|
||||
@ -727,7 +689,6 @@ oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_cp, int index
|
||||
Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD);
|
||||
result_oop = value();
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
MonitorLockerEx ml(this_cp->lock()); // lock cpool to change tag.
|
||||
save_and_throw_exception(this_cp, index, tag, CHECK_NULL);
|
||||
}
|
||||
break;
|
||||
@ -765,22 +726,17 @@ oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_cp, int index
|
||||
}
|
||||
|
||||
if (cache_index >= 0) {
|
||||
// Cache the oop here also.
|
||||
Handle result_handle(THREAD, result_oop);
|
||||
MonitorLockerEx ml(this_cp->lock()); // don't know if we really need this
|
||||
oop result = this_cp->resolved_references()->obj_at(cache_index);
|
||||
// Benign race condition: resolved_references may already be filled in while we were trying to lock.
|
||||
// Benign race condition: resolved_references may already be filled in.
|
||||
// The important thing here is that all threads pick up the same result.
|
||||
// It doesn't matter which racing thread wins, as long as only one
|
||||
// result is used by all threads, and all future queries.
|
||||
// That result may be either a resolved constant or a failure exception.
|
||||
if (result == NULL) {
|
||||
this_cp->resolved_references()->obj_at_put(cache_index, result_handle());
|
||||
return result_handle();
|
||||
oop old_result = this_cp->resolved_references()->atomic_compare_exchange_oop(cache_index, result_oop, NULL);
|
||||
if (old_result == NULL) {
|
||||
return result_oop; // was installed
|
||||
} else {
|
||||
// Return the winning thread's result. This can be different than
|
||||
// result_handle() for MethodHandles.
|
||||
return result;
|
||||
// the result here for MethodHandles.
|
||||
return old_result;
|
||||
}
|
||||
} else {
|
||||
return result_oop;
|
||||
@ -853,9 +809,8 @@ bool ConstantPool::klass_name_at_matches(instanceKlassHandle k,
|
||||
}
|
||||
|
||||
|
||||
// Iterate over symbols and decrement ones which are Symbol*s.
|
||||
// This is done during GC so do not need to lock constantPool unless we
|
||||
// have per-thread safepoints.
|
||||
// Iterate over symbols and decrement ones which are Symbol*s
|
||||
// This is done during GC.
|
||||
// Only decrement the UTF8 symbols. Unresolved classes and strings point to
|
||||
// these symbols but didn't increment the reference count.
|
||||
void ConstantPool::unreference_symbols() {
|
||||
@ -987,8 +942,8 @@ bool ConstantPool::compare_entry_to(int index1, constantPoolHandle cp2,
|
||||
|
||||
case JVM_CONSTANT_UnresolvedClass:
|
||||
{
|
||||
Symbol* k1 = unresolved_klass_at(index1);
|
||||
Symbol* k2 = cp2->unresolved_klass_at(index2);
|
||||
Symbol* k1 = klass_name_at(index1);
|
||||
Symbol* k2 = cp2->klass_name_at(index2);
|
||||
if (k1 == k2) {
|
||||
return true;
|
||||
}
|
||||
@ -1970,7 +1925,6 @@ void ConstantPool::print_entry_on(const int index, outputStream* st) {
|
||||
break;
|
||||
case JVM_CONSTANT_UnresolvedClass : // fall-through
|
||||
case JVM_CONSTANT_UnresolvedClassInError: {
|
||||
// unresolved_klass_at requires lock or safe world.
|
||||
CPSlot entry = slot_at(index);
|
||||
if (entry.is_resolved()) {
|
||||
entry.get_klass()->print_value_on(st);
|
||||
|
||||
@ -112,12 +112,12 @@ class ConstantPool : public Metadata {
|
||||
int _version;
|
||||
} _saved;
|
||||
|
||||
Monitor* _lock;
|
||||
|
||||
void set_tags(Array<u1>* tags) { _tags = tags; }
|
||||
void tag_at_put(int which, jbyte t) { tags()->at_put(which, t); }
|
||||
void release_tag_at_put(int which, jbyte t) { tags()->release_at_put(which, t); }
|
||||
|
||||
u1* tag_addr_at(int which) const { return tags()->adr_at(which); }
|
||||
|
||||
void set_operands(Array<u2>* operands) { _operands = operands; }
|
||||
|
||||
int flags() const { return _flags; }
|
||||
@ -362,14 +362,6 @@ class ConstantPool : public Metadata {
|
||||
return CPSlot((Klass*)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_klass();
|
||||
}
|
||||
|
||||
// This method should only be used with a cpool lock or during parsing or gc
|
||||
Symbol* unresolved_klass_at(int which) { // Temporary until actual use
|
||||
Symbol* s = CPSlot((Symbol*)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_symbol();
|
||||
// check that the klass is still unresolved.
|
||||
assert(tag_at(which).is_unresolved_klass(), "Corrupted constant pool");
|
||||
return s;
|
||||
}
|
||||
|
||||
// RedefineClasses() API support:
|
||||
Symbol* klass_at_noresolve(int which) { return klass_name_at(which); }
|
||||
|
||||
@ -818,6 +810,8 @@ class ConstantPool : public Metadata {
|
||||
static Klass* klass_at_impl(constantPoolHandle this_cp, int which, TRAPS);
|
||||
static oop string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS);
|
||||
|
||||
static void trace_class_resolution(constantPoolHandle this_cp, KlassHandle k);
|
||||
|
||||
// Resolve string constants (to prevent allocation during compilation)
|
||||
static void resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS);
|
||||
|
||||
@ -848,8 +842,6 @@ class ConstantPool : public Metadata {
|
||||
|
||||
void set_resolved_reference_length(int length) { _saved._resolved_reference_length = length; }
|
||||
int resolved_reference_length() const { return _saved._resolved_reference_length; }
|
||||
void set_lock(Monitor* lock) { _lock = lock; }
|
||||
Monitor* lock() { return _lock; }
|
||||
|
||||
// Decrease ref counts of symbols that are in the constant pool
|
||||
// when the holder class is unloaded
|
||||
|
||||
@ -286,7 +286,9 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
|
||||
// the lock, so that when the losing writer returns, he can use the linked
|
||||
// cache entry.
|
||||
|
||||
MonitorLockerEx ml(cpool->lock());
|
||||
// Use the lock from the metaspace for this, which cannot stop for safepoint.
|
||||
Mutex* metaspace_lock = cpool->pool_holder()->class_loader_data()->metaspace_lock();
|
||||
MutexLockerEx ml(metaspace_lock, Mutex::_no_safepoint_check_flag);
|
||||
if (!is_f1_null()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2014, 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
|
||||
@ -27,6 +27,22 @@
|
||||
#include "oops/objArrayOop.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
|
||||
oop objArrayOopDesc::atomic_compare_exchange_oop(int index, oop exchange_value,
|
||||
oop compare_value) {
|
||||
volatile HeapWord* dest;
|
||||
if (UseCompressedOops) {
|
||||
dest = (HeapWord*)obj_at_addr<narrowOop>(index);
|
||||
} else {
|
||||
dest = (HeapWord*)obj_at_addr<oop>(index);
|
||||
}
|
||||
oop res = oopDesc::atomic_compare_exchange_oop(exchange_value, dest, compare_value, true);
|
||||
// update card mark if success
|
||||
if (res == compare_value) {
|
||||
update_barrier_set((void*)dest, exchange_value);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#define ObjArrayOop_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
|
||||
\
|
||||
int objArrayOopDesc::oop_iterate_range(OopClosureType* blk, int start, int end) { \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2014, 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
|
||||
@ -95,6 +95,9 @@ private:
|
||||
oop_store(obj_at_addr<oop>(index), value);
|
||||
}
|
||||
}
|
||||
|
||||
oop atomic_compare_exchange_oop(int index, oop exchange_value, oop compare_value);
|
||||
|
||||
// Sizing
|
||||
static int header_size() { return arrayOopDesc::header_size(T_OBJECT); }
|
||||
int object_size() { return object_size(length()); }
|
||||
|
||||
@ -258,9 +258,6 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {
|
||||
// VM representation. We don't attach the reconstituted class
|
||||
// bytes to the InstanceKlass here because they have not been
|
||||
// validated and we're not at a safepoint.
|
||||
constantPoolHandle constants(current_thread, ikh->constants());
|
||||
MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it
|
||||
|
||||
JvmtiClassFileReconstituter reconstituter(ikh);
|
||||
if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
|
||||
return reconstituter.get_error();
|
||||
@ -2445,9 +2442,6 @@ JvmtiEnv::GetConstantPool(oop k_mirror, jint* constant_pool_count_ptr, jint* con
|
||||
}
|
||||
|
||||
instanceKlassHandle ikh(thread, k_oop);
|
||||
constantPoolHandle constants(thread, ikh->constants());
|
||||
MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it
|
||||
|
||||
JvmtiConstantPoolReconstituter reconstituter(ikh);
|
||||
if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
|
||||
return reconstituter.get_error();
|
||||
@ -2467,6 +2461,7 @@ JvmtiEnv::GetConstantPool(oop k_mirror, jint* constant_pool_count_ptr, jint* con
|
||||
return reconstituter.get_error();
|
||||
}
|
||||
|
||||
constantPoolHandle constants(thread, ikh->constants());
|
||||
*constant_pool_count_ptr = constants->length();
|
||||
*constant_pool_byte_count_ptr = cpool_size;
|
||||
*constant_pool_bytes_ptr = cpool_bytes;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user