comparison src/share/vm/classfile/stackMapFrame.cpp @ 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 3582bf76420e
children 1d1603768966 7144a1d6e0a9
comparison
equal deleted inserted replaced
2302:da091bb67459 2303:c1a6154012c8
168 } 168 }
169 } 169 }
170 return true; 170 return true;
171 } 171 }
172 172
173 bool StackMapFrame::has_flag_match_exception(
174 const StackMapFrame* target) const {
175 // We allow flags of {UninitThis} to assign to {} if-and-only-if the
176 // target frame does not depend upon the current type.
177 // This is slightly too strict, as we need only enforce that the
178 // slots that were initialized by the <init> (the things that were
179 // UninitializedThis before initialize_object() converted them) are unused.
180 // However we didn't save that information so we'll enforce this upon
181 // anything that might have been initialized. This is a rare situation
182 // and javac never generates code that would end up here, but some profilers
183 // (such as NetBeans) might, when adding exception handlers in <init>
184 // methods to cover the invokespecial instruction. See 7020118.
185
186 assert(max_locals() == target->max_locals() &&
187 stack_size() == target->stack_size(), "StackMap sizes must match");
188
189 VerificationType top = VerificationType::top_type();
190 VerificationType this_type = verifier()->current_type();
191
192 if (!flag_this_uninit() || target->flags() != 0) {
193 return false;
194 }
195
196 for (int i = 0; i < target->locals_size(); ++i) {
197 if (locals()[i] == this_type && target->locals()[i] != top) {
198 return false;
199 }
200 }
201
202 for (int i = 0; i < target->stack_size(); ++i) {
203 if (stack()[i] == this_type && target->stack()[i] != top) {
204 return false;
205 }
206 }
207
208 return true;
209 }
210
173 bool StackMapFrame::is_assignable_to(const StackMapFrame* target, TRAPS) const { 211 bool StackMapFrame::is_assignable_to(const StackMapFrame* target, TRAPS) const {
174 if (_max_locals != target->max_locals() || _stack_size != target->stack_size()) { 212 if (_max_locals != target->max_locals() || _stack_size != target->stack_size()) {
175 return false; 213 return false;
176 } 214 }
177 // Only need to compare type elements up to target->locals() or target->stack(). 215 // Only need to compare type elements up to target->locals() or target->stack().
180 bool match_locals = is_assignable_to( 218 bool match_locals = is_assignable_to(
181 _locals, target->locals(), target->locals_size(), CHECK_false); 219 _locals, target->locals(), target->locals_size(), CHECK_false);
182 bool match_stack = is_assignable_to( 220 bool match_stack = is_assignable_to(
183 _stack, target->stack(), _stack_size, CHECK_false); 221 _stack, target->stack(), _stack_size, CHECK_false);
184 bool match_flags = (_flags | target->flags()) == target->flags(); 222 bool match_flags = (_flags | target->flags()) == target->flags();
185 return (match_locals && match_stack && match_flags); 223
224 return match_locals && match_stack &&
225 (match_flags || has_flag_match_exception(target));
186 } 226 }
187 227
188 VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) { 228 VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) {
189 if (_stack_size <= 0) { 229 if (_stack_size <= 0) {
190 verifier()->verify_error(_offset, "Operand stack underflow"); 230 verifier()->verify_error(_offset, "Operand stack underflow");