| 506 | } |
| 507 | |
| 508 | Result BytecodeRewriter::rewriteCodeForLatency(const u8* code, u16 code_length, u8 start_time_loc_index, u16* relocation_table, Latency latency) { |
| 509 | // Method start is relocated |
| 510 | u16 current_relocation = EXTRA_BYTECODES_ENTRY; |
| 511 | |
| 512 | u32 code_start = _dst_len; |
| 513 | |
| 514 | put8(JVM_OPC_invokestatic); |
| 515 | put16(_nanoTime_cpool_idx); |
| 516 | |
| 517 | put8(JVM_OPC_lstore); |
| 518 | put8(start_time_loc_index); |
| 519 | |
| 520 | // nop ensures that tableswitch/lookupswitch needs no realignment |
| 521 | put16(JVM_OPC_nop); |
| 522 | put8(JVM_OPC_nop); |
| 523 | |
| 524 | // Low 16 bytes: jump base index |
| 525 | // High 16 bytes: jump offset index |
| 526 | // This supports narrow and wide jumps, as well as tableswitch and lookupswitch |
| 527 | std::vector<u32> jumps; |
| 528 | // First scan: fill relocation_table and rewrite code. |
| 529 | for (u16 i = 0; i < code_length; /* incremented with instructionBytes */) { |
| 530 | u8 opcode = code[i]; |
| 531 | |
| 532 | if (isFunctionExit(opcode)) { |
| 533 | put8(JVM_OPC_lload); |
| 534 | put8(start_time_loc_index); |
| 535 | |
| 536 | if (latency > 0) { |
| 537 | put8(JVM_OPC_ldc2_w); |
| 538 | put16(_latency_cpool_idx[latency]); |
| 539 | } else { |
| 540 | put8(JVM_OPC_nop); |
| 541 | put8(JVM_OPC_nop); |
| 542 | put8(JVM_OPC_nop); |
| 543 | } |
| 544 | |
| 545 | put8(JVM_OPC_invokestatic); |
| 546 | put16(latency == 0 ? _recordExit_latency0_cpool_idx : _recordExit_cpool_idx); |
| 547 | } else if (isNarrowJump(opcode) || isWideJump(opcode)) { |
| 548 | jumps.push_back((i + 1U) << 16 | i); |
| 549 | } else if (opcode == JVM_OPC_tableswitch) { |
| 550 | // 'default' lies after the padding |
| 551 | u16 default_index = alignUp4(i); |
| 552 | // 4 bytes: default |
| 553 | jumps.push_back((u32) default_index << 16 | i); |
| 554 | // 4 bytes: low |
| 555 | int32_t l = get32(code + default_index + 4); |
| 556 | // 4 bytes: high |
| 557 | int32_t h = get32(code + default_index + 8); |
| 558 | assert(h - l + 1 >= 0); |
| 559 | assert(h - l + 1 <= 0xFFFF); |
| 560 | u16 branches_base_index = default_index + 12; |
| 561 | for (u16 c = 0; c < (u16) (h - l + 1); ++c) { |
| 562 | jumps.push_back((branches_base_index + c * 4) << 16 | i); |
| 563 | } |
| 564 | } else if (opcode == JVM_OPC_lookupswitch) { |
| 565 | // 'default' lies after the padding |
nothing calls this directly
no test coverage detected