提交 927182ae 编写于 作者: D dcubed

Merge

......@@ -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);
}
}
......
/* 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.
......@@ -4139,8 +4139,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
}
// Allocate mirror and initialize static fields
java_lang_Class::create_mirror(this_klass, protection_domain, CHECK_(nullHandle));
java_lang_Class::create_mirror(this_klass, class_loader, protection_domain,
CHECK_(nullHandle));
// Generate any default methods - default methods are interface methods
// that have a default implementation. This is new with Lambda project.
......
......@@ -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() {
......
......@@ -558,7 +558,7 @@ void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) {
}
}
}
create_mirror(k, Handle(NULL), CHECK);
create_mirror(k, Handle(NULL), Handle(NULL), CHECK);
}
void java_lang_Class::initialize_mirror_fields(KlassHandle k,
......@@ -578,7 +578,8 @@ void java_lang_Class::initialize_mirror_fields(KlassHandle k,
InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, mirror, CHECK);
}
void java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRAPS) {
void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
Handle protection_domain, TRAPS) {
assert(k->java_mirror() == NULL, "should only assign mirror once");
// Use this moment of initialization to cache modifier_flags also,
// to support Class.getModifiers(). Instance classes recalculate
......@@ -633,6 +634,9 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRA
}
}
// set the classLoader field in the java_lang_Class instance
set_class_loader(mirror(), class_loader());
// Setup indirection from klass->mirror last
// after any exceptions can happen during allocations.
if (!k.is_null()) {
......@@ -694,6 +698,18 @@ void java_lang_Class::set_signers(oop java_class, objArrayOop signers) {
}
void java_lang_Class::set_class_loader(oop java_class, oop loader) {
// jdk7 runs Queens in bootstrapping and jdk8-9 has no coordinated pushes yet.
if (_class_loader_offset != 0) {
java_class->obj_field_put(_class_loader_offset, loader);
}
}
oop java_lang_Class::class_loader(oop java_class) {
assert(_class_loader_offset != 0, "must be set");
return java_class->obj_field(_class_loader_offset);
}
oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
// This should be improved by adding a field at the Java level or by
// introducing a new VM klass (see comment in ClassFileParser)
......@@ -853,6 +869,12 @@ void java_lang_Class::compute_offsets() {
compute_optional_offset(classRedefinedCount_offset,
klass_oop, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
// Needs to be optional because the old build runs Queens during bootstrapping
// and jdk8-9 doesn't have coordinated pushes yet.
compute_optional_offset(_class_loader_offset,
klass_oop, vmSymbols::classLoader_name(),
vmSymbols::classloader_signature());
CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
......@@ -3073,6 +3095,7 @@ int java_lang_Class::_klass_offset;
int java_lang_Class::_array_klass_offset;
int java_lang_Class::_oop_size_offset;
int java_lang_Class::_static_oop_field_count_offset;
int java_lang_Class::_class_loader_offset;
int java_lang_Class::_protection_domain_offset;
int java_lang_Class::_init_lock_offset;
int java_lang_Class::_signers_offset;
......
......@@ -240,19 +240,23 @@ class java_lang_Class : AllStatic {
static int _protection_domain_offset;
static int _init_lock_offset;
static int _signers_offset;
static int _class_loader_offset;
static bool offsets_computed;
static int classRedefinedCount_offset;
static GrowableArray<Klass*>* _fixup_mirror_list;
static void set_init_lock(oop java_class, oop init_lock);
static void set_protection_domain(oop java_class, oop protection_domain);
static void set_class_loader(oop java_class, oop class_loader);
static void initialize_mirror_fields(KlassHandle k, Handle mirror, Handle protection_domain, TRAPS);
public:
static void compute_offsets();
// Instance creation
static void create_mirror(KlassHandle k, Handle protection_domain, TRAPS);
static void create_mirror(KlassHandle k, Handle class_loader,
Handle protection_domain, TRAPS);
static void fixup_mirror(KlassHandle k, TRAPS);
static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
// Conversion
......@@ -290,6 +294,8 @@ class java_lang_Class : AllStatic {
static objArrayOop signers(oop java_class);
static void set_signers(oop java_class, objArrayOop signers);
static oop class_loader(oop java_class);
static int oop_size(oop java_class);
static void set_oop_size(oop java_class, int size);
static int static_oop_field_count(oop java_class);
......
......@@ -572,6 +572,7 @@
template(serializePropertiesToByteArray_signature, "()[B") \
template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \
template(classRedefinedCount_name, "classRedefinedCount") \
template(classLoader_name, "classLoader") \
\
/* trace signatures */ \
TRACE_TEMPLATES(template) \
......
......@@ -93,7 +93,7 @@ void ArrayKlass::complete_create_array_klass(ArrayKlass* k, KlassHandle super_kl
ResourceMark rm(THREAD);
k->initialize_supers(super_klass(), CHECK);
k->vtable()->initialize_vtable(false, CHECK);
java_lang_Class::create_mirror(k, Handle(NULL), CHECK);
java_lang_Class::create_mirror(k, Handle(NULL), Handle(NULL), CHECK);
}
GrowableArray<Klass*>* ArrayKlass::compute_secondary_supers(int num_extra_slots) {
......
......@@ -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;
}
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) {
// 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.
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);
}
// 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());
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);
}
// 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();
}
// 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);
}
// 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);
}
// 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
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;
}
......
......@@ -508,7 +508,7 @@ void Klass::restore_unshareable_info(TRAPS) {
// Only recreate it if not present. A previous attempt to restore may have
// gotten an OOM later but keep the mirror if it was created.
if (java_mirror() == NULL) {
java_lang_Class::create_mirror(this, Handle(NULL), CHECK);
java_lang_Class::create_mirror(this, Handle(NULL), Handle(NULL), CHECK);
}
}
......
/*
* 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) { \
......
/*
* 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;
......
......@@ -891,6 +891,14 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass(JNIEnv *env, jobject unsafe, jstring nam
}
UNSAFE_END
static jobject get_class_loader(JNIEnv* env, jclass cls) {
if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) {
return NULL;
}
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
oop loader = k->class_loader();
return JNIHandles::make_local(env, loader);
}
UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length))
UnsafeWrapper("Unsafe_DefineClass");
......@@ -899,7 +907,7 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring na
int depthFromDefineClass0 = 1;
jclass caller = JVM_GetCallerClass(env, depthFromDefineClass0);
jobject loader = (caller == NULL) ? NULL : JVM_GetClassLoader(env, caller);
jobject loader = (caller == NULL) ? NULL : get_class_loader(env, caller);
jobject pd = (caller == NULL) ? NULL : JVM_GetProtectionDomain(env, caller);
return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd);
......
/*
* Copyright (c) 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
* 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.
*/
import java.io.File;
import java.io.FileOutputStream;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
import com.oracle.java.testlibrary.*;
/*
* @test
* @summary Test that anewarray bytecode is valid only if it specifies 255 or fewer dimensions.
* @library /testlibrary
* @compile -XDignore.symbol.file TestANewArray.java
* @run main/othervm TestANewArray 49
* @run main/othervm TestANewArray 50
* @run main/othervm TestANewArray 51
* @run main/othervm TestANewArray 52
*/
/*
* Testing anewarray instruction with 254, 255 & 264 dimensions to verify JVMS 8,
* Section 4.9.1, Static Constraints that states the following:
*
* "No anewarray instruction may be used to create an array of more than 255 dimensions."
*
*/
public class TestANewArray {
static String classCName = null; // the generated class name
static final int test_Dimension_254 = 254; // should always pass
static final int test_Dimension_255 = 255; // should always pass, except for cfv 49
static final int test_Dimension_264 = 264; // should always fail
static final String array_Dimension_254 = genArrayDim(test_Dimension_254);
static final String array_Dimension_255 = genArrayDim(test_Dimension_255);
static final String array_Dimension_264 = genArrayDim(test_Dimension_264);
public static void main(String... args) throws Exception {
int cfv = Integer.parseInt(args[0]);
// 254 array dimensions
byte[] classFile_254 = dumpClassFile(cfv, test_Dimension_254, array_Dimension_254);
writeClassFileFromByteArray(classFile_254);
System.err.println("Running with cfv: " + cfv + ", test_Dimension_254");
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-verify", "-cp", ".", classCName);
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldNotContain("java.lang.VerifyError");
output.shouldHaveExitValue(0);
// 255 array dimensions
byte[] classFile_255 = dumpClassFile(cfv, test_Dimension_255, array_Dimension_255);
writeClassFileFromByteArray(classFile_255);
System.err.println("Running with cfv: " + cfv + ", test_Dimension_255");
pb = ProcessTools.createJavaProcessBuilder(true, "-verify", "-cp", ".", classCName);
output = new OutputAnalyzer(pb.start());
if (cfv == 49) {
// The type-inferencing verifier used for <=49.0 ClassFiles detects an anewarray instruction
// with exactly 255 dimensions and incorrectly issues the "Array with too many dimensions" VerifyError.
output.shouldContain("Array with too many dimensions");
output.shouldHaveExitValue(1);
} else {
// 255 dimensions should always pass, except for cfv 49
output.shouldNotContain("java.lang.VerifyError");
output.shouldNotContain("java.lang.ClassFormatError");
output.shouldHaveExitValue(0);
}
// 264 array dimensions
byte[] classFile_264 = dumpClassFile(cfv, test_Dimension_264, array_Dimension_264);
writeClassFileFromByteArray(classFile_264);
System.err.println("Running with cfv: " + cfv + ", test_Dimension_264");
pb = ProcessTools.createJavaProcessBuilder(true, "-verify", "-cp", ".", classCName);
output = new OutputAnalyzer(pb.start());
output.shouldContain("java.lang.ClassFormatError");
output.shouldHaveExitValue(1);
}
public static byte[] dumpClassFile(int cfv, int testDimension264, String arrayDim) throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
MethodVisitor mv;
classCName = "classCName_" + cfv + "_" + testDimension264;
cw.visit(cfv, ACC_PUBLIC + ACC_SUPER, classCName, null, "java/lang/Object", null);
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{ // classCName main method
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
mv.visitCode();
mv.visitIntInsn(BIPUSH, 1);
mv.visitTypeInsn(ANEWARRAY, arrayDim); // Test ANEWARRAY bytecode with various dimensions
mv.visitInsn(RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
public static FileOutputStream writeClassFileFromByteArray(byte[] classFileByteArray) throws Exception {
FileOutputStream fos = new FileOutputStream(new File(classCName + ".class"));
fos.write(classFileByteArray);
fos.close();
return fos;
}
private static String genArrayDim(int testDim) {
StringBuilder array_Dimension = new StringBuilder();
for (int i = 0; i < testDim; i++)
{
array_Dimension.append("[");
}
return array_Dimension.append("Ljava/lang/Object;").toString();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册