Mercurial > hg > truffle
comparison src/share/vm/classfile/stackMapFrame.cpp @ 6646:c38f13903fdf
Merge with http://hg.openjdk.java.net/hsx/hsx25/hotspot/ just before the NPG (no perm gen) changeset
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 29 Oct 2012 21:10:04 +0100 |
parents | 4ee06e614636 |
children | 2373a1f4987c b2daaf70fab2 |
comparison
equal
deleted
inserted
replaced
6590:dc5eec61daba | 6646:c38f13903fdf |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
30 #include "oops/symbol.hpp" | 30 #include "oops/symbol.hpp" |
31 #include "runtime/handles.inline.hpp" | 31 #include "runtime/handles.inline.hpp" |
32 #include "utilities/globalDefinitions.hpp" | 32 #include "utilities/globalDefinitions.hpp" |
33 | 33 |
34 StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* v) : | 34 StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* v) : |
35 _offset(0), _locals_size(0), _stack_size(0), _flags(0), | 35 _offset(0), _locals_size(0), _stack_size(0), |
36 _max_locals(max_locals), _max_stack(max_stack), | 36 _stack_mark(0), _flags(0), _max_locals(max_locals), |
37 _verifier(v) { | 37 _max_stack(max_stack), _verifier(v) { |
38 Thread* thr = v->thread(); | 38 Thread* thr = v->thread(); |
39 _locals = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_locals); | 39 _locals = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_locals); |
40 _stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_stack); | 40 _stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_stack); |
41 int32_t i; | 41 int32_t i; |
42 for(i = 0; i < max_locals; i++) { | 42 for(i = 0; i < max_locals; i++) { |
155 for (int32_t i = 0; i < len; i++) { | 155 for (int32_t i = 0; i < len; i++) { |
156 _stack[i] = src->stack()[i]; | 156 _stack[i] = src->stack()[i]; |
157 } | 157 } |
158 } | 158 } |
159 | 159 |
160 | 160 // Returns the location of the first mismatch, or 'len' if there are no |
161 bool StackMapFrame::is_assignable_to( | 161 // mismatches |
162 int StackMapFrame::is_assignable_to( | |
162 VerificationType* from, VerificationType* to, int32_t len, TRAPS) const { | 163 VerificationType* from, VerificationType* to, int32_t len, TRAPS) const { |
163 for (int32_t i = 0; i < len; i++) { | 164 int32_t i = 0; |
164 bool subtype = to[i].is_assignable_from( | 165 for (i = 0; i < len; i++) { |
165 from[i], verifier(), THREAD); | 166 if (!to[i].is_assignable_from(from[i], verifier(), THREAD)) { |
166 if (!subtype) { | 167 break; |
167 return false; | 168 } |
168 } | 169 } |
169 } | 170 return i; |
170 return true; | |
171 } | 171 } |
172 | 172 |
173 bool StackMapFrame::has_flag_match_exception( | 173 bool StackMapFrame::has_flag_match_exception( |
174 const StackMapFrame* target) const { | 174 const StackMapFrame* target) const { |
175 // We allow flags of {UninitThis} to assign to {} if-and-only-if the | 175 // We allow flags of {UninitThis} to assign to {} if-and-only-if the |
207 | 207 |
208 return true; | 208 return true; |
209 } | 209 } |
210 | 210 |
211 bool StackMapFrame::is_assignable_to( | 211 bool StackMapFrame::is_assignable_to( |
212 const StackMapFrame* target, bool is_exception_handler, TRAPS) const { | 212 const StackMapFrame* target, bool is_exception_handler, |
213 if (_max_locals != target->max_locals() || | 213 ErrorContext* ctx, TRAPS) const { |
214 _stack_size != target->stack_size()) { | 214 if (_max_locals != target->max_locals()) { |
215 *ctx = ErrorContext::locals_size_mismatch( | |
216 _offset, (StackMapFrame*)this, (StackMapFrame*)target); | |
217 return false; | |
218 } | |
219 if (_stack_size != target->stack_size()) { | |
220 *ctx = ErrorContext::stack_size_mismatch( | |
221 _offset, (StackMapFrame*)this, (StackMapFrame*)target); | |
215 return false; | 222 return false; |
216 } | 223 } |
217 // Only need to compare type elements up to target->locals() or target->stack(). | 224 // Only need to compare type elements up to target->locals() or target->stack(). |
218 // The remaining type elements in this state can be ignored because they are | 225 // The remaining type elements in this state can be ignored because they are |
219 // assignable to bogus type. | 226 // assignable to bogus type. |
220 bool match_locals = is_assignable_to( | 227 int mismatch_loc; |
221 _locals, target->locals(), target->locals_size(), CHECK_false); | 228 mismatch_loc = is_assignable_to( |
222 bool match_stack = is_assignable_to( | 229 _locals, target->locals(), target->locals_size(), THREAD); |
223 _stack, target->stack(), _stack_size, CHECK_false); | 230 if (mismatch_loc != target->locals_size()) { |
231 *ctx = ErrorContext::bad_type(target->offset(), | |
232 TypeOrigin::local(mismatch_loc, (StackMapFrame*)this), | |
233 TypeOrigin::sm_local(mismatch_loc, (StackMapFrame*)target)); | |
234 return false; | |
235 } | |
236 mismatch_loc = is_assignable_to(_stack, target->stack(), _stack_size, THREAD); | |
237 if (mismatch_loc != _stack_size) { | |
238 *ctx = ErrorContext::bad_type(target->offset(), | |
239 TypeOrigin::stack(mismatch_loc, (StackMapFrame*)this), | |
240 TypeOrigin::sm_stack(mismatch_loc, (StackMapFrame*)target)); | |
241 return false; | |
242 } | |
243 | |
224 bool match_flags = (_flags | target->flags()) == target->flags(); | 244 bool match_flags = (_flags | target->flags()) == target->flags(); |
225 | 245 if (match_flags || is_exception_handler && has_flag_match_exception(target)) { |
226 return match_locals && match_stack && | 246 return true; |
227 (match_flags || (is_exception_handler && has_flag_match_exception(target))); | 247 } else { |
248 *ctx = ErrorContext::bad_flags(target->offset(), | |
249 (StackMapFrame*)this, (StackMapFrame*)target); | |
250 return false; | |
251 } | |
228 } | 252 } |
229 | 253 |
230 VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) { | 254 VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) { |
231 if (_stack_size <= 0) { | 255 if (_stack_size <= 0) { |
232 verifier()->verify_error(_offset, "Operand stack underflow"); | 256 verifier()->verify_error( |
257 ErrorContext::stack_underflow(_offset, this), | |
258 "Operand stack underflow"); | |
233 return VerificationType::bogus_type(); | 259 return VerificationType::bogus_type(); |
234 } | 260 } |
235 VerificationType top = _stack[--_stack_size]; | 261 VerificationType top = _stack[--_stack_size]; |
236 bool subtype = type.is_assignable_from( | 262 bool subtype = type.is_assignable_from( |
237 top, verifier(), CHECK_(VerificationType::bogus_type())); | 263 top, verifier(), CHECK_(VerificationType::bogus_type())); |
238 if (!subtype) { | 264 if (!subtype) { |
239 verifier()->verify_error(_offset, "Bad type on operand stack"); | 265 verifier()->verify_error( |
266 ErrorContext::bad_type(_offset, stack_top_ctx(), | |
267 TypeOrigin::implicit(type)), | |
268 "Bad type on operand stack"); | |
240 return VerificationType::bogus_type(); | 269 return VerificationType::bogus_type(); |
241 } | 270 } |
242 NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); ) | |
243 return top; | 271 return top; |
244 } | 272 } |
245 | 273 |
246 VerificationType StackMapFrame::get_local( | 274 VerificationType StackMapFrame::get_local( |
247 int32_t index, VerificationType type, TRAPS) { | 275 int32_t index, VerificationType type, TRAPS) { |
248 if (index >= _max_locals) { | 276 if (index >= _max_locals) { |
249 verifier()->verify_error(_offset, "Local variable table overflow"); | 277 verifier()->verify_error( |
278 ErrorContext::bad_local_index(_offset, index), | |
279 "Local variable table overflow"); | |
250 return VerificationType::bogus_type(); | 280 return VerificationType::bogus_type(); |
251 } | 281 } |
252 bool subtype = type.is_assignable_from(_locals[index], | 282 bool subtype = type.is_assignable_from(_locals[index], |
253 verifier(), CHECK_(VerificationType::bogus_type())); | 283 verifier(), CHECK_(VerificationType::bogus_type())); |
254 if (!subtype) { | 284 if (!subtype) { |
255 verifier()->verify_error(_offset, "Bad local variable type"); | 285 verifier()->verify_error( |
286 ErrorContext::bad_type(_offset, | |
287 TypeOrigin::local(index, this), | |
288 TypeOrigin::implicit(type)), | |
289 "Bad local variable type"); | |
256 return VerificationType::bogus_type(); | 290 return VerificationType::bogus_type(); |
257 } | 291 } |
258 if(index >= _locals_size) { _locals_size = index + 1; } | 292 if(index >= _locals_size) { _locals_size = index + 1; } |
259 return _locals[index]; | 293 return _locals[index]; |
260 } | 294 } |
262 void StackMapFrame::get_local_2( | 296 void StackMapFrame::get_local_2( |
263 int32_t index, VerificationType type1, VerificationType type2, TRAPS) { | 297 int32_t index, VerificationType type1, VerificationType type2, TRAPS) { |
264 assert(type1.is_long() || type1.is_double(), "must be long/double"); | 298 assert(type1.is_long() || type1.is_double(), "must be long/double"); |
265 assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); | 299 assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); |
266 if (index >= _locals_size - 1) { | 300 if (index >= _locals_size - 1) { |
267 verifier()->verify_error(_offset, "get long/double overflows locals"); | 301 verifier()->verify_error( |
302 ErrorContext::bad_local_index(_offset, index), | |
303 "get long/double overflows locals"); | |
268 return; | 304 return; |
269 } | 305 } |
270 bool subtype1 = type1.is_assignable_from( | 306 bool subtype = type1.is_assignable_from(_locals[index], verifier(), CHECK); |
271 _locals[index], verifier(), CHECK); | 307 if (!subtype) { |
272 bool subtype2 = type2.is_assignable_from( | 308 verifier()->verify_error( |
273 _locals[index+1], verifier(), CHECK); | 309 ErrorContext::bad_type(_offset, |
274 if (!subtype1 || !subtype2) { | 310 TypeOrigin::local(index, this), TypeOrigin::implicit(type1)), |
275 verifier()->verify_error(_offset, "Bad local variable type"); | 311 "Bad local variable type"); |
276 return; | 312 } else { |
313 subtype = type2.is_assignable_from(_locals[index + 1], verifier(), CHECK); | |
314 if (!subtype) { | |
315 /* Unreachable? All local store routines convert a split long or double | |
316 * into a TOP during the store. So we should never end up seeing an | |
317 * orphaned half. */ | |
318 verifier()->verify_error( | |
319 ErrorContext::bad_type(_offset, | |
320 TypeOrigin::local(index + 1, this), TypeOrigin::implicit(type2)), | |
321 "Bad local variable type"); | |
322 } | |
277 } | 323 } |
278 } | 324 } |
279 | 325 |
280 void StackMapFrame::set_local(int32_t index, VerificationType type, TRAPS) { | 326 void StackMapFrame::set_local(int32_t index, VerificationType type, TRAPS) { |
281 assert(!type.is_check(), "Must be a real type"); | 327 assert(!type.is_check(), "Must be a real type"); |
282 if (index >= _max_locals) { | 328 if (index >= _max_locals) { |
283 verifier()->verify_error("Local variable table overflow", _offset); | 329 verifier()->verify_error( |
330 ErrorContext::bad_local_index(_offset, index), | |
331 "Local variable table overflow"); | |
284 return; | 332 return; |
285 } | 333 } |
286 // If type at index is double or long, set the next location to be unusable | 334 // If type at index is double or long, set the next location to be unusable |
287 if (_locals[index].is_double() || _locals[index].is_long()) { | 335 if (_locals[index].is_double() || _locals[index].is_long()) { |
288 assert((index + 1) < _locals_size, "Local variable table overflow"); | 336 assert((index + 1) < _locals_size, "Local variable table overflow"); |
308 void StackMapFrame::set_local_2( | 356 void StackMapFrame::set_local_2( |
309 int32_t index, VerificationType type1, VerificationType type2, TRAPS) { | 357 int32_t index, VerificationType type1, VerificationType type2, TRAPS) { |
310 assert(type1.is_long() || type1.is_double(), "must be long/double"); | 358 assert(type1.is_long() || type1.is_double(), "must be long/double"); |
311 assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); | 359 assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); |
312 if (index >= _max_locals - 1) { | 360 if (index >= _max_locals - 1) { |
313 verifier()->verify_error("Local variable table overflow", _offset); | 361 verifier()->verify_error( |
362 ErrorContext::bad_local_index(_offset, index), | |
363 "Local variable table overflow"); | |
314 return; | 364 return; |
315 } | 365 } |
316 // If type at index+1 is double or long, set the next location to be unusable | 366 // If type at index+1 is double or long, set the next location to be unusable |
317 if (_locals[index+1].is_double() || _locals[index+1].is_long()) { | 367 if (_locals[index+1].is_double() || _locals[index+1].is_long()) { |
318 assert((index + 2) < _locals_size, "Local variable table overflow"); | 368 assert((index + 2) < _locals_size, "Local variable table overflow"); |
334 #endif | 384 #endif |
335 _locals_size = index + 2; | 385 _locals_size = index + 2; |
336 } | 386 } |
337 } | 387 } |
338 | 388 |
339 #ifndef PRODUCT | 389 TypeOrigin StackMapFrame::stack_top_ctx() { |
340 | 390 return TypeOrigin::stack(_stack_size, this); |
341 void StackMapFrame::print() const { | 391 } |
342 tty->print_cr("stackmap_frame[%d]:", _offset); | 392 |
343 tty->print_cr("flags = 0x%x", _flags); | 393 void StackMapFrame::print_on(outputStream* str) const { |
344 tty->print("locals[%d] = { ", _locals_size); | 394 str->indent().print_cr("bci: @%d", _offset); |
345 for (int32_t i = 0; i < _locals_size; i++) { | 395 str->indent().print_cr("flags: {%s }", |
346 _locals[i].print_on(tty); | 396 flag_this_uninit() ? " flagThisUninit" : ""); |
347 } | 397 str->indent().print("locals: {"); |
348 tty->print_cr(" }"); | 398 for (int32_t i = 0; i < _locals_size; ++i) { |
349 tty->print("stack[%d] = { ", _stack_size); | 399 str->print(" "); |
350 for (int32_t j = 0; j < _stack_size; j++) { | 400 _locals[i].print_on(str); |
351 _stack[j].print_on(tty); | 401 if (i != _locals_size - 1) { |
352 } | 402 str->print(","); |
353 tty->print_cr(" }"); | 403 } |
354 } | 404 } |
355 | 405 str->print_cr(" }"); |
356 #endif | 406 str->indent().print("stack: {"); |
407 for (int32_t j = 0; j < _stack_size; ++j) { | |
408 str->print(" "); | |
409 _stack[j].print_on(str); | |
410 if (j != _stack_size - 1) { | |
411 str->print(","); | |
412 } | |
413 } | |
414 str->print_cr(" }"); | |
415 } |