Mercurial > hg > graal-jvmci-8
changeset 2303:c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
Summary: Add special rule to allow assignment of frames with uninit flags set.
Reviewed-by: never, coleenp
author | kamg |
---|---|
date | Mon, 28 Feb 2011 16:01:59 -0500 |
parents | da091bb67459 |
children | cef8c988e7b8 |
files | src/share/vm/classfile/stackMapFrame.cpp src/share/vm/classfile/stackMapFrame.hpp src/share/vm/classfile/verificationType.hpp |
diffstat | 3 files changed, 44 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/vm/classfile/stackMapFrame.cpp Mon Feb 28 14:19:52 2011 +0100 +++ b/src/share/vm/classfile/stackMapFrame.cpp Mon Feb 28 16:01:59 2011 -0500 @@ -170,6 +170,44 @@ return true; } +bool StackMapFrame::has_flag_match_exception( + const StackMapFrame* target) const { + // We allow flags of {UninitThis} to assign to {} if-and-only-if the + // target frame does not depend upon the current type. + // This is slightly too strict, as we need only enforce that the + // slots that were initialized by the <init> (the things that were + // UninitializedThis before initialize_object() converted them) are unused. + // However we didn't save that information so we'll enforce this upon + // anything that might have been initialized. This is a rare situation + // and javac never generates code that would end up here, but some profilers + // (such as NetBeans) might, when adding exception handlers in <init> + // methods to cover the invokespecial instruction. See 7020118. + + assert(max_locals() == target->max_locals() && + stack_size() == target->stack_size(), "StackMap sizes must match"); + + VerificationType top = VerificationType::top_type(); + VerificationType this_type = verifier()->current_type(); + + if (!flag_this_uninit() || target->flags() != 0) { + return false; + } + + for (int i = 0; i < target->locals_size(); ++i) { + if (locals()[i] == this_type && target->locals()[i] != top) { + return false; + } + } + + for (int i = 0; i < target->stack_size(); ++i) { + if (stack()[i] == this_type && target->stack()[i] != top) { + return false; + } + } + + return true; +} + bool StackMapFrame::is_assignable_to(const StackMapFrame* target, TRAPS) const { if (_max_locals != target->max_locals() || _stack_size != target->stack_size()) { return false; @@ -182,7 +220,9 @@ bool match_stack = is_assignable_to( _stack, target->stack(), _stack_size, CHECK_false); bool match_flags = (_flags | target->flags()) == target->flags(); - return (match_locals && match_stack && match_flags); + + return match_locals && match_stack && + (match_flags || has_flag_match_exception(target)); } VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) {
--- a/src/share/vm/classfile/stackMapFrame.hpp Mon Feb 28 14:19:52 2011 +0100 +++ b/src/share/vm/classfile/stackMapFrame.hpp Mon Feb 28 16:01:59 2011 -0500 @@ -228,6 +228,8 @@ bool is_assignable_to( VerificationType* src, VerificationType* target, int32_t len, TRAPS) const; + bool has_flag_match_exception(const StackMapFrame* target) const; + // Debugging void print() const PRODUCT_RETURN; };
--- a/src/share/vm/classfile/verificationType.hpp Mon Feb 28 14:19:52 2011 +0100 +++ b/src/share/vm/classfile/verificationType.hpp Mon Feb 28 16:01:59 2011 -0500 @@ -128,6 +128,7 @@ // Create verification types static VerificationType bogus_type() { return VerificationType(Bogus); } + static VerificationType top_type() { return bogus_type(); } // alias static VerificationType null_type() { return VerificationType(Null); } static VerificationType integer_type() { return VerificationType(Integer); } static VerificationType float_type() { return VerificationType(Float); }