Skip to content

Commit

Permalink
Merge pull request #141 from Sere-Fu/port_wisp_to_dragonwell11
Browse files Browse the repository at this point in the history
[Backport] Port wisp to dragonwell11
  • Loading branch information
zhengxiaolinX authored Sep 3, 2021
2 parents ff9c8fc + 69d7997 commit f711f33
Show file tree
Hide file tree
Showing 357 changed files with 24,644 additions and 237 deletions.
10 changes: 10 additions & 0 deletions make/copy/Copy-java.base.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,16 @@ $(eval $(call SetupCopyFiles, COPY_NET_PROPERTIES, \

TARGETS += $(COPY_NET_PROPERTIES)

################################################################################

$(eval $(call SetupCopyFiles, COPY_WISP_PROPERTIES, \
FILES := $(TOPDIR)/src/java.base/share/conf/wisp.properties, \
DEST := $(CONF_DST_DIR), \
))

TARGETS += $(COPY_WISP_PROPERTIES)


ifeq ($(OPENJDK_TARGET_OS), solaris)
$(eval $(call SetupCopyFiles, COPY_SDP_CONF, \
FILES := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/sdp/sdp.conf.template, \
Expand Down
5 changes: 5 additions & 0 deletions make/hotspot/symbols/symbols-unix
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ JVM_ArrayCopy
JVM_AssertionStatusDirectives
JVM_BeforeHalt
JVM_CallStackWalk
JVM_CheckAndClearNativeInterruptForWisp
JVM_Clone
JVM_ConstantPoolGetClassAt
JVM_ConstantPoolGetClassAtIfLoaded
Expand Down Expand Up @@ -122,6 +123,7 @@ JVM_GetNestHost
JVM_GetNestMembers
JVM_GetPrimitiveArrayElement
JVM_GetProtectionDomain
JVM_GetProxyUnpark
JVM_GetSimpleBinaryName
JVM_GetStackAccessControlContext
JVM_GetSystemPackage
Expand All @@ -142,6 +144,7 @@ JVM_Interrupt
JVM_InvokeMethod
JVM_IsArrayClass
JVM_IsConstructorIx
JVM_IsInSameNative
JVM_IsInterface
JVM_IsInterrupted
JVM_IsPrimitiveClass
Expand All @@ -151,6 +154,7 @@ JVM_IsThreadAlive
JVM_IsVMGeneratedMethodIx
JVM_LatestUserDefinedLoader
JVM_LoadLibrary
JVM_MarkPreempted
JVM_MaxMemory
JVM_MaxObjectInspectionAge
JVM_MonitorNotify
Expand All @@ -175,6 +179,7 @@ JVM_SetClassSigners
JVM_SetNativeThreadName
JVM_SetPrimitiveArrayElement
JVM_SetThreadPriority
JVM_SetWispTask
JVM_Sleep
JVM_StartThread
JVM_StopThread
Expand Down
33 changes: 33 additions & 0 deletions src/hotspot/cpu/aarch64/aarch64.ad
Original file line number Diff line number Diff line change
Expand Up @@ -3572,8 +3572,15 @@ encode %{
//
// Try to CAS m->owner from NULL to current thread.
__ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes()-markOopDesc::monitor_value));
if (UseWispMonitor) {
__ ldr (rthread, Address(rthread, JavaThread::current_coroutine_offset()));
__ ldr (rthread, Address(rthread, Coroutine::wisp_thread_offset()));
}
__ cmpxchg(tmp, zr, rthread, Assembler::xword, /*acquire*/ true,
/*release*/ true, /*weak*/ false, noreg); // Sets flags for result
if (UseWispMonitor) {
__ ldr (rthread, Address(rthread, WispThread::thread_offset()));
}

// Store a non-null value into the box to avoid looking like a re-entrant
// lock. The fast-path monitor unlock code checks for
Expand Down Expand Up @@ -3638,7 +3645,14 @@ encode %{
__ add(tmp, tmp, -markOopDesc::monitor_value); // monitor
__ ldr(rscratch1, Address(tmp, ObjectMonitor::owner_offset_in_bytes()));
__ ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes()));
if (UseWispMonitor) {
__ ldr (rthread, Address(rthread, JavaThread::current_coroutine_offset()));
__ ldr (rthread, Address(rthread, Coroutine::wisp_thread_offset()));
}
__ eor(rscratch1, rscratch1, rthread); // Will be 0 if we are the owner.
if (UseWispMonitor) {
__ ldr (rthread, Address(rthread, WispThread::thread_offset()));
}
__ orr(rscratch1, rscratch1, disp_hdr); // Will be 0 if there are 0 recursions
__ cmp(rscratch1, zr); // Sets flags for result
__ br(Assembler::NE, cont);
Expand Down Expand Up @@ -15708,6 +15722,25 @@ instruct tlsLoadP(thread_RegP dst)
ins_pipe(pipe_class_empty);
%}

// Thread refetch:
// take two main arguments:
// 1. register @rthread
// 2. one register which contains the `Coroutine *`
// and move Coroutine->_thread to @rthread
instruct tlsRefetchP(thread_RegP dst, iRegP src)
%{
match(Set dst (ThreadRefetch src));

format %{ "Refetch the rthread register" %}

ins_encode %{
__ ldr(rthread, Address($src$$Register, Coroutine::thread_offset()));
%}

ins_pipe(pipe_class_empty);
%}


// ====================VECTOR INSTRUCTIONS=====================================

// Load vector (32 bits)
Expand Down
23 changes: 23 additions & 0 deletions src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,31 @@ void MonitorExitStub::emit_code(LIR_Assembler* ce) {
} else {
exit_id = Runtime1::monitorexit_nofpu_id;
}
// Handle special case for wisp unpark.
// The code stub is entered only when the following four conditions are all satisfied
// 1. A synchronized method is compiled by C1
// 2. An exception happened in this method
// 3. There is no exception handler in this method, So it needs to unwind to its caller
// 4. GC happened during unpark
// if (_info == NULL) is true, the four conditions are all true.
if (UseWispMonitor && (_info == NULL || _at_method_return)) {
if (exit_id == Runtime1::monitorexit_id) {
exit_id = Runtime1::monitorexit_proxy_id;
} else {
assert (exit_id == Runtime1::monitorexit_nofpu_id, "must be monitorexit_nofpu_id");
exit_id = Runtime1::monitorexit_nofpu_proxy_id;
}
}
// on X86, despite we will call java, we have no need to generate an oopmap here,
// because c1_CodeStubs_x86.cpp only emit a jump here, when GC happens, we won't
// see the _last_pc pointing here.
// However, on aarch64 here it uses lr to jump from the far_jump stub.
// so the _last_pc will be seen by stack unwinding as a single frame,
// when GC searches the pc related oopmap, it will crash.
// so, because of this implementation we should emit the OopMap where the `continuation` lays.
__ adr(lr, _continuation);
__ far_jump(RuntimeAddress(Runtime1::entry_for(exit_id)));
__ should_not_reach_here();
}


Expand Down
9 changes: 8 additions & 1 deletion src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ int LIR_Assembler::emit_unwind_handler() {
MonitorExitStub* stub = NULL;
if (method()->is_synchronized()) {
monitor_address(0, FrameMap::r0_opr);
stub = new MonitorExitStub(FrameMap::r0_opr, true, 0);
stub = new MonitorExitStub(FrameMap::r0_opr, true, 0, NULL, true);
__ unlock_object(r5, r4, r0, *stub->entry());
__ bind(*stub->continuation());
}
Expand Down Expand Up @@ -2617,6 +2617,13 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
Unimplemented();
}
__ bind(*op->stub()->continuation());
// add an OopMap here.
if (UseWispMonitor && op->code() == lir_unlock && !op->at_method_return()) {
// For direct unpark in Wisp, _info must be recorded to generate the oopmap.
guarantee(op->info() != NULL, "aarch64 needs an OopMap because the adr(lr, ...), so pc will be searched for the OopMap");
add_call_info_here(op->info());
verify_oop_map(op->info());
}
}


Expand Down
13 changes: 12 additions & 1 deletion src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,18 @@ void LIRGenerator::do_MonitorExit(MonitorExit* x) {
LIR_Opr lock = new_register(T_INT);
LIR_Opr obj_temp = new_register(T_INT);
set_no_result(x);
monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no());
// Info is used to generate the oopmap, which is necessary for calling java code during runtime.
if (UseWispMonitor) {
CodeEmitInfo* info = NULL;
if (x->state()) {
info = state_for(x, x->state(), true);
}
// add info_for_exception CodeInfo here.
CodeEmitInfo* info_for_exception = state_for(x, x->state(), true);
monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no(), info_for_exception, info, x->at_method_return());
} else {
monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no());
}
}


Expand Down
48 changes: 47 additions & 1 deletion src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include "runtime/vframeArray.hpp"
#include "vmreg_aarch64.inline.hpp"

// the Runtime1::monitorenter function pointer
extern address monitorenter_address_C1;

// Implementation of StubAssembler

Expand All @@ -65,6 +67,18 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre
blr(rscratch1);
bind(retaddr);
int call_offset = offset();

// the call_offset is the pc for the call()'s return rip so that it should be
// inserted directly after the call.
// the call_offset is used for something like 'frame::sender_for_compiled_frame'
// in order to use the call_offset as the pc address to find the OopMap address
if (EnableCoroutine) {
// only if the entry_point is equal to `Runtime1::monitorenter()` will we do this amendment.
if (entry == monitorenter_address_C1) {
WISP_V2v_UPDATE;
}
}

// verify callee-saved register
#ifdef ASSERT
push(r0, sp);
Expand Down Expand Up @@ -993,6 +1007,11 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
oop_maps = new OopMapSet();
oop_maps->add_gc_map(call_offset, map);
restore_live_registers(sasm, save_fpu_registers);

if (EnableCoroutine) {
// rthread has been forcibly restored in restore_live_registers so we need to fix it.
WISP_COMPILER_RESTORE_FORCE_UPDATE;
}
}
break;

Expand All @@ -1011,7 +1030,34 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// note: really a leaf routine but must setup last java sp
// => use call_RT for now (speed can be improved by
// doing last java sp setup manually)
int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), r0);
int call_offset = 0;
if (UseWispMonitor) {
call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit_wisp), r0);
} else {
call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), r0);
}
oop_maps = new OopMapSet();
oop_maps->add_gc_map(call_offset, map);
restore_live_registers(sasm, save_fpu_registers);
}
break;
case monitorexit_nofpu_proxy_id:
save_fpu_registers = false;
// fall through
case monitorexit_proxy_id:
{
StubFrame f(sasm, "monitorexit", dont_gc_arguments);
OopMap* map = save_live_registers(sasm, save_fpu_registers);

// Called with store_parameter and not C abi
f.load_argument(0, r0); // r0,: lock address
int call_offset = 0;
if (UseWispMonitor) {
call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit_wisp_proxy), r0);
} else {
call_offset = 0;
__ should_not_reach_here();
}

oop_maps = new OopMapSet();
oop_maps->add_gc_map(call_offset, map);
Expand Down
51 changes: 51 additions & 0 deletions src/hotspot/cpu/aarch64/coroutine_aarch64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. 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. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*
*/

#include "precompiled.hpp"
#include "prims/privilegedStack.hpp"
#include "runtime/coroutine.hpp"
#include "runtime/globals.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/objectMonitor.inline.hpp"
#include "services/threadService.hpp"

#include CPU_HEADER(coroutine)
#include CPU_HEADER_INLINE(vmreg)

void Coroutine::set_coroutine_base(intptr_t **&base, JavaThread* thread, jobject obj, Coroutine *coro, oop coroutineObj, address coroutine_start) {
*(--base) = (intptr_t*)obj;
*(--base) = (intptr_t*)coro;
*(--base) = NULL;
*(--base) = (intptr_t*)coroutine_start;
*(--base) = NULL;
// we need one more pointer space compared to x86:
// see `create_switchTo_contents()`, which will push both `lr` and `rfp` onto the stack.
// rfp will be saved to this space, which will be the end of gc backtrace.
*(--base) = NULL;
}

Register CoroutineStack::get_fp_reg() {
return rfp;
}

31 changes: 31 additions & 0 deletions src/hotspot/cpu/aarch64/coroutine_aarch64.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. 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. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*
*/

#ifndef CPU_AARCH64_VM_COROUTINE_AARCH64_HPP
#define CPU_AARCH64_VM_COROUTINE_AARCH64_HPP

#define R_TH rthread
// the below `thread` lays on the stack: something like
// `const Address thread(rfp, thread_off * wordSize);`
#define WISP_j2v_UPDATE __ str(R_TH, thread)

#endif // CPU_AARCH64_VM_COROUTINE_AARCH64_HPP
13 changes: 13 additions & 0 deletions src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,14 +421,27 @@ void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register

if (JvmtiExport::can_post_interpreter_events()) {
Label run_compiled_code;
Label coroutine_skip_interpret;
// JVMTI events, such as single-stepping, are implemented partly by avoiding running
// compiled code in threads for which the event is enabled. Check here for
// interp_only_mode if these events CAN be enabled.
ldrw(rscratch1, Address(rthread, JavaThread::interp_only_mode_offset()));
cbzw(rscratch1, run_compiled_code);
if (EnableCoroutine) {
ldrh(rscratch1, Address(method, Method::intrinsic_id_offset_in_bytes()));
cmp(rscratch1, vmIntrinsics::_switchTo);
br(Assembler::EQ, coroutine_skip_interpret);
cmp(rscratch1, vmIntrinsics::_switchToAndExit);
br(Assembler::EQ, coroutine_skip_interpret);
cmp(rscratch1, vmIntrinsics::_switchToAndTerminate);
br(Assembler::EQ, coroutine_skip_interpret);
}
ldr(rscratch1, Address(method, Method::interpreter_entry_offset()));
br(rscratch1);
bind(run_compiled_code);
if (EnableCoroutine) {
bind(coroutine_skip_interpret);
}
}

ldr(rscratch1, Address(method, Method::from_interpreted_offset()));
Expand Down
Loading

0 comments on commit f711f33

Please sign in to comment.