Skip to content

8360000: RISC-V: implement aot #26101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ friend class ArrayCopyStub;
_call_stub_size = 11 * MacroAssembler::instruction_size +
1 * MacroAssembler::instruction_size + wordSize,
// See emit_exception_handler for detail
_exception_handler_size = DEBUG_ONLY(256) NOT_DEBUG(32), // or smaller
_exception_handler_size = DEBUG_ONLY(256) NOT_DEBUG(64), // or smaller
// See emit_deopt_handler for detail
// auipc (1) + far_jump (2)
_deopt_handler_size = 1 * MacroAssembler::instruction_size +
Expand Down
57 changes: 51 additions & 6 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "code/aotCodeCache.hpp"
#include "code/compiledIC.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/barrierSet.hpp"
Expand Down Expand Up @@ -758,9 +759,13 @@ void MacroAssembler::resolve_global_jobject(Register value, Register tmp1, Regis
}

void MacroAssembler::stop(const char* msg) {
BLOCK_COMMENT(msg);
// Skip AOT caching C strings in scratch buffer.
const char* str = (code_section()->scratch_emit()) ? msg : AOTCodeCache::add_C_string(msg);
BLOCK_COMMENT(str);
// load msg into c_rarg0 so we can access it from the signal handler
// ExternalAddress enables saving and restoring via the code cache
la(c_rarg0, ExternalAddress((address) str));
illegal_instruction(Assembler::csr::time);
emit_int64((uintptr_t)msg);
}

void MacroAssembler::unimplemented(const char* what) {
Expand Down Expand Up @@ -790,10 +795,9 @@ void MacroAssembler::emit_static_call_stub() {
void MacroAssembler::call_VM_leaf_base(address entry_point,
int number_of_arguments,
Label *retaddr) {
int32_t offset = 0;
push_reg(RegSet::of(t1, xmethod), sp); // push << t1 & xmethod >> to sp
movptr(t1, entry_point, offset, t0);
jalr(t1, offset);
movptr(t1, RuntimeAddress(entry_point), t0);
jalr(t1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This movptr + jalr sequence could be further simplified into rt_call(entry_point), which could help save one add instruction.

if (retaddr != nullptr) {
bind(*retaddr);
}
Expand Down Expand Up @@ -3395,6 +3399,19 @@ void MacroAssembler::store_klass_gap(Register dst, Register src) {
}
}

void MacroAssembler::decode_klass_not_null_for_aot(Register dst, Register src, Register tmp) {
// we have to load the klass base from the AOT constants area but
// not the shift because it is not allowed to change
int shift = CompressedKlassPointers::shift();
assert(shift >= 0 && shift <= CompressedKlassPointers::max_shift(), "unexpected compressed klass shift!");
assert_different_registers(src, tmp);
la(tmp, ExternalAddress(CompressedKlassPointers::base_addr()));
ld(tmp, tmp);
Register t = src == dst ? dst : t0;
assert_different_registers(t, tmp);
shadd(dst, src, tmp, t, shift);
}

void MacroAssembler::decode_klass_not_null(Register r, Register tmp) {
assert_different_registers(r, tmp);
decode_klass_not_null(r, r, tmp);
Expand All @@ -3403,6 +3420,11 @@ void MacroAssembler::decode_klass_not_null(Register r, Register tmp) {
void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) {
assert(UseCompressedClassPointers, "should only be used for compressed headers");

if (AOTCodeCache::is_on_for_dump()) {
decode_klass_not_null_for_aot(dst, src, tmp);
return;
}

if (CompressedKlassPointers::base() == nullptr) {
if (CompressedKlassPointers::shift() != 0) {
slli(dst, src, CompressedKlassPointers::shift());
Expand All @@ -3429,6 +3451,24 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register
}
}

void MacroAssembler::encode_klass_not_null_for_aot(Register dst, Register src, Register tmp) {
// we have to load the klass base from the AOT constants area but
// not the shift because it is not allowed to change
int shift = CompressedKlassPointers::shift();
assert(shift >= 0 && shift <= CompressedKlassPointers::max_shift(), "unexpected compressed klass shift!");
assert_different_registers(src, tmp);
Register xbase = dst;
if (dst == src) {
xbase = tmp;
}
la(xbase, ExternalAddress(CompressedKlassPointers::base_addr()));
ld(xbase, xbase);
sub(dst, src, xbase);
if (shift != 0) {
srli(dst, dst, shift);
}
}

void MacroAssembler::encode_klass_not_null(Register r, Register tmp) {
assert_different_registers(r, tmp);
encode_klass_not_null(r, r, tmp);
Expand All @@ -3437,6 +3477,11 @@ void MacroAssembler::encode_klass_not_null(Register r, Register tmp) {
void MacroAssembler::encode_klass_not_null(Register dst, Register src, Register tmp) {
assert(UseCompressedClassPointers, "should only be used for compressed headers");

if (AOTCodeCache::is_on_for_dump()) {
encode_klass_not_null_for_aot(dst, src, tmp);
return;
}

if (CompressedKlassPointers::base() == nullptr) {
if (CompressedKlassPointers::shift() != 0) {
srli(dst, src, CompressedKlassPointers::shift());
Expand Down Expand Up @@ -4882,7 +4927,7 @@ void MacroAssembler::get_thread(Register thread) {
RegSet::range(x28, x31) + ra - thread;
push_reg(saved_regs, sp);

mv(t1, CAST_FROM_FN_PTR(address, Thread::current));
movptr(t1, ExternalAddress(CAST_FROM_FN_PTR(address, Thread::current)));
Copy link
Member

@RealFYang RealFYang Jul 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be more consistent with other places in riscv code where we move an ExternalAddress into a register if we do: la(t1, ExternalAddress(CAST_FROM_FN_PTR(address, Thread::current))).

jalr(t1);
if (thread != c_rarg0) {
mv(thread, c_rarg0);
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ class MacroAssembler: public Assembler {
void store_klass(Register dst, Register src, Register tmp = t0);
void cmp_klass_compressed(Register oop, Register trial_klass, Register tmp, Label &L, bool equal);

void decode_klass_not_null_for_aot(Register dst, Register src, Register tmp);
void encode_klass_not_null_for_aot(Register dst, Register src, Register tmp);
void encode_klass_not_null(Register r, Register tmp = t0);
void decode_klass_not_null(Register r, Register tmp = t0);
void encode_klass_not_null(Register dst, Register src, Register tmp);
Expand Down
21 changes: 18 additions & 3 deletions src/hotspot/cpu/riscv/runtime_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#ifdef COMPILER2
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/aotCodeCache.hpp"
#include "code/vmreg.hpp"
#include "interpreter/interpreter.hpp"
#include "opto/runtime.hpp"
Expand Down Expand Up @@ -62,6 +63,11 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
ResourceMark rm;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems more reasonable to move this ResourceMark rm; closer to its user CodeBuffer buffer(name, 2048, 1024);.
Similar for other changes in this file and src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp.

// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name);
if (blob != nullptr) {
return blob->as_uncommon_trap_blob();
}

CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
Expand Down Expand Up @@ -243,8 +249,10 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Make sure all code is generated
masm->flush();

return UncommonTrapBlob::create(&buffer, oop_maps,
SimpleRuntimeFrame::framesize >> 1);
UncommonTrapBlob *ut_blob = UncommonTrapBlob::create(&buffer, oop_maps,
SimpleRuntimeFrame::framesize >> 1);
AOTCodeCache::store_code_blob(*ut_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name);
return ut_blob;
}

//------------------------------generate_exception_blob---------------------------
Expand Down Expand Up @@ -284,6 +292,11 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
ResourceMark rm;
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name);
if (blob != nullptr) {
return blob->as_exception_blob();
}

CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
Expand Down Expand Up @@ -382,6 +395,8 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
masm->flush();

// Set exception blob
return ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
ExceptionBlob* ex_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
AOTCodeCache::store_code_blob(*ex_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name);
return ex_blob;
}
#endif // COMPILER2
36 changes: 34 additions & 2 deletions src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/aotCodeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
#include "code/vtableStubs.hpp"
Expand Down Expand Up @@ -2101,6 +2102,12 @@ void SharedRuntime::generate_deopt_blob() {
}
#endif
const char* name = SharedRuntime::stub_name(SharedStubId::deopt_id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)SharedStubId::deopt_id, name);
if (blob != nullptr) {
_deopt_blob = blob->as_deoptimization_blob();
return;
}

CodeBuffer buffer(name, 2048 + pad, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);
int frame_size_in_words = -1;
Expand Down Expand Up @@ -2460,6 +2467,8 @@ void SharedRuntime::generate_deopt_blob() {
_deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
}
#endif

AOTCodeCache::store_code_blob(*_deopt_blob, AOTCodeEntry::SharedBlob, (uint)SharedStubId::deopt_id, name);
}

// Number of stack slots between incoming argument block and the start of
Expand Down Expand Up @@ -2493,6 +2502,11 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal

// Allocate space for the code. Setup code generation tools.
const char* name = SharedRuntime::stub_name(id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name);
if (blob != nullptr) {
return blob->as_safepoint_blob();
}

CodeBuffer buffer(name, 2048, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);
assert_cond(masm != nullptr);
Expand Down Expand Up @@ -2597,7 +2611,10 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal
masm->flush();

// Fill-out other meta info
return SafepointBlob::create(&buffer, oop_maps, frame_size_in_words);
SafepointBlob* sp_blob = SafepointBlob::create(&buffer, oop_maps, frame_size_in_words);

AOTCodeCache::store_code_blob(*sp_blob, AOTCodeEntry::SharedBlob, (uint)id, name);
return sp_blob;
}

//
Expand All @@ -2616,6 +2633,11 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti
ResourceMark rm;

const char* name = SharedRuntime::stub_name(id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name);
if (blob != nullptr) {
return blob->as_runtime_stub();
}

CodeBuffer buffer(name, 1000, 512);
MacroAssembler* masm = new MacroAssembler(&buffer);
assert_cond(masm != nullptr);
Expand Down Expand Up @@ -2686,7 +2708,10 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti
masm->flush();

// return the blob
return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true);
RuntimeStub* rs_blob = RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true);

AOTCodeCache::store_code_blob(*rs_blob, AOTCodeEntry::SharedBlob, (uint)id, name);
return rs_blob;
}

// Continuation point for throwing of implicit exceptions that are
Expand Down Expand Up @@ -2731,6 +2756,11 @@ RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address ru
const char* timer_msg = "SharedRuntime generate_throw_exception";
TraceTime timer(timer_msg, TRACETIME_LOG(Info, startuptime));

CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name);
if (blob != nullptr) {
return blob->as_runtime_stub();
}

CodeBuffer code(name, insts_size, locs_size);
OopMapSet* oop_maps = new OopMapSet();
MacroAssembler* masm = new MacroAssembler(&code);
Expand Down Expand Up @@ -2789,6 +2819,8 @@ RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address ru
(framesize >> (LogBytesPerWord - LogBytesPerInt)),
oop_maps, false);
assert(stub != nullptr, "create runtime stub fail!");

AOTCodeCache::store_code_blob(*stub, AOTCodeEntry::SharedBlob, (uint)id, name);
return stub;
}

Expand Down
7 changes: 2 additions & 5 deletions src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,8 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
} else if (sig == SIGILL && nativeInstruction_at(pc)->is_stop()) {
// Pull a pointer to the error message out of the instruction
// stream.
const uint64_t *detail_msg_ptr
= (uint64_t*)(pc + NativeInstruction::instruction_size);
const char *detail_msg = (const char *)*detail_msg_ptr;
// A pointer to the message will have been placed in a0
const char *detail_msg = (const char *)(uc->uc_mcontext.__gregs[REG_A0]);
const char *msg = "stop";
if (TraceTraps) {
tty->print_cr("trap: %s: (SIGILL)", msg);
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/code/aotCodeCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ uint AOTCodeCache::max_aot_code_size() {
// This method is called during universe_init()
// and does final AOT state and flags settings.
void AOTCodeCache::initialize() {
#if defined(ZERO) || !(defined(AMD64) || defined(AARCH64))
#if defined(ZERO) || !(defined(AMD64) || defined(AARCH64) || defined(RISCV64))
log_info(aot, codecache, init)("AOT Code Cache is not supported on this platform.");
AOTAdapterCaching = false;
AOTStubCaching = false;
Expand Down Expand Up @@ -196,7 +196,7 @@ void AOTCodeCache::initialize() {
FLAG_SET_DEFAULT(ForceUnreachable, true);
}
FLAG_SET_DEFAULT(DelayCompilerStubsGeneration, false);
#endif // defined(AMD64) || defined(AARCH64)
#endif // defined(AMD64) || defined(AARCH64) || defined(RISCV64)
}

static AOTCodeCache* opened_cache = nullptr; // Use this until we verify the cache
Expand Down
2 changes: 1 addition & 1 deletion test/jtreg-ext/requires/VMProps.java
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ protected String vmCDSSupportsAOTCodeCaching() {
if ("true".equals(vmCDSSupportsAOTClassLinking()) &&
!"zero".equals(vmFlavor()) &&
"false".equals(vmJvmciEnabled()) &&
(Platform.isX64() || Platform.isAArch64())) {
(Platform.isX64() || Platform.isAArch64() || Platform.isRISCV64())) {
return "true";
} else {
return "false";
Expand Down