提交 f6d0761e 编写于 作者: T twisti

7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path

Reviewed-by: jrose, kvn
上级 87554e3b
...@@ -2936,6 +2936,7 @@ void TemplateTable::prepare_invoke(int byte_no, ...@@ -2936,6 +2936,7 @@ void TemplateTable::prepare_invoke(int byte_no,
// Push the appendix as a trailing parameter. // Push the appendix as a trailing parameter.
// This must be done before we get the receiver, // This must be done before we get the receiver,
// since the parameter_size includes it. // since the parameter_size includes it.
assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
__ load_resolved_reference_at_index(temp, index); __ load_resolved_reference_at_index(temp, index);
__ verify_oop(temp); __ verify_oop(temp);
__ push_ptr(temp); // push appendix (MethodType, CallSite, etc.) __ push_ptr(temp); // push appendix (MethodType, CallSite, etc.)
...@@ -3235,15 +3236,15 @@ void TemplateTable::invokehandle(int byte_no) { ...@@ -3235,15 +3236,15 @@ void TemplateTable::invokehandle(int byte_no) {
} }
const Register Rret = Lscratch; const Register Rret = Lscratch;
const Register G4_mtype = G4_scratch; // f1 const Register G4_mtype = G4_scratch;
const Register O0_recv = O0; const Register O0_recv = O0;
const Register Rscratch = G3_scratch; const Register Rscratch = G3_scratch;
prepare_invoke(byte_no, G5_method, Rret, G4_mtype, O0_recv); prepare_invoke(byte_no, G5_method, Rret, G4_mtype, O0_recv);
__ null_check(O0_recv); __ null_check(O0_recv);
// G4: MethodType object (from cpool->resolved_references[]) // G4: MethodType object (from cpool->resolved_references[f1], if necessary)
// G5: MH.linkToCallSite method (from f2) // G5: MH.invokeExact_MT method (from f2)
// Note: G4_mtype is already pushed (if necessary) by prepare_invoke // Note: G4_mtype is already pushed (if necessary) by prepare_invoke
...@@ -3275,8 +3276,8 @@ void TemplateTable::invokedynamic(int byte_no) { ...@@ -3275,8 +3276,8 @@ void TemplateTable::invokedynamic(int byte_no) {
prepare_invoke(byte_no, G5_method, Rret, G4_callsite); prepare_invoke(byte_no, G5_method, Rret, G4_callsite);
// G4: CallSite object (from cpool->resolved_references[]) // G4: CallSite object (from cpool->resolved_references[f1])
// G5: MH.linkToCallSite method (from f1) // G5: MH.linkToCallSite method (from f2)
// Note: G4_callsite is already pushed by prepare_invoke // Note: G4_callsite is already pushed by prepare_invoke
......
...@@ -2139,7 +2139,7 @@ void TemplateTable::load_invoke_cp_cache_entry(int byte_no, ...@@ -2139,7 +2139,7 @@ void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
const int index_offset = in_bytes(ConstantPoolCache::base_offset() + const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
ConstantPoolCacheEntry::f2_offset()); ConstantPoolCacheEntry::f2_offset());
size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2)); size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
resolve_cache_and_index(byte_no, cache, index, index_size); resolve_cache_and_index(byte_no, cache, index, index_size);
__ movptr(method, Address(cache, index, Address::times_ptr, method_offset)); __ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
...@@ -2876,6 +2876,7 @@ void TemplateTable::prepare_invoke(int byte_no, ...@@ -2876,6 +2876,7 @@ void TemplateTable::prepare_invoke(int byte_no,
// since the parameter_size includes it. // since the parameter_size includes it.
__ push(rbx); __ push(rbx);
__ mov(rbx, index); __ mov(rbx, index);
assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
__ load_resolved_reference_at_index(index, rbx); __ load_resolved_reference_at_index(index, rbx);
__ pop(rbx); __ pop(rbx);
__ push(index); // push appendix (MethodType, CallSite, etc.) __ push(index); // push appendix (MethodType, CallSite, etc.)
...@@ -3093,8 +3094,8 @@ void TemplateTable::invokeinterface(int byte_no) { ...@@ -3093,8 +3094,8 @@ void TemplateTable::invokeinterface(int byte_no) {
void TemplateTable::invokehandle(int byte_no) { void TemplateTable::invokehandle(int byte_no) {
transition(vtos, vtos); transition(vtos, vtos);
assert(byte_no == f1_byte, "use this argument"); assert(byte_no == f1_byte, "use this argument");
const Register rbx_method = rbx; // (from f2) const Register rbx_method = rbx;
const Register rax_mtype = rax; // (from f1) const Register rax_mtype = rax;
const Register rcx_recv = rcx; const Register rcx_recv = rcx;
const Register rdx_flags = rdx; const Register rdx_flags = rdx;
...@@ -3104,13 +3105,14 @@ void TemplateTable::invokehandle(int byte_no) { ...@@ -3104,13 +3105,14 @@ void TemplateTable::invokehandle(int byte_no) {
return; return;
} }
prepare_invoke(byte_no, prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv);
rbx_method, rax_mtype, // get f2 Method*, f1 MethodType
rcx_recv);
__ verify_method_ptr(rbx_method); __ verify_method_ptr(rbx_method);
__ verify_oop(rcx_recv); __ verify_oop(rcx_recv);
__ null_check(rcx_recv); __ null_check(rcx_recv);
// rax: MethodType object (from cpool->resolved_references[f1], if necessary)
// rbx: MH.invokeExact_MT method (from f2)
// Note: rax_mtype is already pushed (if necessary) by prepare_invoke // Note: rax_mtype is already pushed (if necessary) by prepare_invoke
// FIXME: profile the LambdaForm also // FIXME: profile the LambdaForm also
...@@ -3140,7 +3142,7 @@ void TemplateTable::invokedynamic(int byte_no) { ...@@ -3140,7 +3142,7 @@ void TemplateTable::invokedynamic(int byte_no) {
prepare_invoke(byte_no, rbx_method, rax_callsite); prepare_invoke(byte_no, rbx_method, rax_callsite);
// rax: CallSite object (from cpool->resolved_references[]) // rax: CallSite object (from cpool->resolved_references[f1])
// rbx: MH.linkToCallSite method (from f2) // rbx: MH.linkToCallSite method (from f2)
// Note: rax_callsite is already pushed by prepare_invoke // Note: rax_callsite is already pushed by prepare_invoke
......
...@@ -2184,7 +2184,7 @@ void TemplateTable::load_invoke_cp_cache_entry(int byte_no, ...@@ -2184,7 +2184,7 @@ void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
const int index_offset = in_bytes(ConstantPoolCache::base_offset() + const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
ConstantPoolCacheEntry::f2_offset()); ConstantPoolCacheEntry::f2_offset());
size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2)); size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
resolve_cache_and_index(byte_no, cache, index, index_size); resolve_cache_and_index(byte_no, cache, index, index_size);
__ movptr(method, Address(cache, index, Address::times_ptr, method_offset)); __ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
...@@ -2926,6 +2926,7 @@ void TemplateTable::prepare_invoke(int byte_no, ...@@ -2926,6 +2926,7 @@ void TemplateTable::prepare_invoke(int byte_no,
// since the parameter_size includes it. // since the parameter_size includes it.
__ push(rbx); __ push(rbx);
__ mov(rbx, index); __ mov(rbx, index);
assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
__ load_resolved_reference_at_index(index, rbx); __ load_resolved_reference_at_index(index, rbx);
__ pop(rbx); __ pop(rbx);
__ push(index); // push appendix (MethodType, CallSite, etc.) __ push(index); // push appendix (MethodType, CallSite, etc.)
...@@ -3144,8 +3145,8 @@ void TemplateTable::invokeinterface(int byte_no) { ...@@ -3144,8 +3145,8 @@ void TemplateTable::invokeinterface(int byte_no) {
void TemplateTable::invokehandle(int byte_no) { void TemplateTable::invokehandle(int byte_no) {
transition(vtos, vtos); transition(vtos, vtos);
assert(byte_no == f1_byte, "use this argument"); assert(byte_no == f1_byte, "use this argument");
const Register rbx_method = rbx; // f2 const Register rbx_method = rbx;
const Register rax_mtype = rax; // f1 const Register rax_mtype = rax;
const Register rcx_recv = rcx; const Register rcx_recv = rcx;
const Register rdx_flags = rdx; const Register rdx_flags = rdx;
...@@ -3155,13 +3156,14 @@ void TemplateTable::invokehandle(int byte_no) { ...@@ -3155,13 +3156,14 @@ void TemplateTable::invokehandle(int byte_no) {
return; return;
} }
prepare_invoke(byte_no, prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv);
rbx_method, rax_mtype, // get f2 Method*, f1 MethodType
rcx_recv);
__ verify_method_ptr(rbx_method); __ verify_method_ptr(rbx_method);
__ verify_oop(rcx_recv); __ verify_oop(rcx_recv);
__ null_check(rcx_recv); __ null_check(rcx_recv);
// rax: MethodType object (from cpool->resolved_references[f1], if necessary)
// rbx: MH.invokeExact_MT method (from f2)
// Note: rax_mtype is already pushed (if necessary) by prepare_invoke // Note: rax_mtype is already pushed (if necessary) by prepare_invoke
// FIXME: profile the LambdaForm also // FIXME: profile the LambdaForm also
...@@ -3191,7 +3193,7 @@ void TemplateTable::invokedynamic(int byte_no) { ...@@ -3191,7 +3193,7 @@ void TemplateTable::invokedynamic(int byte_no) {
prepare_invoke(byte_no, rbx_method, rax_callsite); prepare_invoke(byte_no, rbx_method, rax_callsite);
// rax: CallSite object (from cpool->resolved_references[]) // rax: CallSite object (from cpool->resolved_references[f1])
// rbx: MH.linkToCallSite method (from f2) // rbx: MH.linkToCallSite method (from f2)
// Note: rax_callsite is already pushed by prepare_invoke // Note: rax_callsite is already pushed by prepare_invoke
......
...@@ -49,6 +49,7 @@ class ciInstance; ...@@ -49,6 +49,7 @@ class ciInstance;
class ciCallSite; class ciCallSite;
class ciMemberName; class ciMemberName;
class ciMethodHandle; class ciMethodHandle;
class ciMethodType;
class ciArray; class ciArray;
class ciObjArray; class ciObjArray;
class ciTypeArray; class ciTypeArray;
...@@ -99,6 +100,7 @@ friend class ciMemberName; \ ...@@ -99,6 +100,7 @@ friend class ciMemberName; \
friend class ciMethod; \ friend class ciMethod; \
friend class ciMethodData; \ friend class ciMethodData; \
friend class ciMethodHandle; \ friend class ciMethodHandle; \
friend class ciMethodType; \
friend class ciReceiverTypeData; \ friend class ciReceiverTypeData; \
friend class ciSymbol; \ friend class ciSymbol; \
friend class ciArray; \ friend class ciArray; \
......
/*
* Copyright (c) 2012, 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_CI_CIMETHODTYPE_HPP
#define SHARE_VM_CI_CIMETHODTYPE_HPP
#include "ci/ciInstance.hpp"
#include "ci/ciUtilities.hpp"
#include "classfile/javaClasses.hpp"
// ciMethodType
//
// The class represents a java.lang.invoke.MethodType object.
class ciMethodType : public ciInstance {
private:
ciType* class_to_citype(oop klass_oop) const {
if (java_lang_Class::is_primitive(klass_oop)) {
BasicType bt = java_lang_Class::primitive_type(klass_oop);
return ciType::make(bt);
} else {
Klass* k = java_lang_Class::as_Klass(klass_oop);
return CURRENT_ENV->get_klass(k);
}
}
public:
ciMethodType(instanceHandle h_i) : ciInstance(h_i) {}
// What kind of ciObject is this?
bool is_method_type() const { return true; }
ciType* rtype() const {
GUARDED_VM_ENTRY(
oop rtype = java_lang_invoke_MethodType::rtype(get_oop());
return class_to_citype(rtype);
)
}
int ptype_count() const {
GUARDED_VM_ENTRY(return java_lang_invoke_MethodType::ptype_count(get_oop());)
}
int ptype_slot_count() const {
GUARDED_VM_ENTRY(return java_lang_invoke_MethodType::ptype_slot_count(get_oop());)
}
ciType* ptype_at(int index) const {
GUARDED_VM_ENTRY(
oop ptype = java_lang_invoke_MethodType::ptype(get_oop(), index);
return class_to_citype(ptype);
)
}
};
#endif // SHARE_VM_CI_CIMETHODTYPE_HPP
...@@ -123,6 +123,7 @@ public: ...@@ -123,6 +123,7 @@ public:
virtual bool is_instance() { return false; } virtual bool is_instance() { return false; }
virtual bool is_member_name() const { return false; } virtual bool is_member_name() const { return false; }
virtual bool is_method_handle() const { return false; } virtual bool is_method_handle() const { return false; }
virtual bool is_method_type() const { return false; }
virtual bool is_array() { return false; } virtual bool is_array() { return false; }
virtual bool is_obj_array() { return false; } virtual bool is_obj_array() { return false; }
virtual bool is_type_array() { return false; } virtual bool is_type_array() { return false; }
...@@ -142,35 +143,39 @@ public: ...@@ -142,35 +143,39 @@ public:
} }
// Subclass casting with assertions. // Subclass casting with assertions.
ciNullObject* as_null_object() { ciNullObject* as_null_object() {
assert(is_null_object(), "bad cast"); assert(is_null_object(), "bad cast");
return (ciNullObject*)this; return (ciNullObject*)this;
} }
ciCallSite* as_call_site() { ciCallSite* as_call_site() {
assert(is_call_site(), "bad cast"); assert(is_call_site(), "bad cast");
return (ciCallSite*) this; return (ciCallSite*)this;
} }
ciInstance* as_instance() { ciInstance* as_instance() {
assert(is_instance(), "bad cast"); assert(is_instance(), "bad cast");
return (ciInstance*)this; return (ciInstance*)this;
} }
ciMemberName* as_member_name() { ciMemberName* as_member_name() {
assert(is_member_name(), "bad cast"); assert(is_member_name(), "bad cast");
return (ciMemberName*)this; return (ciMemberName*)this;
} }
ciMethodHandle* as_method_handle() { ciMethodHandle* as_method_handle() {
assert(is_method_handle(), "bad cast"); assert(is_method_handle(), "bad cast");
return (ciMethodHandle*) this; return (ciMethodHandle*)this;
} }
ciArray* as_array() { ciMethodType* as_method_type() {
assert(is_method_type(), "bad cast");
return (ciMethodType*)this;
}
ciArray* as_array() {
assert(is_array(), "bad cast"); assert(is_array(), "bad cast");
return (ciArray*)this; return (ciArray*)this;
} }
ciObjArray* as_obj_array() { ciObjArray* as_obj_array() {
assert(is_obj_array(), "bad cast"); assert(is_obj_array(), "bad cast");
return (ciObjArray*)this; return (ciObjArray*)this;
} }
ciTypeArray* as_type_array() { ciTypeArray* as_type_array() {
assert(is_type_array(), "bad cast"); assert(is_type_array(), "bad cast");
return (ciTypeArray*)this; return (ciTypeArray*)this;
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "ci/ciMethod.hpp" #include "ci/ciMethod.hpp"
#include "ci/ciMethodData.hpp" #include "ci/ciMethodData.hpp"
#include "ci/ciMethodHandle.hpp" #include "ci/ciMethodHandle.hpp"
#include "ci/ciMethodType.hpp"
#include "ci/ciNullObject.hpp" #include "ci/ciNullObject.hpp"
#include "ci/ciObjArray.hpp" #include "ci/ciObjArray.hpp"
#include "ci/ciObjArrayKlass.hpp" #include "ci/ciObjArrayKlass.hpp"
...@@ -237,23 +238,23 @@ ciObject* ciObjectFactory::get(oop key) { ...@@ -237,23 +238,23 @@ ciObject* ciObjectFactory::get(oop key) {
assert(key == NULL || Universe::heap()->is_in_reserved(key), "must be"); assert(key == NULL || Universe::heap()->is_in_reserved(key), "must be");
NonPermObject* &bucket = find_non_perm(key); NonPermObject* &bucket = find_non_perm(key);
if (bucket != NULL) { if (bucket != NULL) {
return bucket->object(); return bucket->object();
} }
// The ciObject does not yet exist. Create it and insert it // The ciObject does not yet exist. Create it and insert it
// into the cache. // into the cache.
Handle keyHandle(key); Handle keyHandle(key);
ciObject* new_object = create_new_object(keyHandle()); ciObject* new_object = create_new_object(keyHandle());
assert(keyHandle() == new_object->get_oop(), "must be properly recorded"); assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
init_ident_of(new_object); init_ident_of(new_object);
assert(Universe::heap()->is_in_reserved(new_object->get_oop()), "must be"); assert(Universe::heap()->is_in_reserved(new_object->get_oop()), "must be");
// Not a perm-space object. // Not a perm-space object.
insert_non_perm(bucket, keyHandle(), new_object); insert_non_perm(bucket, keyHandle(), new_object);
return new_object; return new_object;
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciObjectFactory::get // ciObjectFactory::get
...@@ -324,6 +325,8 @@ ciObject* ciObjectFactory::create_new_object(oop o) { ...@@ -324,6 +325,8 @@ ciObject* ciObjectFactory::create_new_object(oop o) {
return new (arena()) ciMemberName(h_i); return new (arena()) ciMemberName(h_i);
else if (java_lang_invoke_MethodHandle::is_instance(o)) else if (java_lang_invoke_MethodHandle::is_instance(o))
return new (arena()) ciMethodHandle(h_i); return new (arena()) ciMethodHandle(h_i);
else if (java_lang_invoke_MethodType::is_instance(o))
return new (arena()) ciMethodType(h_i);
else else
return new (arena()) ciInstance(h_i); return new (arena()) ciInstance(h_i);
} else if (o->is_objArray()) { } else if (o->is_objArray()) {
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "ci/ciMethodType.hpp"
#include "ci/ciSignature.hpp" #include "ci/ciSignature.hpp"
#include "ci/ciUtilities.hpp" #include "ci/ciUtilities.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
...@@ -79,6 +80,24 @@ ciSignature::ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciS ...@@ -79,6 +80,24 @@ ciSignature::ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciS
_count = count; _count = count;
} }
// ------------------------------------------------------------------
// ciSignature::ciSignature
ciSignature::ciSignature(ciKlass* accessing_klass, ciSymbol* symbol, ciMethodType* method_type) :
_symbol(symbol),
_accessing_klass(accessing_klass),
_size( method_type->ptype_slot_count()),
_count(method_type->ptype_count())
{
ASSERT_IN_VM;
EXCEPTION_CONTEXT;
Arena* arena = CURRENT_ENV->arena();
_types = new (arena) GrowableArray<ciType*>(arena, _count + 1, 0, NULL);
for (int i = 0; i < _count; i++) {
_types->append(method_type->ptype_at(i));
}
_types->append(method_type->rtype());
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciSignature::return_type // ciSignature::return_type
// //
......
...@@ -47,6 +47,7 @@ private: ...@@ -47,6 +47,7 @@ private:
friend class ciObjectFactory; friend class ciObjectFactory;
ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature); ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature);
ciSignature(ciKlass* accessing_klass, ciSymbol* signature, ciMethodType* method_type);
void get_all_klasses(); void get_all_klasses();
......
...@@ -364,12 +364,15 @@ ciMethod* ciBytecodeStream::get_method(bool& will_link, ciSignature* *declared_s ...@@ -364,12 +364,15 @@ ciMethod* ciBytecodeStream::get_method(bool& will_link, ciSignature* *declared_s
constantPoolHandle cpool(_method->get_Method()->constants()); constantPoolHandle cpool(_method->get_Method()->constants());
ciMethod* m = env->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder); ciMethod* m = env->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
will_link = m->is_loaded(); will_link = m->is_loaded();
// Get declared method signature and return it.
if (has_optional_appendix()) { // Use the MethodType stored in the CP cache to create a signature
const int sig_index = get_method_signature_index(); // with correct types (in respect to class loaders).
Symbol* sig_sym = cpool->symbol_at(sig_index); if (has_method_type()) {
ciKlass* pool_holder = env->get_klass(cpool->pool_holder()); ciSymbol* sig_sym = env->get_symbol(cpool->symbol_at(get_method_signature_index()));
(*declared_signature_result) = new (env->arena()) ciSignature(pool_holder, cpool, env->get_symbol(sig_sym)); ciKlass* pool_holder = env->get_klass(cpool->pool_holder());
ciMethodType* method_type = get_method_type();
ciSignature* declared_signature = new (env->arena()) ciSignature(pool_holder, sig_sym, method_type);
(*declared_signature_result) = declared_signature;
} else { } else {
(*declared_signature_result) = m->signature(); (*declared_signature_result) = m->signature();
} }
...@@ -399,6 +402,31 @@ ciObject* ciBytecodeStream::get_appendix() { ...@@ -399,6 +402,31 @@ ciObject* ciBytecodeStream::get_appendix() {
return CURRENT_ENV->get_object(appendix_oop); return CURRENT_ENV->get_object(appendix_oop);
} }
// ------------------------------------------------------------------
// ciBytecodeStream::has_method_type
//
// Returns true if there is a MethodType argument stored in the
// constant pool cache at the current bci.
bool ciBytecodeStream::has_method_type() {
GUARDED_VM_ENTRY(
constantPoolHandle cpool(_method->get_Method()->constants());
return ConstantPool::has_method_type_at_if_loaded(cpool, get_method_index());
)
}
// ------------------------------------------------------------------
// ciBytecodeStream::get_method_type
//
// Return the MethodType stored in the constant pool cache at
// the current bci.
ciMethodType* ciBytecodeStream::get_method_type() {
GUARDED_VM_ENTRY(
constantPoolHandle cpool(_method->get_Method()->constants());
oop method_type_oop = ConstantPool::method_type_at_if_loaded(cpool, get_method_index());
return CURRENT_ENV->get_object(method_type_oop)->as_method_type();
)
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciBytecodeStream::get_declared_method_holder // ciBytecodeStream::get_declared_method_holder
// //
......
...@@ -257,12 +257,14 @@ public: ...@@ -257,12 +257,14 @@ public:
int get_field_holder_index(); int get_field_holder_index();
int get_field_signature_index(); int get_field_signature_index();
ciMethod* get_method(bool& will_link, ciSignature* *declared_signature_result); ciMethod* get_method(bool& will_link, ciSignature* *declared_signature_result);
bool has_appendix(); bool has_appendix();
ciObject* get_appendix(); ciObject* get_appendix();
ciKlass* get_declared_method_holder(); bool has_method_type();
int get_method_holder_index(); ciMethodType* get_method_type();
int get_method_signature_index(); ciKlass* get_declared_method_holder();
int get_method_holder_index();
int get_method_signature_index();
// Get the resolved references arrays from the constant pool // Get the resolved references arrays from the constant pool
ciObjArray* get_resolved_references(); ciObjArray* get_resolved_references();
......
...@@ -2429,7 +2429,8 @@ static methodHandle unpack_method_and_appendix(Handle mname, ...@@ -2429,7 +2429,8 @@ static methodHandle unpack_method_and_appendix(Handle mname,
methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name, methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name,
Symbol* signature, Symbol* signature,
KlassHandle accessing_klass, KlassHandle accessing_klass,
Handle* appendix_result, Handle *appendix_result,
Handle *method_type_result,
TRAPS) { TRAPS) {
methodHandle empty; methodHandle empty;
assert(EnableInvokeDynamic, ""); assert(EnableInvokeDynamic, "");
...@@ -2461,6 +2462,7 @@ methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name, ...@@ -2461,6 +2462,7 @@ methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name,
vmSymbols::linkMethod_signature(), vmSymbols::linkMethod_signature(),
&args, CHECK_(empty)); &args, CHECK_(empty));
Handle mname(THREAD, (oop) result.get_jobject()); Handle mname(THREAD, (oop) result.get_jobject());
(*method_type_result) = method_type;
return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD); return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD);
} }
...@@ -2607,7 +2609,8 @@ methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller ...@@ -2607,7 +2609,8 @@ methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller
Handle bootstrap_specifier, Handle bootstrap_specifier,
Symbol* name, Symbol* name,
Symbol* type, Symbol* type,
Handle* appendix_result, Handle *appendix_result,
Handle *method_type_result,
TRAPS) { TRAPS) {
methodHandle empty; methodHandle empty;
Handle bsm, info; Handle bsm, info;
...@@ -2650,6 +2653,7 @@ methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller ...@@ -2650,6 +2653,7 @@ methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller
vmSymbols::linkCallSite_signature(), vmSymbols::linkCallSite_signature(),
&args, CHECK_(empty)); &args, CHECK_(empty));
Handle mname(THREAD, (oop) result.get_jobject()); Handle mname(THREAD, (oop) result.get_jobject());
(*method_type_result) = method_type;
return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD); return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD);
} }
......
...@@ -497,6 +497,7 @@ public: ...@@ -497,6 +497,7 @@ public:
Symbol* signature, Symbol* signature,
KlassHandle accessing_klass, KlassHandle accessing_klass,
Handle *appendix_result, Handle *appendix_result,
Handle *method_type_result,
TRAPS); TRAPS);
// for a given signature, find the internal MethodHandle method (linkTo* or invokeBasic) // for a given signature, find the internal MethodHandle method (linkTo* or invokeBasic)
// (does not ask Java, since this is a low-level intrinsic defined by the JVM) // (does not ask Java, since this is a low-level intrinsic defined by the JVM)
...@@ -523,6 +524,7 @@ public: ...@@ -523,6 +524,7 @@ public:
Symbol* name, Symbol* name,
Symbol* type, Symbol* type,
Handle *appendix_result, Handle *appendix_result,
Handle *method_type_result,
TRAPS); TRAPS);
// Utility for printing loader "name" as part of tracing constraints // Utility for printing loader "name" as part of tracing constraints
......
...@@ -737,6 +737,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokehandle(JavaThread* thread)) { ...@@ -737,6 +737,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokehandle(JavaThread* thread)) {
pool, pool,
info.resolved_method(), info.resolved_method(),
info.resolved_appendix(), info.resolved_appendix(),
info.resolved_method_type(),
pool->resolved_references()); pool->resolved_references());
} }
IRT_END IRT_END
...@@ -765,6 +766,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { ...@@ -765,6 +766,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
pool, pool,
info.resolved_method(), info.resolved_method(),
info.resolved_appendix(), info.resolved_appendix(),
info.resolved_method_type(),
pool->resolved_references()); pool->resolved_references());
} }
IRT_END IRT_END
......
...@@ -99,7 +99,7 @@ void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klas ...@@ -99,7 +99,7 @@ void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klas
assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call"); assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call");
} }
void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix, TRAPS) { void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS) {
if (resolved_method.is_null()) { if (resolved_method.is_null()) {
THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null"); THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null");
} }
...@@ -110,7 +110,8 @@ void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix ...@@ -110,7 +110,8 @@ void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix
int vtable_index = Method::nonvirtual_vtable_index; int vtable_index = Method::nonvirtual_vtable_index;
assert(resolved_method->vtable_index() == vtable_index, ""); assert(resolved_method->vtable_index() == vtable_index, "");
set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, vtable_index, CHECK); set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, vtable_index, CHECK);
_resolved_appendix = resolved_appendix; _resolved_appendix = resolved_appendix;
_resolved_method_type = resolved_method_type;
} }
void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) {
...@@ -221,7 +222,8 @@ void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle ...@@ -221,7 +222,8 @@ void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle
void LinkResolver::lookup_polymorphic_method(methodHandle& result, void LinkResolver::lookup_polymorphic_method(methodHandle& result,
KlassHandle klass, Symbol* name, Symbol* full_signature, KlassHandle klass, Symbol* name, Symbol* full_signature,
KlassHandle current_klass, KlassHandle current_klass,
Handle* appendix_result_or_null, Handle *appendix_result_or_null,
Handle *method_type_result,
TRAPS) { TRAPS) {
vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name); vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name);
if (TraceMethodHandles) { if (TraceMethodHandles) {
...@@ -275,10 +277,12 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result, ...@@ -275,10 +277,12 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
} }
Handle appendix; Handle appendix;
Handle method_type;
result = SystemDictionary::find_method_handle_invoker(name, result = SystemDictionary::find_method_handle_invoker(name,
full_signature, full_signature,
current_klass, current_klass,
&appendix, &appendix,
&method_type,
CHECK); CHECK);
if (TraceMethodHandles) { if (TraceMethodHandles) {
tty->print("lookup_polymorphic_method => (via Java) "); tty->print("lookup_polymorphic_method => (via Java) ");
...@@ -307,6 +311,7 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result, ...@@ -307,6 +311,7 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
assert(appendix_result_or_null != NULL, ""); assert(appendix_result_or_null != NULL, "");
(*appendix_result_or_null) = appendix; (*appendix_result_or_null) = appendix;
(*method_type_result) = method_type;
return; return;
} }
} }
...@@ -419,7 +424,7 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res ...@@ -419,7 +424,7 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
if (resolved_method.is_null()) { if (resolved_method.is_null()) {
// JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc // JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc
lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature, lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature,
current_klass, (Handle*)NULL, THREAD); current_klass, (Handle*)NULL, (Handle*)NULL, THREAD);
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
nested_exception = Handle(THREAD, PENDING_EXCEPTION); nested_exception = Handle(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION;
...@@ -1207,11 +1212,12 @@ void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_kl ...@@ -1207,11 +1212,12 @@ void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_kl
assert(resolved_klass() == SystemDictionary::MethodHandle_klass(), ""); assert(resolved_klass() == SystemDictionary::MethodHandle_klass(), "");
assert(MethodHandles::is_signature_polymorphic_name(method_name), ""); assert(MethodHandles::is_signature_polymorphic_name(method_name), "");
methodHandle resolved_method; methodHandle resolved_method;
Handle resolved_appendix; Handle resolved_appendix;
Handle resolved_method_type;
lookup_polymorphic_method(resolved_method, resolved_klass, lookup_polymorphic_method(resolved_method, resolved_klass,
method_name, method_signature, method_name, method_signature,
current_klass, &resolved_appendix, CHECK); current_klass, &resolved_appendix, &resolved_method_type, CHECK);
result.set_handle(resolved_method, resolved_appendix, CHECK); result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
} }
...@@ -1219,7 +1225,7 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po ...@@ -1219,7 +1225,7 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po
assert(EnableInvokeDynamic, ""); assert(EnableInvokeDynamic, "");
pool->set_invokedynamic(); // mark header to flag active call sites pool->set_invokedynamic(); // mark header to flag active call sites
//resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK); //resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK);
Symbol* method_name = pool->name_ref_at(index); Symbol* method_name = pool->name_ref_at(index);
Symbol* method_signature = pool->signature_ref_at(index); Symbol* method_signature = pool->signature_ref_at(index);
KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder()); KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder());
...@@ -1236,9 +1242,10 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po ...@@ -1236,9 +1242,10 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po
bootstrap_specifier = Handle(THREAD, bsm_info); bootstrap_specifier = Handle(THREAD, bsm_info);
} }
if (!cpce->is_f1_null()) { if (!cpce->is_f1_null()) {
methodHandle method(THREAD, cpce->f1_as_method()); methodHandle method( THREAD, cpce->f1_as_method());
Handle appendix(THREAD, cpce->appendix_if_resolved(pool)); Handle appendix( THREAD, cpce->appendix_if_resolved(pool));
result.set_handle(method, appendix, CHECK); Handle method_type(THREAD, cpce->method_type_if_resolved(pool));
result.set_handle(method, appendix, method_type, CHECK);
return; return;
} }
...@@ -1260,11 +1267,13 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result, ...@@ -1260,11 +1267,13 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result,
// JSR 292: this must resolve to an implicitly generated method MH.linkToCallSite(*...) // JSR 292: this must resolve to an implicitly generated method MH.linkToCallSite(*...)
// The appendix argument is likely to be a freshly-created CallSite. // The appendix argument is likely to be a freshly-created CallSite.
Handle resolved_appendix; Handle resolved_appendix;
Handle resolved_method_type;
methodHandle resolved_method = methodHandle resolved_method =
SystemDictionary::find_dynamic_call_site_invoker(current_klass, SystemDictionary::find_dynamic_call_site_invoker(current_klass,
bootstrap_specifier, bootstrap_specifier,
method_name, method_signature, method_name, method_signature,
&resolved_appendix, &resolved_appendix,
&resolved_method_type,
THREAD); THREAD);
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
if (TraceMethodHandles) { if (TraceMethodHandles) {
...@@ -1284,7 +1293,7 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result, ...@@ -1284,7 +1293,7 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result,
CLEAR_PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION;
THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception) THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception)
} }
result.set_handle(resolved_method, resolved_appendix, CHECK); result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
} }
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
......
...@@ -76,12 +76,13 @@ class CallInfo: public LinkInfo { ...@@ -76,12 +76,13 @@ class CallInfo: public LinkInfo {
methodHandle _selected_method; // dynamic (actual) target method methodHandle _selected_method; // dynamic (actual) target method
int _vtable_index; // vtable index of selected method int _vtable_index; // vtable index of selected method
Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix) Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix)
Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites)
void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS); void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS);
void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method , TRAPS); void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method , TRAPS);
void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS); void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS);
void set_handle( methodHandle resolved_method, Handle resolved_appendix, TRAPS); void set_handle( methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS);
void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS); void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS);
friend class LinkResolver; friend class LinkResolver;
...@@ -91,6 +92,7 @@ class CallInfo: public LinkInfo { ...@@ -91,6 +92,7 @@ class CallInfo: public LinkInfo {
methodHandle resolved_method() const { return _resolved_method; } methodHandle resolved_method() const { return _resolved_method; }
methodHandle selected_method() const { return _selected_method; } methodHandle selected_method() const { return _selected_method; }
Handle resolved_appendix() const { return _resolved_appendix; } Handle resolved_appendix() const { return _resolved_appendix; }
Handle resolved_method_type() const { return _resolved_method_type; }
BasicType result_type() const { return selected_method()->result_type(); } BasicType result_type() const { return selected_method()->result_type(); }
bool has_vtable_index() const { return _vtable_index >= 0; } bool has_vtable_index() const { return _vtable_index >= 0; }
...@@ -113,7 +115,7 @@ class LinkResolver: AllStatic { ...@@ -113,7 +115,7 @@ class LinkResolver: AllStatic {
static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
KlassHandle current_klass, Handle* appendix_result_or_null, TRAPS); KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
static int vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); static int vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
......
...@@ -179,7 +179,7 @@ void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, int cache_i ...@@ -179,7 +179,7 @@ void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, int cache_i
MethodHandles::is_signature_polymorphic_name(SystemDictionary::MethodHandle_klass(), MethodHandles::is_signature_polymorphic_name(SystemDictionary::MethodHandle_klass(),
_pool->name_ref_at(cp_index))) { _pool->name_ref_at(cp_index))) {
// we may need a resolved_refs entry for the appendix // we may need a resolved_refs entry for the appendix
add_invokedynamic_resolved_references_entry(cp_index, cache_index); add_invokedynamic_resolved_references_entries(cp_index, cache_index);
status = +1; status = +1;
} else { } else {
status = -1; status = -1;
...@@ -211,7 +211,7 @@ void Rewriter::rewrite_invokedynamic(address bcp, int offset, bool reverse) { ...@@ -211,7 +211,7 @@ void Rewriter::rewrite_invokedynamic(address bcp, int offset, bool reverse) {
if (!reverse) { if (!reverse) {
int cp_index = Bytes::get_Java_u2(p); int cp_index = Bytes::get_Java_u2(p);
int cache_index = add_invokedynamic_cp_cache_entry(cp_index); int cache_index = add_invokedynamic_cp_cache_entry(cp_index);
add_invokedynamic_resolved_references_entry(cp_index, cache_index); add_invokedynamic_resolved_references_entries(cp_index, cache_index);
// Replace the trailing four bytes with a CPC index for the dynamic // Replace the trailing four bytes with a CPC index for the dynamic
// call site. Unlike other CPC entries, there is one per bytecode, // call site. Unlike other CPC entries, there is one per bytecode,
// not just one per distinct CP entry. In other words, the // not just one per distinct CP entry. In other words, the
......
...@@ -113,12 +113,19 @@ class Rewriter: public StackObj { ...@@ -113,12 +113,19 @@ class Rewriter: public StackObj {
return ref_index; return ref_index;
} }
// add a new entry to the resolved_references map (for invokedynamic only) // add a new entries to the resolved_references map (for invokedynamic and invokehandle only)
int add_invokedynamic_resolved_references_entry(int cp_index, int cache_index) { int add_invokedynamic_resolved_references_entries(int cp_index, int cache_index) {
assert(_resolved_reference_limit >= 0, "must add indy refs after first iteration"); assert(_resolved_reference_limit >= 0, "must add indy refs after first iteration");
int ref_index = _resolved_references_map.append(cp_index); // many-to-one int ref_index = -1;
assert(ref_index >= _resolved_reference_limit, ""); for (int entry = 0; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) {
_invokedynamic_references_map.at_put_grow(ref_index, cache_index, -1); const int index = _resolved_references_map.append(cp_index); // many-to-one
assert(index >= _resolved_reference_limit, "");
if (entry == 0) {
ref_index = index;
}
assert((index - entry) == ref_index, "entries must be consecutive");
_invokedynamic_references_map.at_put_grow(index, cache_index, -1);
}
return ref_index; return ref_index;
} }
...@@ -127,15 +134,6 @@ class Rewriter: public StackObj { ...@@ -127,15 +134,6 @@ class Rewriter: public StackObj {
return cp_index; return cp_index;
} }
// invokedynamic support - append the cpCache entry (encoded) in object map.
// The resolved_references_map should still be in ascending order
// The resolved_references has the invokedynamic call site objects appended after
// the objects that are resolved in the constant pool.
int add_callsite_entry(int main_cpc_entry) {
int ref_index = _resolved_references_map.append(main_cpc_entry);
return ref_index;
}
// Access the contents of _cp_cache_map to determine CP cache layout. // Access the contents of _cp_cache_map to determine CP cache layout.
int cp_cache_entry_pool_index(int cache_index) { int cp_cache_entry_pool_index(int cache_index) {
int cp_index = _cp_cache_map[cache_index]; int cp_index = _cp_cache_map[cache_index];
......
...@@ -445,7 +445,6 @@ bool ConstantPool::has_appendix_at_if_loaded(constantPoolHandle cpool, int which ...@@ -445,7 +445,6 @@ bool ConstantPool::has_appendix_at_if_loaded(constantPoolHandle cpool, int which
return e->has_appendix(); return e->has_appendix();
} }
oop ConstantPool::appendix_at_if_loaded(constantPoolHandle cpool, int which) { oop ConstantPool::appendix_at_if_loaded(constantPoolHandle cpool, int which) {
if (cpool->cache() == NULL) return NULL; // nothing to load yet if (cpool->cache() == NULL) return NULL; // nothing to load yet
int cache_index = decode_cpcache_index(which, true); int cache_index = decode_cpcache_index(which, true);
...@@ -454,6 +453,21 @@ oop ConstantPool::appendix_at_if_loaded(constantPoolHandle cpool, int which) { ...@@ -454,6 +453,21 @@ oop ConstantPool::appendix_at_if_loaded(constantPoolHandle cpool, int which) {
} }
bool ConstantPool::has_method_type_at_if_loaded(constantPoolHandle cpool, int which) {
if (cpool->cache() == NULL) return false; // nothing to load yet
int cache_index = decode_cpcache_index(which, true);
ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index);
return e->has_method_type();
}
oop ConstantPool::method_type_at_if_loaded(constantPoolHandle cpool, int which) {
if (cpool->cache() == NULL) return NULL; // nothing to load yet
int cache_index = decode_cpcache_index(which, true);
ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index);
return e->method_type_if_resolved(cpool);
}
Symbol* ConstantPool::impl_name_ref_at(int which, bool uncached) { Symbol* ConstantPool::impl_name_ref_at(int which, bool uncached) {
int name_index = name_ref_index_at(impl_name_and_type_ref_index_at(which, uncached)); int name_index = name_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
return symbol_at(name_index); return symbol_at(name_index);
......
...@@ -694,13 +694,15 @@ class ConstantPool : public Metadata { ...@@ -694,13 +694,15 @@ class ConstantPool : public Metadata {
friend class SystemDictionary; friend class SystemDictionary;
// Used by compiler to prevent classloading. // Used by compiler to prevent classloading.
static Method* method_at_if_loaded (constantPoolHandle this_oop, int which); static Method* method_at_if_loaded (constantPoolHandle this_oop, int which);
static bool has_appendix_at_if_loaded (constantPoolHandle this_oop, int which); static bool has_appendix_at_if_loaded (constantPoolHandle this_oop, int which);
static oop appendix_at_if_loaded (constantPoolHandle this_oop, int which); static oop appendix_at_if_loaded (constantPoolHandle this_oop, int which);
static Klass* klass_at_if_loaded (constantPoolHandle this_oop, int which); static bool has_method_type_at_if_loaded (constantPoolHandle this_oop, int which);
static Klass* klass_ref_at_if_loaded (constantPoolHandle this_oop, int which); static oop method_type_at_if_loaded (constantPoolHandle this_oop, int which);
static Klass* klass_at_if_loaded (constantPoolHandle this_oop, int which);
static Klass* klass_ref_at_if_loaded (constantPoolHandle this_oop, int which);
// Same as above - but does LinkResolving. // Same as above - but does LinkResolving.
static Klass* klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int which, TRAPS); static Klass* klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int which, TRAPS);
// Routines currently used for annotations (only called by jvm.cpp) but which might be used in the // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
// future by other Java code. These take constant pool indices rather than // future by other Java code. These take constant pool indices rather than
......
...@@ -244,21 +244,23 @@ void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) ...@@ -244,21 +244,23 @@ void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index)
void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool, void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool,
methodHandle adapter, Handle appendix, methodHandle adapter,
Handle appendix, Handle method_type,
objArrayHandle resolved_references) { objArrayHandle resolved_references) {
set_method_handle_common(cpool, Bytecodes::_invokehandle, adapter, appendix, resolved_references); set_method_handle_common(cpool, Bytecodes::_invokehandle, adapter, appendix, method_type, resolved_references);
} }
void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool, void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool,
methodHandle adapter, Handle appendix, methodHandle adapter,
Handle appendix, Handle method_type,
objArrayHandle resolved_references) { objArrayHandle resolved_references) {
set_method_handle_common(cpool, Bytecodes::_invokedynamic, adapter, appendix, resolved_references); set_method_handle_common(cpool, Bytecodes::_invokedynamic, adapter, appendix, method_type, resolved_references);
} }
void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
Bytecodes::Code invoke_code, Bytecodes::Code invoke_code,
methodHandle adapter, methodHandle adapter,
Handle appendix, Handle appendix, Handle method_type,
objArrayHandle resolved_references) { objArrayHandle resolved_references) {
// NOTE: This CPCE can be the subject of data races. // NOTE: This CPCE can be the subject of data races.
// There are three words to update: flags, refs[f2], f1 (in that order). // There are three words to update: flags, refs[f2], f1 (in that order).
...@@ -274,18 +276,21 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, ...@@ -274,18 +276,21 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
return; return;
} }
bool has_appendix = appendix.not_null(); const bool has_appendix = appendix.not_null();
const bool has_method_type = method_type.not_null();
// Write the flags. // Write the flags.
set_method_flags(as_TosState(adapter->result_type()), set_method_flags(as_TosState(adapter->result_type()),
((has_appendix ? 1 : 0) << has_appendix_shift) | ((has_appendix ? 1 : 0) << has_appendix_shift ) |
( 1 << is_final_shift), ((has_method_type ? 1 : 0) << has_method_type_shift) |
( 1 << is_final_shift ),
adapter->size_of_parameters()); adapter->size_of_parameters());
if (TraceInvokeDynamic) { if (TraceInvokeDynamic) {
tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method="PTR_FORMAT" ", tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method_type="PTR_FORMAT"%s method="PTR_FORMAT" ",
invoke_code, invoke_code,
(intptr_t)appendix(), (has_appendix ? "" : " (unused)"), (intptr_t)appendix(), (has_appendix ? "" : " (unused)"),
(intptr_t)method_type(), (has_method_type ? "" : " (unused)"),
(intptr_t)adapter()); (intptr_t)adapter());
adapter->print(); adapter->print();
if (has_appendix) appendix()->print(); if (has_appendix) appendix()->print();
...@@ -310,17 +315,26 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, ...@@ -310,17 +315,26 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
// This allows us to create fewer method oops, while keeping type safety. // This allows us to create fewer method oops, while keeping type safety.
// //
// Store appendix, if any.
if (has_appendix) { if (has_appendix) {
int ref_index = f2_as_index(); const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset;
assert(ref_index >= 0 && ref_index < resolved_references->length(), "oob"); assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob");
assert(resolved_references->obj_at(ref_index) == NULL, "init just once"); assert(resolved_references->obj_at(appendix_index) == NULL, "init just once");
resolved_references->obj_at_put(ref_index, appendix()); resolved_references->obj_at_put(appendix_index, appendix());
}
// Store MethodType, if any.
if (has_method_type) {
const int method_type_index = f2_as_index() + _indy_resolved_references_method_type_offset;
assert(method_type_index >= 0 && method_type_index < resolved_references->length(), "oob");
assert(resolved_references->obj_at(method_type_index) == NULL, "init just once");
resolved_references->obj_at_put(method_type_index, method_type());
} }
release_set_f1(adapter()); // This must be the last one to set (see NOTE above)! release_set_f1(adapter()); // This must be the last one to set (see NOTE above)!
// The interpreter assembly code does not check byte_2, // The interpreter assembly code does not check byte_2,
// but it is used by is_resolved, method_if_resolved, etc. // but it is used by is_resolved, method_if_resolved, etc.
set_bytecode_1(invoke_code); set_bytecode_1(invoke_code);
NOT_PRODUCT(verify(tty)); NOT_PRODUCT(verify(tty));
if (TraceInvokeDynamic) { if (TraceInvokeDynamic) {
...@@ -376,7 +390,16 @@ Method* ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) { ...@@ -376,7 +390,16 @@ Method* ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) {
oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) { oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) {
if (is_f1_null() || !has_appendix()) if (is_f1_null() || !has_appendix())
return NULL; return NULL;
int ref_index = f2_as_index(); const int ref_index = f2_as_index() + _indy_resolved_references_appendix_offset;
objArrayOop resolved_references = cpool->resolved_references();
return resolved_references->obj_at(ref_index);
}
oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) {
if (is_f1_null() || !has_method_type())
return NULL;
const int ref_index = f2_as_index() + _indy_resolved_references_method_type_offset;
objArrayOop resolved_references = cpool->resolved_references(); objArrayOop resolved_references = cpool->resolved_references();
return resolved_references->obj_at(ref_index); return resolved_references->obj_at(ref_index);
} }
...@@ -513,13 +536,23 @@ void ConstantPoolCache::initialize(intArray& inverse_index_map, intArray& invoke ...@@ -513,13 +536,23 @@ void ConstantPoolCache::initialize(intArray& inverse_index_map, intArray& invoke
for (int i = 0; i < length(); i++) { for (int i = 0; i < length(); i++) {
ConstantPoolCacheEntry* e = entry_at(i); ConstantPoolCacheEntry* e = entry_at(i);
int original_index = inverse_index_map[i]; int original_index = inverse_index_map[i];
e->initialize_entry(original_index); e->initialize_entry(original_index);
assert(entry_at(i) == e, "sanity"); assert(entry_at(i) == e, "sanity");
} }
for (int ref = 0; ref < invokedynamic_references_map.length(); ref++) { for (int ref = 0; ref < invokedynamic_references_map.length(); ref++) {
int cpci = invokedynamic_references_map[ref]; const int cpci = invokedynamic_references_map[ref];
if (cpci >= 0) if (cpci >= 0) {
#ifdef ASSERT
// invokedynamic and invokehandle have more entries; check if they
// all point to the same constant pool cache entry.
for (int entry = 1; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) {
const int cpci_next = invokedynamic_references_map[ref + entry];
assert(cpci == cpci_next, err_msg_res("%d == %d", cpci, cpci_next));
}
#endif
entry_at(cpci)->initialize_resolved_reference_index(ref); entry_at(cpci)->initialize_resolved_reference_index(ref);
ref += ConstantPoolCacheEntry::_indy_resolved_references_entries - 1; // skip extra entries
}
} }
} }
......
...@@ -42,10 +42,10 @@ class PSPromotionManager; ...@@ -42,10 +42,10 @@ class PSPromotionManager;
// _indices [ b2 | b1 | index ] index = constant_pool_index // _indices [ b2 | b1 | index ] index = constant_pool_index
// _f1 [ entry specific ] metadata ptr (method or klass) // _f1 [ entry specific ] metadata ptr (method or klass)
// _f2 [ entry specific ] vtable or res_ref index, or vfinal method ptr // _f2 [ entry specific ] vtable or res_ref index, or vfinal method ptr
// _flags [tos|0|F=1|0|0|f|v|0 |00000|field_index] (for field entries) // _flags [tos|0|F=1|0|0|0|f|v|0 |0000|field_index] (for field entries)
// bit length [ 4 |1| 1 |1|1|1|1|1 |--5--|----16-----] // bit length [ 4 |1| 1 |1|1|1|1|1|1 |-4--|----16-----]
// _flags [tos|0|F=0|A|I|f|0|vf|00000|00000|psize] (for method entries) // _flags [tos|0|F=0|M|A|I|f|0|vf|0000|00000|psize] (for method entries)
// bit length [ 4 |1| 1 |1|1|1|1|1 |--5--|--8--|--8--] // bit length [ 4 |1| 1 |1|1|1|1|1|1 |-4--|--8--|--8--]
// -------------------------------- // --------------------------------
// //
...@@ -166,11 +166,12 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { ...@@ -166,11 +166,12 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
tos_state_shift = BitsPerInt - tos_state_bits, // see verify_tos_state_shift below tos_state_shift = BitsPerInt - tos_state_bits, // see verify_tos_state_shift below
// misc. option bits; can be any bit position in [16..27] // misc. option bits; can be any bit position in [16..27]
is_field_entry_shift = 26, // (F) is it a field or a method? is_field_entry_shift = 26, // (F) is it a field or a method?
has_appendix_shift = 25, // (A) does the call site have an appendix argument? has_method_type_shift = 25, // (M) does the call site have a MethodType?
is_forced_virtual_shift = 24, // (I) is the interface reference forced to virtual mode? has_appendix_shift = 24, // (A) does the call site have an appendix argument?
is_final_shift = 23, // (f) is the field or method final? is_forced_virtual_shift = 23, // (I) is the interface reference forced to virtual mode?
is_volatile_shift = 22, // (v) is the field volatile? is_final_shift = 22, // (f) is the field or method final?
is_vfinal_shift = 21, // (vf) did the call resolve to a final method? is_volatile_shift = 21, // (v) is the field volatile?
is_vfinal_shift = 20, // (vf) did the call resolve to a final method?
// low order bits give field index (for FieldInfo) or method parameter size: // low order bits give field index (for FieldInfo) or method parameter size:
field_index_bits = 16, field_index_bits = 16,
field_index_mask = right_n_bits(field_index_bits), field_index_mask = right_n_bits(field_index_bits),
...@@ -223,14 +224,16 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { ...@@ -223,14 +224,16 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
void set_method_handle( void set_method_handle(
constantPoolHandle cpool, // holding constant pool (required for locking) constantPoolHandle cpool, // holding constant pool (required for locking)
methodHandle method, // adapter for invokeExact, etc. methodHandle method, // adapter for invokeExact, etc.
Handle appendix, // stored in refs[f2]; could be a java.lang.invoke.MethodType Handle appendix, // stored in refs[f2+0]; could be a java.lang.invoke.MethodType
Handle method_type, // stored in refs[f2+1]; is a java.lang.invoke.MethodType
objArrayHandle resolved_references objArrayHandle resolved_references
); );
void set_dynamic_call( void set_dynamic_call(
constantPoolHandle cpool, // holding constant pool (required for locking) constantPoolHandle cpool, // holding constant pool (required for locking)
methodHandle method, // adapter for this call site methodHandle method, // adapter for this call site
Handle appendix, // stored in refs[f2]; could be a java.lang.invoke.CallSite Handle appendix, // stored in refs[f2+0]; could be a java.lang.invoke.CallSite
Handle method_type, // stored in refs[f2+1]; is a java.lang.invoke.MethodType
objArrayHandle resolved_references objArrayHandle resolved_references
); );
...@@ -253,12 +256,24 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { ...@@ -253,12 +256,24 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
constantPoolHandle cpool, // holding constant pool (required for locking) constantPoolHandle cpool, // holding constant pool (required for locking)
Bytecodes::Code invoke_code, // _invokehandle or _invokedynamic Bytecodes::Code invoke_code, // _invokehandle or _invokedynamic
methodHandle adapter, // invoker method (f1) methodHandle adapter, // invoker method (f1)
Handle appendix, // appendix such as CallSite, MethodType, etc. (refs[f2]) Handle appendix, // appendix such as CallSite, MethodType, etc. (refs[f2+0])
Handle method_type, // MethodType (refs[f2+1])
objArrayHandle resolved_references objArrayHandle resolved_references
); );
Method* method_if_resolved(constantPoolHandle cpool); // invokedynamic and invokehandle call sites have two entries in the
oop appendix_if_resolved(constantPoolHandle cpool); // resolved references array:
// appendix (at index+0)
// MethodType (at index+1)
enum {
_indy_resolved_references_appendix_offset = 0,
_indy_resolved_references_method_type_offset = 1,
_indy_resolved_references_entries
};
Method* method_if_resolved(constantPoolHandle cpool);
oop appendix_if_resolved(constantPoolHandle cpool);
oop method_type_if_resolved(constantPoolHandle cpool);
void set_parameter_size(int value); void set_parameter_size(int value);
...@@ -270,11 +285,11 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { ...@@ -270,11 +285,11 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
case Bytecodes::_getfield : // fall through case Bytecodes::_getfield : // fall through
case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokespecial : // fall through
case Bytecodes::_invokestatic : // fall through case Bytecodes::_invokestatic : // fall through
case Bytecodes::_invokehandle : // fall through
case Bytecodes::_invokedynamic : // fall through
case Bytecodes::_invokeinterface : return 1; case Bytecodes::_invokeinterface : return 1;
case Bytecodes::_putstatic : // fall through case Bytecodes::_putstatic : // fall through
case Bytecodes::_putfield : // fall through case Bytecodes::_putfield : // fall through
case Bytecodes::_invokehandle : // fall through
case Bytecodes::_invokedynamic : // fall through
case Bytecodes::_invokevirtual : return 2; case Bytecodes::_invokevirtual : return 2;
default : break; default : break;
} }
...@@ -307,6 +322,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { ...@@ -307,6 +322,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
bool is_forced_virtual() const { return (_flags & (1 << is_forced_virtual_shift)) != 0; } bool is_forced_virtual() const { return (_flags & (1 << is_forced_virtual_shift)) != 0; }
bool is_vfinal() const { return (_flags & (1 << is_vfinal_shift)) != 0; } bool is_vfinal() const { return (_flags & (1 << is_vfinal_shift)) != 0; }
bool has_appendix() const { return (_flags & (1 << has_appendix_shift)) != 0; } bool has_appendix() const { return (_flags & (1 << has_appendix_shift)) != 0; }
bool has_method_type() const { return (_flags & (1 << has_method_type_shift)) != 0; }
bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; }
bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; }
bool is_byte() const { return flag_state() == btos; } bool is_byte() const { return flag_state() == btos; }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册