7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
Add special rule to allow assignment of frames with uninit flags set. Reviewed-by: never, coleenp
This commit is contained in:
parent
cc6f461357
commit
ffab67875d
@ -170,6 +170,44 @@ bool StackMapFrame::is_assignable_to(
|
||||
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 StackMapFrame::is_assignable_to(const StackMapFrame* target, TRAPS) const {
|
||||
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) {
|
||||
|
@ -228,6 +228,8 @@ class StackMapFrame : public ResourceObj {
|
||||
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;
|
||||
};
|
||||
|
@ -128,6 +128,7 @@ class VerificationType VALUE_OBJ_CLASS_SPEC {
|
||||
|
||||
// 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); }
|
||||
|
Loading…
Reference in New Issue
Block a user