Skip to content

Commit

Permalink
8290154: [JVMCI] partially implement JVMCI for RISC-V
Browse files Browse the repository at this point in the history
Reviewed-by: ihse, dnsimon, yadongwang
  • Loading branch information
Zeavee authored and Doug Simon committed Oct 7, 2022
1 parent b38bed6 commit 7a194d3
Show file tree
Hide file tree
Showing 20 changed files with 1,722 additions and 22 deletions.
2 changes: 2 additions & 0 deletions make/autoconf/jvm-features.m4
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_JVMCI],
AC_MSG_RESULT([yes])
elif test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then
AC_MSG_RESULT([yes])
elif test "x$OPENJDK_TARGET_CPU" = "xriscv64"; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU])
AVAILABLE=false
Expand Down
124 changes: 124 additions & 0 deletions src/hotspot/cpu/riscv/jvmciCodeInstaller_riscv.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/

#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "jvmci/jvmci.hpp"
#include "jvmci/jvmciCodeInstaller.hpp"
#include "jvmci/jvmciRuntime.hpp"
#include "jvmci/jvmciCompilerToVM.hpp"
#include "jvmci/jvmciJavaClasses.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/sharedRuntime.hpp"
#include "vmreg_riscv.inline.hpp"

jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCI_TRAPS) {
address pc = (address) inst;
if (inst->is_call()) {
return pc_offset + NativeCall::instruction_size;
} else if (inst->is_jump()) {
return pc_offset + NativeJump::instruction_size;
} else if (inst->is_movptr()) {
return pc_offset + NativeMovConstReg::movptr_instruction_size;
} else {
JVMCI_ERROR_0("unsupported type of instruction for call site");
}
}

void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& obj, bool compressed, JVMCI_TRAPS) {
address pc = _instructions->start() + pc_offset;
jobject value = JNIHandles::make_local(obj());
MacroAssembler::patch_oop(pc, cast_from_oop<address>(obj()));
int oop_index = _oop_recorder->find_index(value);
RelocationHolder rspec = oop_Relocation::spec(oop_index);
_instructions->relocate(pc, rspec);
}

void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, HotSpotCompiledCodeStream* stream, u1 tag, JVMCI_TRAPS) {
address pc = _instructions->start() + pc_offset;
if (tag == PATCH_NARROW_KLASS) {
narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, stream, tag, JVMCI_CHECK);
MacroAssembler::pd_patch_instruction_size(pc, (address) (long) narrowOop);
JVMCI_event_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop);
} else {
NativeMovConstReg* move = nativeMovConstReg_at(pc);
void* reference = record_metadata_reference(_instructions, pc, stream, tag, JVMCI_CHECK);
move->set_data((intptr_t) reference);
JVMCI_event_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference));
}
}

void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS) {
address pc = _instructions->start() + pc_offset;
address dest = _constants->start() + data_offset;
_instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS));
JVMCI_event_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
}

void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS) {
address pc = (address) inst;
if (inst->is_jal()) {
NativeCall* call = nativeCall_at(pc);
call->set_destination((address) foreign_call_destination);
_instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
} else if (inst->is_jump()) {
NativeJump* jump = nativeJump_at(pc);
jump->set_jump_destination((address) foreign_call_destination);
_instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
} else if (inst->is_movptr()) {
NativeMovConstReg* movptr = nativeMovConstReg_at(pc);
movptr->set_data((intptr_t) foreign_call_destination);
_instructions->relocate(movptr->instruction_address(), runtime_call_Relocation::spec());
} else {
JVMCI_ERROR("unknown call or jump instruction at " PTR_FORMAT, p2i(pc));
}
JVMCI_event_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
}

void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, methodHandle& method, jint pc_offset, JVMCI_TRAPS) {
Unimplemented();
}

void CodeInstaller::pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS) {
Unimplemented();
}

// convert JVMCI register indices (as used in oop maps) to HotSpot registers
VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) {
if (jvmci_reg < Register::number_of_registers) {
return as_Register(jvmci_reg)->as_VMReg();
} else {
jint floatRegisterNumber = jvmci_reg - Register::number_of_registers;
if (floatRegisterNumber >= 0 && floatRegisterNumber < FloatRegister::number_of_registers) {
return as_FloatRegister(floatRegisterNumber)->as_VMReg();
}
JVMCI_ERROR_NULL("invalid register number: %d", jvmci_reg);
}
}

bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
return !(hotspotRegister->is_FloatRegister() || hotspotRegister->is_VectorRegister());
}
79 changes: 79 additions & 0 deletions src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
#include "adfiles/ad_riscv.hpp"
#include "opto/runtime.hpp"
#endif
#if INCLUDE_JVMCI
#include "jvmci/jvmciJavaClasses.hpp"
#endif

#define __ masm->

Expand Down Expand Up @@ -208,6 +211,9 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm) {
#ifdef COMPILER2
__ pop_CPU_state(_save_vectors, Matcher::scalable_vector_reg_size(T_BYTE));
#else
#if !INCLUDE_JVMCI
assert(!_save_vectors, "vectors are generated only by C2 and JVMCI");
#endif
__ pop_CPU_state(_save_vectors);
#endif
__ leave();
Expand Down Expand Up @@ -493,6 +499,18 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
// Pre-load the register-jump target early, to schedule it better.
__ ld(t1, Address(xmethod, in_bytes(Method::from_compiled_offset())));

#if INCLUDE_JVMCI
if (EnableJVMCI) {
// check if this call should be routed towards a specific entry point
__ ld(t0, Address(xthread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
Label no_alternative_target;
__ beqz(t0, no_alternative_target);
__ mv(t1, t0);
__ sd(zr, Address(xthread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
__ bind(no_alternative_target);
}
#endif // INCLUDE_JVMCI

// Now generate the shuffle code.
for (int i = 0; i < total_args_passed; i++) {
if (sig_bt[i] == T_VOID) {
Expand Down Expand Up @@ -1675,6 +1693,11 @@ void SharedRuntime::generate_deopt_blob() {
ResourceMark rm;
// Setup code generation tools
int pad = 0;
#if INCLUDE_JVMCI
if (EnableJVMCI) {
pad += 512; // Increase the buffer size when compiling for JVMCI
}
#endif
CodeBuffer buffer("deopt_blob", 2048 + pad, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);
int frame_size_in_words = -1;
Expand Down Expand Up @@ -1726,6 +1749,12 @@ void SharedRuntime::generate_deopt_blob() {
__ j(cont);

int reexecute_offset = __ pc() - start;
#if INCLUDE_JVMCI && !defined(COMPILER1)
if (EnableJVMCI && UseJVMCICompiler) {
// JVMCI does not use this kind of deoptimization
__ should_not_reach_here();
}
#endif

// Reexecute case
// return address is the pc describes what bci to do re-execute at
Expand All @@ -1736,6 +1765,44 @@ void SharedRuntime::generate_deopt_blob() {
__ mvw(xcpool, Deoptimization::Unpack_reexecute); // callee-saved
__ j(cont);

#if INCLUDE_JVMCI
Label after_fetch_unroll_info_call;
int implicit_exception_uncommon_trap_offset = 0;
int uncommon_trap_offset = 0;

if (EnableJVMCI) {
implicit_exception_uncommon_trap_offset = __ pc() - start;

__ ld(ra, Address(xthread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
__ sd(zr, Address(xthread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));

uncommon_trap_offset = __ pc() - start;

// Save everything in sight.
reg_saver.save_live_registers(masm, 0, &frame_size_in_words);
// fetch_unroll_info needs to call last_java_frame()
Label retaddr;
__ set_last_Java_frame(sp, noreg, retaddr, t0);

__ lw(c_rarg1, Address(xthread, in_bytes(JavaThread::pending_deoptimization_offset())));
__ mvw(t0, -1);
__ sw(t0, Address(xthread, in_bytes(JavaThread::pending_deoptimization_offset())));

__ mvw(xcpool, (int32_t)Deoptimization::Unpack_reexecute);
__ mv(c_rarg0, xthread);
__ orrw(c_rarg2, zr, xcpool); // exec mode
int32_t offset = 0;
__ la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)), offset);
__ jalr(x1, t0, offset);
__ bind(retaddr);
oop_maps->add_gc_map( __ pc()-start, map->deep_copy());

__ reset_last_Java_frame(false);

__ j(after_fetch_unroll_info_call);
} // EnableJVMCI
#endif // INCLUDE_JVMCI

int exception_offset = __ pc() - start;

// Prolog for exception case
Expand Down Expand Up @@ -1829,6 +1896,12 @@ void SharedRuntime::generate_deopt_blob() {

__ reset_last_Java_frame(false);

#if INCLUDE_JVMCI
if (EnableJVMCI) {
__ bind(after_fetch_unroll_info_call);
}
#endif

// Load UnrollBlock* into x15
__ mv(x15, x10);

Expand Down Expand Up @@ -1984,6 +2057,12 @@ void SharedRuntime::generate_deopt_blob() {
_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words);
assert(_deopt_blob != NULL, "create deoptimization blob fail!");
_deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
#if INCLUDE_JVMCI
if (EnableJVMCI) {
_deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
_deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
}
#endif
}

// Number of stack slots between incoming argument block and the start of
Expand Down

1 comment on commit 7a194d3

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

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

Please sign in to comment.