|
77 | 77 | #include "memory/universe.hpp" |
78 | 78 | #include "nmt/memTracker.hpp" |
79 | 79 | #include "oops/compressedKlass.hpp" |
| 80 | +#include "oops/constantPool.inline.hpp" |
80 | 81 | #include "oops/instanceMirrorKlass.hpp" |
81 | 82 | #include "oops/klass.inline.hpp" |
82 | 83 | #include "oops/objArrayOop.hpp" |
83 | 84 | #include "oops/oop.inline.hpp" |
84 | 85 | #include "oops/oopHandle.hpp" |
| 86 | +#include "oops/resolvedFieldEntry.hpp" |
85 | 87 | #include "oops/trainingData.hpp" |
86 | 88 | #include "prims/jvmtiExport.hpp" |
87 | 89 | #include "runtime/arguments.hpp" |
@@ -519,33 +521,114 @@ void AOTMetaspace::serialize(SerializeClosure* soc) { |
519 | 521 | soc->do_tag(666); |
520 | 522 | } |
521 | 523 |
|
522 | | -static void rewrite_nofast_bytecode(const methodHandle& method) { |
| 524 | +// In AOTCache workflow, when dumping preimage, the constant pool entries are stored in unresolved state. |
| 525 | +// So the fast version of getfield/putfield needs to be converted to nofast version. |
| 526 | +// When dumping the final image in the assembly phase, these nofast versions are converted back to fast versions |
| 527 | +// if the constant pool entry refered by these bytecodes is stored in resolved state. |
| 528 | +// Same principle applies to static and dynamic archives. If the constant pool entry is in resolved state, then |
| 529 | +// the fast version of the bytecodes can be preserved, else use the nofast version. |
| 530 | +// |
| 531 | +// The fast versions of aload_0 (i.e. _fast_Xaccess_0) merges the bytecode pair (aload_0, fast_Xgetfield). |
| 532 | +// If the fast version of aload_0 is preserved in AOTCache, then the JVMTI notifications for field access and |
| 533 | +// breakpoint events will be skipped for the second bytecode (fast_Xgetfield) in the pair. |
| 534 | +// Same holds for fast versions of iload_0. So for these bytecodes, nofast version is used. |
| 535 | +static void rewrite_bytecodes(const methodHandle& method) { |
| 536 | + ConstantPool* cp = method->constants(); |
523 | 537 | BytecodeStream bcs(method); |
| 538 | + Bytecodes::Code new_code; |
| 539 | + |
| 540 | + LogStreamHandle(Trace, aot, resolve) lsh; |
| 541 | + if (lsh.is_enabled()) { |
| 542 | + lsh.print("Rewriting bytecodes for "); |
| 543 | + method()->print_external_name(&lsh); |
| 544 | + lsh.print("\n"); |
| 545 | + } |
| 546 | + |
524 | 547 | while (!bcs.is_last_bytecode()) { |
525 | 548 | Bytecodes::Code opcode = bcs.next(); |
526 | | - switch (opcode) { |
527 | | - case Bytecodes::_getfield: *bcs.bcp() = Bytecodes::_nofast_getfield; break; |
528 | | - case Bytecodes::_putfield: *bcs.bcp() = Bytecodes::_nofast_putfield; break; |
529 | | - case Bytecodes::_aload_0: *bcs.bcp() = Bytecodes::_nofast_aload_0; break; |
530 | | - case Bytecodes::_iload: { |
| 549 | + // Use current opcode as the default value of new_code |
| 550 | + new_code = opcode; |
| 551 | + switch(opcode) { |
| 552 | + case Bytecodes::_getfield: { |
| 553 | + uint rfe_index = bcs.get_index_u2(); |
| 554 | + bool is_resolved = cp->is_resolved(rfe_index, opcode); |
| 555 | + if (is_resolved) { |
| 556 | + assert(!CDSConfig::is_dumping_preimage_static_archive(), "preimage should not have resolved field references"); |
| 557 | + ResolvedFieldEntry* rfe = cp->resolved_field_entry_at(bcs.get_index_u2()); |
| 558 | + switch(rfe->tos_state()) { |
| 559 | + case btos: |
| 560 | + // fallthrough |
| 561 | + case ztos: new_code = Bytecodes::_fast_bgetfield; break; |
| 562 | + case atos: new_code = Bytecodes::_fast_agetfield; break; |
| 563 | + case itos: new_code = Bytecodes::_fast_igetfield; break; |
| 564 | + case ctos: new_code = Bytecodes::_fast_cgetfield; break; |
| 565 | + case stos: new_code = Bytecodes::_fast_sgetfield; break; |
| 566 | + case ltos: new_code = Bytecodes::_fast_lgetfield; break; |
| 567 | + case ftos: new_code = Bytecodes::_fast_fgetfield; break; |
| 568 | + case dtos: new_code = Bytecodes::_fast_dgetfield; break; |
| 569 | + default: |
| 570 | + ShouldNotReachHere(); |
| 571 | + break; |
| 572 | + } |
| 573 | + } else { |
| 574 | + new_code = Bytecodes::_nofast_getfield; |
| 575 | + } |
| 576 | + break; |
| 577 | + } |
| 578 | + case Bytecodes::_putfield: { |
| 579 | + uint rfe_index = bcs.get_index_u2(); |
| 580 | + bool is_resolved = cp->is_resolved(rfe_index, opcode); |
| 581 | + if (is_resolved) { |
| 582 | + assert(!CDSConfig::is_dumping_preimage_static_archive(), "preimage should not have resolved field references"); |
| 583 | + ResolvedFieldEntry* rfe = cp->resolved_field_entry_at(bcs.get_index_u2()); |
| 584 | + switch(rfe->tos_state()) { |
| 585 | + case btos: new_code = Bytecodes::_fast_bputfield; break; |
| 586 | + case ztos: new_code = Bytecodes::_fast_zputfield; break; |
| 587 | + case atos: new_code = Bytecodes::_fast_aputfield; break; |
| 588 | + case itos: new_code = Bytecodes::_fast_iputfield; break; |
| 589 | + case ctos: new_code = Bytecodes::_fast_cputfield; break; |
| 590 | + case stos: new_code = Bytecodes::_fast_sputfield; break; |
| 591 | + case ltos: new_code = Bytecodes::_fast_lputfield; break; |
| 592 | + case ftos: new_code = Bytecodes::_fast_fputfield; break; |
| 593 | + case dtos: new_code = Bytecodes::_fast_dputfield; break; |
| 594 | + default: |
| 595 | + ShouldNotReachHere(); |
| 596 | + break; |
| 597 | + } |
| 598 | + } else { |
| 599 | + new_code = Bytecodes::_nofast_putfield; |
| 600 | + } |
| 601 | + break; |
| 602 | + } |
| 603 | + case Bytecodes::_aload_0: |
| 604 | + // Revert _fast_Xaccess_0 or _aload_0 to _nofast_aload_0 |
| 605 | + new_code = Bytecodes::_nofast_aload_0; |
| 606 | + break; |
| 607 | + case Bytecodes::_iload: |
531 | 608 | if (!bcs.is_wide()) { |
532 | | - *bcs.bcp() = Bytecodes::_nofast_iload; |
| 609 | + new_code = Bytecodes::_nofast_iload; |
533 | 610 | } |
534 | 611 | break; |
| 612 | + default: |
| 613 | + break; |
535 | 614 | } |
536 | | - default: break; |
| 615 | + if (opcode != new_code) { |
| 616 | + *bcs.bcp() = new_code; |
| 617 | + if (lsh.is_enabled()) { |
| 618 | + lsh.print_cr("%d:%s -> %s", bcs.bci(), Bytecodes::name(opcode), Bytecodes::name(new_code)); |
| 619 | + } |
537 | 620 | } |
538 | 621 | } |
539 | 622 | } |
540 | 623 |
|
541 | 624 | // [1] Rewrite all bytecodes as needed, so that the ConstMethod* will not be modified |
542 | 625 | // at run time by RewriteBytecodes/RewriteFrequentPairs |
543 | 626 | // [2] Assign a fingerprint, so one doesn't need to be assigned at run-time. |
544 | | -void AOTMetaspace::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread* thread, InstanceKlass* ik) { |
| 627 | +void AOTMetaspace::rewrite_bytecodes_and_calculate_fingerprints(Thread* thread, InstanceKlass* ik) { |
545 | 628 | for (int i = 0; i < ik->methods()->length(); i++) { |
546 | 629 | methodHandle m(thread, ik->methods()->at(i)); |
547 | 630 | if (ik->can_be_verified_at_dumptime() && ik->is_linked()) { |
548 | | - rewrite_nofast_bytecode(m); |
| 631 | + rewrite_bytecodes(m); |
549 | 632 | } |
550 | 633 | Fingerprinter fp(m); |
551 | 634 | // The side effect of this call sets method's fingerprint field. |
|
0 commit comments