Mercurial > hg > graal-compiler
comparison src/share/vm/interpreter/rewriter.cpp @ 13390:d61a1a166f44
8028347: Rewriter::scan_method asserts with array oob in RT_Baseline
Summary: Fix reversing rewriting for invokespecial
Reviewed-by: jrose, hseigel
author | coleenp |
---|---|
date | Fri, 15 Nov 2013 17:20:22 -0500 |
parents | 41cb10cbfb3c |
children | 02f27ecb4f3a 26c3b944dc35 |
comparison
equal
deleted
inserted
replaced
13389:438fe38c63c8 | 13390:d61a1a166f44 |
---|---|
68 if (saw_mh_symbol) | 68 if (saw_mh_symbol) |
69 _method_handle_invokers.initialize(length, (int)0); | 69 _method_handle_invokers.initialize(length, (int)0); |
70 } | 70 } |
71 | 71 |
72 // Unrewrite the bytecodes if an error occurs. | 72 // Unrewrite the bytecodes if an error occurs. |
73 void Rewriter::restore_bytecodes(TRAPS) { | 73 void Rewriter::restore_bytecodes() { |
74 int len = _methods->length(); | 74 int len = _methods->length(); |
75 bool invokespecial_error = false; | |
75 | 76 |
76 for (int i = len-1; i >= 0; i--) { | 77 for (int i = len-1; i >= 0; i--) { |
77 Method* method = _methods->at(i); | 78 Method* method = _methods->at(i); |
78 scan_method(method, true, CHECK); | 79 scan_method(method, true, &invokespecial_error); |
80 assert(!invokespecial_error, "reversing should not get an invokespecial error"); | |
79 } | 81 } |
80 } | 82 } |
81 | 83 |
82 // Creates a constant pool cache given a CPC map | 84 // Creates a constant pool cache given a CPC map |
83 void Rewriter::make_constant_pool_cache(TRAPS) { | 85 void Rewriter::make_constant_pool_cache(TRAPS) { |
158 // we need to add a separate cpCache entry for its resolution, because it is | 160 // we need to add a separate cpCache entry for its resolution, because it is |
159 // different than the resolution for invokeinterface with InterfaceMethodref. | 161 // different than the resolution for invokeinterface with InterfaceMethodref. |
160 // These cannot share cpCache entries. It's unclear if all invokespecial to | 162 // These cannot share cpCache entries. It's unclear if all invokespecial to |
161 // InterfaceMethodrefs would resolve to the same thing so a new cpCache entry | 163 // InterfaceMethodrefs would resolve to the same thing so a new cpCache entry |
162 // is created for each one. This was added with lambda. | 164 // is created for each one. This was added with lambda. |
163 void Rewriter::rewrite_invokespecial(address bcp, int offset, bool reverse, TRAPS) { | 165 void Rewriter::rewrite_invokespecial(address bcp, int offset, bool reverse, bool* invokespecial_error) { |
164 static int count = 0; | |
165 address p = bcp + offset; | 166 address p = bcp + offset; |
166 if (!reverse) { | 167 if (!reverse) { |
167 int cp_index = Bytes::get_Java_u2(p); | 168 int cp_index = Bytes::get_Java_u2(p); |
169 if (_pool->tag_at(cp_index).is_interface_method()) { | |
168 int cache_index = add_invokespecial_cp_cache_entry(cp_index); | 170 int cache_index = add_invokespecial_cp_cache_entry(cp_index); |
169 if (cache_index != (int)(jushort) cache_index) { | 171 if (cache_index != (int)(jushort) cache_index) { |
170 THROW_MSG(vmSymbols::java_lang_InternalError(), | 172 *invokespecial_error = true; |
171 "This classfile overflows invokespecial for interfaces " | |
172 "and cannot be loaded"); | |
173 } | 173 } |
174 Bytes::put_native_u2(p, cache_index); | 174 Bytes::put_native_u2(p, cache_index); |
175 } else { | 175 } else { |
176 int cache_index = Bytes::get_native_u2(p); | 176 rewrite_member_reference(bcp, offset, reverse); |
177 int cp_index = cp_cache_entry_pool_index(cache_index); | 177 } |
178 Bytes::put_Java_u2(p, cp_index); | 178 } else { |
179 rewrite_member_reference(bcp, offset, reverse); | |
179 } | 180 } |
180 } | 181 } |
181 | 182 |
182 | 183 |
183 // Adjust the invocation bytecode for a signature-polymorphic method (MethodHandle.invoke, etc.) | 184 // Adjust the invocation bytecode for a signature-polymorphic method (MethodHandle.invoke, etc.) |
327 } | 328 } |
328 } | 329 } |
329 | 330 |
330 | 331 |
331 // Rewrites a method given the index_map information | 332 // Rewrites a method given the index_map information |
332 void Rewriter::scan_method(Method* method, bool reverse, TRAPS) { | 333 void Rewriter::scan_method(Method* method, bool reverse, bool* invokespecial_error) { |
333 | 334 |
334 int nof_jsrs = 0; | 335 int nof_jsrs = 0; |
335 bool has_monitor_bytecodes = false; | 336 bool has_monitor_bytecodes = false; |
336 | 337 |
337 { | 338 { |
389 #endif | 390 #endif |
390 break; | 391 break; |
391 } | 392 } |
392 | 393 |
393 case Bytecodes::_invokespecial : { | 394 case Bytecodes::_invokespecial : { |
394 int offset = prefix_length + 1; | 395 rewrite_invokespecial(bcp, prefix_length+1, reverse, invokespecial_error); |
395 address p = bcp + offset; | |
396 int cp_index = Bytes::get_Java_u2(p); | |
397 // InterfaceMethodref | |
398 if (_pool->tag_at(cp_index).is_interface_method()) { | |
399 rewrite_invokespecial(bcp, offset, reverse, CHECK); | |
400 } else { | |
401 rewrite_member_reference(bcp, offset, reverse); | |
402 } | |
403 break; | 396 break; |
404 } | 397 } |
405 | 398 |
406 case Bytecodes::_getstatic : // fall through | 399 case Bytecodes::_getstatic : // fall through |
407 case Bytecodes::_putstatic : // fall through | 400 case Bytecodes::_putstatic : // fall through |
494 assert(did_rewrite, "must find Object::<init> to rewrite it"); | 487 assert(did_rewrite, "must find Object::<init> to rewrite it"); |
495 } | 488 } |
496 | 489 |
497 // rewrite methods, in two passes | 490 // rewrite methods, in two passes |
498 int len = _methods->length(); | 491 int len = _methods->length(); |
492 bool invokespecial_error = false; | |
499 | 493 |
500 for (int i = len-1; i >= 0; i--) { | 494 for (int i = len-1; i >= 0; i--) { |
501 Method* method = _methods->at(i); | 495 Method* method = _methods->at(i); |
502 scan_method(method, false, CHECK); // If you get an error here, | 496 scan_method(method, false, &invokespecial_error); |
503 // there is no reversing bytecodes | 497 if (invokespecial_error) { |
498 // If you get an error here, there is no reversing bytecodes | |
499 // This exception is stored for this class and no further attempt is | |
500 // made at verifying or rewriting. | |
501 THROW_MSG(vmSymbols::java_lang_InternalError(), | |
502 "This classfile overflows invokespecial for interfaces " | |
503 "and cannot be loaded"); | |
504 return; | |
505 } | |
504 } | 506 } |
505 | 507 |
506 // May have to fix invokedynamic bytecodes if invokestatic/InterfaceMethodref | 508 // May have to fix invokedynamic bytecodes if invokestatic/InterfaceMethodref |
507 // entries had to be added. | 509 // entries had to be added. |
508 patch_invokedynamic_bytecodes(); | 510 patch_invokedynamic_bytecodes(); |
511 make_constant_pool_cache(THREAD); | 513 make_constant_pool_cache(THREAD); |
512 | 514 |
513 // Restore bytecodes to their unrewritten state if there are exceptions | 515 // Restore bytecodes to their unrewritten state if there are exceptions |
514 // rewriting bytecodes or allocating the cpCache | 516 // rewriting bytecodes or allocating the cpCache |
515 if (HAS_PENDING_EXCEPTION) { | 517 if (HAS_PENDING_EXCEPTION) { |
516 restore_bytecodes(CATCH); | 518 restore_bytecodes(); |
517 return; | 519 return; |
518 } | 520 } |
519 | 521 |
520 // Relocate after everything, but still do this under the is_rewritten flag, | 522 // Relocate after everything, but still do this under the is_rewritten flag, |
521 // so methods with jsrs in custom class lists in aren't attempted to be | 523 // so methods with jsrs in custom class lists in aren't attempted to be |
528 m = rewrite_jsrs(m, THREAD); | 530 m = rewrite_jsrs(m, THREAD); |
529 // Restore bytecodes to their unrewritten state if there are exceptions | 531 // Restore bytecodes to their unrewritten state if there are exceptions |
530 // relocating bytecodes. If some are relocated, that is ok because that | 532 // relocating bytecodes. If some are relocated, that is ok because that |
531 // doesn't affect constant pool to cpCache rewriting. | 533 // doesn't affect constant pool to cpCache rewriting. |
532 if (HAS_PENDING_EXCEPTION) { | 534 if (HAS_PENDING_EXCEPTION) { |
533 restore_bytecodes(CATCH); | 535 restore_bytecodes(); |
534 return; | 536 return; |
535 } | 537 } |
536 // Method might have gotten rewritten. | 538 // Method might have gotten rewritten. |
537 methods->at_put(i, m()); | 539 methods->at_put(i, m()); |
538 } | 540 } |