Mercurial > hg > graal-jvmci-8
comparison src/share/vm/runtime/relocator.cpp @ 1877:a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
Summary: Repair stackmap table attribute when relocating bytecode
Reviewed-by: acorn, never
author | kamg |
---|---|
date | Thu, 21 Oct 2010 10:10:23 -0400 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
comparison
equal
deleted
inserted
replaced
1874:75ab0162aa84 | 1877:a4c7fe54bf3f |
---|---|
433 } | 433 } |
434 } | 434 } |
435 } | 435 } |
436 } | 436 } |
437 | 437 |
438 // Create a new array, copying the src array but adding a hole at | |
439 // the specified location | |
440 static typeArrayOop insert_hole_at( | |
441 size_t where, int hole_sz, typeArrayOop src) { | |
442 Thread* THREAD = Thread::current(); | |
443 Handle src_hnd(THREAD, src); | |
444 typeArrayOop dst = | |
445 oopFactory::new_permanent_byteArray(src->length() + hole_sz, CHECK_NULL); | |
446 src = (typeArrayOop)src_hnd(); | |
447 | |
448 address src_addr = (address)src->byte_at_addr(0); | |
449 address dst_addr = (address)dst->byte_at_addr(0); | |
450 | |
451 memcpy(dst_addr, src_addr, where); | |
452 memcpy(dst_addr + where + hole_sz, | |
453 src_addr + where, src->length() - where); | |
454 return dst; | |
455 } | |
456 | |
457 // The width of instruction at "bci" is changing by "delta". Adjust the stack | |
458 // map frames. | |
459 void Relocator::adjust_stack_map_table(int bci, int delta) { | |
460 if (method()->has_stackmap_table()) { | |
461 typeArrayOop data = method()->stackmap_data(); | |
462 // The data in the array is a classfile representation of the stackmap | |
463 // table attribute, less the initial u2 tag and u4 attribute_length fields. | |
464 stack_map_table_attribute* attr = stack_map_table_attribute::at( | |
465 (address)data->byte_at_addr(0) - (sizeof(u2) + sizeof(u4))); | |
466 | |
467 int count = attr->number_of_entries(); | |
468 stack_map_frame* frame = attr->entries(); | |
469 int bci_iter = -1; | |
470 bool offset_adjusted = false; // only need to adjust one offset | |
471 | |
472 for (int i = 0; i < count; ++i) { | |
473 int offset_delta = frame->offset_delta(); | |
474 bci_iter += offset_delta; | |
475 | |
476 if (!offset_adjusted && bci_iter > bci) { | |
477 int new_offset_delta = offset_delta + delta; | |
478 | |
479 if (frame->is_valid_offset(new_offset_delta)) { | |
480 frame->set_offset_delta(new_offset_delta); | |
481 } else { | |
482 assert(frame->is_same_frame() || | |
483 frame->is_same_frame_1_stack_item_frame(), | |
484 "Frame must be one of the compressed forms"); | |
485 // The new delta exceeds the capacity of the 'same_frame' or | |
486 // 'same_frame_1_stack_item_frame' frame types. We need to | |
487 // convert these frames to the extended versions, but the extended | |
488 // version is bigger and requires more room. So we allocate a | |
489 // new array and copy the data, being sure to leave u2-sized hole | |
490 // right after the 'frame_type' for the new offset field. | |
491 // | |
492 // We can safely ignore the reverse situation as a small delta | |
493 // can still be used in an extended version of the frame. | |
494 | |
495 size_t frame_offset = (address)frame - (address)data->byte_at_addr(0); | |
496 | |
497 data = insert_hole_at(frame_offset + 1, 2, data); | |
498 if (data == NULL) { | |
499 return; // out-of-memory? | |
500 } | |
501 | |
502 address frame_addr = (address)(data->byte_at_addr(0) + frame_offset); | |
503 frame = stack_map_frame::at(frame_addr); | |
504 | |
505 | |
506 // Now convert the frames in place | |
507 if (frame->is_same_frame()) { | |
508 same_frame_extended::create_at(frame_addr, new_offset_delta); | |
509 } else { | |
510 same_frame_1_stack_item_extended::create_at( | |
511 frame_addr, new_offset_delta, NULL); | |
512 // the verification_info_type should already be at the right spot | |
513 } | |
514 } | |
515 offset_adjusted = true; // needs to be done only once, since subsequent | |
516 // values are offsets from the current | |
517 } | |
518 | |
519 // The stack map frame may contain verification types, if so we need to | |
520 // check and update any Uninitialized type's bci (no matter where it is). | |
521 int number_of_types = frame->number_of_types(); | |
522 verification_type_info* types = frame->types(); | |
523 | |
524 for (int i = 0; i < number_of_types; ++i) { | |
525 if (types->is_uninitialized() && types->bci() > bci) { | |
526 types->set_bci(types->bci() + delta); | |
527 } | |
528 types = types->next(); | |
529 } | |
530 | |
531 // Full frame has stack values too | |
532 full_frame* ff = frame->as_full_frame(); | |
533 if (ff != NULL) { | |
534 address eol = (address)types; | |
535 number_of_types = ff->stack_slots(eol); | |
536 types = ff->stack(eol); | |
537 for (int i = 0; i < number_of_types; ++i) { | |
538 if (types->is_uninitialized() && types->bci() > bci) { | |
539 types->set_bci(types->bci() + delta); | |
540 } | |
541 types = types->next(); | |
542 } | |
543 } | |
544 | |
545 frame = frame->next(); | |
546 } | |
547 | |
548 method()->set_stackmap_data(data); // in case it has changed | |
549 } | |
550 } | |
551 | |
438 | 552 |
439 bool Relocator::expand_code_array(int delta) { | 553 bool Relocator::expand_code_array(int delta) { |
440 int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100); | 554 int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100); |
441 | 555 |
442 if (length > MAX_METHOD_LENGTH) { | 556 if (length > MAX_METHOD_LENGTH) { |
496 adjust_exception_table(bci, delta); | 610 adjust_exception_table(bci, delta); |
497 // Line number tables... | 611 // Line number tables... |
498 adjust_line_no_table(bci, delta); | 612 adjust_line_no_table(bci, delta); |
499 // And local variable table... | 613 // And local variable table... |
500 adjust_local_var_table(bci, delta); | 614 adjust_local_var_table(bci, delta); |
615 | |
616 // Adjust stack maps | |
617 adjust_stack_map_table(bci, delta); | |
501 | 618 |
502 // Relocate the pending change stack... | 619 // Relocate the pending change stack... |
503 for (int j = 0; j < _changes->length(); j++) { | 620 for (int j = 0; j < _changes->length(); j++) { |
504 ChangeItem* ci = _changes->at(j); | 621 ChangeItem* ci = _changes->at(j); |
505 ci->relocate(bci, delta); | 622 ci->relocate(bci, delta); |
639 assert(pad_delta > 0, "check"); | 756 assert(pad_delta > 0, "check"); |
640 // Move the expanded instruction up. | 757 // Move the expanded instruction up. |
641 memmove(addr_at(bci +1 + new_pad), | 758 memmove(addr_at(bci +1 + new_pad), |
642 addr_at(bci +1 + old_pad), | 759 addr_at(bci +1 + old_pad), |
643 len * 4); | 760 len * 4); |
761 memset(addr_at(bci + 1), 0, new_pad); // pad must be 0 | |
644 } | 762 } |
645 } | 763 } |
646 return true; | 764 return true; |
647 } | 765 } |