提交 dc2b1bc0 编写于 作者: J jrose

6987991: JSR 292 phpreboot test/testtracefun2.phpr segfaults

Summary: Make MH verification tests more correct, robust, and informative.  Fix lingering symbol refcount problems.
Reviewed-by: twisti
上级 a2335786
...@@ -921,6 +921,10 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, ...@@ -921,6 +921,10 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
tty->cr(); tty->cr();
} }
// invariant: cp->symbol_at_put is preceded by a refcount increment (more usually a lookup)
name->increment_refcount();
signature->increment_refcount();
constantPoolHandle cp; constantPoolHandle cp;
{ {
constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty)); constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty));
......
...@@ -343,6 +343,7 @@ private: ...@@ -343,6 +343,7 @@ private:
int cpool_symbol_put(int tag, Symbol* con) { int cpool_symbol_put(int tag, Symbol* con) {
if (con == NULL) return 0; if (con == NULL) return 0;
ConstantValue* cv = new ConstantValue(tag, con); ConstantValue* cv = new ConstantValue(tag, con);
con->increment_refcount();
return _constants.append(cv); return _constants.append(cv);
} }
......
...@@ -928,6 +928,7 @@ static const char* always_null_names[] = { ...@@ -928,6 +928,7 @@ static const char* always_null_names[] = {
}; };
static bool is_always_null_type(klassOop klass) { static bool is_always_null_type(klassOop klass) {
if (klass == NULL) return false; // safety
if (!Klass::cast(klass)->oop_is_instance()) return false; if (!Klass::cast(klass)->oop_is_instance()) return false;
instanceKlass* ik = instanceKlass::cast(klass); instanceKlass* ik = instanceKlass::cast(klass);
// Must be on the boot class path: // Must be on the boot class path:
...@@ -944,6 +945,8 @@ static bool is_always_null_type(klassOop klass) { ...@@ -944,6 +945,8 @@ static bool is_always_null_type(klassOop klass) {
} }
bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) { bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) {
if (dst == NULL) return true;
if (src == NULL) return (dst != SystemDictionary::Object_klass());
if (src == dst || dst == SystemDictionary::Object_klass()) if (src == dst || dst == SystemDictionary::Object_klass())
return false; // quickest checks return false; // quickest checks
Klass* srck = Klass::cast(src); Klass* srck = Klass::cast(src);
...@@ -1026,10 +1029,15 @@ void MethodHandles::verify_method_signature(methodHandle m, ...@@ -1026,10 +1029,15 @@ void MethodHandles::verify_method_signature(methodHandle m,
int first_ptype_pos, int first_ptype_pos,
KlassHandle insert_ptype, KlassHandle insert_ptype,
TRAPS) { TRAPS) {
Handle mhi_type;
if (m->is_method_handle_invoke()) {
// use this more exact typing instead of the symbolic signature:
mhi_type = Handle(THREAD, m->method_handle_type());
}
objArrayHandle ptypes(THREAD, java_lang_invoke_MethodType::ptypes(mtype())); objArrayHandle ptypes(THREAD, java_lang_invoke_MethodType::ptypes(mtype()));
int pnum = first_ptype_pos; int pnum = first_ptype_pos;
int pmax = ptypes->length(); int pmax = ptypes->length();
int mnum = 0; // method argument int anum = 0; // method argument
const char* err = NULL; const char* err = NULL;
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) { for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) {
...@@ -1048,47 +1056,70 @@ void MethodHandles::verify_method_signature(methodHandle m, ...@@ -1048,47 +1056,70 @@ void MethodHandles::verify_method_signature(methodHandle m,
else else
ptype_oop = insert_ptype->java_mirror(); ptype_oop = insert_ptype->java_mirror();
pnum += 1; pnum += 1;
mnum += 1; anum += 1;
} }
klassOop pklass = NULL; KlassHandle pklass;
BasicType ptype = T_OBJECT; BasicType ptype = T_OBJECT;
if (ptype_oop != NULL) bool have_ptype = false;
ptype = java_lang_Class::as_BasicType(ptype_oop, &pklass); // missing ptype_oop does not match any non-reference; use Object to report the error
else pklass = SystemDictionaryHandles::Object_klass();
// null does not match any non-reference; use Object to report the error if (ptype_oop != NULL) {
pklass = SystemDictionary::Object_klass(); have_ptype = true;
klassOop mklass = NULL; klassOop pklass_oop = NULL;
BasicType mtype = ss.type(); ptype = java_lang_Class::as_BasicType(ptype_oop, &pklass_oop);
if (mtype == T_ARRAY) mtype = T_OBJECT; // fold all refs to T_OBJECT pklass = KlassHandle(THREAD, pklass_oop);
if (mtype == T_OBJECT) { }
if (ptype_oop == NULL) { ptype_oop = NULL; //done with this
KlassHandle aklass;
BasicType atype = ss.type();
if (atype == T_ARRAY) atype = T_OBJECT; // fold all refs to T_OBJECT
if (atype == T_OBJECT) {
if (!have_ptype) {
// null matches any reference // null matches any reference
continue; continue;
} }
KlassHandle pklass_handle(THREAD, pklass); pklass = NULL; if (mhi_type.is_null()) {
// If we fail to resolve types at this point, we will throw an error. // If we fail to resolve types at this point, we will usually throw an error.
Symbol* name = ss.as_symbol(CHECK); TempNewSymbol name = ss.as_symbol_or_null();
if (name != NULL) {
instanceKlass* mk = instanceKlass::cast(m->method_holder()); instanceKlass* mk = instanceKlass::cast(m->method_holder());
Handle loader(THREAD, mk->class_loader()); Handle loader(THREAD, mk->class_loader());
Handle domain(THREAD, mk->protection_domain()); Handle domain(THREAD, mk->protection_domain());
mklass = SystemDictionary::resolve_or_null(name, loader, domain, CHECK); klassOop aklass_oop = SystemDictionary::resolve_or_null(name, loader, domain, CHECK);
pklass = pklass_handle(); if (aklass_oop != NULL)
if (mklass == NULL && pklass != NULL && aklass = KlassHandle(THREAD, aklass_oop);
Klass::cast(pklass)->name() == name && }
m->is_method_handle_invoke()) { } else {
// Assume a match. We can't really decode the signature of MH.invoke*. // for method handle invokers we don't look at the name in the signature
continue; oop atype_oop;
if (ss.at_return_type())
atype_oop = java_lang_invoke_MethodType::rtype(mhi_type());
else
atype_oop = java_lang_invoke_MethodType::ptype(mhi_type(), anum-1);
klassOop aklass_oop = NULL;
atype = java_lang_Class::as_BasicType(atype_oop, &aklass_oop);
aklass = KlassHandle(THREAD, aklass_oop);
} }
} }
if (!ss.at_return_type()) { if (!ss.at_return_type()) {
err = check_argument_type_change(ptype, pklass, mtype, mklass, mnum); err = check_argument_type_change(ptype, pklass(), atype, aklass(), anum);
} else { } else {
err = check_return_type_change(mtype, mklass, ptype, pklass); // note reversal! err = check_return_type_change(atype, aklass(), ptype, pklass()); // note reversal!
} }
if (err != NULL) break; if (err != NULL) break;
} }
if (err != NULL) { if (err != NULL) {
#ifndef PRODUCT
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print("*** verify_method_signature failed: ");
java_lang_invoke_MethodType::print_signature(mtype(), tty);
tty->cr();
tty->print_cr(" first_ptype_pos = %d, insert_ptype = "UINTX_FORMAT, first_ptype_pos, insert_ptype());
tty->print(" Failing method: ");
m->print();
}
#endif //PRODUCT
THROW_MSG(vmSymbols::java_lang_InternalError(), err); THROW_MSG(vmSymbols::java_lang_InternalError(), err);
} }
} }
...@@ -1288,10 +1319,12 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type, ...@@ -1288,10 +1319,12 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
// format, format, format // format, format, format
const char* src_name = type2name(src_type); const char* src_name = type2name(src_type);
const char* dst_name = type2name(dst_type); const char* dst_name = type2name(dst_type);
if (src_type == T_OBJECT) src_name = Klass::cast(src_klass)->external_name();
if (dst_type == T_OBJECT) dst_name = Klass::cast(dst_klass)->external_name();
if (src_name == NULL) src_name = "unknown type"; if (src_name == NULL) src_name = "unknown type";
if (dst_name == NULL) dst_name = "unknown type"; if (dst_name == NULL) dst_name = "unknown type";
if (src_type == T_OBJECT)
src_name = (src_klass != NULL) ? Klass::cast(src_klass)->external_name() : "an unresolved class";
if (dst_type == T_OBJECT)
dst_name = (dst_klass != NULL) ? Klass::cast(dst_klass)->external_name() : "an unresolved class";
size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11);
char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册