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"); |