--- old/src/share/vm/ci/ciEnv.cpp 2011-10-12 04:37:37.294872036 -0700 +++ new/src/share/vm/ci/ciEnv.cpp 2011-10-12 04:37:37.032020690 -0700 @@ -473,6 +473,7 @@ } if (require_local) return NULL; + // Not yet loaded into the VM, or not governed by loader constraints. // Make a CI representative for it. return get_unloaded_klass(accessing_klass, name); @@ -498,7 +499,7 @@ bool& is_accessible, ciInstanceKlass* accessor) { EXCEPTION_CONTEXT; - KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); + KlassHandle klass(THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); Symbol* klass_name = NULL; if (klass.is_null()) { // The klass has not been inserted into the constant pool. @@ -785,17 +786,17 @@ // Either the declared holder was not loaded, or the method could // not be found. Create a dummy ciMethod to represent the failed // lookup. - - return get_unloaded_method(declared_holder, - get_symbol(name_sym), - get_symbol(sig_sym)); + ciSymbol* name = get_symbol(name_sym); + ciSymbol* signature = get_symbol(sig_sym); + return get_unloaded_method(declared_holder, name, signature, accessor); } // ------------------------------------------------------------------ // ciEnv::get_fake_invokedynamic_method_impl ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, - int index, Bytecodes::Code bc) { + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor) { // Compare the following logic with InterpreterRuntime::resolve_invokedynamic. assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic"); @@ -807,9 +808,10 @@ // Call site might not be resolved yet. We could create a real invoker method from the // compiler, but it is simpler to stop the code path here with an unlinked method. if (!is_resolved) { - ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); - ciSymbol* sig_sym = get_symbol(cpool->signature_ref_at(index)); - return get_unloaded_method(mh_klass, ciSymbol::invokeExact_name(), sig_sym); + ciInstanceKlass* holder = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); + ciSymbol* name = ciSymbol::invokeExact_name(); + ciSymbol* signature = get_symbol(cpool->signature_ref_at(index)); + return get_unloaded_method(holder, name, signature, accessor); } // Get the invoker methodOop from the constant pool. @@ -850,9 +852,9 @@ int index, Bytecodes::Code bc, ciInstanceKlass* accessor) { if (bc == Bytecodes::_invokedynamic) { - GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc);) + GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc, accessor);) } else { - GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);) + GUARDED_VM_ENTRY(return get_method_by_index_impl( cpool, index, bc, accessor);) } } --- old/src/share/vm/ci/ciEnv.hpp 2011-10-12 04:37:38.521305129 -0700 +++ new/src/share/vm/ci/ciEnv.hpp 2011-10-12 04:37:38.251888121 -0700 @@ -153,7 +153,8 @@ int method_index, Bytecodes::Code bc, ciInstanceKlass* loading_klass); ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool, - int index, Bytecodes::Code bc); + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor); // Helper methods bool check_klass_accessibility(ciKlass* accessing_klass, @@ -192,13 +193,14 @@ // the result. ciMethod* get_unloaded_method(ciInstanceKlass* holder, ciSymbol* name, - ciSymbol* signature) { - return _factory->get_unloaded_method(holder, name, signature); + ciSymbol* signature, + ciInstanceKlass* accessor) { + return _factory->get_unloaded_method(holder, name, signature, accessor); } // Get a ciKlass representing an unloaded klass. // Ensures uniqueness of the result. - ciKlass* get_unloaded_klass(ciKlass* accessing_klass, + ciKlass* get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) { return _factory->get_unloaded_klass(accessing_klass, name, true); } @@ -224,7 +226,7 @@ // See if we already have an unloaded klass for the given name // or return NULL if not. - ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) { + ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) { return _factory->get_unloaded_klass(accessing_klass, name, false); } --- old/src/share/vm/ci/ciMethod.cpp 2011-10-12 04:37:39.711073502 -0700 +++ new/src/share/vm/ci/ciMethod.cpp 2011-10-12 04:37:39.445516216 -0700 @@ -148,21 +148,27 @@ // // Unloaded method. ciMethod::ciMethod(ciInstanceKlass* holder, - ciSymbol* name, - ciSymbol* signature) : ciObject(ciMethodKlass::make()) { - // These fields are always filled in. - _name = name; - _holder = holder; - _signature = new (CURRENT_ENV->arena()) ciSignature(_holder, constantPoolHandle(), signature); - _intrinsic_id = vmIntrinsics::_none; - _liveness = NULL; - _can_be_statically_bound = false; - _method_blocks = NULL; - _method_data = NULL; + ciSymbol* name, + ciSymbol* signature, + ciInstanceKlass* accessor) : + ciObject(ciMethodKlass::make()), + _name( name), + _holder( holder), + _intrinsic_id( vmIntrinsics::_none), + _liveness( NULL), + _can_be_statically_bound(false), + _method_blocks( NULL), + _method_data( NULL) #if defined(COMPILER2) || defined(SHARK) - _flow = NULL; - _bcea = NULL; + , + _flow( NULL), + _bcea( NULL) #endif // COMPILER2 || SHARK +{ + // Usually holder and accessor are the same type but in some cases + // the holder has the wrong class loader (e.g. invokedynamic call + // sites) so we pass the accessor. + _signature = new (CURRENT_ENV->arena()) ciSignature(accessor, constantPoolHandle(), signature); } --- old/src/share/vm/ci/ciMethod.hpp 2011-10-12 04:37:40.949956872 -0700 +++ new/src/share/vm/ci/ciMethod.hpp 2011-10-12 04:37:40.671070685 -0700 @@ -88,7 +88,7 @@ #endif ciMethod(methodHandle h_m); - ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature); + ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor); methodOop get_methodOop() const { methodOop m = (methodOop)get_oop(); --- old/src/share/vm/ci/ciObjectFactory.cpp 2011-10-12 04:37:42.124902357 -0700 +++ new/src/share/vm/ci/ciObjectFactory.cpp 2011-10-12 04:37:41.862212253 -0700 @@ -374,20 +374,32 @@ // unloaded method. This may need to change. ciMethod* ciObjectFactory::get_unloaded_method(ciInstanceKlass* holder, ciSymbol* name, - ciSymbol* signature) { - for (int i=0; i<_unloaded_methods->length(); i++) { + ciSymbol* signature, + ciInstanceKlass* accessor) { + ciSignature* that = NULL; + for (int i = 0; i < _unloaded_methods->length(); i++) { ciMethod* entry = _unloaded_methods->at(i); if (entry->holder()->equals(holder) && entry->name()->equals(name) && entry->signature()->as_symbol()->equals(signature)) { - // We've found a match. - return entry; + // Short-circuit slow resolve. + if (entry->signature()->accessing_klass() == accessor) { + // We've found a match. + return entry; + } else { + // Lazily create ciSignature + if (that == NULL) that = new (arena()) ciSignature(accessor, constantPoolHandle(), signature); + if (entry->signature()->equals(that)) { + // We've found a match. + return entry; + } + } } } // This is a new unloaded method. Create it and stick it in // the cache. - ciMethod* new_method = new (arena()) ciMethod(holder, name, signature); + ciMethod* new_method = new (arena()) ciMethod(holder, name, signature, accessor); init_ident_of(new_method); _unloaded_methods->append(new_method); --- old/src/share/vm/ci/ciObjectFactory.hpp 2011-10-12 04:37:43.318914850 -0700 +++ new/src/share/vm/ci/ciObjectFactory.hpp 2011-10-12 04:37:43.053552860 -0700 @@ -108,7 +108,8 @@ // Get the ciMethod representing an unloaded/unfound method. ciMethod* get_unloaded_method(ciInstanceKlass* holder, ciSymbol* name, - ciSymbol* signature); + ciSymbol* signature, + ciInstanceKlass* accessor); // Get a ciKlass representing an unloaded klass. ciKlass* get_unloaded_klass(ciKlass* accessing_klass, --- old/src/share/vm/ci/ciSignature.cpp 2011-10-12 04:37:44.488910285 -0700 +++ new/src/share/vm/ci/ciSignature.cpp 2011-10-12 04:37:44.225092547 -0700 @@ -80,7 +80,7 @@ } // ------------------------------------------------------------------ -// ciSignature::return_ciType +// ciSignature::return_type // // What is the return type of this signature? ciType* ciSignature::return_type() const { @@ -88,7 +88,7 @@ } // ------------------------------------------------------------------ -// ciSignature::ciType_at +// ciSignature::type_at // // What is the type of the index'th element of this // signature? @@ -99,6 +99,24 @@ } // ------------------------------------------------------------------ +// ciSignature::equals +// +// Compare this signature to another one. Signatures with different +// accessing classes but with signature-types resolved to the same +// types are defined to be equal. +bool ciSignature::equals(ciSignature* that) { + // Compare signature + if (!this->as_symbol()->equals(that->as_symbol())) return false; + // Compare all types of the arguments + for (int i = 0; i < _count; i++) { + if (this->type_at(i) != that->type_at(i)) return false; + } + // Compare the return type + if (this->return_type() != that->return_type()) return false; + return true; +} + +// ------------------------------------------------------------------ // ciSignature::print_signature void ciSignature::print_signature() { _symbol->print_symbol(); --- old/src/share/vm/ci/ciSignature.hpp 2011-10-12 04:37:45.658524943 -0700 +++ new/src/share/vm/ci/ciSignature.hpp 2011-10-12 04:37:45.395574644 -0700 @@ -43,6 +43,7 @@ int _count; friend class ciMethod; + friend class ciObjectFactory; ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature); @@ -52,6 +53,7 @@ public: ciSymbol* as_symbol() const { return _symbol; } + ciKlass* accessing_klass() const { return _accessing_klass; } ciType* return_type() const; ciType* type_at(int index) const; @@ -59,6 +61,8 @@ int size() const { return _size; } int count() const { return _count; } + bool equals(ciSignature* that); + void print_signature(); void print(); }; --- old/src/share/vm/prims/methodHandleWalk.cpp 2011-10-12 04:37:46.808659753 -0700 +++ new/src/share/vm/prims/methodHandleWalk.cpp 2011-10-12 04:37:46.539165761 -0700 @@ -1387,10 +1387,8 @@ int total = count1 + count2; if (count1 != -1 && count2 != -1 && total != 0) { // Normalize the collect counts to the invoke_count - tty->print("counts %d %d scaled by %d = ", count2, count1, _invoke_count); if (count1 != 0) _not_taken_count = (int)(_invoke_count * count1 / (double)total); if (count2 != 0) _taken_count = (int)(_invoke_count * count2 / (double)total); - tty->print_cr("%d %d", _taken_count, _not_taken_count); return true; } return false;