Mercurial > hg > truffle
diff src/share/vm/oops/instanceKlass.cpp @ 13086:096c224171c4
Merge with http://hg.openjdk.java.net/hsx/hsx25/hotspot/
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 20 Nov 2013 00:10:38 +0100 |
parents | cefad50507d8 6e1826d5c23e |
children | 02f27ecb4f3a |
line wrap: on
line diff
--- a/src/share/vm/oops/instanceKlass.cpp Tue Nov 19 17:44:26 2013 +0100 +++ b/src/share/vm/oops/instanceKlass.cpp Wed Nov 20 00:10:38 2013 +0100 @@ -238,6 +238,13 @@ } } +// create a new array of vtable_indices for default methods +Array<int>* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) { + Array<int>* vtable_indices = MetadataFactory::new_array<int>(class_loader_data(), len, CHECK_NULL); + assert(default_vtable_indices() == NULL, "only create once"); + set_default_vtable_indices(vtable_indices); + return vtable_indices; +} InstanceKlass::InstanceKlass(int vtable_len, int itable_len, @@ -263,6 +270,8 @@ set_array_klasses(NULL); set_methods(NULL); set_method_ordering(NULL); + set_default_methods(NULL); + set_default_vtable_indices(NULL); set_local_interfaces(NULL); set_transitive_interfaces(NULL); init_implementor(); @@ -311,7 +320,8 @@ void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data, Array<Method*>* methods) { - if (methods != NULL && methods != Universe::the_empty_method_array()) { + if (methods != NULL && methods != Universe::the_empty_method_array() && + !methods->is_shared()) { for (int i = 0; i < methods->length(); i++) { Method* method = methods->at(i); if (method == NULL) continue; // maybe null if error processing @@ -335,13 +345,14 @@ // check that the interfaces don't come from super class Array<Klass*>* sti = (super_klass == NULL) ? NULL : InstanceKlass::cast(super_klass)->transitive_interfaces(); - if (ti != sti) { + if (ti != sti && ti != NULL && !ti->is_shared()) { MetadataFactory::free_array<Klass*>(loader_data, ti); } } // local interfaces can be empty - if (local_interfaces != Universe::the_empty_klass_array()) { + if (local_interfaces != Universe::the_empty_klass_array() && + local_interfaces != NULL && !local_interfaces->is_shared()) { MetadataFactory::free_array<Klass*>(loader_data, local_interfaces); } } @@ -371,16 +382,37 @@ deallocate_methods(loader_data, methods()); set_methods(NULL); - if (method_ordering() != Universe::the_empty_int_array()) { + if (method_ordering() != NULL && + method_ordering() != Universe::the_empty_int_array() && + !method_ordering()->is_shared()) { MetadataFactory::free_array<int>(loader_data, method_ordering()); } set_method_ordering(NULL); + // default methods can be empty + if (default_methods() != NULL && + default_methods() != Universe::the_empty_method_array() && + !default_methods()->is_shared()) { + MetadataFactory::free_array<Method*>(loader_data, default_methods()); + } + // Do NOT deallocate the default methods, they are owned by superinterfaces. + set_default_methods(NULL); + + // default methods vtable indices can be empty + if (default_vtable_indices() != NULL && + !default_vtable_indices()->is_shared()) { + MetadataFactory::free_array<int>(loader_data, default_vtable_indices()); + } + set_default_vtable_indices(NULL); + + // This array is in Klass, but remove it with the InstanceKlass since // this place would be the only caller and it can share memory with transitive // interfaces. - if (secondary_supers() != Universe::the_empty_klass_array() && - secondary_supers() != transitive_interfaces()) { + if (secondary_supers() != NULL && + secondary_supers() != Universe::the_empty_klass_array() && + secondary_supers() != transitive_interfaces() && + !secondary_supers()->is_shared()) { MetadataFactory::free_array<Klass*>(loader_data, secondary_supers()); } set_secondary_supers(NULL); @@ -389,24 +421,32 @@ set_transitive_interfaces(NULL); set_local_interfaces(NULL); - MetadataFactory::free_array<jushort>(loader_data, fields()); + if (fields() != NULL && !fields()->is_shared()) { + MetadataFactory::free_array<jushort>(loader_data, fields()); + } set_fields(NULL, 0); // If a method from a redefined class is using this constant pool, don't // delete it, yet. The new class's previous version will point to this. if (constants() != NULL) { assert (!constants()->on_stack(), "shouldn't be called if anything is onstack"); - MetadataFactory::free_metadata(loader_data, constants()); + if (!constants()->is_shared()) { + MetadataFactory::free_metadata(loader_data, constants()); + } set_constants(NULL); } - if (inner_classes() != Universe::the_empty_short_array()) { + if (inner_classes() != NULL && + inner_classes() != Universe::the_empty_short_array() && + !inner_classes()->is_shared()) { MetadataFactory::free_array<jushort>(loader_data, inner_classes()); } set_inner_classes(NULL); - // We should deallocate the Annotations instance - MetadataFactory::free_metadata(loader_data, annotations()); + // We should deallocate the Annotations instance if it's not in shared spaces. + if (annotations() != NULL && !annotations()->is_shared()) { + MetadataFactory::free_metadata(loader_data, annotations()); + } set_annotations(NULL); } @@ -456,15 +496,29 @@ return java_lang_Class::signers(java_mirror()); } -volatile oop InstanceKlass::init_lock() const { +oop InstanceKlass::init_lock() const { // return the init lock from the mirror - return java_lang_Class::init_lock(java_mirror()); + oop lock = java_lang_Class::init_lock(java_mirror()); + assert((oop)lock != NULL || !is_not_initialized(), // initialized or in_error state + "only fully initialized state can have a null lock"); + return lock; +} + +// Set the initialization lock to null so the object can be GC'ed. Any racing +// threads to get this lock will see a null lock and will not lock. +// That's okay because they all check for initialized state after getting +// the lock and return. +void InstanceKlass::fence_and_clear_init_lock() { + // make sure previous stores are all done, notably the init_state. + OrderAccess::storestore(); + java_lang_Class::set_init_lock(java_mirror(), NULL); + assert(!is_not_initialized(), "class must be initialized now"); } void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) { EXCEPTION_MARK; - volatile oop init_lock = this_oop->init_lock(); - ObjectLocker ol(init_lock, THREAD); + oop init_lock = this_oop->init_lock(); + ObjectLocker ol(init_lock, THREAD, init_lock != NULL); // abort if someone beat us to the initialization if (!this_oop->is_not_initialized()) return; // note: not equivalent to is_initialized() @@ -483,6 +537,7 @@ } else { // linking successfull, mark class as initialized this_oop->set_init_state (fully_initialized); + this_oop->fence_and_clear_init_lock(); // trace if (TraceClassInitialization) { ResourceMark rm(THREAD); @@ -608,8 +663,8 @@ // verification & rewriting { - volatile oop init_lock = this_oop->init_lock(); - ObjectLocker ol(init_lock, THREAD); + oop init_lock = this_oop->init_lock(); + ObjectLocker ol(init_lock, THREAD, init_lock != NULL); // rewritten will have been set if loader constraint error found // on an earlier link attempt // don't verify or rewrite if already rewritten @@ -731,8 +786,8 @@ // refer to the JVM book page 47 for description of steps // Step 1 { - volatile oop init_lock = this_oop->init_lock(); - ObjectLocker ol(init_lock, THREAD); + oop init_lock = this_oop->init_lock(); + ObjectLocker ol(init_lock, THREAD, init_lock != NULL); Thread *self = THREAD; // it's passed the current thread @@ -879,9 +934,10 @@ } void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_oop, ClassState state, TRAPS) { - volatile oop init_lock = this_oop->init_lock(); - ObjectLocker ol(init_lock, THREAD); + oop init_lock = this_oop->init_lock(); + ObjectLocker ol(init_lock, THREAD, init_lock != NULL); this_oop->set_init_state(state); + this_oop->fence_and_clear_init_lock(); ol.notify_all(CHECK); } @@ -1354,32 +1410,44 @@ return -1; } +// find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const { return InstanceKlass::find_method(methods(), name, signature); } +// find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method( Array<Method*>* methods, Symbol* name, Symbol* signature) { + int hit = find_method_index(methods, name, signature); + return hit >= 0 ? methods->at(hit): NULL; +} + +// Used directly for default_methods to find the index into the +// default_vtable_indices, and indirectly by find_method +// find_method_index looks in the local methods array to return the index +// of the matching name/signature +int InstanceKlass::find_method_index( + Array<Method*>* methods, Symbol* name, Symbol* signature) { int hit = binary_search(methods, name); if (hit != -1) { Method* m = methods->at(hit); // Do linear search to find matching signature. First, quick check // for common case - if (m->signature() == signature) return m; + if (m->signature() == signature) return hit; // search downwards through overloaded methods int i; for (i = hit - 1; i >= 0; --i) { Method* m = methods->at(i); assert(m->is_method(), "must be method"); if (m->name() != name) break; - if (m->signature() == signature) return m; + if (m->signature() == signature) return i; } // search upwards for (i = hit + 1; i < methods->length(); ++i) { Method* m = methods->at(i); assert(m->is_method(), "must be method"); if (m->name() != name) break; - if (m->signature() == signature) return m; + if (m->signature() == signature) return i; } // not found #ifdef ASSERT @@ -1387,9 +1455,8 @@ assert(index == -1, err_msg("binary search should have found entry %d", index)); #endif } - return NULL; + return -1; } - int InstanceKlass::find_method_by_name(Symbol* name, int* end) { return find_method_by_name(methods(), name, end); } @@ -1408,6 +1475,7 @@ return -1; } +// lookup_method searches both the local methods array and all superclasses methods arrays Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const { Klass* klass = const_cast<InstanceKlass*>(this); while (klass != NULL) { @@ -1418,6 +1486,21 @@ return NULL; } +// lookup a method in the default methods list then in all transitive interfaces +// Do NOT return private or static methods +Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name, + Symbol* signature) const { + Method* m = NULL; + if (default_methods() != NULL) { + m = find_method(default_methods(), name, signature); + } + // Look up interfaces + if (m == NULL) { + m = lookup_method_in_all_interfaces(name, signature); + } + return m; +} + // lookup a method in all the interfaces that this class implements // Do NOT return private or static methods, new in JDK8 which are not externally visible // They should only be found in the initial InterfaceMethodRef @@ -2128,6 +2211,10 @@ data = mdo->next_data(data)) { data->clean_weak_klass_links(is_alive); } + ParametersTypeData* parameters = mdo->parameters_type_data(); + if (parameters != NULL) { + parameters->clean_weak_klass_links(is_alive); + } } } } @@ -2310,15 +2397,38 @@ const char* InstanceKlass::signature_name() const { + int hash_len = 0; + char hash_buf[40]; + + // If this is an anonymous class, append a hash to make the name unique + if (is_anonymous()) { + assert(EnableInvokeDynamic, "EnableInvokeDynamic was not set."); + intptr_t hash = (java_mirror() != NULL) ? java_mirror()->identity_hash() : 0; + sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash); + hash_len = (int)strlen(hash_buf); + } + + // Get the internal name as a c string const char* src = (const char*) (name()->as_C_string()); const int src_length = (int)strlen(src); - char* dest = NEW_RESOURCE_ARRAY(char, src_length + 3); - int src_index = 0; + + char* dest = NEW_RESOURCE_ARRAY(char, src_length + hash_len + 3); + + // Add L as type indicator int dest_index = 0; dest[dest_index++] = 'L'; - while (src_index < src_length) { + + // Add the actual class name + for (int src_index = 0; src_index < src_length; ) { dest[dest_index++] = src[src_index++]; } + + // If we have a hash, append it + for (int hash_index = 0; hash_index < hash_len; ) { + dest[dest_index++] = hash_buf[hash_index++]; + } + + // Add the semicolon and the NULL dest[dest_index++] = ';'; dest[dest_index] = '\0'; return dest; @@ -2548,6 +2658,42 @@ return m; } + +#if INCLUDE_JVMTI +// update default_methods for redefineclasses for methods that are +// not yet in the vtable due to concurrent subclass define and superinterface +// redefinition +// Note: those in the vtable, should have been updated via adjust_method_entries +void InstanceKlass::adjust_default_methods(Method** old_methods, Method** new_methods, + int methods_length, bool* trace_name_printed) { + // search the default_methods for uses of either obsolete or EMCP methods + if (default_methods() != NULL) { + for (int j = 0; j < methods_length; j++) { + Method* old_method = old_methods[j]; + Method* new_method = new_methods[j]; + + for (int index = 0; index < default_methods()->length(); index ++) { + if (default_methods()->at(index) == old_method) { + default_methods()->at_put(index, new_method); + if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { + if (!(*trace_name_printed)) { + // RC_TRACE_MESG macro has an embedded ResourceMark + RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s", + external_name(), + old_method->method_holder()->external_name())); + *trace_name_printed = true; + } + RC_TRACE(0x00100000, ("default method update: %s(%s) ", + new_method->name()->as_C_string(), + new_method->signature()->as_C_string())); + } + } + } + } + } +} +#endif // INCLUDE_JVMTI + // On-stack replacement stuff void InstanceKlass::add_osr_nmethod(nmethod* n) { // only one compilation can be active @@ -2742,11 +2888,21 @@ st->print(BULLET"methods: "); methods()->print_value_on(st); st->cr(); if (Verbose || WizardMode) { Array<Method*>* method_array = methods(); - for(int i = 0; i < method_array->length(); i++) { + for (int i = 0; i < method_array->length(); i++) { st->print("%d : ", i); method_array->at(i)->print_value(); st->cr(); } } - st->print(BULLET"method ordering: "); method_ordering()->print_value_on(st); st->cr(); + st->print(BULLET"method ordering: "); method_ordering()->print_value_on(st); st->cr(); + st->print(BULLET"default_methods: "); default_methods()->print_value_on(st); st->cr(); + if (Verbose && default_methods() != NULL) { + Array<Method*>* method_array = default_methods(); + for (int i = 0; i < method_array->length(); i++) { + st->print("%d : ", i); method_array->at(i)->print_value(); st->cr(); + } + } + if (default_vtable_indices() != NULL) { + st->print(BULLET"default vtable indices: "); default_vtable_indices()->print_value_on(st); st->cr(); + } st->print(BULLET"local interfaces: "); local_interfaces()->print_value_on(st); st->cr(); st->print(BULLET"trans. interfaces: "); transitive_interfaces()->print_value_on(st); st->cr(); st->print(BULLET"constants: "); constants()->print_value_on(st); st->cr(); @@ -3099,6 +3255,19 @@ } } + // Verify default methods + if (default_methods() != NULL) { + Array<Method*>* methods = this->default_methods(); + for (int j = 0; j < methods->length(); j++) { + guarantee(methods->at(j)->is_method(), "non-method in methods array"); + } + for (int j = 0; j < methods->length() - 1; j++) { + Method* m1 = methods->at(j); + Method* m2 = methods->at(j + 1); + guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly"); + } + } + // Verify JNI static field identifiers if (jni_ids() != NULL) { jni_ids()->verify(this);