Mercurial > hg > truffle
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"); |