Skip to content

Commit 84ee1a2

Browse files
Yanhong ZhuRealFYang
authored andcommitted
8293781: RISC-V: Clarify types of calls
Reviewed-by: fjiang, fyang, yadongwang
1 parent 1b49606 commit 84ee1a2

File tree

4 files changed

+85
-12
lines changed

4 files changed

+85
-12
lines changed

src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) {
127127
ce->compilation()->implicit_exception_table()->append(_offset, __ offset());
128128
}
129129
__ bind(_entry);
130-
__ far_call(Address(Runtime1::entry_for(Runtime1::throw_div0_exception_id), relocInfo::runtime_call_type));
130+
__ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::throw_div0_exception_id)));
131131
ce->add_call_info_here(_info);
132132
ce->verify_oop_map(_info);
133133
#ifdef ASSERT

src/hotspot/cpu/riscv/frame_riscv.inline.hpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -392,15 +392,11 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {
392392
// frame::update_map_with_saved_link
393393
template <typename RegisterMapT>
394394
void frame::update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr) {
395-
// The interpreter and compiler(s) always save fp in a known
396-
// location on entry. We must record where that location is
397-
// so that if fp was live on callout from c2 we can find
398-
// the saved copy no matter what it called.
399-
400-
// Since the interpreter always saves fp if we record where it is then
401-
// we don't have to always save fp on entry and exit to c2 compiled
402-
// code, on entry will be enough.
403395
assert(map != NULL, "map must be set");
396+
// The interpreter and compiler(s) always save FP in a known
397+
// location on entry. C2-compiled code uses FP as an allocatable
398+
// callee-saved register. We must record where that location is so
399+
// that if FP was live on callout from C2 we can find the saved copy.
404400
map->set_location(::fp->as_VMReg(), (address) link_addr);
405401
// this is weird "H" ought to be at a higher address however the
406402
// oopMaps seems to have the "H" regs at the same address and the

src/hotspot/cpu/riscv/macroAssembler_riscv.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2439,6 +2439,9 @@ void MacroAssembler::far_jump(Address entry, Register tmp) {
24392439
assert(ReservedCodeCacheSize < 4*G, "branch out of range");
24402440
assert(CodeCache::find_blob(entry.target()) != NULL,
24412441
"destination of far call not found in code cache");
2442+
assert(entry.rspec().type() == relocInfo::external_word_type
2443+
|| entry.rspec().type() == relocInfo::runtime_call_type
2444+
|| entry.rspec().type() == relocInfo::none, "wrong entry relocInfo type");
24422445
int32_t offset = 0;
24432446
if (far_branches()) {
24442447
// We can use auipc + jalr here because we know that the total size of
@@ -2454,6 +2457,9 @@ void MacroAssembler::far_call(Address entry, Register tmp) {
24542457
assert(ReservedCodeCacheSize < 4*G, "branch out of range");
24552458
assert(CodeCache::find_blob(entry.target()) != NULL,
24562459
"destination of far call not found in code cache");
2460+
assert(entry.rspec().type() == relocInfo::external_word_type
2461+
|| entry.rspec().type() == relocInfo::runtime_call_type
2462+
|| entry.rspec().type() == relocInfo::none, "wrong entry relocInfo type");
24572463
int32_t offset = 0;
24582464
if (far_branches()) {
24592465
// We can use auipc + jalr here because we know that the total size of
@@ -2701,7 +2707,7 @@ void MacroAssembler::la_patchable(Register reg1, const Address &dest, int32_t &o
27012707
// RISC-V doesn't compute a page-aligned address, in order to partially
27022708
// compensate for the use of *signed* offsets in its base+disp12
27032709
// addressing mode (RISC-V's PC-relative reach remains asymmetric
2704-
// [-(2G + 2K), 2G - 2k).
2710+
// [-(2G + 2K), 2G - 2K).
27052711
if (offset_high >= -((1L << 31) + (1L << 11)) && offset_low < (1L << 31) - (1L << 11)) {
27062712
int64_t distance = dest.target() - pc();
27072713
auipc(reg1, (int32_t)distance + 0x800);

src/hotspot/cpu/riscv/macroAssembler_riscv.hpp

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,15 @@ class MacroAssembler: public Assembler {
596596
return ReservedCodeCacheSize > branch_range;
597597
}
598598

599-
// Jumps that can reach anywhere in the code cache.
600-
// Trashes tmp.
599+
// Emit a direct call/jump if the entry address will always be in range,
600+
// otherwise a far call/jump.
601+
// The address must be inside the code cache.
602+
// Supported entry.rspec():
603+
// - relocInfo::external_word_type
604+
// - relocInfo::runtime_call_type
605+
// - relocInfo::none
606+
// In the case of a far call/jump, the entry address is put in the tmp register.
607+
// The tmp register is invalidated.
601608
void far_call(Address entry, Register tmp = t0);
602609
void far_jump(Address entry, Register tmp = t0);
603610

@@ -635,6 +642,70 @@ class MacroAssembler: public Assembler {
635642
void get_polling_page(Register dest, relocInfo::relocType rtype);
636643
address read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype);
637644

645+
// RISCV64 OpenJDK uses four different types of calls:
646+
// - direct call: jal pc_relative_offset
647+
// This is the shortest and the fastest, but the offset has the range: +/-1MB.
648+
//
649+
// - far call: auipc reg, pc_relative_offset; jalr ra, reg, offset
650+
// This is longer than a direct call. The offset has
651+
// the range [-(2G + 2K), 2G - 2K). Addresses out of the range in the code cache
652+
// requires indirect call.
653+
// If a jump is needed rather than a call, a far jump 'jalr x0, reg, offset' can
654+
// be used instead.
655+
// All instructions are embedded at a call site.
656+
//
657+
// - trampoline call:
658+
// This is only available in C1/C2-generated code (nmethod). It is a combination
659+
// of a direct call, which is used if the destination of a call is in range,
660+
// and a register-indirect call. It has the advantages of reaching anywhere in
661+
// the RISCV address space and being patchable at runtime when the generated
662+
// code is being executed by other threads.
663+
//
664+
// [Main code section]
665+
// jal trampoline
666+
// [Stub code section]
667+
// trampoline:
668+
// ld reg, pc + 8 (auipc + ld)
669+
// jr reg
670+
// <64-bit destination address>
671+
//
672+
// If the destination is in range when the generated code is moved to the code
673+
// cache, 'jal trampoline' is replaced with 'jal destination' and the trampoline
674+
// is not used.
675+
// The optimization does not remove the trampoline from the stub section.
676+
677+
// This is necessary because the trampoline may well be redirected later when
678+
// code is patched, and the new destination may not be reachable by a simple JAL
679+
// instruction.
680+
//
681+
// - indirect call: movptr_with_offset + jalr
682+
// This too can reach anywhere in the address space, but it cannot be
683+
// patched while code is running, so it must only be modified at a safepoint.
684+
// This form of call is most suitable for targets at fixed addresses, which
685+
// will never be patched.
686+
//
687+
//
688+
// To patch a trampoline call when the JAL can't reach, we first modify
689+
// the 64-bit destination address in the trampoline, then modify the
690+
// JAL to point to the trampoline, then flush the instruction cache to
691+
// broadcast the change to all executing threads. See
692+
// NativeCall::set_destination_mt_safe for the details.
693+
//
694+
// There is a benign race in that the other thread might observe the
695+
// modified JAL before it observes the modified 64-bit destination
696+
// address. That does not matter because the destination method has been
697+
// invalidated, so there will be a trap at its start.
698+
// For this to work, the destination address in the trampoline is
699+
// always updated, even if we're not using the trampoline.
700+
701+
// Emit a direct call if the entry address will always be in range,
702+
// otherwise a trampoline call.
703+
// Supported entry.rspec():
704+
// - relocInfo::runtime_call_type
705+
// - relocInfo::opt_virtual_call_type
706+
// - relocInfo::static_call_type
707+
// - relocInfo::virtual_call_type
708+
//
638709
// Return: the call PC or NULL if CodeCache is full.
639710
address trampoline_call(Address entry);
640711
address ic_call(address entry, jint method_index = 0);

0 commit comments

Comments
 (0)