8284161: Implementation of Virtual Threads (Preview)
Co-authored-by: Ron Pressler <rpressler@openjdk.org> Co-authored-by: Alan Bateman <alanb@openjdk.org> Co-authored-by: Erik Österlund <eosterlund@openjdk.org> Co-authored-by: Andrew Haley <aph@openjdk.org> Co-authored-by: Rickard Bäckman <rbackman@openjdk.org> Co-authored-by: Markus Grönlund <mgronlun@openjdk.org> Co-authored-by: Leonid Mesnik <lmesnik@openjdk.org> Co-authored-by: Serguei Spitsyn <sspitsyn@openjdk.org> Co-authored-by: Chris Plummer <cjplummer@openjdk.org> Co-authored-by: Coleen Phillimore <coleenp@openjdk.org> Co-authored-by: Robbin Ehn <rehn@openjdk.org> Co-authored-by: Stefan Karlsson <stefank@openjdk.org> Co-authored-by: Thomas Schatzl <tschatzl@openjdk.org> Co-authored-by: Sergey Kuksenko <skuksenko@openjdk.org> Reviewed-by: lancea, eosterlund, rehn, sspitsyn, stefank, tschatzl, dfuchs, lmesnik, dcubed, kevinw, amenkov, dlong, mchung, psandoz, bpb, coleenp, smarks, egahlin, mseledtsov, coffeys, darcy
This commit is contained in:
parent
5212535a27
commit
9583e3657e
@ -46,7 +46,9 @@ JVM_ConstantPoolGetSize
|
|||||||
JVM_ConstantPoolGetStringAt
|
JVM_ConstantPoolGetStringAt
|
||||||
JVM_ConstantPoolGetTagAt
|
JVM_ConstantPoolGetTagAt
|
||||||
JVM_ConstantPoolGetUTF8At
|
JVM_ConstantPoolGetUTF8At
|
||||||
|
JVM_CurrentCarrierThread
|
||||||
JVM_CurrentThread
|
JVM_CurrentThread
|
||||||
|
JVM_SetCurrentThread
|
||||||
JVM_CurrentTimeMillis
|
JVM_CurrentTimeMillis
|
||||||
JVM_DefineClass
|
JVM_DefineClass
|
||||||
JVM_DefineClassWithSource
|
JVM_DefineClassWithSource
|
||||||
@ -120,6 +122,7 @@ JVM_GetMethodTypeAnnotations
|
|||||||
JVM_GetNanoTimeAdjustment
|
JVM_GetNanoTimeAdjustment
|
||||||
JVM_GetNestHost
|
JVM_GetNestHost
|
||||||
JVM_GetNestMembers
|
JVM_GetNestMembers
|
||||||
|
JVM_GetNextThreadIdOffset
|
||||||
JVM_GetPermittedSubclasses
|
JVM_GetPermittedSubclasses
|
||||||
JVM_GetPrimitiveArrayElement
|
JVM_GetPrimitiveArrayElement
|
||||||
JVM_GetProperties
|
JVM_GetProperties
|
||||||
@ -135,6 +138,7 @@ JVM_GetVmArguments
|
|||||||
JVM_Halt
|
JVM_Halt
|
||||||
JVM_HasReferencePendingList
|
JVM_HasReferencePendingList
|
||||||
JVM_HoldsLock
|
JVM_HoldsLock
|
||||||
|
JVM_GetStackTrace
|
||||||
JVM_IHashCode
|
JVM_IHashCode
|
||||||
JVM_InitClassName
|
JVM_InitClassName
|
||||||
JVM_InitStackTraceElement
|
JVM_InitStackTraceElement
|
||||||
@ -150,6 +154,7 @@ JVM_IsDumpingClassList
|
|||||||
JVM_IsFinalizationEnabled
|
JVM_IsFinalizationEnabled
|
||||||
JVM_IsHiddenClass
|
JVM_IsHiddenClass
|
||||||
JVM_IsInterface
|
JVM_IsInterface
|
||||||
|
JVM_IsPreviewEnabled
|
||||||
JVM_IsPrimitiveClass
|
JVM_IsPrimitiveClass
|
||||||
JVM_IsRecord
|
JVM_IsRecord
|
||||||
JVM_IsSameClassPackage
|
JVM_IsSameClassPackage
|
||||||
@ -182,15 +187,19 @@ JVM_RawMonitorEnter
|
|||||||
JVM_RawMonitorExit
|
JVM_RawMonitorExit
|
||||||
JVM_ReferenceClear
|
JVM_ReferenceClear
|
||||||
JVM_ReferenceRefersTo
|
JVM_ReferenceRefersTo
|
||||||
|
JVM_RegisterContinuationMethods
|
||||||
JVM_RegisterLambdaProxyClassForArchiving
|
JVM_RegisterLambdaProxyClassForArchiving
|
||||||
JVM_RegisterSignal
|
JVM_RegisterSignal
|
||||||
JVM_ReleaseUTF
|
JVM_ReleaseUTF
|
||||||
JVM_ReportFinalizationComplete
|
JVM_ReportFinalizationComplete
|
||||||
JVM_ResumeThread
|
JVM_ResumeThread
|
||||||
|
JVM_ExtentLocalCache
|
||||||
|
JVM_SetExtentLocalCache
|
||||||
JVM_SetArrayElement
|
JVM_SetArrayElement
|
||||||
JVM_SetClassSigners
|
JVM_SetClassSigners
|
||||||
JVM_SetNativeThreadName
|
JVM_SetNativeThreadName
|
||||||
JVM_SetPrimitiveArrayElement
|
JVM_SetPrimitiveArrayElement
|
||||||
|
JVM_SetStackWalkContinuation
|
||||||
JVM_SetThreadPriority
|
JVM_SetThreadPriority
|
||||||
JVM_Sleep
|
JVM_Sleep
|
||||||
JVM_StartThread
|
JVM_StartThread
|
||||||
@ -210,3 +219,10 @@ JVM_AddReadsModule
|
|||||||
JVM_DefineArchivedModules
|
JVM_DefineArchivedModules
|
||||||
JVM_DefineModule
|
JVM_DefineModule
|
||||||
JVM_SetBootLoaderUnnamedModule
|
JVM_SetBootLoaderUnnamedModule
|
||||||
|
|
||||||
|
# Virtual thread notifications for JVMTI
|
||||||
|
JVM_VirtualThreadMountBegin
|
||||||
|
JVM_VirtualThreadMountEnd
|
||||||
|
JVM_VirtualThreadUnmountBegin
|
||||||
|
JVM_VirtualThreadUnmountEnd
|
||||||
|
#
|
||||||
|
@ -95,8 +95,12 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
|
|||||||
SRC := $(MICROBENCHMARK_SRC), \
|
SRC := $(MICROBENCHMARK_SRC), \
|
||||||
BIN := $(MICROBENCHMARK_CLASSES), \
|
BIN := $(MICROBENCHMARK_CLASSES), \
|
||||||
JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \
|
JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \
|
||||||
--add-exports java.base/sun.invoke.util=ALL-UNNAMED, \
|
--add-exports java.base/sun.invoke.util=ALL-UNNAMED \
|
||||||
JAVA_FLAGS := --add-modules jdk.unsupported --limit-modules java.management, \
|
--add-exports java.base/jdk.internal.vm=ALL-UNNAMED \
|
||||||
|
--enable-preview, \
|
||||||
|
JAVA_FLAGS := --add-modules jdk.unsupported --limit-modules java.management \
|
||||||
|
--add-exports java.base/jdk.internal.vm=ALL-UNNAMED \
|
||||||
|
--enable-preview, \
|
||||||
))
|
))
|
||||||
|
|
||||||
$(BUILD_JDK_MICROBENCHMARK): $(JMH_COMPILE_JARS)
|
$(BUILD_JDK_MICROBENCHMARK): $(JMH_COMPILE_JARS)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
@ -148,8 +148,10 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libNoFramePointer := $(NO_FRAMEPOINTER_CFLA
|
|||||||
# Optimization -O3 needed, HIGH == -O3
|
# Optimization -O3 needed, HIGH == -O3
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_OPTIMIZATION_libNoFramePointer := HIGH
|
BUILD_HOTSPOT_JTREG_LIBRARIES_OPTIMIZATION_libNoFramePointer := HIGH
|
||||||
|
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS := -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS
|
JVMTI_COMMON_INCLUDES=-I$(TOPDIR)/test/lib/jdk/test/lib/jvmti
|
||||||
BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS := -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS
|
|
||||||
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS := -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS $(JVMTI_COMMON_INCLUDES)
|
||||||
|
BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS := -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS $(JVMTI_COMMON_INCLUDES)
|
||||||
|
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libProcessUtils := $(VM_SHARE_INCLUDES)
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libProcessUtils := $(VM_SHARE_INCLUDES)
|
||||||
|
|
||||||
@ -346,6 +348,7 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libvminit001 := $(NSK_JVMTI_AGENT_INCLUDES)
|
|||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrd001 := $(NSK_JVMTI_AGENT_INCLUDES)
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrd001 := $(NSK_JVMTI_AGENT_INCLUDES)
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrd002 := $(NSK_JVMTI_AGENT_INCLUDES)
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrd002 := $(NSK_JVMTI_AGENT_INCLUDES)
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrd003 := $(NSK_JVMTI_AGENT_INCLUDES)
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrd003 := $(NSK_JVMTI_AGENT_INCLUDES)
|
||||||
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendvthr001 := $(NSK_JVMTI_AGENT_INCLUDES)
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdeclcls002 := $(NSK_JVMTI_AGENT_INCLUDES)
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdeclcls002 := $(NSK_JVMTI_AGENT_INCLUDES)
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdeclcls003 := $(NSK_JVMTI_AGENT_INCLUDES)
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdeclcls003 := $(NSK_JVMTI_AGENT_INCLUDES)
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdeclcls001 := $(NSK_JVMTI_AGENT_INCLUDES)
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdeclcls001 := $(NSK_JVMTI_AGENT_INCLUDES)
|
||||||
@ -1012,6 +1015,7 @@ else
|
|||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrd001 += -lpthread
|
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrd001 += -lpthread
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrd002 += -lpthread
|
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrd002 += -lpthread
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrd003 += -lpthread
|
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrd003 += -lpthread
|
||||||
|
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendvthr001 += -lpthread
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdeclcls002 += -lpthread
|
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdeclcls002 += -lpthread
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdeclcls003 += -lpthread
|
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdeclcls003 += -lpthread
|
||||||
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdeclcls001 += -lpthread
|
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdeclcls001 += -lpthread
|
||||||
|
@ -3829,6 +3829,8 @@ encode %{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__ post_call_nop();
|
||||||
|
|
||||||
// Only non uncommon_trap calls need to reinitialize ptrue.
|
// Only non uncommon_trap calls need to reinitialize ptrue.
|
||||||
if (Compile::current()->max_vector_size() > 0 && uncommon_trap_request() == 0) {
|
if (Compile::current()->max_vector_size() > 0 && uncommon_trap_request() == 0) {
|
||||||
__ reinitialize_ptrue();
|
__ reinitialize_ptrue();
|
||||||
@ -3842,7 +3844,9 @@ encode %{
|
|||||||
if (call == NULL) {
|
if (call == NULL) {
|
||||||
ciEnv::current()->record_failure("CodeCache is full");
|
ciEnv::current()->record_failure("CodeCache is full");
|
||||||
return;
|
return;
|
||||||
} else if (Compile::current()->max_vector_size() > 0) {
|
}
|
||||||
|
__ post_call_nop();
|
||||||
|
if (Compile::current()->max_vector_size() > 0) {
|
||||||
__ reinitialize_ptrue();
|
__ reinitialize_ptrue();
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
@ -3870,6 +3874,7 @@ encode %{
|
|||||||
ciEnv::current()->record_failure("CodeCache is full");
|
ciEnv::current()->record_failure("CodeCache is full");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
__ post_call_nop();
|
||||||
} else {
|
} else {
|
||||||
Label retaddr;
|
Label retaddr;
|
||||||
__ adr(rscratch2, retaddr);
|
__ adr(rscratch2, retaddr);
|
||||||
@ -3878,6 +3883,7 @@ encode %{
|
|||||||
__ stp(zr, rscratch2, Address(__ pre(sp, -2 * wordSize)));
|
__ stp(zr, rscratch2, Address(__ pre(sp, -2 * wordSize)));
|
||||||
__ blr(rscratch1);
|
__ blr(rscratch1);
|
||||||
__ bind(retaddr);
|
__ bind(retaddr);
|
||||||
|
__ post_call_nop();
|
||||||
__ add(sp, sp, 2 * wordSize);
|
__ add(sp, sp, 2 * wordSize);
|
||||||
}
|
}
|
||||||
if (Compile::current()->max_vector_size() > 0) {
|
if (Compile::current()->max_vector_size() > 0) {
|
||||||
|
@ -123,9 +123,9 @@ void AbstractInterpreter::layout_activation(Method* method,
|
|||||||
// It is also guaranteed to be walkable even though it is in a
|
// It is also guaranteed to be walkable even though it is in a
|
||||||
// skeletal state
|
// skeletal state
|
||||||
|
|
||||||
int max_locals = method->max_locals() * Interpreter::stackElementWords;
|
const int max_locals = method->max_locals() * Interpreter::stackElementWords;
|
||||||
int extra_locals = (method->max_locals() - method->size_of_parameters()) *
|
const int params = method->size_of_parameters() * Interpreter::stackElementWords;
|
||||||
Interpreter::stackElementWords;
|
const int extra_locals = max_locals - params;
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable");
|
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable");
|
||||||
@ -144,12 +144,9 @@ void AbstractInterpreter::layout_activation(Method* method,
|
|||||||
// align the incoming parameters with the caller's temporary
|
// align the incoming parameters with the caller's temporary
|
||||||
// expression stack. For other types of caller frame it doesn't
|
// expression stack. For other types of caller frame it doesn't
|
||||||
// matter.
|
// matter.
|
||||||
intptr_t* locals;
|
intptr_t* const locals = caller->is_interpreted_frame()
|
||||||
if (caller->is_interpreted_frame()) {
|
? caller->interpreter_frame_last_sp() + caller_actual_parameters - 1
|
||||||
locals = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1;
|
: interpreter_frame->sender_sp() + max_locals - 1;
|
||||||
} else {
|
|
||||||
locals = interpreter_frame->sender_sp() + max_locals - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if (caller->is_interpreted_frame()) {
|
if (caller->is_interpreted_frame()) {
|
||||||
@ -171,14 +168,10 @@ void AbstractInterpreter::layout_activation(Method* method,
|
|||||||
// All frames but the initial (oldest) interpreter frame we fill in have
|
// All frames but the initial (oldest) interpreter frame we fill in have
|
||||||
// a value for sender_sp that allows walking the stack but isn't
|
// a value for sender_sp that allows walking the stack but isn't
|
||||||
// truly correct. Correct the value here.
|
// truly correct. Correct the value here.
|
||||||
if (extra_locals != 0 &&
|
if (extra_locals != 0 && interpreter_frame->sender_sp() == interpreter_frame->interpreter_frame_sender_sp()) {
|
||||||
interpreter_frame->sender_sp() ==
|
interpreter_frame->set_interpreter_frame_sender_sp(caller->sp() + extra_locals);
|
||||||
interpreter_frame->interpreter_frame_sender_sp()) {
|
|
||||||
interpreter_frame->set_interpreter_frame_sender_sp(caller->sp() +
|
|
||||||
extra_locals);
|
|
||||||
}
|
}
|
||||||
*interpreter_frame->interpreter_frame_cache_addr() =
|
|
||||||
method->constants()->cache();
|
*interpreter_frame->interpreter_frame_cache_addr() = method->constants()->cache();
|
||||||
*interpreter_frame->interpreter_frame_mirror_addr() =
|
*interpreter_frame->interpreter_frame_mirror_addr() = method->method_holder()->java_mirror();
|
||||||
method->method_holder()->java_mirror();
|
|
||||||
}
|
}
|
||||||
|
@ -438,6 +438,7 @@ int LIR_Assembler::emit_unwind_handler() {
|
|||||||
__ unlock_object(r5, r4, r0, *stub->entry());
|
__ unlock_object(r5, r4, r0, *stub->entry());
|
||||||
}
|
}
|
||||||
__ bind(*stub->continuation());
|
__ bind(*stub->continuation());
|
||||||
|
__ dec_held_monitor_count(rthread);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compilation()->env()->dtrace_method_probes()) {
|
if (compilation()->env()->dtrace_method_probes()) {
|
||||||
@ -2037,6 +2038,7 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
add_call_info(code_offset(), op->info());
|
add_call_info(code_offset(), op->info());
|
||||||
|
__ post_call_nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2047,6 +2049,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
add_call_info(code_offset(), op->info());
|
add_call_info(code_offset(), op->info());
|
||||||
|
__ post_call_nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LIR_Assembler::emit_static_call_stub() {
|
void LIR_Assembler::emit_static_call_stub() {
|
||||||
@ -2571,7 +2574,18 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
|||||||
} else {
|
} else {
|
||||||
Unimplemented();
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
if (op->code() == lir_lock) {
|
||||||
|
// If deoptimization happens in Runtime1::monitorenter, inc_held_monitor_count after backing from slowpath
|
||||||
|
// will be skipped. Solution is:
|
||||||
|
// 1. Increase only in fastpath
|
||||||
|
// 2. Runtime1::monitorenter increase count after locking
|
||||||
|
__ inc_held_monitor_count(rthread);
|
||||||
|
}
|
||||||
__ bind(*op->stub()->continuation());
|
__ bind(*op->stub()->continuation());
|
||||||
|
if (op->code() == lir_unlock) {
|
||||||
|
// unlock in slowpath is JRT_Leaf stub, no deoptimization can happen
|
||||||
|
__ dec_held_monitor_count(rthread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
|
void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
|
||||||
@ -2899,6 +2913,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* arg
|
|||||||
if (info != NULL) {
|
if (info != NULL) {
|
||||||
add_call_info_here(info);
|
add_call_info_here(info);
|
||||||
}
|
}
|
||||||
|
__ post_call_nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) {
|
void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -338,6 +338,17 @@ void LIRGenerator::do_MonitorExit(MonitorExit* x) {
|
|||||||
monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no());
|
monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LIRGenerator::do_continuation_doYield(Intrinsic* x) {
|
||||||
|
BasicTypeList signature(0);
|
||||||
|
CallingConvention* cc = frame_map()->java_calling_convention(&signature, true);
|
||||||
|
|
||||||
|
const LIR_Opr result_reg = result_register_for(x->type());
|
||||||
|
address entry = StubRoutines::cont_doYield();
|
||||||
|
LIR_Opr result = rlock_result(x);
|
||||||
|
CodeEmitInfo* info = state_for(x, x->state());
|
||||||
|
__ call_runtime(entry, LIR_OprFact::illegalOpr, result_reg, cc->args(), info);
|
||||||
|
__ move(result_reg, result);
|
||||||
|
}
|
||||||
|
|
||||||
void LIRGenerator::do_NegateOp(NegateOp* x) {
|
void LIRGenerator::do_NegateOp(NegateOp* x) {
|
||||||
|
|
||||||
|
51
src/hotspot/cpu/aarch64/continuationEntry_aarch64.inline.hpp
Normal file
51
src/hotspot/cpu/aarch64/continuationEntry_aarch64.inline.hpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_AARCH64_CONTINUATIONENTRY_AARCH64_INLINE_HPP
|
||||||
|
#define CPU_AARCH64_CONTINUATIONENTRY_AARCH64_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationEntry.hpp"
|
||||||
|
|
||||||
|
#include "code/codeCache.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
inline frame ContinuationEntry::to_frame() const {
|
||||||
|
static CodeBlob* cb = CodeCache::find_blob_fast(entry_pc());
|
||||||
|
assert(cb != nullptr, "");
|
||||||
|
assert(cb->as_compiled_method()->method()->is_continuation_enter_intrinsic(), "");
|
||||||
|
return frame(entry_sp(), entry_sp(), entry_fp(), entry_pc(), cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationEntry::entry_fp() const {
|
||||||
|
return (intptr_t*)((address)this + size());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationEntry::update_register_map(RegisterMap* map) const {
|
||||||
|
intptr_t** fp = (intptr_t**)(bottom_sender_sp() - frame::sender_sp_offset);
|
||||||
|
frame::update_map_with_saved_link(map, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CPU_AARCH64_CONTINUATIONENTRY_AARCH64_INLINE_HPP
|
@ -0,0 +1,301 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_AARCH64_CONTINUATIONFREEZETHAW_AARCH64_INLINE_HPP
|
||||||
|
#define CPU_AARCH64_CONTINUATIONFREEZETHAW_AARCH64_INLINE_HPP
|
||||||
|
|
||||||
|
#include "code/codeBlob.inline.hpp"
|
||||||
|
#include "oops/stackChunkOop.inline.hpp"
|
||||||
|
#include "runtime/frame.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
inline void patch_callee_link(const frame& f, intptr_t* fp) {
|
||||||
|
DEBUG_ONLY(intptr_t* orig = *ContinuationHelper::Frame::callee_link_address(f));
|
||||||
|
*ContinuationHelper::Frame::callee_link_address(f) = fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void patch_callee_link_relative(const frame& f, intptr_t* fp) {
|
||||||
|
intptr_t* la = (intptr_t*)ContinuationHelper::Frame::callee_link_address(f);
|
||||||
|
intptr_t new_value = fp - la;
|
||||||
|
*la = new_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////// Freeze
|
||||||
|
|
||||||
|
// Fast path
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
|
||||||
|
// copy the spilled fp from the heap to the stack
|
||||||
|
*(frame_sp - frame::sender_sp_offset) = *(heap_sp - frame::sender_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slow path
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline frame FreezeBase::sender(const frame& f) {
|
||||||
|
assert(FKind::is_instance(f), "");
|
||||||
|
if (FKind::interpreted) {
|
||||||
|
return frame(f.sender_sp(), f.interpreter_frame_sender_sp(), f.link(), f.sender_pc());
|
||||||
|
}
|
||||||
|
intptr_t** link_addr = link_address<FKind>(f);
|
||||||
|
|
||||||
|
intptr_t* sender_sp = (intptr_t*)(link_addr + frame::sender_sp_offset); // f.unextended_sp() + (fsize/wordSize); //
|
||||||
|
address sender_pc = (address) *(sender_sp-1);
|
||||||
|
assert(sender_sp != f.sp(), "must have changed");
|
||||||
|
|
||||||
|
int slot = 0;
|
||||||
|
CodeBlob* sender_cb = CodeCache::find_blob_and_oopmap(sender_pc, slot);
|
||||||
|
return sender_cb != nullptr
|
||||||
|
? frame(sender_sp, sender_sp, *link_addr, sender_pc, sender_cb,
|
||||||
|
slot == -1 ? nullptr : sender_cb->oop_map_for_slot(slot, sender_pc),
|
||||||
|
false /* on_heap ? */)
|
||||||
|
: frame(sender_sp, sender_sp, *link_addr, sender_pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
|
||||||
|
assert(FKind::is_instance(f), "");
|
||||||
|
assert(!caller.is_interpreted_frame()
|
||||||
|
|| caller.unextended_sp() == (intptr_t*)caller.at(frame::interpreter_frame_last_sp_offset), "");
|
||||||
|
|
||||||
|
intptr_t *sp, *fp; // sp is really our unextended_sp
|
||||||
|
if (FKind::interpreted) {
|
||||||
|
assert((intptr_t*)f.at(frame::interpreter_frame_last_sp_offset) == nullptr
|
||||||
|
|| f.unextended_sp() == (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset), "");
|
||||||
|
int locals = f.interpreter_frame_method()->max_locals();
|
||||||
|
// If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set
|
||||||
|
// the chunk's argsize in finalize_freeze and make room for it above the unextended_sp
|
||||||
|
bool overlap_caller = caller.is_interpreted_frame() || caller.is_empty();
|
||||||
|
fp = caller.unextended_sp() - (locals + frame::sender_sp_offset) + (overlap_caller ? ContinuationHelper::InterpretedFrame::stack_argsize(f) : 0);
|
||||||
|
sp = fp - (f.fp() - f.unextended_sp());
|
||||||
|
assert(sp <= fp, "");
|
||||||
|
assert(fp <= caller.unextended_sp(), "");
|
||||||
|
caller.set_sp(fp + frame::sender_sp_offset);
|
||||||
|
|
||||||
|
assert(_cont.tail()->is_in_chunk(sp), "");
|
||||||
|
|
||||||
|
frame hf(sp, sp, fp, f.pc(), nullptr, nullptr, true /* on_heap */);
|
||||||
|
*hf.addr_at(frame::interpreter_frame_locals_offset) = frame::sender_sp_offset + locals - 1;
|
||||||
|
return hf;
|
||||||
|
} else {
|
||||||
|
// We need to re-read fp out of the frame because it may be an oop and we might have
|
||||||
|
// had a safepoint in finalize_freeze, after constructing f.
|
||||||
|
fp = *(intptr_t**)(f.sp() - frame::sender_sp_offset);
|
||||||
|
|
||||||
|
int fsize = FKind::size(f);
|
||||||
|
sp = caller.unextended_sp() - fsize;
|
||||||
|
if (caller.is_interpreted_frame()) {
|
||||||
|
// If the caller is interpreted, our stackargs are not supposed to overlap with it
|
||||||
|
// so we make more room by moving sp down by argsize
|
||||||
|
int argsize = FKind::stack_argsize(f);
|
||||||
|
sp -= argsize;
|
||||||
|
}
|
||||||
|
caller.set_sp(sp + fsize);
|
||||||
|
|
||||||
|
assert(_cont.tail()->is_in_chunk(sp), "");
|
||||||
|
|
||||||
|
return frame(sp, sp, fp, f.pc(), nullptr, nullptr, true /* on_heap */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
|
||||||
|
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
|
||||||
|
intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset);
|
||||||
|
if (real_unextended_sp != nullptr) {
|
||||||
|
f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void relativize_one(intptr_t* const vfp, intptr_t* const hfp, int offset) {
|
||||||
|
assert(*(hfp + offset) == *(vfp + offset), "");
|
||||||
|
intptr_t* addr = hfp + offset;
|
||||||
|
intptr_t value = *(intptr_t**)addr - vfp;
|
||||||
|
*addr = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, const frame& hf) {
|
||||||
|
intptr_t* vfp = f.fp();
|
||||||
|
intptr_t* hfp = hf.fp();
|
||||||
|
assert(hfp == hf.unextended_sp() + (f.fp() - f.unextended_sp()), "");
|
||||||
|
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0)
|
||||||
|
|| (f.unextended_sp() == f.sp()), "");
|
||||||
|
assert(f.fp() > (intptr_t*)f.at(frame::interpreter_frame_initial_sp_offset), "");
|
||||||
|
|
||||||
|
// on AARCH64, we may insert padding between the locals and the rest of the frame
|
||||||
|
// (see TemplateInterpreterGenerator::generate_normal_entry, and AbstractInterpreter::layout_activation)
|
||||||
|
// so we compute locals "from scratch" rather than relativizing the value in the stack frame, which might include padding,
|
||||||
|
// since we don't freeze the padding word (see recurse_freeze_interpreted_frame).
|
||||||
|
|
||||||
|
// at(frame::interpreter_frame_last_sp_offset) can be NULL at safepoint preempts
|
||||||
|
*hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp();
|
||||||
|
*hf.addr_at(frame::interpreter_frame_locals_offset) = frame::sender_sp_offset + f.interpreter_frame_method()->max_locals() - 1;
|
||||||
|
|
||||||
|
relativize_one(vfp, hfp, frame::interpreter_frame_initial_sp_offset); // == block_top == block_bottom
|
||||||
|
|
||||||
|
assert((hf.fp() - hf.unextended_sp()) == (f.fp() - f.unextended_sp()), "");
|
||||||
|
assert(hf.unextended_sp() == (intptr_t*)hf.at(frame::interpreter_frame_last_sp_offset), "");
|
||||||
|
assert(hf.unextended_sp() <= (intptr_t*)hf.at(frame::interpreter_frame_initial_sp_offset), "");
|
||||||
|
assert(hf.fp() > (intptr_t*)hf.at(frame::interpreter_frame_initial_sp_offset), "");
|
||||||
|
assert(hf.fp() <= (intptr_t*)hf.at(frame::interpreter_frame_locals_offset), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::set_top_frame_metadata_pd(const frame& hf) {
|
||||||
|
stackChunkOop chunk = _cont.tail();
|
||||||
|
assert(chunk->is_in_chunk(hf.sp() - 1), "");
|
||||||
|
assert(chunk->is_in_chunk(hf.sp() - frame::sender_sp_offset), "");
|
||||||
|
|
||||||
|
*(hf.sp() - 1) = (intptr_t)hf.pc();
|
||||||
|
|
||||||
|
intptr_t* fp_addr = hf.sp() - frame::sender_sp_offset;
|
||||||
|
*fp_addr = hf.is_interpreted_frame() ? (intptr_t)(hf.fp() - fp_addr)
|
||||||
|
: (intptr_t)hf.fp();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
|
||||||
|
if (caller.is_interpreted_frame()) {
|
||||||
|
assert(!caller.is_empty(), "");
|
||||||
|
patch_callee_link_relative(caller, caller.fp());
|
||||||
|
} else {
|
||||||
|
// If we're the bottom-most frame frozen in this freeze, the caller might have stayed frozen in the chunk,
|
||||||
|
// and its oop-containing fp fixed. We've now just overwritten it, so we must patch it back to its value
|
||||||
|
// as read from the chunk.
|
||||||
|
patch_callee_link(caller, caller.fp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////// Thaw
|
||||||
|
|
||||||
|
// Fast path
|
||||||
|
|
||||||
|
inline void ThawBase::prefetch_chunk_pd(void* start, int size) {
|
||||||
|
size <<= LogBytesPerWord;
|
||||||
|
Prefetch::read(start, size);
|
||||||
|
Prefetch::read(start, size - 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThawBase::patch_chunk_pd(intptr_t* sp) {
|
||||||
|
intptr_t* fp = _cont.entryFP();
|
||||||
|
*(intptr_t**)(sp - frame::sender_sp_offset) = fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slow path
|
||||||
|
|
||||||
|
inline frame ThawBase::new_entry_frame() {
|
||||||
|
intptr_t* sp = _cont.entrySP();
|
||||||
|
return frame(sp, sp, _cont.entryFP(), _cont.entryPC()); // TODO PERF: This finds code blob and computes deopt state
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) {
|
||||||
|
assert(FKind::is_instance(hf), "");
|
||||||
|
// The values in the returned frame object will be written into the callee's stack in patch.
|
||||||
|
|
||||||
|
if (FKind::interpreted) {
|
||||||
|
intptr_t* heap_sp = hf.unextended_sp();
|
||||||
|
const int fsize = ContinuationHelper::InterpretedFrame::frame_bottom(hf) - hf.unextended_sp();
|
||||||
|
const int locals = hf.interpreter_frame_method()->max_locals();
|
||||||
|
intptr_t* frame_sp = caller.unextended_sp() - fsize;
|
||||||
|
intptr_t* fp = frame_sp + (hf.fp() - heap_sp);
|
||||||
|
int padding = 0;
|
||||||
|
if ((intptr_t)fp % frame::frame_alignment != 0) {
|
||||||
|
fp--;
|
||||||
|
frame_sp--;
|
||||||
|
padding++;
|
||||||
|
log_develop_trace(continuations)("Adding internal interpreted frame alignment");
|
||||||
|
}
|
||||||
|
DEBUG_ONLY(intptr_t* unextended_sp = fp + *hf.addr_at(frame::interpreter_frame_last_sp_offset);)
|
||||||
|
assert(frame_sp == unextended_sp, "");
|
||||||
|
caller.set_sp(fp + frame::sender_sp_offset);
|
||||||
|
frame f(frame_sp, frame_sp, fp, hf.pc());
|
||||||
|
// it's set again later in set_interpreter_frame_bottom, but we need to set the locals now so that
|
||||||
|
// we could call ContinuationHelper::InterpretedFrame::frame_bottom
|
||||||
|
intptr_t offset = *hf.addr_at(frame::interpreter_frame_locals_offset);
|
||||||
|
assert((int)offset == frame::sender_sp_offset + locals - 1, "");
|
||||||
|
// derelativize locals
|
||||||
|
*(intptr_t**)f.addr_at(frame::interpreter_frame_locals_offset) = fp + padding + offset;
|
||||||
|
assert((intptr_t)f.fp() % frame::frame_alignment == 0, "");
|
||||||
|
return f;
|
||||||
|
} else {
|
||||||
|
int fsize = FKind::size(hf);
|
||||||
|
intptr_t* frame_sp = caller.unextended_sp() - fsize;
|
||||||
|
if (bottom || caller.is_interpreted_frame()) {
|
||||||
|
int argsize = hf.compiled_frame_stack_argsize();
|
||||||
|
|
||||||
|
fsize += argsize;
|
||||||
|
frame_sp -= argsize;
|
||||||
|
caller.set_sp(caller.sp() - argsize);
|
||||||
|
assert(caller.sp() == frame_sp + (fsize-argsize), "");
|
||||||
|
|
||||||
|
frame_sp = align(hf, frame_sp, caller, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(hf.cb() != nullptr, "");
|
||||||
|
assert(hf.oop_map() != nullptr, "");
|
||||||
|
intptr_t* fp;
|
||||||
|
if (PreserveFramePointer) {
|
||||||
|
// we need to recreate a "real" frame pointer, pointing into the stack
|
||||||
|
fp = frame_sp + FKind::size(hf) - frame::sender_sp_offset;
|
||||||
|
} else {
|
||||||
|
fp = FKind::stub
|
||||||
|
? frame_sp + fsize - frame::sender_sp_offset // on AArch64, this value is used for the safepoint stub
|
||||||
|
: *(intptr_t**)(hf.sp() - frame::sender_sp_offset); // we need to re-read fp because it may be an oop and we might have fixed the frame.
|
||||||
|
}
|
||||||
|
return frame(frame_sp, frame_sp, fp, hf.pc(), hf.cb(), hf.oop_map(), false); // TODO PERF : this computes deopt state; is it necessary?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& caller, bool bottom) {
|
||||||
|
#ifdef _LP64
|
||||||
|
if (((intptr_t)frame_sp & 0xf) != 0) {
|
||||||
|
assert(caller.is_interpreted_frame() || (bottom && hf.compiled_frame_stack_argsize() % 2 != 0), "");
|
||||||
|
frame_sp--;
|
||||||
|
caller.set_sp(caller.sp() - 1);
|
||||||
|
}
|
||||||
|
assert(is_aligned(frame_sp, frame::frame_alignment), "");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return frame_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::patch_pd(frame& f, const frame& caller) {
|
||||||
|
patch_callee_link(caller, caller.fp());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void derelativize_one(intptr_t* const fp, int offset) {
|
||||||
|
intptr_t* addr = fp + offset;
|
||||||
|
*addr = (intptr_t)(fp + *addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
|
||||||
|
intptr_t* vfp = f.fp();
|
||||||
|
|
||||||
|
derelativize_one(vfp, frame::interpreter_frame_last_sp_offset);
|
||||||
|
derelativize_one(vfp, frame::interpreter_frame_initial_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::set_interpreter_frame_bottom(const frame& f, intptr_t* bottom) {
|
||||||
|
*(intptr_t**)f.addr_at(frame::interpreter_frame_locals_offset) = bottom - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_AARCH64_CONTINUATIONFREEZETHAW_AARCH64_INLINE_HPP
|
140
src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp
Normal file
140
src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_AARCH64_CONTINUATIONHELPER_AARCH64_INLINE_HPP
|
||||||
|
#define CPU_AARCH64_CONTINUATIONHELPER_AARCH64_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationHelper.hpp"
|
||||||
|
|
||||||
|
#include "runtime/continuationEntry.inline.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
#include "utilities/macros.hpp"
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t** link_address(const frame& f) {
|
||||||
|
assert(FKind::is_instance(f), "");
|
||||||
|
return FKind::interpreted
|
||||||
|
? (intptr_t**)(f.fp() + frame::link_offset)
|
||||||
|
: (intptr_t**)(f.unextended_sp() + f.cb()->frame_size() - frame::sender_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ContinuationHelper::frame_align_words(int size) {
|
||||||
|
#ifdef _LP64
|
||||||
|
return size & 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::frame_align_pointer(intptr_t* sp) {
|
||||||
|
#ifdef _LP64
|
||||||
|
sp = align_down(sp, frame::frame_alignment);
|
||||||
|
#endif
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline void ContinuationHelper::update_register_map(const frame& f, RegisterMap* map) {
|
||||||
|
frame::update_map_with_saved_link(map, link_address<FKind>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::update_register_map_with_callee(const frame& f, RegisterMap* map) {
|
||||||
|
frame::update_map_with_saved_link(map, ContinuationHelper::Frame::callee_link_address(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::push_pd(const frame& f) {
|
||||||
|
*(intptr_t**)(f.sp() - frame::sender_sp_offset) = f.fp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void ContinuationHelper::set_anchor_to_entry_pd(JavaFrameAnchor* anchor, ContinuationEntry* entry) {
|
||||||
|
anchor->set_last_Java_fp(entry->entry_fp());
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
inline void ContinuationHelper::set_anchor_pd(JavaFrameAnchor* anchor, intptr_t* sp) {
|
||||||
|
intptr_t* fp = *(intptr_t**)(sp - frame::sender_sp_offset);
|
||||||
|
anchor->set_last_Java_fp(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ContinuationHelper::Frame::assert_frame_laid_out(frame f) {
|
||||||
|
intptr_t* sp = f.sp();
|
||||||
|
address pc = *(address*)(sp - frame::sender_sp_ret_address_offset());
|
||||||
|
intptr_t* fp = *(intptr_t**)(sp - frame::sender_sp_offset);
|
||||||
|
assert(f.raw_pc() == pc, "f.ra_pc: " INTPTR_FORMAT " actual: " INTPTR_FORMAT, p2i(f.raw_pc()), p2i(pc));
|
||||||
|
assert(f.fp() == fp, "f.fp: " INTPTR_FORMAT " actual: " INTPTR_FORMAT, p2i(f.fp()), p2i(fp));
|
||||||
|
return f.raw_pc() == pc && f.fp() == fp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline intptr_t** ContinuationHelper::Frame::callee_link_address(const frame& f) {
|
||||||
|
return (intptr_t**)(f.sp() - frame::sender_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::Frame::return_pc_address(const frame& f) {
|
||||||
|
return (address*)(f.real_fp() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::InterpretedFrame::return_pc_address(const frame& f) {
|
||||||
|
return (address*)(f.fp() + frame::return_addr_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::InterpretedFrame::patch_sender_sp(frame& f, intptr_t* sp) {
|
||||||
|
assert(f.is_interpreted_frame(), "");
|
||||||
|
intptr_t* la = f.addr_at(frame::interpreter_frame_sender_sp_offset);
|
||||||
|
*la = f.is_heap_frame() ? (intptr_t)(sp - f.fp()) : (intptr_t)sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address ContinuationHelper::Frame::real_pc(const frame& f) {
|
||||||
|
address* pc_addr = &(((address*) f.sp())[-1]);
|
||||||
|
return *pc_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
|
||||||
|
address* pc_addr = &(((address*) f.sp())[-1]);
|
||||||
|
*pc_addr = pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, InterpreterOopMap* mask) { // inclusive; this will be copied with the frame
|
||||||
|
// interpreter_frame_last_sp_offset, points to unextended_sp includes arguments in the frame
|
||||||
|
// interpreter_frame_initial_sp_offset excludes expression stack slots
|
||||||
|
int expression_stack_sz = expression_stack_size(f, mask);
|
||||||
|
intptr_t* res = *(intptr_t**)f.addr_at(frame::interpreter_frame_initial_sp_offset) - expression_stack_sz;
|
||||||
|
assert(res == (intptr_t*)f.interpreter_frame_monitor_end() - expression_stack_sz, "");
|
||||||
|
assert(res >= f.unextended_sp(),
|
||||||
|
"res: " INTPTR_FORMAT " initial_sp: " INTPTR_FORMAT " last_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " expression_stack_size: %d",
|
||||||
|
p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at(frame::interpreter_frame_last_sp_offset), p2i(f.unextended_sp()), expression_stack_sz);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_bottom(const frame& f) { // exclusive; this will not be copied with the frame
|
||||||
|
return (intptr_t*)f.at(frame::interpreter_frame_locals_offset) + 1; // exclusive, so we add 1 word
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) {
|
||||||
|
return f.unextended_sp() + (callee_interpreted ? callee_argsize : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_AARCH64_CONTINUATIONHELPER_AARCH64_INLINE_HPP
|
@ -56,6 +56,9 @@ void RegisterMap::check_location_valid() {
|
|||||||
// Profiling/safepoint support
|
// Profiling/safepoint support
|
||||||
|
|
||||||
bool frame::safe_for_sender(JavaThread *thread) {
|
bool frame::safe_for_sender(JavaThread *thread) {
|
||||||
|
if (is_heap_frame()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
address sp = (address)_sp;
|
address sp = (address)_sp;
|
||||||
address fp = (address)_fp;
|
address fp = (address)_fp;
|
||||||
address unextended_sp = (address)_unextended_sp;
|
address unextended_sp = (address)_unextended_sp;
|
||||||
@ -156,6 +159,12 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
|||||||
sender_pc = pauth_strip_verifiable((address) *(sender_sp-1), (address)saved_fp);
|
sender_pc = pauth_strip_verifiable((address) *(sender_sp-1), (address)saved_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Continuation::is_return_barrier_entry(sender_pc)) {
|
||||||
|
// If our sender_pc is the return barrier, then our "real" sender is the continuation entry
|
||||||
|
frame s = Continuation::continuation_bottom_sender(thread, *this, sender_sp);
|
||||||
|
sender_sp = s.sp();
|
||||||
|
sender_pc = s.pc();
|
||||||
|
}
|
||||||
|
|
||||||
// If the potential sender is the interpreter then we can do some more checking
|
// If the potential sender is the interpreter then we can do some more checking
|
||||||
if (Interpreter::contains(sender_pc)) {
|
if (Interpreter::contains(sender_pc)) {
|
||||||
@ -271,6 +280,7 @@ void frame::patch_pc(Thread* thread, address pc) {
|
|||||||
address signing_sp = (((address*) sp())[-2]);
|
address signing_sp = (((address*) sp())[-2]);
|
||||||
address signed_pc = pauth_sign_return_address(pc, (address)signing_sp);
|
address signed_pc = pauth_sign_return_address(pc, (address)signing_sp);
|
||||||
address pc_old = pauth_strip_verifiable(*pc_addr, (address)signing_sp);
|
address pc_old = pauth_strip_verifiable(*pc_addr, (address)signing_sp);
|
||||||
|
|
||||||
if (TracePcPatching) {
|
if (TracePcPatching) {
|
||||||
tty->print("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
|
tty->print("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
|
||||||
p2i(pc_addr), p2i(pc_old), p2i(pc));
|
p2i(pc_addr), p2i(pc_old), p2i(pc));
|
||||||
@ -280,30 +290,24 @@ void frame::patch_pc(Thread* thread, address pc) {
|
|||||||
tty->print_cr("");
|
tty->print_cr("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(!Continuation::is_return_barrier_entry(pc_old), "return barrier");
|
||||||
|
|
||||||
// Either the return address is the original one or we are going to
|
// Either the return address is the original one or we are going to
|
||||||
// patch in the same address that's already there.
|
// patch in the same address that's already there.
|
||||||
assert(_pc == pc_old || pc == pc_old, "must be");
|
assert(_pc == pc_old || pc == pc_old || pc_old == 0, "");
|
||||||
|
DEBUG_ONLY(address old_pc = _pc;)
|
||||||
*pc_addr = signed_pc;
|
*pc_addr = signed_pc;
|
||||||
|
_pc = pc; // must be set before call to get_deopt_original_pc
|
||||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||||
if (original_pc != NULL) {
|
if (original_pc != NULL) {
|
||||||
assert(original_pc == _pc, "expected original PC to be stored before patching");
|
assert(original_pc == old_pc, "expected original PC to be stored before patching");
|
||||||
_deopt_state = is_deoptimized;
|
_deopt_state = is_deoptimized;
|
||||||
// leave _pc as is
|
_pc = original_pc;
|
||||||
} else {
|
} else {
|
||||||
_deopt_state = not_deoptimized;
|
_deopt_state = not_deoptimized;
|
||||||
_pc = pc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool frame::is_interpreted_frame() const {
|
|
||||||
return Interpreter::contains(pc());
|
|
||||||
}
|
|
||||||
|
|
||||||
int frame::frame_size(RegisterMap* map) const {
|
|
||||||
frame sender = this->sender(map);
|
|
||||||
return sender.sp() - sp();
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t* frame::entry_frame_argument_at(int offset) const {
|
intptr_t* frame::entry_frame_argument_at(int offset) const {
|
||||||
// convert offset to index to deal with tsi
|
// convert offset to index to deal with tsi
|
||||||
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
||||||
@ -330,7 +334,7 @@ BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
||||||
BasicObjectLock* result = (BasicObjectLock*) *addr_at(interpreter_frame_monitor_block_top_offset);
|
BasicObjectLock* result = (BasicObjectLock*) at(interpreter_frame_monitor_block_top_offset);
|
||||||
// make sure the pointer points inside the frame
|
// make sure the pointer points inside the frame
|
||||||
assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer");
|
assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer");
|
||||||
assert((intptr_t*) result < fp(), "monitor end should be strictly below the frame pointer");
|
assert((intptr_t*) result < fp(), "monitor end should be strictly below the frame pointer");
|
||||||
@ -401,6 +405,7 @@ void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// frame::adjust_unextended_sp
|
// frame::adjust_unextended_sp
|
||||||
|
#ifdef ASSERT
|
||||||
void frame::adjust_unextended_sp() {
|
void frame::adjust_unextended_sp() {
|
||||||
// On aarch64, sites calling method handle intrinsics and lambda forms are treated
|
// On aarch64, sites calling method handle intrinsics and lambda forms are treated
|
||||||
// as any other call site. Therefore, no special action is needed when we are
|
// as any other call site. Therefore, no special action is needed when we are
|
||||||
@ -412,32 +417,12 @@ void frame::adjust_unextended_sp() {
|
|||||||
// If the sender PC is a deoptimization point, get the original PC.
|
// If the sender PC is a deoptimization point, get the original PC.
|
||||||
if (sender_cm->is_deopt_entry(_pc) ||
|
if (sender_cm->is_deopt_entry(_pc) ||
|
||||||
sender_cm->is_deopt_mh_entry(_pc)) {
|
sender_cm->is_deopt_mh_entry(_pc)) {
|
||||||
DEBUG_ONLY(verify_deopt_original_pc(sender_cm, _unextended_sp));
|
verify_deopt_original_pc(sender_cm, _unextended_sp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// frame::update_map_with_saved_link
|
|
||||||
void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) {
|
|
||||||
// The interpreter and compiler(s) always save fp in a known
|
|
||||||
// location on entry. We must record where that location is
|
|
||||||
// so that if fp was live on callout from c2 we can find
|
|
||||||
// the saved copy no matter what it called.
|
|
||||||
|
|
||||||
// Since the interpreter always saves fp if we record where it is then
|
|
||||||
// we don't have to always save fp on entry and exit to c2 compiled
|
|
||||||
// code, on entry will be enough.
|
|
||||||
map->set_location(rfp->as_VMReg(), (address) link_addr);
|
|
||||||
// this is weird "H" ought to be at a higher address however the
|
|
||||||
// oopMaps seems to have the "H" regs at the same address and the
|
|
||||||
// vanilla register.
|
|
||||||
// XXXX make this go away
|
|
||||||
if (true) {
|
|
||||||
map->set_location(rfp->as_VMReg()->next(), (address) link_addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -449,6 +434,7 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
|||||||
|
|
||||||
// This is the sp before any possible extension (adapter/locals).
|
// This is the sp before any possible extension (adapter/locals).
|
||||||
intptr_t* unextended_sp = interpreter_frame_sender_sp();
|
intptr_t* unextended_sp = interpreter_frame_sender_sp();
|
||||||
|
intptr_t* sender_fp = link();
|
||||||
|
|
||||||
#if COMPILER2_OR_JVMCI
|
#if COMPILER2_OR_JVMCI
|
||||||
if (map->update_map()) {
|
if (map->update_map()) {
|
||||||
@ -459,94 +445,15 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
|||||||
// For ROP protection, Interpreter will have signed the sender_pc, but there is no requirement to authenticate it here.
|
// For ROP protection, Interpreter will have signed the sender_pc, but there is no requirement to authenticate it here.
|
||||||
address sender_pc = pauth_strip_verifiable(sender_pc_maybe_signed(), (address)link());
|
address sender_pc = pauth_strip_verifiable(sender_pc_maybe_signed(), (address)link());
|
||||||
|
|
||||||
return frame(sender_sp, unextended_sp, link(), sender_pc);
|
if (Continuation::is_return_barrier_entry(sender_pc)) {
|
||||||
}
|
if (map->walk_cont()) { // about to walk into an h-stack
|
||||||
|
return Continuation::top_frame(*this, map);
|
||||||
//------------------------------------------------------------------------------
|
} else {
|
||||||
// frame::sender_for_compiled_frame
|
return Continuation::continuation_bottom_sender(map->thread(), *this, sender_sp);
|
||||||
frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
}
|
||||||
// When the sp of a compiled frame is correct, we can get the correct sender sp
|
|
||||||
// by unextended sp + frame size.
|
|
||||||
// For the following two scenarios, the sp of a compiled frame is correct:
|
|
||||||
// a) This compiled frame is built from the anchor.
|
|
||||||
// b) This compiled frame is built from a callee frame, and the callee frame can
|
|
||||||
// calculate its sp correctly.
|
|
||||||
//
|
|
||||||
// For b), if the callee frame is a native code frame (such as leaf call), the sp of
|
|
||||||
// the compiled frame cannot be calculated correctly. There is currently no suitable
|
|
||||||
// solution to solve this problem perfectly. But when PreserveFramePointer is enabled,
|
|
||||||
// we can get the correct sender sp by fp + 2 (that is sender_sp()).
|
|
||||||
|
|
||||||
assert(_cb->frame_size() >= 0, "must have non-zero frame size");
|
|
||||||
intptr_t* l_sender_sp = (!PreserveFramePointer || _sp_is_trusted) ? unextended_sp() + _cb->frame_size()
|
|
||||||
: sender_sp();
|
|
||||||
intptr_t* unextended_sp = l_sender_sp;
|
|
||||||
|
|
||||||
// the return_address is always the word on the stack
|
|
||||||
|
|
||||||
// For ROP protection, C1/C2 will have signed the sender_pc, but there is no requirement to authenticate it here.
|
|
||||||
address sender_pc = pauth_strip_verifiable((address) *(l_sender_sp-1), (address) *(l_sender_sp-2));
|
|
||||||
|
|
||||||
intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp - frame::sender_sp_offset);
|
|
||||||
|
|
||||||
// assert (sender_sp() == l_sender_sp, "should be");
|
|
||||||
// assert (*saved_fp_addr == link(), "should be");
|
|
||||||
|
|
||||||
if (map->update_map()) {
|
|
||||||
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
|
||||||
// For C1, the runtime stub might not have oop maps, so set this flag
|
|
||||||
// outside of update_register_map.
|
|
||||||
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
|
||||||
if (_cb->oop_maps() != NULL) {
|
|
||||||
OopMapSet::update_register_map(this, map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since the prolog does the save and restore of FP there is no
|
return frame(sender_sp, unextended_sp, sender_fp, sender_pc);
|
||||||
// oopmap for it so we must fill in its location as if there was
|
|
||||||
// an oopmap entry since if our caller was compiled code there
|
|
||||||
// could be live jvm state in it.
|
|
||||||
update_map_with_saved_link(map, saved_fp_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return frame(l_sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// frame::sender_raw
|
|
||||||
frame frame::sender_raw(RegisterMap* map) const {
|
|
||||||
// Default is we done have to follow them. The sender_for_xxx will
|
|
||||||
// update it accordingly
|
|
||||||
map->set_include_argument_oops(false);
|
|
||||||
|
|
||||||
if (is_entry_frame())
|
|
||||||
return sender_for_entry_frame(map);
|
|
||||||
if (is_interpreted_frame())
|
|
||||||
return sender_for_interpreter_frame(map);
|
|
||||||
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
|
||||||
|
|
||||||
// This test looks odd: why is it not is_compiled_frame() ? That's
|
|
||||||
// because stubs also have OOP maps.
|
|
||||||
if (_cb != NULL) {
|
|
||||||
return sender_for_compiled_frame(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
|
||||||
// methods that exists in the core system.
|
|
||||||
|
|
||||||
// Native code may or may not have signed the return address, we have no way to be sure or what
|
|
||||||
// signing methods they used. Instead, just ensure the stripped value is used.
|
|
||||||
|
|
||||||
return frame(sender_sp(), link(), sender_pc());
|
|
||||||
}
|
|
||||||
|
|
||||||
frame frame::sender(RegisterMap* map) const {
|
|
||||||
frame result = sender_raw(map);
|
|
||||||
|
|
||||||
if (map->process_frames()) {
|
|
||||||
StackWatermarkSet::on_iteration(map->thread(), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
||||||
@ -655,7 +562,6 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result)
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
||||||
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
||||||
return &interpreter_frame_tos_address()[index];
|
return &interpreter_frame_tos_address()[index];
|
||||||
@ -678,6 +584,14 @@ void frame::describe_pd(FrameValues& values, int frame_no) {
|
|||||||
DESCRIBE_FP_OFFSET(interpreter_frame_bcp);
|
DESCRIBE_FP_OFFSET(interpreter_frame_bcp);
|
||||||
DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp);
|
DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intptr_t* ret_pc_loc = sp() - return_addr_offset;
|
||||||
|
address ret_pc = *(address*)ret_pc_loc;
|
||||||
|
if (Continuation::is_return_barrier_entry(ret_pc))
|
||||||
|
values.describe(frame_no, ret_pc_loc, "return address (return barrier)");
|
||||||
|
else
|
||||||
|
values.describe(frame_no, ret_pc_loc, err_msg("return address for #%d", frame_no));
|
||||||
|
values.describe(frame_no, sp() - sender_sp_offset, err_msg("saved fp for #%d", frame_no), 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -686,19 +600,6 @@ intptr_t *frame::initial_deoptimization_info() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr_t* frame::real_fp() const {
|
|
||||||
if (_cb != NULL) {
|
|
||||||
// use the frame size if valid
|
|
||||||
int size = _cb->frame_size();
|
|
||||||
if (size > 0) {
|
|
||||||
return unextended_sp() + size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else rely on fp()
|
|
||||||
assert(! is_compiled_frame(), "unknown compiled frame size");
|
|
||||||
return fp();
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef DESCRIBE_FP_OFFSET
|
#undef DESCRIBE_FP_OFFSET
|
||||||
|
|
||||||
#define DESCRIBE_FP_OFFSET(name) \
|
#define DESCRIBE_FP_OFFSET(name) \
|
||||||
|
@ -99,8 +99,14 @@
|
|||||||
entry_frame_call_wrapper_offset = -8,
|
entry_frame_call_wrapper_offset = -8,
|
||||||
|
|
||||||
// we don't need a save area
|
// we don't need a save area
|
||||||
arg_reg_save_area_bytes = 0
|
arg_reg_save_area_bytes = 0,
|
||||||
|
|
||||||
|
// size, in words, of frame metadata (e.g. pc and link)
|
||||||
|
metadata_words = sender_sp_offset,
|
||||||
|
// in bytes
|
||||||
|
frame_alignment = 16,
|
||||||
|
// size, in words, of maximum shift in frame position due to alignment
|
||||||
|
align_wiggle = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
intptr_t ptr_at(int offset) const {
|
intptr_t ptr_at(int offset) const {
|
||||||
@ -113,7 +119,10 @@
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// an additional field beyond _sp and _pc:
|
// an additional field beyond _sp and _pc:
|
||||||
|
union {
|
||||||
intptr_t* _fp; // frame pointer
|
intptr_t* _fp; // frame pointer
|
||||||
|
int _offset_fp; // relative frame pointer for use in stack-chunk frames
|
||||||
|
};
|
||||||
// The interpreter and adapters will extend the frame of the caller.
|
// The interpreter and adapters will extend the frame of the caller.
|
||||||
// Since oopMaps are based on the sp of the caller before extension
|
// Since oopMaps are based on the sp of the caller before extension
|
||||||
// we need to know that value. However in order to compute the address
|
// we need to know that value. However in order to compute the address
|
||||||
@ -121,8 +130,12 @@
|
|||||||
// uses sp() to mean "raw" sp and unextended_sp() to mean the caller's
|
// uses sp() to mean "raw" sp and unextended_sp() to mean the caller's
|
||||||
// original sp we use that convention.
|
// original sp we use that convention.
|
||||||
|
|
||||||
|
union {
|
||||||
intptr_t* _unextended_sp;
|
intptr_t* _unextended_sp;
|
||||||
void adjust_unextended_sp();
|
int _offset_unextended_sp; // for use in stack-chunk frames
|
||||||
|
};
|
||||||
|
|
||||||
|
void adjust_unextended_sp() NOT_DEBUG_RETURN;
|
||||||
|
|
||||||
// true means _sp value is correct and we can use it to get the sender's sp
|
// true means _sp value is correct and we can use it to get the sender's sp
|
||||||
// of the compiled frame, otherwise, _sp value may be invalid and we can use
|
// of the compiled frame, otherwise, _sp value may be invalid and we can use
|
||||||
@ -138,6 +151,8 @@
|
|||||||
static void verify_deopt_original_pc( CompiledMethod* nm, intptr_t* unextended_sp);
|
static void verify_deopt_original_pc( CompiledMethod* nm, intptr_t* unextended_sp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const ImmutableOopMap* get_oop_map() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
@ -145,13 +160,21 @@
|
|||||||
|
|
||||||
frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc);
|
frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc);
|
||||||
|
|
||||||
|
frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb);
|
||||||
|
// used for fast frame construction by continuations
|
||||||
|
frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map, bool on_heap);
|
||||||
|
|
||||||
frame(intptr_t* sp, intptr_t* fp);
|
frame(intptr_t* sp, intptr_t* fp);
|
||||||
|
|
||||||
void init(intptr_t* sp, intptr_t* fp, address pc);
|
void init(intptr_t* sp, intptr_t* fp, address pc);
|
||||||
|
void setup(address pc);
|
||||||
|
|
||||||
// accessors for the instance variables
|
// accessors for the instance variables
|
||||||
// Note: not necessarily the real 'frame pointer' (see real_fp)
|
// Note: not necessarily the real 'frame pointer' (see real_fp)
|
||||||
intptr_t* fp() const { return _fp; }
|
intptr_t* fp() const { assert_absolute(); return _fp; }
|
||||||
|
void set_fp(intptr_t* newfp) { _fp = newfp; }
|
||||||
|
int offset_fp() const { assert_offset(); return _offset_fp; }
|
||||||
|
void set_offset_fp(int value) { assert_on_heap(); _offset_fp = value; }
|
||||||
|
|
||||||
inline address* sender_pc_addr() const;
|
inline address* sender_pc_addr() const;
|
||||||
inline address sender_pc_maybe_signed() const;
|
inline address sender_pc_maybe_signed() const;
|
||||||
@ -159,8 +182,8 @@
|
|||||||
// expression stack tos if we are nested in a java call
|
// expression stack tos if we are nested in a java call
|
||||||
intptr_t* interpreter_frame_last_sp() const;
|
intptr_t* interpreter_frame_last_sp() const;
|
||||||
|
|
||||||
// helper to update a map with callee-saved RBP
|
template <typename RegisterMapT>
|
||||||
static void update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr);
|
static void update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr);
|
||||||
|
|
||||||
// deoptimization support
|
// deoptimization support
|
||||||
void interpreter_frame_set_last_sp(intptr_t* sp);
|
void interpreter_frame_set_last_sp(intptr_t* sp);
|
||||||
@ -168,7 +191,7 @@
|
|||||||
static jint interpreter_frame_expression_stack_direction() { return -1; }
|
static jint interpreter_frame_expression_stack_direction() { return -1; }
|
||||||
|
|
||||||
// returns the sending frame, without applying any barriers
|
// returns the sending frame, without applying any barriers
|
||||||
frame sender_raw(RegisterMap* map) const;
|
inline frame sender_raw(RegisterMap* map) const;
|
||||||
|
|
||||||
void set_sp_is_trusted() { _sp_is_trusted = true; }
|
void set_sp_is_trusted() { _sp_is_trusted = true; }
|
||||||
|
|
||||||
|
@ -26,8 +26,12 @@
|
|||||||
#ifndef CPU_AARCH64_FRAME_AARCH64_INLINE_HPP
|
#ifndef CPU_AARCH64_FRAME_AARCH64_INLINE_HPP
|
||||||
#define CPU_AARCH64_FRAME_AARCH64_INLINE_HPP
|
#define CPU_AARCH64_FRAME_AARCH64_INLINE_HPP
|
||||||
|
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeBlob.inline.hpp"
|
||||||
|
#include "code/codeCache.inline.hpp"
|
||||||
#include "code/vmreg.inline.hpp"
|
#include "code/vmreg.inline.hpp"
|
||||||
|
#include "interpreter/interpreter.hpp"
|
||||||
|
#include "interpreter/oopMapCache.hpp"
|
||||||
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "pauth_aarch64.hpp"
|
#include "pauth_aarch64.hpp"
|
||||||
|
|
||||||
// Inline functions for AArch64 frames:
|
// Inline functions for AArch64 frames:
|
||||||
@ -42,6 +46,8 @@ inline frame::frame() {
|
|||||||
_cb = NULL;
|
_cb = NULL;
|
||||||
_deopt_state = unknown;
|
_deopt_state = unknown;
|
||||||
_sp_is_trusted = false;
|
_sp_is_trusted = false;
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spin;
|
static int spin;
|
||||||
@ -54,17 +60,31 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
|
|||||||
_unextended_sp = sp;
|
_unextended_sp = sp;
|
||||||
_fp = fp;
|
_fp = fp;
|
||||||
_pc = pc;
|
_pc = pc;
|
||||||
|
_oop_map = NULL;
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
|
||||||
assert(pc != NULL, "no pc?");
|
assert(pc != NULL, "no pc?");
|
||||||
_cb = CodeCache::find_blob(pc);
|
_cb = CodeCache::find_blob(pc);
|
||||||
|
setup(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::setup(address pc) {
|
||||||
adjust_unextended_sp();
|
adjust_unextended_sp();
|
||||||
|
|
||||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||||
if (original_pc != NULL) {
|
if (original_pc != NULL) {
|
||||||
_pc = original_pc;
|
_pc = original_pc;
|
||||||
_deopt_state = is_deoptimized;
|
_deopt_state = is_deoptimized;
|
||||||
|
assert(_cb == NULL || _cb->as_compiled_method()->insts_contains_inclusive(_pc),
|
||||||
|
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
|
||||||
|
} else {
|
||||||
|
if (_cb == SharedRuntime::deopt_blob()) {
|
||||||
|
_deopt_state = is_deoptimized;
|
||||||
} else {
|
} else {
|
||||||
_deopt_state = not_deoptimized;
|
_deopt_state = not_deoptimized;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_sp_is_trusted = false;
|
_sp_is_trusted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +92,7 @@ inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
|
|||||||
init(sp, fp, pc);
|
init(sp, fp, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) {
|
inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb) {
|
||||||
assert(pauth_ptr_is_raw(pc), "cannot be signed");
|
assert(pauth_ptr_is_raw(pc), "cannot be signed");
|
||||||
intptr_t a = intptr_t(sp);
|
intptr_t a = intptr_t(sp);
|
||||||
intptr_t b = intptr_t(fp);
|
intptr_t b = intptr_t(fp);
|
||||||
@ -81,21 +101,59 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
|
|||||||
_fp = fp;
|
_fp = fp;
|
||||||
_pc = pc;
|
_pc = pc;
|
||||||
assert(pc != NULL, "no pc?");
|
assert(pc != NULL, "no pc?");
|
||||||
_cb = CodeCache::find_blob(pc);
|
_cb = cb;
|
||||||
adjust_unextended_sp();
|
_oop_map = NULL;
|
||||||
|
assert(_cb != NULL, "pc: " INTPTR_FORMAT, p2i(pc));
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
|
||||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
setup(pc);
|
||||||
if (original_pc != NULL) {
|
|
||||||
_pc = original_pc;
|
|
||||||
assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
|
|
||||||
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
|
|
||||||
_deopt_state = is_deoptimized;
|
|
||||||
} else {
|
|
||||||
_deopt_state = not_deoptimized;
|
|
||||||
}
|
|
||||||
_sp_is_trusted = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map, bool on_heap) {
|
||||||
|
_sp = sp;
|
||||||
|
_unextended_sp = unextended_sp;
|
||||||
|
_fp = fp;
|
||||||
|
_pc = pc;
|
||||||
|
_cb = cb;
|
||||||
|
_oop_map = oop_map;
|
||||||
|
_deopt_state = not_deoptimized;
|
||||||
|
_sp_is_trusted = false;
|
||||||
|
_on_heap = on_heap;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
|
||||||
|
// In thaw, non-heap frames use this constructor to pass oop_map. I don't know why.
|
||||||
|
assert(_on_heap || _cb != nullptr, "these frames are always heap frames");
|
||||||
|
if (cb != NULL) {
|
||||||
|
setup(pc);
|
||||||
|
}
|
||||||
|
#ifdef ASSERT
|
||||||
|
// The following assertion has been disabled because it would sometime trap for Continuation.run,
|
||||||
|
// which is not *in* a continuation and therefore does not clear the _cont_fastpath flag, but this
|
||||||
|
// is benign even in fast mode (see Freeze::setup_jump)
|
||||||
|
// We might freeze deoptimized frame in slow mode
|
||||||
|
// assert(_pc == pc && _deopt_state == not_deoptimized, "");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) {
|
||||||
|
intptr_t a = intptr_t(sp);
|
||||||
|
intptr_t b = intptr_t(fp);
|
||||||
|
_sp = sp;
|
||||||
|
_unextended_sp = unextended_sp;
|
||||||
|
_fp = fp;
|
||||||
|
_pc = pc;
|
||||||
|
_cb = CodeCache::find_blob_fast(pc);
|
||||||
|
_oop_map = NULL;
|
||||||
|
assert(_cb != NULL, "pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " fp: " INTPTR_FORMAT, p2i(pc), p2i(sp), p2i(unextended_sp), p2i(fp));
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
|
||||||
|
setup(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame::frame(intptr_t* sp) : frame(sp, sp, *(intptr_t**)(sp - frame::sender_sp_offset), *(address*)(sp - 1)) {}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* sp, intptr_t* fp) {
|
inline frame::frame(intptr_t* sp, intptr_t* fp) {
|
||||||
intptr_t a = intptr_t(sp);
|
intptr_t a = intptr_t(sp);
|
||||||
intptr_t b = intptr_t(fp);
|
intptr_t b = intptr_t(fp);
|
||||||
@ -103,6 +161,8 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) {
|
|||||||
_unextended_sp = sp;
|
_unextended_sp = sp;
|
||||||
_fp = fp;
|
_fp = fp;
|
||||||
_pc = (address)(sp[-1]);
|
_pc = (address)(sp[-1]);
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
|
||||||
// Here's a sticky one. This constructor can be called via AsyncGetCallTrace
|
// Here's a sticky one. This constructor can be called via AsyncGetCallTrace
|
||||||
// when last_Java_sp is non-null but the pc fetched is junk. If we are truly
|
// when last_Java_sp is non-null but the pc fetched is junk. If we are truly
|
||||||
@ -155,7 +215,41 @@ inline intptr_t* frame::link_or_null() const {
|
|||||||
return os::is_readable_pointer(ptr) ? *ptr : NULL;
|
return os::is_readable_pointer(ptr) ? *ptr : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline intptr_t* frame::unextended_sp() const { return _unextended_sp; }
|
inline intptr_t* frame::unextended_sp() const { assert_absolute(); return _unextended_sp; }
|
||||||
|
inline void frame::set_unextended_sp(intptr_t* value) { _unextended_sp = value; }
|
||||||
|
inline int frame::offset_unextended_sp() const { assert_offset(); return _offset_unextended_sp; }
|
||||||
|
inline void frame::set_offset_unextended_sp(int value) { assert_on_heap(); _offset_unextended_sp = value; }
|
||||||
|
|
||||||
|
inline intptr_t* frame::real_fp() const {
|
||||||
|
if (_cb != NULL) {
|
||||||
|
// use the frame size if valid
|
||||||
|
int size = _cb->frame_size();
|
||||||
|
if (size > 0) {
|
||||||
|
return unextended_sp() + size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// else rely on fp()
|
||||||
|
assert(! is_compiled_frame(), "unknown compiled frame size");
|
||||||
|
return fp();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::frame_size() const {
|
||||||
|
return is_interpreted_frame()
|
||||||
|
? sender_sp() - sp()
|
||||||
|
: cb()->frame_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::compiled_frame_stack_argsize() const {
|
||||||
|
assert(cb()->is_compiled(), "");
|
||||||
|
return (cb()->as_compiled_method()->method()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::interpreted_frame_oop_map(InterpreterOopMap* mask) const {
|
||||||
|
assert(mask != NULL, "");
|
||||||
|
Method* m = interpreter_frame_method();
|
||||||
|
int bci = interpreter_frame_bci();
|
||||||
|
m->mask_for(bci, mask); // OopMapCache::compute_one_oop_map(m, bci, mask);
|
||||||
|
}
|
||||||
|
|
||||||
// Return address:
|
// Return address:
|
||||||
|
|
||||||
@ -170,7 +264,7 @@ inline intptr_t** frame::interpreter_frame_locals_addr() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline intptr_t* frame::interpreter_frame_last_sp() const {
|
inline intptr_t* frame::interpreter_frame_last_sp() const {
|
||||||
return *(intptr_t**)addr_at(interpreter_frame_last_sp_offset);
|
return (intptr_t*)at(interpreter_frame_last_sp_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline intptr_t* frame::interpreter_frame_bcp_addr() const {
|
inline intptr_t* frame::interpreter_frame_bcp_addr() const {
|
||||||
@ -244,21 +338,147 @@ inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
|
|||||||
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
||||||
PRAGMA_DIAG_PUSH
|
PRAGMA_DIAG_PUSH
|
||||||
PRAGMA_NONNULL_IGNORED
|
PRAGMA_NONNULL_IGNORED
|
||||||
oop* result_adr = (oop *)map->location(r0->as_VMReg());
|
oop* result_adr = (oop *)map->location(r0->as_VMReg(), sp());
|
||||||
PRAGMA_DIAG_POP
|
PRAGMA_DIAG_POP
|
||||||
guarantee(result_adr != NULL, "bad register save location");
|
guarantee(result_adr != NULL, "bad register save location");
|
||||||
|
return *result_adr;
|
||||||
return (*result_adr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
||||||
PRAGMA_DIAG_PUSH
|
PRAGMA_DIAG_PUSH
|
||||||
PRAGMA_NONNULL_IGNORED
|
PRAGMA_NONNULL_IGNORED
|
||||||
oop* result_adr = (oop *)map->location(r0->as_VMReg());
|
oop* result_adr = (oop *)map->location(r0->as_VMReg(), sp());
|
||||||
PRAGMA_DIAG_POP
|
PRAGMA_DIAG_POP
|
||||||
guarantee(result_adr != NULL, "bad register save location");
|
guarantee(result_adr != NULL, "bad register save location");
|
||||||
|
|
||||||
*result_adr = obj;
|
*result_adr = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool frame::is_interpreted_frame() const {
|
||||||
|
return Interpreter::contains(pc());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::sender_sp_ret_address_offset() {
|
||||||
|
return frame::sender_sp_offset - frame::return_addr_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ImmutableOopMap* frame::get_oop_map() const {
|
||||||
|
if (_cb == NULL) return NULL;
|
||||||
|
if (_cb->oop_maps() != NULL) {
|
||||||
|
NativePostCallNop* nop = nativePostCallNop_at(_pc);
|
||||||
|
if (nop != NULL && nop->displacement() != 0) {
|
||||||
|
int slot = ((nop->displacement() >> 24) & 0xff);
|
||||||
|
return _cb->oop_map_for_slot(slot, _pc);
|
||||||
|
}
|
||||||
|
const ImmutableOopMap* oop_map = OopMapSet::find_map(this);
|
||||||
|
return oop_map;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// frame::sender
|
||||||
|
inline frame frame::sender(RegisterMap* map) const {
|
||||||
|
frame result = sender_raw(map);
|
||||||
|
|
||||||
|
if (map->process_frames() && !map->in_cont()) {
|
||||||
|
StackWatermarkSet::on_iteration(map->thread(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame frame::sender_raw(RegisterMap* map) const {
|
||||||
|
// Default is we done have to follow them. The sender_for_xxx will
|
||||||
|
// update it accordingly
|
||||||
|
map->set_include_argument_oops(false);
|
||||||
|
|
||||||
|
if (map->in_cont()) { // already in an h-stack
|
||||||
|
return map->stack_chunk()->sender(*this, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_entry_frame()) return sender_for_entry_frame(map);
|
||||||
|
if (is_optimized_entry_frame()) return sender_for_optimized_entry_frame(map);
|
||||||
|
if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
|
||||||
|
|
||||||
|
assert(_cb == CodeCache::find_blob(pc()), "Must be the same");
|
||||||
|
if (_cb != NULL) return sender_for_compiled_frame(map);
|
||||||
|
|
||||||
|
// Must be native-compiled frame, i.e. the marshaling code for native
|
||||||
|
// methods that exists in the core system.
|
||||||
|
|
||||||
|
// Native code may or may not have signed the return address, we have no way to be sure or what
|
||||||
|
// signing methods they used. Instead, just ensure the stripped value is used.
|
||||||
|
|
||||||
|
return frame(sender_sp(), link(), sender_pc());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
||||||
|
// we cannot rely upon the last fp having been saved to the thread
|
||||||
|
// in C2 code but it will have been pushed onto the stack. so we
|
||||||
|
// have to find it relative to the unextended sp
|
||||||
|
|
||||||
|
assert(_cb->frame_size() >= 0, "must have non-zero frame size");
|
||||||
|
intptr_t* l_sender_sp = (!PreserveFramePointer || _sp_is_trusted) ? unextended_sp() + _cb->frame_size()
|
||||||
|
: sender_sp();
|
||||||
|
assert(!_sp_is_trusted || l_sender_sp == real_fp(), "");
|
||||||
|
|
||||||
|
// the return_address is always the word on the stack
|
||||||
|
// For ROP protection, C1/C2 will have signed the sender_pc, but there is no requirement to authenticate it here.
|
||||||
|
address sender_pc = pauth_strip_verifiable((address) *(l_sender_sp-1), (address) *(l_sender_sp-2));
|
||||||
|
|
||||||
|
intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp - frame::sender_sp_offset);
|
||||||
|
|
||||||
|
if (map->update_map()) {
|
||||||
|
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
||||||
|
// For C1, the runtime stub might not have oop maps, so set this flag
|
||||||
|
// outside of update_register_map.
|
||||||
|
if (!_cb->is_compiled()) { // compiled frames do not use callee-saved registers
|
||||||
|
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
||||||
|
if (oop_map() != NULL) {
|
||||||
|
_oop_map->update_register_map(this, map);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(!_cb->caller_must_gc_arguments(map->thread()), "");
|
||||||
|
assert(!map->include_argument_oops(), "");
|
||||||
|
assert(oop_map() == NULL || !oop_map()->has_any(OopMapValue::callee_saved_value), "callee-saved value in compiled frame");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the prolog does the save and restore of EBP there is no oopmap
|
||||||
|
// for it so we must fill in its location as if there was an oopmap entry
|
||||||
|
// since if our caller was compiled code there could be live jvm state in it.
|
||||||
|
update_map_with_saved_link(map, saved_fp_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Continuation::is_return_barrier_entry(sender_pc)) {
|
||||||
|
if (map->walk_cont()) { // about to walk into an h-stack
|
||||||
|
return Continuation::top_frame(*this, map);
|
||||||
|
} else {
|
||||||
|
return Continuation::continuation_bottom_sender(map->thread(), *this, l_sender_sp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t* unextended_sp = l_sender_sp;
|
||||||
|
return frame(l_sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
void frame::update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr) {
|
||||||
|
// The interpreter and compiler(s) always save EBP/RBP in a known
|
||||||
|
// location on entry. We must record where that location is
|
||||||
|
// so this if EBP/RBP was live on callout from c2 we can find
|
||||||
|
// the saved copy no matter what it called.
|
||||||
|
|
||||||
|
// Since the interpreter always saves EBP/RBP if we record where it is then
|
||||||
|
// we don't have to always save EBP/RBP on entry and exit to c2 compiled
|
||||||
|
// code, on entry will be enough.
|
||||||
|
map->set_location(rfp->as_VMReg(), (address) link_addr);
|
||||||
|
// this is weird "H" ought to be at a higher address however the
|
||||||
|
// oopMaps seems to have the "H" regs at the same address and the
|
||||||
|
// vanilla register.
|
||||||
|
// XXXX make this go away
|
||||||
|
if (true) {
|
||||||
|
map->set_location(rfp->as_VMReg()->next(), (address) link_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // CPU_AARCH64_FRAME_AARCH64_INLINE_HPP
|
#endif // CPU_AARCH64_FRAME_AARCH64_INLINE_HPP
|
||||||
|
@ -154,12 +154,8 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
|
|||||||
__ b(done);
|
__ b(done);
|
||||||
|
|
||||||
__ bind(runtime);
|
__ bind(runtime);
|
||||||
// save the live input values
|
|
||||||
RegSet saved = RegSet::of(pre_val);
|
|
||||||
if (tosca_live) saved += RegSet::of(r0);
|
|
||||||
if (obj != noreg) saved += RegSet::of(obj);
|
|
||||||
|
|
||||||
__ push(saved, sp);
|
__ push_call_clobbered_registers();
|
||||||
|
|
||||||
// Calling the runtime using the regular call_VM_leaf mechanism generates
|
// Calling the runtime using the regular call_VM_leaf mechanism generates
|
||||||
// code (generated by InterpreterMacroAssember::call_VM_leaf_base)
|
// code (generated by InterpreterMacroAssember::call_VM_leaf_base)
|
||||||
@ -180,7 +176,7 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
|
|||||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
|
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
__ pop(saved, sp);
|
__ pop_call_clobbered_registers();
|
||||||
|
|
||||||
__ bind(done);
|
__ bind(done);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -232,6 +232,20 @@ void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm,
|
|||||||
__ str(t1, Address(rthread, in_bytes(JavaThread::allocated_bytes_offset())));
|
__ str(t1, Address(rthread, in_bytes(JavaThread::allocated_bytes_offset())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static volatile uint32_t _patching_epoch = 0;
|
||||||
|
|
||||||
|
address BarrierSetAssembler::patching_epoch_addr() {
|
||||||
|
return (address)&_patching_epoch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetAssembler::increment_patching_epoch() {
|
||||||
|
Atomic::inc(&_patching_epoch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetAssembler::clear_patching_epoch() {
|
||||||
|
_patching_epoch = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) {
|
void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) {
|
||||||
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
|
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
|
||||||
|
|
||||||
@ -239,27 +253,51 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Label skip, guard;
|
Label skip_barrier, guard;
|
||||||
Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_offset()));
|
|
||||||
|
|
||||||
__ ldrw(rscratch1, guard);
|
__ ldrw(rscratch1, guard);
|
||||||
|
|
||||||
|
if (nmethod_code_patching()) {
|
||||||
|
// If we patch code we need both a code patching and a loadload
|
||||||
|
// fence. It's not super cheap, so we use a global epoch mechanism
|
||||||
|
// to hide them in a slow path.
|
||||||
|
// The high level idea of the global epoch mechanism is to detect
|
||||||
|
// when any thread has performed the required fencing, after the
|
||||||
|
// last nmethod was disarmed. This implies that the required
|
||||||
|
// fencing has been performed for all preceding nmethod disarms
|
||||||
|
// as well. Therefore, we do not need any further fencing.
|
||||||
|
__ lea(rscratch2, ExternalAddress((address)&_patching_epoch));
|
||||||
|
// Embed an artificial data dependency to order the guard load
|
||||||
|
// before the epoch load.
|
||||||
|
__ orr(rscratch2, rscratch2, rscratch1, Assembler::LSR, 32);
|
||||||
|
// Read the global epoch value.
|
||||||
|
__ ldrw(rscratch2, rscratch2);
|
||||||
|
// Combine the guard value (low order) with the epoch value (high order).
|
||||||
|
__ orr(rscratch1, rscratch1, rscratch2, Assembler::LSL, 32);
|
||||||
|
// Compare the global values with the thread-local values.
|
||||||
|
Address thread_disarmed_and_epoch_addr(rthread, in_bytes(bs_nm->thread_disarmed_offset()));
|
||||||
|
__ ldr(rscratch2, thread_disarmed_and_epoch_addr);
|
||||||
|
__ cmp(rscratch1, rscratch2);
|
||||||
|
__ br(Assembler::EQ, skip_barrier);
|
||||||
|
} else {
|
||||||
// Subsequent loads of oops must occur after load of guard value.
|
// Subsequent loads of oops must occur after load of guard value.
|
||||||
// BarrierSetNMethod::disarm sets guard with release semantics.
|
// BarrierSetNMethod::disarm sets guard with release semantics.
|
||||||
__ membar(__ LoadLoad);
|
__ membar(__ LoadLoad);
|
||||||
|
Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_offset()));
|
||||||
__ ldrw(rscratch2, thread_disarmed_addr);
|
__ ldrw(rscratch2, thread_disarmed_addr);
|
||||||
__ cmpw(rscratch1, rscratch2);
|
__ cmpw(rscratch1, rscratch2);
|
||||||
__ br(Assembler::EQ, skip);
|
__ br(Assembler::EQ, skip_barrier);
|
||||||
|
}
|
||||||
|
|
||||||
__ movptr(rscratch1, (uintptr_t) StubRoutines::aarch64::method_entry_barrier());
|
__ movptr(rscratch1, (uintptr_t) StubRoutines::aarch64::method_entry_barrier());
|
||||||
__ blr(rscratch1);
|
__ blr(rscratch1);
|
||||||
__ b(skip);
|
__ b(skip_barrier);
|
||||||
|
|
||||||
__ bind(guard);
|
__ bind(guard);
|
||||||
|
|
||||||
__ emit_int32(0); // nmethod guard value. Skipped over in common case.
|
__ emit_int32(0); // nmethod guard value. Skipped over in common case.
|
||||||
|
|
||||||
__ bind(skip);
|
__ bind(skip_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
|
void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -68,9 +68,14 @@ public:
|
|||||||
);
|
);
|
||||||
virtual void barrier_stubs_init() {}
|
virtual void barrier_stubs_init() {}
|
||||||
|
|
||||||
|
virtual bool nmethod_code_patching() { return true; }
|
||||||
|
|
||||||
virtual void nmethod_entry_barrier(MacroAssembler* masm);
|
virtual void nmethod_entry_barrier(MacroAssembler* masm);
|
||||||
virtual void c2i_entry_barrier(MacroAssembler* masm);
|
virtual void c2i_entry_barrier(MacroAssembler* masm);
|
||||||
|
|
||||||
|
static address patching_epoch_addr();
|
||||||
|
static void clear_patching_epoch();
|
||||||
|
static void increment_patching_epoch();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPU_AARCH64_GC_SHARED_BARRIERSETASSEMBLER_AARCH64_HPP
|
#endif // CPU_AARCH64_GC_SHARED_BARRIERSETASSEMBLER_AARCH64_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,9 +25,12 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "code/nativeInst.hpp"
|
#include "code/nativeInst.hpp"
|
||||||
|
#include "gc/shared/barrierSet.hpp"
|
||||||
|
#include "gc/shared/barrierSetAssembler.hpp"
|
||||||
#include "gc/shared/barrierSetNMethod.hpp"
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
#include "logging/log.hpp"
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/registerMap.hpp"
|
#include "runtime/registerMap.hpp"
|
||||||
#include "runtime/thread.hpp"
|
#include "runtime/thread.hpp"
|
||||||
@ -37,8 +40,17 @@
|
|||||||
class NativeNMethodBarrier: public NativeInstruction {
|
class NativeNMethodBarrier: public NativeInstruction {
|
||||||
address instruction_address() const { return addr_at(0); }
|
address instruction_address() const { return addr_at(0); }
|
||||||
|
|
||||||
|
int guard_offset() {
|
||||||
|
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||||
|
if (bs_asm->nmethod_code_patching()) {
|
||||||
|
return 4 * 15;
|
||||||
|
} else {
|
||||||
|
return 4 * 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int *guard_addr() {
|
int *guard_addr() {
|
||||||
return reinterpret_cast<int*>(instruction_address() + 10 * 4);
|
return reinterpret_cast<int*>(instruction_address() + guard_offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -60,31 +72,14 @@ struct CheckInsn {
|
|||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct CheckInsn barrierInsn[] = {
|
// The first instruction of the nmethod entry barrier is an ldr (literal)
|
||||||
{ 0xff000000, 0x18000000, "ldr (literal)" },
|
// instruction. Verify that it's really there, so the offsets are not skewed.
|
||||||
{ 0xfffff0ff, 0xd50330bf, "dmb" },
|
|
||||||
{ 0xffc00000, 0xb9400000, "ldr"},
|
|
||||||
{ 0x7f20001f, 0x6b00001f, "cmp"},
|
|
||||||
{ 0xff00001f, 0x54000000, "b.eq"},
|
|
||||||
{ 0xff800000, 0xd2800000, "mov"},
|
|
||||||
{ 0xff800000, 0xf2800000, "movk"},
|
|
||||||
{ 0xff800000, 0xf2800000, "movk"},
|
|
||||||
{ 0xfffffc1f, 0xd63f0000, "blr"},
|
|
||||||
{ 0xfc000000, 0x14000000, "b"}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The encodings must match the instructions emitted by
|
|
||||||
// BarrierSetAssembler::nmethod_entry_barrier. The matching ignores the specific
|
|
||||||
// register numbers and immediate values in the encoding.
|
|
||||||
void NativeNMethodBarrier::verify() const {
|
void NativeNMethodBarrier::verify() const {
|
||||||
intptr_t addr = (intptr_t) instruction_address();
|
uint32_t* addr = (uint32_t*) instruction_address();
|
||||||
for(unsigned int i = 0; i < sizeof(barrierInsn)/sizeof(struct CheckInsn); i++ ) {
|
uint32_t inst = *addr;
|
||||||
uint32_t inst = *((uint32_t*) addr);
|
if ((inst & 0xff000000) != 0x18000000) {
|
||||||
if ((inst & barrierInsn[i].mask) != barrierInsn[i].bits) {
|
tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", (intptr_t)addr, inst);
|
||||||
tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", addr, inst);
|
fatal("not an ldr (literal) instruction.");
|
||||||
fatal("not an %s instruction.", barrierInsn[i].name);
|
|
||||||
}
|
|
||||||
addr +=4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,10 +127,17 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
|||||||
// not find the expected native instruction at this offset, which needs updating.
|
// not find the expected native instruction at this offset, which needs updating.
|
||||||
// Note that this offset is invariant of PreserveFramePointer.
|
// Note that this offset is invariant of PreserveFramePointer.
|
||||||
|
|
||||||
static const int entry_barrier_offset = -4 * 11;
|
static int entry_barrier_offset() {
|
||||||
|
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||||
|
if (bs_asm->nmethod_code_patching()) {
|
||||||
|
return -4 * 16;
|
||||||
|
} else {
|
||||||
|
return -4 * 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) {
|
static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) {
|
||||||
address barrier_address = nm->code_begin() + nm->frame_complete_offset() + entry_barrier_offset;
|
address barrier_address = nm->code_begin() + nm->frame_complete_offset() + entry_barrier_offset();
|
||||||
NativeNMethodBarrier* barrier = reinterpret_cast<NativeNMethodBarrier*>(barrier_address);
|
NativeNMethodBarrier* barrier = reinterpret_cast<NativeNMethodBarrier*>(barrier_address);
|
||||||
debug_only(barrier->verify());
|
debug_only(barrier->verify());
|
||||||
return barrier;
|
return barrier;
|
||||||
@ -146,13 +148,41 @@ void BarrierSetNMethod::disarm(nmethod* nm) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The patching epoch is incremented before the nmethod is disarmed. Disarming
|
||||||
|
// is performed with a release store. In the nmethod entry barrier, the values
|
||||||
|
// are read in the opposite order, such that the load of the nmethod guard
|
||||||
|
// acquires the patching epoch. This way, the guard is guaranteed to block
|
||||||
|
// entries to the nmethod, until it has safely published the requirement for
|
||||||
|
// further fencing by mutators, before they are allowed to enter.
|
||||||
|
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||||
|
bs_asm->increment_patching_epoch();
|
||||||
|
|
||||||
// Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier.
|
// Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier.
|
||||||
// Symmetric "LDR; DMB ISHLD" is in the nmethod barrier.
|
// Symmetric "LDR; DMB ISHLD" is in the nmethod barrier.
|
||||||
NativeNMethodBarrier* barrier = native_nmethod_barrier(nm);
|
NativeNMethodBarrier* barrier = native_nmethod_barrier(nm);
|
||||||
|
|
||||||
barrier->set_value(disarmed_value());
|
barrier->set_value(disarmed_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::arm(nmethod* nm, int arm_value) {
|
||||||
|
if (!supports_entry_barrier(nm)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arm_value == disarmed_value()) {
|
||||||
|
// The patching epoch is incremented before the nmethod is disarmed. Disarming
|
||||||
|
// is performed with a release store. In the nmethod entry barrier, the values
|
||||||
|
// are read in the opposite order, such that the load of the nmethod guard
|
||||||
|
// acquires the patching epoch. This way, the guard is guaranteed to block
|
||||||
|
// entries to the nmethod, until it has safely published the requirement for
|
||||||
|
// further fencing by mutators, before they are allowed to enter.
|
||||||
|
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||||
|
bs_asm->increment_patching_epoch();
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeNMethodBarrier* barrier = native_nmethod_barrier(nm);
|
||||||
|
barrier->set_value(arm_value);
|
||||||
|
}
|
||||||
|
|
||||||
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
if (!supports_entry_barrier(nm)) {
|
if (!supports_entry_barrier(nm)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -62,6 +62,8 @@ public:
|
|||||||
|
|
||||||
void iu_barrier(MacroAssembler* masm, Register dst, Register tmp);
|
void iu_barrier(MacroAssembler* masm, Register dst, Register tmp);
|
||||||
|
|
||||||
|
virtual bool nmethod_code_patching() { return false; }
|
||||||
|
|
||||||
#ifdef COMPILER1
|
#ifdef COMPILER1
|
||||||
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
|
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
|
||||||
void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
|
void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -76,6 +76,8 @@ public:
|
|||||||
Register tmp,
|
Register tmp,
|
||||||
Label& slowpath);
|
Label& slowpath);
|
||||||
|
|
||||||
|
virtual bool nmethod_code_patching() { return false; }
|
||||||
|
|
||||||
#ifdef COMPILER1
|
#ifdef COMPILER1
|
||||||
void generate_c1_load_barrier_test(LIR_Assembler* ce,
|
void generate_c1_load_barrier_test(LIR_Assembler* ce,
|
||||||
LIR_Opr ref) const;
|
LIR_Opr ref) const;
|
||||||
|
@ -606,6 +606,7 @@ void InterpreterMacroAssembler::remove_activation(
|
|||||||
|
|
||||||
bind(unlock);
|
bind(unlock);
|
||||||
unlock_object(c_rarg1);
|
unlock_object(c_rarg1);
|
||||||
|
dec_held_monitor_count(rthread);
|
||||||
pop(state);
|
pop(state);
|
||||||
|
|
||||||
// Check that for block-structured locking (i.e., that all locked
|
// Check that for block-structured locking (i.e., that all locked
|
||||||
@ -648,6 +649,7 @@ void InterpreterMacroAssembler::remove_activation(
|
|||||||
|
|
||||||
push(state);
|
push(state);
|
||||||
unlock_object(c_rarg1);
|
unlock_object(c_rarg1);
|
||||||
|
dec_held_monitor_count(rthread);
|
||||||
pop(state);
|
pop(state);
|
||||||
|
|
||||||
if (install_monitor_exception) {
|
if (install_monitor_exception) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -82,4 +82,6 @@ public:
|
|||||||
|
|
||||||
intptr_t* last_Java_fp(void) { return _last_Java_fp; }
|
intptr_t* last_Java_fp(void) { return _last_Java_fp; }
|
||||||
|
|
||||||
|
void set_last_Java_fp(intptr_t* fp) { _last_Java_fp = fp; }
|
||||||
|
|
||||||
#endif // CPU_AARCH64_JAVAFRAMEANCHOR_AARCH64_HPP
|
#endif // CPU_AARCH64_JAVAFRAMEANCHOR_AARCH64_HPP
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "oops/accessDecorators.hpp"
|
#include "oops/accessDecorators.hpp"
|
||||||
#include "oops/compressedOops.inline.hpp"
|
#include "oops/compressedOops.inline.hpp"
|
||||||
#include "oops/klass.inline.hpp"
|
#include "oops/klass.inline.hpp"
|
||||||
|
#include "runtime/continuation.hpp"
|
||||||
#include "runtime/icache.hpp"
|
#include "runtime/icache.hpp"
|
||||||
#include "runtime/interfaceSupport.inline.hpp"
|
#include "runtime/interfaceSupport.inline.hpp"
|
||||||
#include "runtime/jniHandles.inline.hpp"
|
#include "runtime/jniHandles.inline.hpp"
|
||||||
@ -313,6 +314,41 @@ void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool acqui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::push_cont_fastpath(Register java_thread) {
|
||||||
|
if (!Continuations::enabled()) return;
|
||||||
|
Label done;
|
||||||
|
ldr(rscratch1, Address(java_thread, JavaThread::cont_fastpath_offset()));
|
||||||
|
cmp(sp, rscratch1);
|
||||||
|
br(Assembler::LS, done);
|
||||||
|
mov(rscratch1, sp); // we can't use sp as the source in str
|
||||||
|
str(rscratch1, Address(java_thread, JavaThread::cont_fastpath_offset()));
|
||||||
|
bind(done);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::pop_cont_fastpath(Register java_thread) {
|
||||||
|
if (!Continuations::enabled()) return;
|
||||||
|
Label done;
|
||||||
|
ldr(rscratch1, Address(java_thread, JavaThread::cont_fastpath_offset()));
|
||||||
|
cmp(sp, rscratch1);
|
||||||
|
br(Assembler::LO, done);
|
||||||
|
str(zr, Address(java_thread, JavaThread::cont_fastpath_offset()));
|
||||||
|
bind(done);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::inc_held_monitor_count(Register java_thread) {
|
||||||
|
if (!Continuations::enabled()) return;
|
||||||
|
incrementw(Address(java_thread, JavaThread::held_monitor_count_offset()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::dec_held_monitor_count(Register java_thread) {
|
||||||
|
if (!Continuations::enabled()) return;
|
||||||
|
decrementw(Address(java_thread, JavaThread::held_monitor_count_offset()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::reset_held_monitor_count(Register java_thread) {
|
||||||
|
strw(zr, Address(java_thread, JavaThread::held_monitor_count_offset()));
|
||||||
|
}
|
||||||
|
|
||||||
void MacroAssembler::reset_last_Java_frame(bool clear_fp) {
|
void MacroAssembler::reset_last_Java_frame(bool clear_fp) {
|
||||||
// we must set sp to zero to clear frame
|
// we must set sp to zero to clear frame
|
||||||
str(zr, Address(rthread, JavaThread::last_Java_sp_offset()));
|
str(zr, Address(rthread, JavaThread::last_Java_sp_offset()));
|
||||||
@ -566,9 +602,7 @@ void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, in
|
|||||||
|
|
||||||
// Maybe emit a call via a trampoline. If the code cache is small
|
// Maybe emit a call via a trampoline. If the code cache is small
|
||||||
// trampolines won't be emitted.
|
// trampolines won't be emitted.
|
||||||
|
address MacroAssembler::trampoline_call1(Address entry, CodeBuffer* cbuf, bool check_emit_size) {
|
||||||
address MacroAssembler::trampoline_call(Address entry, CodeBuffer* cbuf) {
|
|
||||||
assert(JavaThread::current()->is_Compiler_thread(), "just checking");
|
|
||||||
assert(entry.rspec().type() == relocInfo::runtime_call_type
|
assert(entry.rspec().type() == relocInfo::runtime_call_type
|
||||||
|| entry.rspec().type() == relocInfo::opt_virtual_call_type
|
|| entry.rspec().type() == relocInfo::opt_virtual_call_type
|
||||||
|| entry.rspec().type() == relocInfo::static_call_type
|
|| entry.rspec().type() == relocInfo::static_call_type
|
||||||
@ -578,12 +612,14 @@ address MacroAssembler::trampoline_call(Address entry, CodeBuffer* cbuf) {
|
|||||||
if (far_branches()) {
|
if (far_branches()) {
|
||||||
bool in_scratch_emit_size = false;
|
bool in_scratch_emit_size = false;
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
|
if (check_emit_size) {
|
||||||
// We don't want to emit a trampoline if C2 is generating dummy
|
// We don't want to emit a trampoline if C2 is generating dummy
|
||||||
// code during its branch shortening phase.
|
// code during its branch shortening phase.
|
||||||
CompileTask* task = ciEnv::current()->task();
|
CompileTask* task = ciEnv::current()->task();
|
||||||
in_scratch_emit_size =
|
in_scratch_emit_size =
|
||||||
(task != NULL && is_c2_compile(task->comp_level()) &&
|
(task != NULL && is_c2_compile(task->comp_level()) &&
|
||||||
Compile::current()->output()->in_scratch_emit_size());
|
Compile::current()->output()->in_scratch_emit_size());
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!in_scratch_emit_size) {
|
if (!in_scratch_emit_size) {
|
||||||
address stub = emit_trampoline_stub(offset(), entry.target());
|
address stub = emit_trampoline_stub(offset(), entry.target());
|
||||||
@ -790,6 +826,14 @@ void MacroAssembler::align(int modulus) {
|
|||||||
while (offset() % modulus != 0) nop();
|
while (offset() % modulus != 0) nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::post_call_nop() {
|
||||||
|
if (!Continuations::enabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
relocate(post_call_nop_Relocation::spec());
|
||||||
|
nop();
|
||||||
|
}
|
||||||
|
|
||||||
// these are no-ops overridden by InterpreterMacroAssembler
|
// these are no-ops overridden by InterpreterMacroAssembler
|
||||||
|
|
||||||
void MacroAssembler::check_and_handle_earlyret(Register java_thread) { }
|
void MacroAssembler::check_and_handle_earlyret(Register java_thread) { }
|
||||||
@ -2196,6 +2240,15 @@ void MacroAssembler::unimplemented(const char* what) {
|
|||||||
stop(buf);
|
stop(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::_assert_asm(Assembler::Condition cc, const char* msg) {
|
||||||
|
#ifdef ASSERT
|
||||||
|
Label OK;
|
||||||
|
br(cc, OK);
|
||||||
|
stop(msg);
|
||||||
|
bind(OK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// If a constant does not fit in an immediate field, generate some
|
// If a constant does not fit in an immediate field, generate some
|
||||||
// number of MOV instructions and then perform the operation.
|
// number of MOV instructions and then perform the operation.
|
||||||
void MacroAssembler::wrap_add_sub_imm_insn(Register Rd, Register Rn, unsigned imm,
|
void MacroAssembler::wrap_add_sub_imm_insn(Register Rd, Register Rn, unsigned imm,
|
||||||
@ -4148,7 +4201,8 @@ void MacroAssembler::movoop(Register dst, jobject obj, bool immediate) {
|
|||||||
// nmethod entry barrier necessitate using the constant pool. They have to be
|
// nmethod entry barrier necessitate using the constant pool. They have to be
|
||||||
// ordered with respected to oop accesses.
|
// ordered with respected to oop accesses.
|
||||||
// Using immediate literals would necessitate ISBs.
|
// Using immediate literals would necessitate ISBs.
|
||||||
if (BarrierSet::barrier_set()->barrier_set_nmethod() != NULL || !immediate) {
|
BarrierSet* bs = BarrierSet::barrier_set();
|
||||||
|
if ((bs->barrier_set_nmethod() != NULL && bs->barrier_set_assembler()->nmethod_code_patching()) || !immediate) {
|
||||||
address dummy = address(uintptr_t(pc()) & -wordSize); // A nearby aligned address
|
address dummy = address(uintptr_t(pc()) & -wordSize); // A nearby aligned address
|
||||||
ldr_constant(dst, Address(dummy, rspec));
|
ldr_constant(dst, Address(dummy, rspec));
|
||||||
} else
|
} else
|
||||||
|
@ -687,6 +687,9 @@ public:
|
|||||||
// Alignment
|
// Alignment
|
||||||
void align(int modulus);
|
void align(int modulus);
|
||||||
|
|
||||||
|
// nop
|
||||||
|
void post_call_nop();
|
||||||
|
|
||||||
// Stack frame creation/removal
|
// Stack frame creation/removal
|
||||||
void enter(bool strip_ret_addr = false);
|
void enter(bool strip_ret_addr = false);
|
||||||
void leave();
|
void leave();
|
||||||
@ -874,6 +877,12 @@ public:
|
|||||||
void pop_CPU_state(bool restore_vectors = false, bool use_sve = false,
|
void pop_CPU_state(bool restore_vectors = false, bool use_sve = false,
|
||||||
int sve_vector_size_in_bytes = 0, int total_predicate_in_bytes = 0);
|
int sve_vector_size_in_bytes = 0, int total_predicate_in_bytes = 0);
|
||||||
|
|
||||||
|
void push_cont_fastpath(Register java_thread);
|
||||||
|
void pop_cont_fastpath(Register java_thread);
|
||||||
|
void inc_held_monitor_count(Register java_thread);
|
||||||
|
void dec_held_monitor_count(Register java_thread);
|
||||||
|
void reset_held_monitor_count(Register java_thread);
|
||||||
|
|
||||||
// Round up to a power of two
|
// Round up to a power of two
|
||||||
void round_to(Register reg, int modulus);
|
void round_to(Register reg, int modulus);
|
||||||
|
|
||||||
@ -1004,6 +1013,10 @@ public:
|
|||||||
|
|
||||||
void should_not_reach_here() { stop("should not reach here"); }
|
void should_not_reach_here() { stop("should not reach here"); }
|
||||||
|
|
||||||
|
void _assert_asm(Condition cc, const char* msg);
|
||||||
|
#define assert_asm0(cc, msg) _assert_asm(cc, FILE_AND_LINE ": " msg)
|
||||||
|
#define assert_asm(masm, command, cc, msg) DEBUG_ONLY(command; (masm)->_assert_asm(cc, FILE_AND_LINE ": " #command " " #cc ": " msg))
|
||||||
|
|
||||||
// Stack overflow checking
|
// Stack overflow checking
|
||||||
void bang_stack_with_offset(int offset) {
|
void bang_stack_with_offset(int offset) {
|
||||||
// stack grows down, caller passes positive offset
|
// stack grows down, caller passes positive offset
|
||||||
@ -1084,7 +1097,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
// Calls
|
// Calls
|
||||||
|
|
||||||
address trampoline_call(Address entry, CodeBuffer* cbuf = NULL);
|
address trampoline_call(Address entry, CodeBuffer* cbuf = NULL) { return trampoline_call1(entry, cbuf, true); }
|
||||||
|
address trampoline_call1(Address entry, CodeBuffer* cbuf, bool check_emit_size = true);
|
||||||
|
|
||||||
static bool far_branches() {
|
static bool far_branches() {
|
||||||
return ReservedCodeCacheSize > branch_range;
|
return ReservedCodeCacheSize > branch_range;
|
||||||
|
@ -544,3 +544,29 @@ address NativeCall::trampoline_jump(CodeBuffer &cbuf, address dest) {
|
|||||||
|
|
||||||
return stub;
|
return stub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativePostCallNop::make_deopt() {
|
||||||
|
NativeDeoptInstruction::insert(addr_at(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativePostCallNop::patch(jint diff) {
|
||||||
|
// unsupported for now
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeDeoptInstruction::verify() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inserts an undefined instruction at a given pc
|
||||||
|
void NativeDeoptInstruction::insert(address code_pos) {
|
||||||
|
// 1 1 0 1 | 0 1 0 0 | 1 0 1 imm16 0 0 0 0 1
|
||||||
|
// d | 4 | a | de | 0 | 0 |
|
||||||
|
// 0xd4, 0x20, 0x00, 0x00
|
||||||
|
uint32_t insn = 0xd4ade001;
|
||||||
|
uint32_t *pos = (uint32_t *) code_pos;
|
||||||
|
*pos = insn;
|
||||||
|
/**code_pos = 0xd4;
|
||||||
|
*(code_pos+1) = 0x60;
|
||||||
|
*(code_pos+2) = 0x00;
|
||||||
|
*(code_pos+3) = 0x00;*/
|
||||||
|
ICache::invalidate_range(code_pos, 4);
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, 2108, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, 2108, Red Hat Inc. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -71,7 +71,7 @@ public:
|
|||||||
return (encoding() & 0xff000000) == 0x10000000;
|
return (encoding() & 0xff000000) == 0x10000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_nop();
|
inline bool is_nop() const;
|
||||||
bool is_jump();
|
bool is_jump();
|
||||||
bool is_general_jump();
|
bool is_general_jump();
|
||||||
inline bool is_jump_or_nop();
|
inline bool is_jump_or_nop();
|
||||||
@ -543,7 +543,7 @@ class NativeTstRegMem: public NativeInstruction {
|
|||||||
public:
|
public:
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool NativeInstruction::is_nop() {
|
inline bool NativeInstruction::is_nop() const{
|
||||||
uint32_t insn = *(uint32_t*)addr_at(0);
|
uint32_t insn = *(uint32_t*)addr_at(0);
|
||||||
return insn == 0xd503201f;
|
return insn == 0xd503201f;
|
||||||
}
|
}
|
||||||
@ -666,4 +666,48 @@ inline NativeLdSt* NativeLdSt_at(address addr) {
|
|||||||
return (NativeLdSt*)addr;
|
return (NativeLdSt*)addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NativePostCallNop: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
bool check() const { return is_nop(); }
|
||||||
|
int displacement() const { return 0; }
|
||||||
|
void patch(jint diff);
|
||||||
|
void make_deopt();
|
||||||
|
};
|
||||||
|
|
||||||
|
inline NativePostCallNop* nativePostCallNop_at(address address) {
|
||||||
|
NativePostCallNop* nop = (NativePostCallNop*) address;
|
||||||
|
if (nop->check()) {
|
||||||
|
return nop;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline NativePostCallNop* nativePostCallNop_unsafe_at(address address) {
|
||||||
|
NativePostCallNop* nop = (NativePostCallNop*) address;
|
||||||
|
assert(nop->check(), "");
|
||||||
|
return nop;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NativeDeoptInstruction: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
instruction_size = 4,
|
||||||
|
instruction_offset = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
address instruction_address() const { return addr_at(instruction_offset); }
|
||||||
|
address next_instruction_address() const { return addr_at(instruction_size); }
|
||||||
|
|
||||||
|
void verify();
|
||||||
|
|
||||||
|
static bool is_deopt_at(address instr) {
|
||||||
|
assert(instr != NULL, "");
|
||||||
|
uint32_t value = *(uint32_t *) instr;
|
||||||
|
return value == 0xd4ade001;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MT-safe patching
|
||||||
|
static void insert(address code_pos);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // CPU_AARCH64_NATIVEINST_AARCH64_HPP
|
#endif // CPU_AARCH64_NATIVEINST_AARCH64_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -36,13 +36,13 @@ address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const {
|
|||||||
int base_reg_enc = (base_reg->value() - ConcreteRegisterImpl::max_gpr) /
|
int base_reg_enc = (base_reg->value() - ConcreteRegisterImpl::max_gpr) /
|
||||||
FloatRegisterImpl::max_slots_per_register;
|
FloatRegisterImpl::max_slots_per_register;
|
||||||
intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size;
|
intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size;
|
||||||
address base_location = location(base_reg);
|
address base_location = location(base_reg, nullptr);
|
||||||
if (base_location != NULL) {
|
if (base_location != NULL) {
|
||||||
return base_location + offset_in_bytes;
|
return base_location + offset_in_bytes;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return location(base_reg->next(slot_idx));
|
return location(base_reg->next(slot_idx), nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "asm/macroAssembler.hpp"
|
#include "asm/macroAssembler.hpp"
|
||||||
#include "asm/macroAssembler.inline.hpp"
|
#include "asm/macroAssembler.inline.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
#include "code/compiledIC.hpp"
|
||||||
#include "code/debugInfoRec.hpp"
|
#include "code/debugInfoRec.hpp"
|
||||||
#include "code/icBuffer.hpp"
|
#include "code/icBuffer.hpp"
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
@ -41,6 +42,8 @@
|
|||||||
#include "oops/compiledICHolder.hpp"
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "oops/klass.inline.hpp"
|
#include "oops/klass.inline.hpp"
|
||||||
#include "prims/methodHandles.hpp"
|
#include "prims/methodHandles.hpp"
|
||||||
|
#include "runtime/continuation.hpp"
|
||||||
|
#include "runtime/continuationEntry.inline.hpp"
|
||||||
#include "runtime/jniHandles.hpp"
|
#include "runtime/jniHandles.hpp"
|
||||||
#include "runtime/safepointMechanism.hpp"
|
#include "runtime/safepointMechanism.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
@ -267,7 +270,7 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm) {
|
|||||||
#endif
|
#endif
|
||||||
__ pop_CPU_state(_save_vectors);
|
__ pop_CPU_state(_save_vectors);
|
||||||
#endif
|
#endif
|
||||||
__ leave();
|
__ ldp(rfp, lr, Address(__ post(sp, 2 * wordSize)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,6 +723,10 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__ mov(rscratch2, rscratch1);
|
||||||
|
__ push_cont_fastpath(rthread); // Set JavaThread::_cont_fastpath to the sp of the oldest interpreted frame we know about; kills rscratch1
|
||||||
|
__ mov(rscratch1, rscratch2);
|
||||||
|
|
||||||
// 6243940 We might end up in handle_wrong_method if
|
// 6243940 We might end up in handle_wrong_method if
|
||||||
// the callee is deoptimized as we race thru here. If that
|
// the callee is deoptimized as we race thru here. If that
|
||||||
// happens we don't want to take a safepoint because the
|
// happens we don't want to take a safepoint because the
|
||||||
@ -1182,6 +1189,91 @@ static void verify_oop_args(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// defined in stubGenerator_aarch64.cpp
|
||||||
|
OopMap* continuation_enter_setup(MacroAssembler* masm, int& stack_slots);
|
||||||
|
void fill_continuation_entry(MacroAssembler* masm);
|
||||||
|
void continuation_enter_cleanup(MacroAssembler* masm);
|
||||||
|
|
||||||
|
// enterSpecial(Continuation c, boolean isContinue, boolean isVirtualThread)
|
||||||
|
// On entry: c_rarg1 -- the continuation object
|
||||||
|
// c_rarg2 -- isContinue
|
||||||
|
// c_rarg3 -- isVirtualThread
|
||||||
|
static void gen_continuation_enter(MacroAssembler* masm,
|
||||||
|
const methodHandle& method,
|
||||||
|
const BasicType* sig_bt,
|
||||||
|
const VMRegPair* regs,
|
||||||
|
int& exception_offset,
|
||||||
|
OopMapSet*oop_maps,
|
||||||
|
int& frame_complete,
|
||||||
|
int& stack_slots) {
|
||||||
|
//verify_oop_args(masm, method, sig_bt, regs);
|
||||||
|
Address resolve(SharedRuntime::get_resolve_static_call_stub(),
|
||||||
|
relocInfo::static_call_type);
|
||||||
|
|
||||||
|
stack_slots = 2; // will be overwritten
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
Label call_thaw, exit;
|
||||||
|
|
||||||
|
__ enter();
|
||||||
|
|
||||||
|
OopMap* map = continuation_enter_setup(masm, stack_slots);
|
||||||
|
|
||||||
|
// Frame is now completed as far as size and linkage.
|
||||||
|
frame_complete =__ pc() - start;
|
||||||
|
|
||||||
|
fill_continuation_entry(masm);
|
||||||
|
|
||||||
|
__ cmp(c_rarg2, (u1)0);
|
||||||
|
__ br(Assembler::NE, call_thaw);
|
||||||
|
|
||||||
|
address mark = __ pc();
|
||||||
|
|
||||||
|
__ trampoline_call1(resolve, NULL, false);
|
||||||
|
|
||||||
|
oop_maps->add_gc_map(__ pc() - start, map);
|
||||||
|
__ post_call_nop();
|
||||||
|
|
||||||
|
__ b(exit);
|
||||||
|
|
||||||
|
__ bind(call_thaw);
|
||||||
|
|
||||||
|
rt_call(masm, CAST_FROM_FN_PTR(address, StubRoutines::cont_thaw()));
|
||||||
|
oop_maps->add_gc_map(__ pc() - start, map->deep_copy());
|
||||||
|
ContinuationEntry::return_pc_offset = __ pc() - start;
|
||||||
|
__ post_call_nop();
|
||||||
|
|
||||||
|
__ bind(exit);
|
||||||
|
continuation_enter_cleanup(masm);
|
||||||
|
__ leave();
|
||||||
|
__ ret(lr);
|
||||||
|
|
||||||
|
/// exception handling
|
||||||
|
|
||||||
|
exception_offset = __ pc() - start;
|
||||||
|
{
|
||||||
|
__ mov(r19, r0); // save return value contaning the exception oop in callee-saved R19
|
||||||
|
|
||||||
|
continuation_enter_cleanup(masm);
|
||||||
|
|
||||||
|
__ ldr(c_rarg1, Address(rfp, wordSize)); // return address
|
||||||
|
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rthread, c_rarg1);
|
||||||
|
|
||||||
|
// see OptoRuntime::generate_exception_blob: r0 -- exception oop, r3 -- exception pc
|
||||||
|
|
||||||
|
__ mov(r1, r0); // the exception handler
|
||||||
|
__ mov(r0, r19); // restore return value contaning the exception oop
|
||||||
|
__ verify_oop(r0);
|
||||||
|
|
||||||
|
__ leave();
|
||||||
|
__ mov(r3, lr);
|
||||||
|
__ br(r1); // the exception handler
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeBuffer* cbuf = masm->code_section()->outer();
|
||||||
|
address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, mark);
|
||||||
|
}
|
||||||
|
|
||||||
static void gen_special_dispatch(MacroAssembler* masm,
|
static void gen_special_dispatch(MacroAssembler* masm,
|
||||||
const methodHandle& method,
|
const methodHandle& method,
|
||||||
const BasicType* sig_bt,
|
const BasicType* sig_bt,
|
||||||
@ -1263,6 +1355,37 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
|||||||
BasicType* in_sig_bt,
|
BasicType* in_sig_bt,
|
||||||
VMRegPair* in_regs,
|
VMRegPair* in_regs,
|
||||||
BasicType ret_type) {
|
BasicType ret_type) {
|
||||||
|
if (method->is_continuation_enter_intrinsic()) {
|
||||||
|
vmIntrinsics::ID iid = method->intrinsic_id();
|
||||||
|
intptr_t start = (intptr_t)__ pc();
|
||||||
|
int vep_offset = ((intptr_t)__ pc()) - start;
|
||||||
|
int exception_offset = 0;
|
||||||
|
int frame_complete = 0;
|
||||||
|
int stack_slots = 0;
|
||||||
|
OopMapSet* oop_maps = new OopMapSet();
|
||||||
|
gen_continuation_enter(masm,
|
||||||
|
method,
|
||||||
|
in_sig_bt,
|
||||||
|
in_regs,
|
||||||
|
exception_offset,
|
||||||
|
oop_maps,
|
||||||
|
frame_complete,
|
||||||
|
stack_slots);
|
||||||
|
__ flush();
|
||||||
|
nmethod* nm = nmethod::new_native_nmethod(method,
|
||||||
|
compile_id,
|
||||||
|
masm->code(),
|
||||||
|
vep_offset,
|
||||||
|
frame_complete,
|
||||||
|
stack_slots,
|
||||||
|
in_ByteSize(-1),
|
||||||
|
in_ByteSize(-1),
|
||||||
|
oop_maps,
|
||||||
|
exception_offset);
|
||||||
|
ContinuationEntry::set_enter_nmethod(nm);
|
||||||
|
return nm;
|
||||||
|
}
|
||||||
|
|
||||||
if (method->is_method_handle_intrinsic()) {
|
if (method->is_method_handle_intrinsic()) {
|
||||||
vmIntrinsics::ID iid = method->intrinsic_id();
|
vmIntrinsics::ID iid = method->intrinsic_id();
|
||||||
intptr_t start = (intptr_t)__ pc();
|
intptr_t start = (intptr_t)__ pc();
|
||||||
|
91
src/hotspot/cpu/aarch64/smallRegisterMap_aarch64.inline.hpp
Normal file
91
src/hotspot/cpu/aarch64/smallRegisterMap_aarch64.inline.hpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_AARCH64_SMALLREGISTERMAP_AARCH64_INLINE_HPP
|
||||||
|
#define CPU_AARCH64_SMALLREGISTERMAP_AARCH64_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
// Java frames don't have callee saved registers (except for rfp), so we can use a smaller RegisterMap
|
||||||
|
class SmallRegisterMap {
|
||||||
|
public:
|
||||||
|
static constexpr SmallRegisterMap* instance = nullptr;
|
||||||
|
private:
|
||||||
|
static void assert_is_rfp(VMReg r) NOT_DEBUG_RETURN
|
||||||
|
DEBUG_ONLY({ assert (r == rfp->as_VMReg() || r == rfp->as_VMReg()->next(), "Reg: %s", r->name()); })
|
||||||
|
public:
|
||||||
|
// as_RegisterMap is used when we didn't want to templatize and abstract over RegisterMap type to support SmallRegisterMap
|
||||||
|
// Consider enhancing SmallRegisterMap to support those cases
|
||||||
|
const RegisterMap* as_RegisterMap() const { return nullptr; }
|
||||||
|
RegisterMap* as_RegisterMap() { return nullptr; }
|
||||||
|
|
||||||
|
RegisterMap* copy_to_RegisterMap(RegisterMap* map, intptr_t* sp) const {
|
||||||
|
map->clear();
|
||||||
|
map->set_include_argument_oops(this->include_argument_oops());
|
||||||
|
frame::update_map_with_saved_link(map, (intptr_t**)sp - frame::sender_sp_offset);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallRegisterMap() {}
|
||||||
|
|
||||||
|
SmallRegisterMap(const RegisterMap* map) {
|
||||||
|
#ifdef ASSERT
|
||||||
|
for(int i = 0; i < RegisterMap::reg_count; i++) {
|
||||||
|
VMReg r = VMRegImpl::as_VMReg(i);
|
||||||
|
if (map->location(r, (intptr_t*)nullptr) != nullptr) assert_is_rfp(r);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address location(VMReg reg, intptr_t* sp) const {
|
||||||
|
assert_is_rfp(reg);
|
||||||
|
return (address)(sp - frame::sender_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_location(VMReg reg, address loc) { assert_is_rfp(reg); }
|
||||||
|
|
||||||
|
JavaThread* thread() const {
|
||||||
|
#ifndef ASSERT
|
||||||
|
guarantee (false, "unreachable");
|
||||||
|
#endif
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update_map() const { return false; }
|
||||||
|
bool walk_cont() const { return false; }
|
||||||
|
bool include_argument_oops() const { return false; }
|
||||||
|
void set_include_argument_oops(bool f) {}
|
||||||
|
bool in_cont() const { return false; }
|
||||||
|
stackChunkHandle stack_chunk() const { return stackChunkHandle(); }
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
bool should_skip_missing() const { return false; }
|
||||||
|
VMReg find_register_spilled_here(void* p, intptr_t* sp) { return rfp->as_VMReg(); }
|
||||||
|
void print() const { print_on(tty); }
|
||||||
|
void print_on(outputStream* st) const { st->print_cr("Small register map"); }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CPU_AARCH64_SMALLREGISTERMAP_AARCH64_INLINE_HPP
|
149
src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp
Normal file
149
src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_AARCH64_STACKCHUNKFRAMESTREAM_AARCH64_INLINE_HPP
|
||||||
|
#define CPU_AARCH64_STACKCHUNKFRAMESTREAM_AARCH64_INLINE_HPP
|
||||||
|
|
||||||
|
#include "interpreter/oopMapCache.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline bool StackChunkFrameStream<frame_kind>::is_in_frame(void* p0) const {
|
||||||
|
assert(!is_done(), "");
|
||||||
|
intptr_t* p = (intptr_t*)p0;
|
||||||
|
int argsize = is_compiled() ? (_cb->as_compiled_method()->method()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord : 0;
|
||||||
|
int frame_size = _cb->frame_size() + argsize;
|
||||||
|
return p == sp() - frame::sender_sp_offset || ((p - unextended_sp()) >= 0 && (p - unextended_sp()) < frame_size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline frame StackChunkFrameStream<frame_kind>::to_frame() const {
|
||||||
|
if (is_done()) {
|
||||||
|
return frame(_sp, _sp, nullptr, nullptr, nullptr, nullptr, true);
|
||||||
|
} else {
|
||||||
|
return frame(sp(), unextended_sp(), fp(), pc(), cb(), _oopmap, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline address StackChunkFrameStream<frame_kind>::get_pc() const {
|
||||||
|
assert(!is_done(), "");
|
||||||
|
return *(address*)(_sp - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::fp() const {
|
||||||
|
intptr_t* fp_addr = _sp - frame::sender_sp_offset;
|
||||||
|
return (frame_kind == ChunkFrames::Mixed && is_interpreted())
|
||||||
|
? fp_addr + *fp_addr // derelativize
|
||||||
|
: *(intptr_t**)fp_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::derelativize(int offset) const {
|
||||||
|
intptr_t* fp = this->fp();
|
||||||
|
assert(fp != nullptr, "");
|
||||||
|
return fp + fp[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::unextended_sp_for_interpreter_frame() const {
|
||||||
|
assert_is_interpreted_and_frame_type_mixed();
|
||||||
|
return derelativize(frame::interpreter_frame_last_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
intptr_t* StackChunkFrameStream<frame_kind>::next_sp_for_interpreter_frame() const {
|
||||||
|
assert_is_interpreted_and_frame_type_mixed();
|
||||||
|
return (derelativize(frame::interpreter_frame_locals_offset) + 1 >= _end) ? _end : fp() + frame::sender_sp_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::next_for_interpreter_frame() {
|
||||||
|
assert_is_interpreted_and_frame_type_mixed();
|
||||||
|
if (derelativize(frame::interpreter_frame_locals_offset) + 1 >= _end) {
|
||||||
|
_unextended_sp = _end;
|
||||||
|
_sp = _end;
|
||||||
|
} else {
|
||||||
|
intptr_t* fp = this->fp();
|
||||||
|
_unextended_sp = fp + fp[frame::interpreter_frame_sender_sp_offset];
|
||||||
|
_sp = fp + frame::sender_sp_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_size() const {
|
||||||
|
assert_is_interpreted_and_frame_type_mixed();
|
||||||
|
|
||||||
|
intptr_t* top = unextended_sp(); // later subtract argsize if callee is interpreted
|
||||||
|
intptr_t* bottom = derelativize(frame::interpreter_frame_locals_offset) + 1; // the sender's unextended sp: derelativize(frame::interpreter_frame_sender_sp_offset);
|
||||||
|
return (int)(bottom - top);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_stack_argsize() const {
|
||||||
|
assert_is_interpreted_and_frame_type_mixed();
|
||||||
|
int diff = (int)(derelativize(frame::interpreter_frame_locals_offset) - derelativize(frame::interpreter_frame_sender_sp_offset) + 1);
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_num_oops() const {
|
||||||
|
assert_is_interpreted_and_frame_type_mixed();
|
||||||
|
ResourceMark rm;
|
||||||
|
InterpreterOopMap mask;
|
||||||
|
frame f = to_frame();
|
||||||
|
f.interpreted_frame_oop_map(&mask);
|
||||||
|
return mask.num_oops()
|
||||||
|
+ 1 // for the mirror oop
|
||||||
|
+ ((intptr_t*)f.interpreter_frame_monitor_begin()
|
||||||
|
- (intptr_t*)f.interpreter_frame_monitor_end())/BasicObjectLock::size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::Mixed>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
if (map->update_map()) {
|
||||||
|
frame::update_map_with_saved_link(map, map->in_cont() ? (intptr_t**)(intptr_t)frame::sender_sp_offset
|
||||||
|
: (intptr_t**)(_sp - frame::sender_sp_offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::CompiledOnly>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
if (map->update_map()) {
|
||||||
|
frame::update_map_with_saved_link(map, map->in_cont() ? (intptr_t**)(intptr_t)frame::sender_sp_offset
|
||||||
|
: (intptr_t**)(_sp - frame::sender_sp_offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::update_reg_map_pd(RegisterMapT* map) {}
|
||||||
|
|
||||||
|
#endif // CPU_AARCH64_STACKCHUNKFRAMESTREAM_AARCH64_INLINE_HPP
|
42
src/hotspot/cpu/aarch64/stackChunkOop_aarch64.inline.hpp
Normal file
42
src/hotspot/cpu/aarch64/stackChunkOop_aarch64.inline.hpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_AARCH64_STACKCHUNKOOP_AARCH64_INLINE_HPP
|
||||||
|
#define CPU_AARCH64_STACKCHUNKOOP_AARCH64_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::relativize_frame_pd(frame& fr) const {
|
||||||
|
if (fr.is_interpreted_frame()) {
|
||||||
|
fr.set_offset_fp(relativize_address(fr.fp()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::derelativize_frame_pd(frame& fr) const {
|
||||||
|
if (fr.is_interpreted_frame()) {
|
||||||
|
fr.set_fp(derelativize_address(fr.offset_fp()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_AARCH64_STACKCHUNKOOP_AARCH64_INLINE_HPP
|
@ -42,6 +42,8 @@
|
|||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/methodHandles.hpp"
|
#include "prims/methodHandles.hpp"
|
||||||
#include "runtime/atomic.hpp"
|
#include "runtime/atomic.hpp"
|
||||||
|
#include "runtime/continuation.hpp"
|
||||||
|
#include "runtime/continuationEntry.inline.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
@ -49,6 +51,7 @@
|
|||||||
#include "runtime/stubRoutines.hpp"
|
#include "runtime/stubRoutines.hpp"
|
||||||
#include "runtime/thread.inline.hpp"
|
#include "runtime/thread.inline.hpp"
|
||||||
#include "utilities/align.hpp"
|
#include "utilities/align.hpp"
|
||||||
|
#include "utilities/globalDefinitions.hpp"
|
||||||
#include "utilities/powerOfTwo.hpp"
|
#include "utilities/powerOfTwo.hpp"
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
#include "opto/runtime.hpp"
|
#include "opto/runtime.hpp"
|
||||||
@ -73,6 +76,10 @@
|
|||||||
|
|
||||||
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
|
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
|
||||||
|
|
||||||
|
OopMap* continuation_enter_setup(MacroAssembler* masm, int& stack_slots);
|
||||||
|
void fill_continuation_entry(MacroAssembler* masm);
|
||||||
|
void continuation_enter_cleanup(MacroAssembler* masm);
|
||||||
|
|
||||||
// Stub Code definitions
|
// Stub Code definitions
|
||||||
|
|
||||||
class StubGenerator: public StubCodeGenerator {
|
class StubGenerator: public StubCodeGenerator {
|
||||||
@ -349,6 +356,8 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
__ pop_cont_fastpath(rthread);
|
||||||
|
|
||||||
// restore callee-save registers
|
// restore callee-save registers
|
||||||
__ ldpd(v15, v14, d15_save);
|
__ ldpd(v15, v14, d15_save);
|
||||||
__ ldpd(v13, v12, d13_save);
|
__ ldpd(v13, v12, d13_save);
|
||||||
@ -5144,6 +5153,20 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
|
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
|
||||||
|
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||||
|
|
||||||
|
if (bs_asm->nmethod_code_patching()) {
|
||||||
|
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
|
||||||
|
// We can get here despite the nmethod being good, if we have not
|
||||||
|
// yet applied our cross modification fence.
|
||||||
|
Address thread_epoch_addr(rthread, in_bytes(bs_nm->thread_disarmed_offset()) + 4);
|
||||||
|
__ lea(rscratch2, ExternalAddress(bs_asm->patching_epoch_addr()));
|
||||||
|
__ ldrw(rscratch2, rscratch2);
|
||||||
|
__ strw(rscratch2, thread_epoch_addr);
|
||||||
|
__ isb();
|
||||||
|
__ membar(__ LoadLoad);
|
||||||
|
}
|
||||||
|
|
||||||
__ set_last_Java_frame(sp, rfp, lr, rscratch1);
|
__ set_last_Java_frame(sp, rfp, lr, rscratch1);
|
||||||
|
|
||||||
__ enter();
|
__ enter();
|
||||||
@ -6466,6 +6489,268 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
}
|
}
|
||||||
#endif // LINUX
|
#endif // LINUX
|
||||||
|
|
||||||
|
RuntimeStub* generate_cont_doYield() {
|
||||||
|
if (!Continuations::enabled()) return nullptr;
|
||||||
|
|
||||||
|
const char *name = "cont_doYield";
|
||||||
|
|
||||||
|
enum layout {
|
||||||
|
rfp_off1,
|
||||||
|
rfp_off2,
|
||||||
|
lr_off,
|
||||||
|
lr_off2,
|
||||||
|
framesize // inclusive of return address
|
||||||
|
};
|
||||||
|
// assert(is_even(framesize/2), "sp not 16-byte aligned");
|
||||||
|
|
||||||
|
int insts_size = 512;
|
||||||
|
int locs_size = 64;
|
||||||
|
CodeBuffer code(name, insts_size, locs_size);
|
||||||
|
OopMapSet* oop_maps = new OopMapSet();
|
||||||
|
MacroAssembler* masm = new MacroAssembler(&code);
|
||||||
|
MacroAssembler* _masm = masm;
|
||||||
|
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
__ enter();
|
||||||
|
|
||||||
|
__ mov(c_rarg1, sp);
|
||||||
|
|
||||||
|
int frame_complete = __ pc() - start;
|
||||||
|
address the_pc = __ pc();
|
||||||
|
|
||||||
|
__ post_call_nop(); // this must be exactly after the pc value that is pushed into the frame info, we use this nop for fast CodeBlob lookup
|
||||||
|
|
||||||
|
__ mov(c_rarg0, rthread);
|
||||||
|
__ set_last_Java_frame(sp, rfp, the_pc, rscratch1);
|
||||||
|
__ call_VM_leaf(Continuation::freeze_entry(), 2);
|
||||||
|
__ reset_last_Java_frame(true);
|
||||||
|
|
||||||
|
Label pinned;
|
||||||
|
|
||||||
|
__ cbnz(r0, pinned);
|
||||||
|
|
||||||
|
// We've succeeded, set sp to the ContinuationEntry
|
||||||
|
__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset()));
|
||||||
|
__ mov(sp, rscratch1);
|
||||||
|
continuation_enter_cleanup(masm);
|
||||||
|
|
||||||
|
__ bind(pinned); // pinned -- return to caller
|
||||||
|
|
||||||
|
__ leave();
|
||||||
|
__ ret(lr);
|
||||||
|
|
||||||
|
OopMap* map = new OopMap(framesize, 1);
|
||||||
|
oop_maps->add_gc_map(the_pc - start, map);
|
||||||
|
|
||||||
|
RuntimeStub* stub = // codeBlob framesize is in words (not VMRegImpl::slot_size)
|
||||||
|
RuntimeStub::new_runtime_stub(name,
|
||||||
|
&code,
|
||||||
|
frame_complete,
|
||||||
|
(framesize >> (LogBytesPerWord - LogBytesPerInt)),
|
||||||
|
oop_maps, false);
|
||||||
|
return stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
address generate_cont_thaw(bool return_barrier, bool exception) {
|
||||||
|
assert(return_barrier || !exception, "must be");
|
||||||
|
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
if (return_barrier) {
|
||||||
|
__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset()));
|
||||||
|
__ mov(sp, rscratch1);
|
||||||
|
}
|
||||||
|
assert_asm(_masm, (__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset())), __ cmp(sp, rscratch1)), Assembler::EQ, "incorrect sp");
|
||||||
|
|
||||||
|
if (return_barrier) {
|
||||||
|
// preserve possible return value from a method returning to the return barrier
|
||||||
|
__ fmovd(rscratch1, v0);
|
||||||
|
__ stp(rscratch1, r0, Address(__ pre(sp, -2 * wordSize)));
|
||||||
|
}
|
||||||
|
|
||||||
|
__ movw(c_rarg1, (return_barrier ? 1 : 0) + (exception ? 1 : 0));
|
||||||
|
__ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::prepare_thaw), rthread, c_rarg1);
|
||||||
|
__ mov(rscratch2, r0); // r0 contains the size of the frames to thaw, 0 if overflow or no more frames
|
||||||
|
|
||||||
|
if (return_barrier) {
|
||||||
|
// restore return value (no safepoint in the call to thaw, so even an oop return value should be OK)
|
||||||
|
__ ldp(rscratch1, r0, Address(__ post(sp, 2 * wordSize)));
|
||||||
|
__ fmovd(v0, rscratch1);
|
||||||
|
}
|
||||||
|
assert_asm(_masm, (__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset())), __ cmp(sp, rscratch1)), Assembler::EQ, "incorrect sp");
|
||||||
|
|
||||||
|
|
||||||
|
Label thaw_success;
|
||||||
|
// rscratch2 contains the size of the frames to thaw, 0 if overflow or no more frames
|
||||||
|
__ cbnz(rscratch2, thaw_success);
|
||||||
|
__ lea(rscratch1, ExternalAddress(StubRoutines::throw_StackOverflowError_entry()));
|
||||||
|
__ br(rscratch1);
|
||||||
|
__ bind(thaw_success);
|
||||||
|
|
||||||
|
// make room for the thawed frames
|
||||||
|
__ sub(rscratch1, sp, rscratch2);
|
||||||
|
__ andr(rscratch1, rscratch1, -16); // align
|
||||||
|
__ mov(sp, rscratch1);
|
||||||
|
|
||||||
|
if (return_barrier) {
|
||||||
|
// save original return value -- again
|
||||||
|
__ fmovd(rscratch1, v0);
|
||||||
|
__ stp(rscratch1, r0, Address(__ pre(sp, -2 * wordSize)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we want, we can templatize thaw by kind, and have three different entries
|
||||||
|
if (exception) __ movw(c_rarg1, (uint32_t)Continuation::thaw_exception);
|
||||||
|
else if (return_barrier) __ movw(c_rarg1, (uint32_t)Continuation::thaw_return_barrier);
|
||||||
|
else __ movw(c_rarg1, (uint32_t)Continuation::thaw_top);
|
||||||
|
|
||||||
|
__ call_VM_leaf(Continuation::thaw_entry(), rthread, c_rarg1);
|
||||||
|
__ mov(rscratch2, r0); // r0 is the sp of the yielding frame
|
||||||
|
|
||||||
|
if (return_barrier) {
|
||||||
|
// restore return value (no safepoint in the call to thaw, so even an oop return value should be OK)
|
||||||
|
__ ldp(rscratch1, r0, Address(__ post(sp, 2 * wordSize)));
|
||||||
|
__ fmovd(v0, rscratch1);
|
||||||
|
} else {
|
||||||
|
__ mov(r0, zr); // return 0 (success) from doYield
|
||||||
|
}
|
||||||
|
|
||||||
|
// we're now on the yield frame (which is in an address above us b/c rsp has been pushed down)
|
||||||
|
__ sub(sp, rscratch2, 2*wordSize); // now pointing to rfp spill
|
||||||
|
__ mov(rfp, sp);
|
||||||
|
|
||||||
|
if (exception) {
|
||||||
|
__ ldr(c_rarg1, Address(rfp, wordSize)); // return address
|
||||||
|
__ verify_oop(r0);
|
||||||
|
__ mov(r19, r0); // save return value contaning the exception oop in callee-saved R19
|
||||||
|
|
||||||
|
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rthread, c_rarg1);
|
||||||
|
|
||||||
|
// Reinitialize the ptrue predicate register, in case the external runtime call clobbers ptrue reg, as we may return to SVE compiled code.
|
||||||
|
// __ reinitialize_ptrue();
|
||||||
|
|
||||||
|
// see OptoRuntime::generate_exception_blob: r0 -- exception oop, r3 -- exception pc
|
||||||
|
|
||||||
|
__ mov(r1, r0); // the exception handler
|
||||||
|
__ mov(r0, r19); // restore return value contaning the exception oop
|
||||||
|
__ verify_oop(r0);
|
||||||
|
|
||||||
|
__ leave();
|
||||||
|
__ mov(r3, lr);
|
||||||
|
__ br(r1); // the exception handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're "returning" into the topmost thawed frame; see Thaw::push_return_frame
|
||||||
|
__ leave();
|
||||||
|
__ ret(lr);
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
address generate_cont_thaw() {
|
||||||
|
if (!Continuations::enabled()) return nullptr;
|
||||||
|
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "Cont thaw");
|
||||||
|
address start = __ pc();
|
||||||
|
generate_cont_thaw(false, false);
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
address generate_cont_returnBarrier() {
|
||||||
|
if (!Continuations::enabled()) return nullptr;
|
||||||
|
|
||||||
|
// TODO: will probably need multiple return barriers depending on return type
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "cont return barrier");
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
generate_cont_thaw(true, false);
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
address generate_cont_returnBarrier_exception() {
|
||||||
|
if (!Continuations::enabled()) return nullptr;
|
||||||
|
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "cont return barrier exception handler");
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
generate_cont_thaw(true, true);
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_JFR
|
||||||
|
|
||||||
|
static void jfr_prologue(address the_pc, MacroAssembler* _masm, Register thread) {
|
||||||
|
__ set_last_Java_frame(sp, rfp, the_pc, rscratch1);
|
||||||
|
__ mov(c_rarg0, thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The handle is dereferenced through a load barrier.
|
||||||
|
static void jfr_epilogue(MacroAssembler* _masm, Register thread) {
|
||||||
|
__ reset_last_Java_frame(true);
|
||||||
|
Label null_jobject;
|
||||||
|
__ cbz(r0, null_jobject);
|
||||||
|
DecoratorSet decorators = ACCESS_READ | IN_NATIVE;
|
||||||
|
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||||
|
bs->load_at(_masm, decorators, T_OBJECT, r0, Address(r0, 0), c_rarg0, thread);
|
||||||
|
__ bind(null_jobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RuntimeStub* generate_jfr_stub(const char* name, address entrypoint) {
|
||||||
|
|
||||||
|
enum layout {
|
||||||
|
rbp_off,
|
||||||
|
rbpH_off,
|
||||||
|
return_off,
|
||||||
|
return_off2,
|
||||||
|
framesize // inclusive of return address
|
||||||
|
};
|
||||||
|
|
||||||
|
int insts_size = 512;
|
||||||
|
int locs_size = 64;
|
||||||
|
CodeBuffer code(name, insts_size, locs_size);
|
||||||
|
OopMapSet* oop_maps = new OopMapSet();
|
||||||
|
MacroAssembler* masm = new MacroAssembler(&code);
|
||||||
|
MacroAssembler* _masm = masm;
|
||||||
|
|
||||||
|
address start = __ pc();
|
||||||
|
__ enter();
|
||||||
|
int frame_complete = __ pc() - start;
|
||||||
|
address the_pc = __ pc();
|
||||||
|
jfr_prologue(the_pc, _masm, rthread);
|
||||||
|
__ call_VM_leaf(entrypoint, 1);
|
||||||
|
jfr_epilogue(_masm, rthread);
|
||||||
|
__ leave();
|
||||||
|
__ ret(lr);
|
||||||
|
|
||||||
|
OopMap* map = new OopMap(framesize, 1); // rfp
|
||||||
|
oop_maps->add_gc_map(the_pc - start, map);
|
||||||
|
|
||||||
|
RuntimeStub* stub = // codeBlob framesize is in words (not VMRegImpl::slot_size)
|
||||||
|
RuntimeStub::new_runtime_stub(name, &code, frame_complete,
|
||||||
|
(framesize >> (LogBytesPerWord - LogBytesPerInt)),
|
||||||
|
oop_maps, false);
|
||||||
|
return stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For c2: c_rarg0 is junk, call to runtime to write a checkpoint.
|
||||||
|
// It returns a jobject handle to the event writer.
|
||||||
|
// The handle is dereferenced and the return value is the event writer oop.
|
||||||
|
RuntimeStub* generate_jfr_write_checkpoint() {
|
||||||
|
return generate_jfr_stub("jfr_write_checkpoint",
|
||||||
|
CAST_FROM_FN_PTR(address, JfrIntrinsicSupport::write_checkpoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
// For c1: call the corresponding runtime routine, it returns a jobject handle to the event writer.
|
||||||
|
// The handle is dereferenced and the return value is the event writer oop.
|
||||||
|
RuntimeStub* generate_jfr_get_event_writer() {
|
||||||
|
return generate_jfr_stub("jfr_get_event_writer",
|
||||||
|
CAST_FROM_FN_PTR(address, JfrIntrinsicSupport::event_writer));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // INCLUDE_JFR
|
||||||
|
|
||||||
// Continuation point for throwing of implicit exceptions that are
|
// Continuation point for throwing of implicit exceptions that are
|
||||||
// not handled in the current activation. Fabricates an exception
|
// not handled in the current activation. Fabricates an exception
|
||||||
// oop and initiates normal exception dispatching in this
|
// oop and initiates normal exception dispatching in this
|
||||||
@ -7450,6 +7735,21 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generate_phase1() {
|
||||||
|
// Continuation stubs:
|
||||||
|
StubRoutines::_cont_thaw = generate_cont_thaw();
|
||||||
|
StubRoutines::_cont_returnBarrier = generate_cont_returnBarrier();
|
||||||
|
StubRoutines::_cont_returnBarrierExc = generate_cont_returnBarrier_exception();
|
||||||
|
StubRoutines::_cont_doYield_stub = generate_cont_doYield();
|
||||||
|
StubRoutines::_cont_doYield = StubRoutines::_cont_doYield_stub == nullptr ? nullptr
|
||||||
|
: StubRoutines::_cont_doYield_stub->entry_point();
|
||||||
|
|
||||||
|
JFR_ONLY(StubRoutines::_jfr_write_checkpoint_stub = generate_jfr_write_checkpoint();)
|
||||||
|
JFR_ONLY(StubRoutines::_jfr_write_checkpoint = StubRoutines::_jfr_write_checkpoint_stub->entry_point();)
|
||||||
|
JFR_ONLY(StubRoutines::_jfr_get_event_writer_stub = generate_jfr_get_event_writer();)
|
||||||
|
JFR_ONLY(StubRoutines::_jfr_get_event_writer = StubRoutines::_jfr_get_event_writer_stub->entry_point();)
|
||||||
|
}
|
||||||
|
|
||||||
void generate_all() {
|
void generate_all() {
|
||||||
// support for verify_oop (must happen after universe_init)
|
// support for verify_oop (must happen after universe_init)
|
||||||
if (VerifyOops) {
|
if (VerifyOops) {
|
||||||
@ -7592,21 +7892,23 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) {
|
StubGenerator(CodeBuffer* code, int phase) : StubCodeGenerator(code) {
|
||||||
if (all) {
|
if (phase == 0) {
|
||||||
generate_all();
|
|
||||||
} else {
|
|
||||||
generate_initial();
|
generate_initial();
|
||||||
|
} else if (phase == 1) {
|
||||||
|
generate_phase1(); // stubs that must be available for the interpreter
|
||||||
|
} else {
|
||||||
|
generate_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}; // end class declaration
|
}; // end class declaration
|
||||||
|
|
||||||
#define UCM_TABLE_MAX_ENTRIES 8
|
#define UCM_TABLE_MAX_ENTRIES 8
|
||||||
void StubGenerator_generate(CodeBuffer* code, bool all) {
|
void StubGenerator_generate(CodeBuffer* code, int phase) {
|
||||||
if (UnsafeCopyMemory::_table == NULL) {
|
if (UnsafeCopyMemory::_table == NULL) {
|
||||||
UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES);
|
UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES);
|
||||||
}
|
}
|
||||||
StubGenerator g(code, all);
|
StubGenerator g(code, phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7641,3 +7943,75 @@ DEFAULT_ATOMIC_OP(cmpxchg, 8, _seq_cst)
|
|||||||
#undef DEFAULT_ATOMIC_OP
|
#undef DEFAULT_ATOMIC_OP
|
||||||
|
|
||||||
#endif // LINUX
|
#endif // LINUX
|
||||||
|
|
||||||
|
|
||||||
|
#undef __
|
||||||
|
#define __ masm->
|
||||||
|
|
||||||
|
// on exit, sp points to the ContinuationEntry
|
||||||
|
OopMap* continuation_enter_setup(MacroAssembler* masm, int& stack_slots) {
|
||||||
|
assert(ContinuationEntry::size() % VMRegImpl::stack_slot_size == 0, "");
|
||||||
|
assert(in_bytes(ContinuationEntry::cont_offset()) % VMRegImpl::stack_slot_size == 0, "");
|
||||||
|
assert(in_bytes(ContinuationEntry::chunk_offset()) % VMRegImpl::stack_slot_size == 0, "");
|
||||||
|
|
||||||
|
stack_slots += (int)ContinuationEntry::size()/wordSize;
|
||||||
|
__ sub(sp, sp, (int)ContinuationEntry::size()); // place Continuation metadata
|
||||||
|
|
||||||
|
OopMap* map = new OopMap(((int)ContinuationEntry::size() + wordSize)/ VMRegImpl::stack_slot_size, 0 /* arg_slots*/);
|
||||||
|
ContinuationEntry::setup_oopmap(map);
|
||||||
|
|
||||||
|
__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset()));
|
||||||
|
__ str(rscratch1, Address(sp, ContinuationEntry::parent_offset()));
|
||||||
|
__ mov(rscratch1, sp); // we can't use sp as the source in str
|
||||||
|
__ str(rscratch1, Address(rthread, JavaThread::cont_entry_offset()));
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on entry c_rarg1 points to the continuation
|
||||||
|
// sp points to ContinuationEntry
|
||||||
|
// c_rarg3 -- isVirtualThread
|
||||||
|
void fill_continuation_entry(MacroAssembler* masm) {
|
||||||
|
#ifdef ASSERT
|
||||||
|
__ movw(rscratch1, 0x1234);
|
||||||
|
__ strw(rscratch1, Address(sp, ContinuationEntry::cookie_offset()));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__ str (c_rarg1, Address(sp, ContinuationEntry::cont_offset()));
|
||||||
|
__ strw(c_rarg3, Address(sp, ContinuationEntry::flags_offset()));
|
||||||
|
__ str (zr, Address(sp, ContinuationEntry::chunk_offset()));
|
||||||
|
__ strw(zr, Address(sp, ContinuationEntry::argsize_offset()));
|
||||||
|
__ strw(zr, Address(sp, ContinuationEntry::pin_count_offset()));
|
||||||
|
|
||||||
|
__ ldr(rscratch1, Address(rthread, JavaThread::cont_fastpath_offset()));
|
||||||
|
__ str(rscratch1, Address(sp, ContinuationEntry::parent_cont_fastpath_offset()));
|
||||||
|
__ ldrw(rscratch1, Address(rthread, JavaThread::held_monitor_count_offset()));
|
||||||
|
__ strw(rscratch1, Address(sp, ContinuationEntry::parent_held_monitor_count_offset()));
|
||||||
|
|
||||||
|
__ str(zr, Address(rthread, JavaThread::cont_fastpath_offset()));
|
||||||
|
__ reset_held_monitor_count(rthread);
|
||||||
|
}
|
||||||
|
|
||||||
|
// on entry, sp points to the ContinuationEntry
|
||||||
|
// on exit, rfp points to the spilled rfp in the entry frame
|
||||||
|
void continuation_enter_cleanup(MacroAssembler* masm) {
|
||||||
|
#ifndef PRODUCT
|
||||||
|
Label OK;
|
||||||
|
__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset()));
|
||||||
|
__ cmp(sp, rscratch1);
|
||||||
|
__ br(Assembler::EQ, OK);
|
||||||
|
__ stop("incorrect sp1");
|
||||||
|
__ bind(OK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__ ldr(rscratch1, Address(sp, ContinuationEntry::parent_cont_fastpath_offset()));
|
||||||
|
__ str(rscratch1, Address(rthread, JavaThread::cont_fastpath_offset()));
|
||||||
|
__ ldrw(rscratch1, Address(sp, ContinuationEntry::parent_held_monitor_count_offset()));
|
||||||
|
__ strw(rscratch1, Address(rthread, JavaThread::held_monitor_count_offset()));
|
||||||
|
|
||||||
|
__ ldr(rscratch2, Address(sp, ContinuationEntry::parent_offset()));
|
||||||
|
__ str(rscratch2, Address(rthread, JavaThread::cont_entry_offset()));
|
||||||
|
__ add(rfp, sp, (int)ContinuationEntry::size());
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef __
|
||||||
|
@ -573,7 +573,9 @@ address TemplateInterpreterGenerator::generate_safept_entry_for(
|
|||||||
address runtime_entry) {
|
address runtime_entry) {
|
||||||
address entry = __ pc();
|
address entry = __ pc();
|
||||||
__ push(state);
|
__ push(state);
|
||||||
|
__ push_cont_fastpath(rthread);
|
||||||
__ call_VM(noreg, runtime_entry);
|
__ call_VM(noreg, runtime_entry);
|
||||||
|
__ pop_cont_fastpath(rthread);
|
||||||
__ membar(Assembler::AnyAny);
|
__ membar(Assembler::AnyAny);
|
||||||
__ dispatch_via(vtos, Interpreter::_normal_table.table_for(vtos));
|
__ dispatch_via(vtos, Interpreter::_normal_table.table_for(vtos));
|
||||||
return entry;
|
return entry;
|
||||||
@ -786,6 +788,7 @@ void TemplateInterpreterGenerator::lock_method() {
|
|||||||
__ str(r0, Address(esp, BasicObjectLock::obj_offset_in_bytes()));
|
__ str(r0, Address(esp, BasicObjectLock::obj_offset_in_bytes()));
|
||||||
__ mov(c_rarg1, esp); // object address
|
__ mov(c_rarg1, esp); // object address
|
||||||
__ lock_object(c_rarg1);
|
__ lock_object(c_rarg1);
|
||||||
|
__ inc_held_monitor_count(rthread);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a fixed interpreter frame. This is identical setup for
|
// Generate a fixed interpreter frame. This is identical setup for
|
||||||
@ -852,6 +855,18 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
|||||||
|
|
||||||
// End of helpers
|
// End of helpers
|
||||||
|
|
||||||
|
address TemplateInterpreterGenerator::generate_Continuation_doYield_entry(void) {
|
||||||
|
if (!Continuations::enabled()) return nullptr;
|
||||||
|
|
||||||
|
address entry = __ pc();
|
||||||
|
assert(StubRoutines::cont_doYield() != NULL, "stub not yet generated");
|
||||||
|
|
||||||
|
__ push_cont_fastpath(rthread);
|
||||||
|
__ far_jump(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::cont_doYield())));
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
// Various method entries
|
// Various method entries
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@ -1490,6 +1505,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
|
|||||||
|
|
||||||
__ bind(unlock);
|
__ bind(unlock);
|
||||||
__ unlock_object(c_rarg1);
|
__ unlock_object(c_rarg1);
|
||||||
|
__ dec_held_monitor_count(rthread);
|
||||||
}
|
}
|
||||||
__ bind(L);
|
__ bind(L);
|
||||||
}
|
}
|
||||||
|
@ -3862,6 +3862,9 @@ void TemplateTable::monitorenter()
|
|||||||
__ str(r0, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes()));
|
__ str(r0, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes()));
|
||||||
__ lock_object(c_rarg1);
|
__ lock_object(c_rarg1);
|
||||||
|
|
||||||
|
// The object is stored so counter should be increased even if stackoverflow is generated
|
||||||
|
__ inc_held_monitor_count(rthread);
|
||||||
|
|
||||||
// check to make sure this monitor doesn't cause stack overflow after locking
|
// check to make sure this monitor doesn't cause stack overflow after locking
|
||||||
__ save_bcp(); // in case of exception
|
__ save_bcp(); // in case of exception
|
||||||
__ generate_stack_overflow_check(0);
|
__ generate_stack_overflow_check(0);
|
||||||
@ -3920,6 +3923,7 @@ void TemplateTable::monitorexit()
|
|||||||
__ bind(found);
|
__ bind(found);
|
||||||
__ push_ptr(r0); // make sure object is on stack (contract with oopMaps)
|
__ push_ptr(r0); // make sure object is on stack (contract with oopMaps)
|
||||||
__ unlock_object(c_rarg1);
|
__ unlock_object(c_rarg1);
|
||||||
|
__ dec_held_monitor_count(rthread);
|
||||||
__ pop_ptr(r0); // discard object
|
__ pop_ptr(r0); // discard object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1328,3 +1328,7 @@ void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
|
|||||||
}
|
}
|
||||||
__ load(address, result, info, lir_patch_none);
|
__ load(address, result, info, lir_patch_none);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LIRGenerator::do_continuation_doYield(Intrinsic* x) {
|
||||||
|
fatal("Continuation.doYield intrinsic is not implemented on this platform");
|
||||||
|
}
|
||||||
|
47
src/hotspot/cpu/arm/continuationEntry_arm.inline.hpp
Normal file
47
src/hotspot/cpu/arm/continuationEntry_arm.inline.hpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_ARM_CONTINUATIONENTRY_ARM_INLINE_HPP
|
||||||
|
#define CPU_ARM_CONTINUATIONENTRY_ARM_INLINE_HPP
|
||||||
|
|
||||||
|
|
||||||
|
#include "runtime/continuationEntry.hpp"
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
|
|
||||||
|
inline frame ContinuationEntry::to_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationEntry::entry_fp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationEntry::update_register_map(RegisterMap* map) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_ARM_CONTINUATIONENTRY_ARM_INLINE_HPP
|
98
src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp
Normal file
98
src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_ARM_CONTINUATION_ARM_INLINE_HPP
|
||||||
|
#define CPU_ARM_CONTINUATION_ARM_INLINE_HPP
|
||||||
|
|
||||||
|
#include "oops/stackChunkOop.inline.hpp"
|
||||||
|
#include "runtime/frame.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
|
||||||
|
inline void FreezeBase::set_top_frame_metadata_pd(const frame& hf) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline frame FreezeBase::sender(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, const frame& hf) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame ThawBase::new_entry_frame() {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::set_interpreter_frame_bottom(const frame& f, intptr_t* bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& caller, bool bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::patch_pd(frame& f, const frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThawBase::patch_chunk_pd(intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::prefetch_chunk_pd(void* start, int size) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_ARM_CONTINUATION_ARM_INLINE_HPP
|
125
src/hotspot/cpu/arm/continuationHelper_arm.inline.hpp
Normal file
125
src/hotspot/cpu/arm/continuationHelper_arm.inline.hpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_ARM_CONTINUATIONHELPER_ARM_INLINE_HPP
|
||||||
|
#define CPU_ARM_CONTINUATIONHELPER_ARM_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationHelper.hpp"
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t** link_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ContinuationHelper::frame_align_words(int size) {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::frame_align_pointer(intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline void ContinuationHelper::update_register_map(const frame& f, RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::update_register_map_with_callee(const frame& f, RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::push_pd(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::set_anchor_to_entry_pd(JavaFrameAnchor* anchor, ContinuationEntry* cont) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
inline void ContinuationHelper::set_anchor_pd(JavaFrameAnchor* anchor, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ContinuationHelper::Frame::assert_frame_laid_out(frame f) {
|
||||||
|
Unimplemented();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline intptr_t** ContinuationHelper::Frame::callee_link_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t* real_fp(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::InterpretedFrame::return_pc_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::InterpretedFrame::patch_sender_sp(frame& f, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::Frame::return_pc_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address ContinuationHelper::Frame::real_pc(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, InterpreterOopMap* mask) { // inclusive; this will be copied with the frame
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_bottom(const frame& f) { // exclusive; this will not be copied with the frame
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_ARM_CONTINUATIONHELPER_ARM_INLINE_HPP
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -230,10 +230,12 @@ void frame::patch_pc(Thread* thread, address pc) {
|
|||||||
tty->print_cr("patch_pc at address" INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "] ",
|
tty->print_cr("patch_pc at address" INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "] ",
|
||||||
p2i(pc_addr), p2i(*pc_addr), p2i(pc));
|
p2i(pc_addr), p2i(*pc_addr), p2i(pc));
|
||||||
}
|
}
|
||||||
|
DEBUG_ONLY(address old_pc = _pc;)
|
||||||
*pc_addr = pc;
|
*pc_addr = pc;
|
||||||
|
_pc = pc; // must be set before call to get_deopt_original_pc
|
||||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||||
if (original_pc != NULL) {
|
if (original_pc != NULL) {
|
||||||
assert(original_pc == _pc, "expected original PC to be stored before patching");
|
assert(original_pc == old_pc, "expected original PC to be stored before patching");
|
||||||
_deopt_state = is_deoptimized;
|
_deopt_state = is_deoptimized;
|
||||||
// leave _pc as is
|
// leave _pc as is
|
||||||
} else {
|
} else {
|
||||||
@ -246,11 +248,6 @@ bool frame::is_interpreted_frame() const {
|
|||||||
return Interpreter::contains(pc());
|
return Interpreter::contains(pc());
|
||||||
}
|
}
|
||||||
|
|
||||||
int frame::frame_size(RegisterMap* map) const {
|
|
||||||
frame sender = this->sender(map);
|
|
||||||
return sender.sp() - sp();
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t* frame::entry_frame_argument_at(int offset) const {
|
intptr_t* frame::entry_frame_argument_at(int offset) const {
|
||||||
assert(is_entry_frame(), "entry frame expected");
|
assert(is_entry_frame(), "entry frame expected");
|
||||||
// convert offset to index to deal with tsi
|
// convert offset to index to deal with tsi
|
||||||
@ -277,6 +274,7 @@ BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
|
|||||||
return (BasicObjectLock*) addr_at(interpreter_frame_monitor_block_bottom_offset);
|
return (BasicObjectLock*) addr_at(interpreter_frame_monitor_block_bottom_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pointer beyond the "oldest/deepest" BasicObjectLock on stack.
|
||||||
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
||||||
BasicObjectLock* result = (BasicObjectLock*) *addr_at(interpreter_frame_monitor_block_top_offset);
|
BasicObjectLock* result = (BasicObjectLock*) *addr_at(interpreter_frame_monitor_block_top_offset);
|
||||||
// make sure the pointer points inside the frame
|
// make sure the pointer points inside the frame
|
||||||
@ -397,56 +395,6 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
|||||||
return frame(sender_sp, unextended_sp, link(), sender_pc());
|
return frame(sender_sp, unextended_sp, link(), sender_pc());
|
||||||
}
|
}
|
||||||
|
|
||||||
frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
|
||||||
assert(map != NULL, "map must be set");
|
|
||||||
|
|
||||||
// frame owned by optimizing compiler
|
|
||||||
assert(_cb->frame_size() >= 0, "must have non-zero frame size");
|
|
||||||
intptr_t* sender_sp = unextended_sp() + _cb->frame_size();
|
|
||||||
intptr_t* unextended_sp = sender_sp;
|
|
||||||
|
|
||||||
address sender_pc = (address) *(sender_sp - sender_sp_offset + return_addr_offset);
|
|
||||||
|
|
||||||
// This is the saved value of FP which may or may not really be an FP.
|
|
||||||
// It is only an FP if the sender is an interpreter frame (or C1?).
|
|
||||||
intptr_t** saved_fp_addr = (intptr_t**) (sender_sp - sender_sp_offset + link_offset);
|
|
||||||
|
|
||||||
if (map->update_map()) {
|
|
||||||
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
|
||||||
// For C1, the runtime stub might not have oop maps, so set this flag
|
|
||||||
// outside of update_register_map.
|
|
||||||
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
|
||||||
if (_cb->oop_maps() != NULL) {
|
|
||||||
OopMapSet::update_register_map(this, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since the prolog does the save and restore of FP there is no oopmap
|
|
||||||
// for it so we must fill in its location as if there was an oopmap entry
|
|
||||||
// since if our caller was compiled code there could be live jvm state in it.
|
|
||||||
update_map_with_saved_link(map, saved_fp_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(sender_sp != sp(), "must have changed");
|
|
||||||
return frame(sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
frame frame::sender(RegisterMap* map) const {
|
|
||||||
// Default is we done have to follow them. The sender_for_xxx will
|
|
||||||
// update it accordingly
|
|
||||||
map->set_include_argument_oops(false);
|
|
||||||
|
|
||||||
if (is_entry_frame()) return sender_for_entry_frame(map);
|
|
||||||
if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
|
|
||||||
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
|
||||||
|
|
||||||
if (_cb != NULL) {
|
|
||||||
return sender_for_compiled_frame(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(false, "should not be called for a C frame");
|
|
||||||
return frame();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
||||||
assert(is_interpreted_frame(), "Not an interpreted frame");
|
assert(is_interpreted_frame(), "Not an interpreted frame");
|
||||||
// These are reasonable sanity checks
|
// These are reasonable sanity checks
|
||||||
@ -545,7 +493,6 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result)
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
||||||
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
||||||
return &interpreter_frame_tos_address()[index];
|
return &interpreter_frame_tos_address()[index];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -54,7 +54,11 @@
|
|||||||
interpreter_frame_monitor_block_bottom_offset = interpreter_frame_initial_sp_offset,
|
interpreter_frame_monitor_block_bottom_offset = interpreter_frame_initial_sp_offset,
|
||||||
|
|
||||||
// Entry frames
|
// Entry frames
|
||||||
entry_frame_call_wrapper_offset = 0
|
entry_frame_call_wrapper_offset = 0,
|
||||||
|
metadata_words = sender_sp_offset,
|
||||||
|
frame_alignment = 16,
|
||||||
|
// size, in words, of maximum shift in frame position due to alignment
|
||||||
|
align_wiggle = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
intptr_t ptr_at(int offset) const {
|
intptr_t ptr_at(int offset) const {
|
||||||
@ -90,6 +94,8 @@
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const ImmutableOopMap* get_oop_map() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
@ -110,6 +116,9 @@
|
|||||||
// expression stack tos if we are nested in a java call
|
// expression stack tos if we are nested in a java call
|
||||||
intptr_t* interpreter_frame_last_sp() const;
|
intptr_t* interpreter_frame_last_sp() const;
|
||||||
|
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
static void update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr);
|
||||||
|
|
||||||
// deoptimization support
|
// deoptimization support
|
||||||
void interpreter_frame_set_last_sp(intptr_t* sp);
|
void interpreter_frame_set_last_sp(intptr_t* sp);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -39,6 +39,12 @@ inline frame::frame() {
|
|||||||
_fp = NULL;
|
_fp = NULL;
|
||||||
_cb = NULL;
|
_cb = NULL;
|
||||||
_deopt_state = unknown;
|
_deopt_state = unknown;
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame::frame(intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
|
inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
|
||||||
@ -49,6 +55,7 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
|
|||||||
assert(pc != NULL, "no pc?");
|
assert(pc != NULL, "no pc?");
|
||||||
_cb = CodeCache::find_blob(pc);
|
_cb = CodeCache::find_blob(pc);
|
||||||
adjust_unextended_sp();
|
adjust_unextended_sp();
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
|
||||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||||
if (original_pc != NULL) {
|
if (original_pc != NULL) {
|
||||||
@ -57,6 +64,7 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
|
|||||||
} else {
|
} else {
|
||||||
_deopt_state = not_deoptimized;
|
_deopt_state = not_deoptimized;
|
||||||
}
|
}
|
||||||
|
_on_heap = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
|
inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
|
||||||
@ -71,6 +79,7 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
|
|||||||
assert(pc != NULL, "no pc?");
|
assert(pc != NULL, "no pc?");
|
||||||
_cb = CodeCache::find_blob(pc);
|
_cb = CodeCache::find_blob(pc);
|
||||||
adjust_unextended_sp();
|
adjust_unextended_sp();
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
|
||||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||||
if (original_pc != NULL) {
|
if (original_pc != NULL) {
|
||||||
@ -81,6 +90,7 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
|
|||||||
} else {
|
} else {
|
||||||
_deopt_state = not_deoptimized;
|
_deopt_state = not_deoptimized;
|
||||||
}
|
}
|
||||||
|
_on_heap = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -93,6 +103,7 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) {
|
|||||||
// assert(_pc != NULL, "no pc?"); // see comments in x86
|
// assert(_pc != NULL, "no pc?"); // see comments in x86
|
||||||
_cb = CodeCache::find_blob(_pc);
|
_cb = CodeCache::find_blob(_pc);
|
||||||
adjust_unextended_sp();
|
adjust_unextended_sp();
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
|
||||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||||
if (original_pc != NULL) {
|
if (original_pc != NULL) {
|
||||||
@ -101,6 +112,7 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) {
|
|||||||
} else {
|
} else {
|
||||||
_deopt_state = not_deoptimized;
|
_deopt_state = not_deoptimized;
|
||||||
}
|
}
|
||||||
|
_on_heap = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -215,15 +227,107 @@ inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
|
|||||||
// Compiled frames
|
// Compiled frames
|
||||||
|
|
||||||
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
||||||
oop* result_adr = (oop*) map->location(R0->as_VMReg());
|
oop* result_adr = (oop*) map->location(R0->as_VMReg(), nullptr);
|
||||||
guarantee(result_adr != NULL, "bad register save location");
|
guarantee(result_adr != NULL, "bad register save location");
|
||||||
return (*result_adr);
|
return (*result_adr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
||||||
oop* result_adr = (oop*) map->location(R0->as_VMReg());
|
oop* result_adr = (oop*) map->location(R0->as_VMReg(), nullptr);
|
||||||
guarantee(result_adr != NULL, "bad register save location");
|
guarantee(result_adr != NULL, "bad register save location");
|
||||||
*result_adr = obj;
|
*result_adr = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int frame::frame_size() const {
|
||||||
|
return sender_sp() - sp();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ImmutableOopMap* frame::get_oop_map() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::compiled_frame_stack_argsize() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::interpreted_frame_oop_map(InterpreterOopMap* mask) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::sender_sp_ret_address_offset() {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::set_unextended_sp(intptr_t* value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::offset_unextended_sp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::set_offset_unextended_sp(int value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// frame::sender
|
||||||
|
|
||||||
|
inline frame frame::sender(RegisterMap* map) const {
|
||||||
|
// Default is we done have to follow them. The sender_for_xxx will
|
||||||
|
// update it accordingly
|
||||||
|
map->set_include_argument_oops(false);
|
||||||
|
|
||||||
|
if (is_entry_frame()) return sender_for_entry_frame(map);
|
||||||
|
if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
|
||||||
|
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
||||||
|
|
||||||
|
if (_cb != NULL) return sender_for_compiled_frame(map);
|
||||||
|
|
||||||
|
assert(false, "should not be called for a C frame");
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
||||||
|
assert(map != NULL, "map must be set");
|
||||||
|
|
||||||
|
// frame owned by optimizing compiler
|
||||||
|
assert(_cb->frame_size() >= 0, "must have non-zero frame size");
|
||||||
|
intptr_t* sender_sp = unextended_sp() + _cb->frame_size();
|
||||||
|
intptr_t* unextended_sp = sender_sp;
|
||||||
|
|
||||||
|
address sender_pc = (address) *(sender_sp - sender_sp_offset + return_addr_offset);
|
||||||
|
|
||||||
|
// This is the saved value of FP which may or may not really be an FP.
|
||||||
|
// It is only an FP if the sender is an interpreter frame (or C1?).
|
||||||
|
intptr_t** saved_fp_addr = (intptr_t**) (sender_sp - sender_sp_offset + link_offset);
|
||||||
|
|
||||||
|
if (map->update_map()) {
|
||||||
|
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
||||||
|
// For C1, the runtime stub might not have oop maps, so set this flag
|
||||||
|
// outside of update_register_map.
|
||||||
|
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
||||||
|
if (_cb->oop_maps() != NULL) {
|
||||||
|
OopMapSet::update_register_map(this, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the prolog does the save and restore of FP there is no oopmap
|
||||||
|
// for it so we must fill in its location as if there was an oopmap entry
|
||||||
|
// since if our caller was compiled code there could be live jvm state in it.
|
||||||
|
update_map_with_saved_link(map, saved_fp_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sender_sp != sp(), "must have changed");
|
||||||
|
return frame(sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
void frame::update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
#endif // CPU_ARM_FRAME_ARM_INLINE_HPP
|
#endif // CPU_ARM_FRAME_ARM_INLINE_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -432,4 +432,35 @@ inline NativeCall* nativeCall_before(address return_address) {
|
|||||||
return (NativeCall *) rawNativeCall_before(return_address);
|
return (NativeCall *) rawNativeCall_before(return_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NativePostCallNop: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
bool check() const { Unimplemented(); return false; }
|
||||||
|
int displacement() const { Unimplemented(); return 0; }
|
||||||
|
void patch(jint diff) { Unimplemented(); }
|
||||||
|
void make_deopt() { Unimplemented(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline NativePostCallNop* nativePostCallNop_at(address address) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NativeDeoptInstruction: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
address instruction_address() const { Unimplemented(); return NULL; }
|
||||||
|
address next_instruction_address() const { Unimplemented(); return NULL; }
|
||||||
|
|
||||||
|
void verify() { Unimplemented(); }
|
||||||
|
|
||||||
|
static bool is_deopt_at(address instr) {
|
||||||
|
Unimplemented();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MT-safe patching
|
||||||
|
static void insert(address code_pos) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // CPU_ARM_NATIVEINST_ARM_32_HPP
|
#endif // CPU_ARM_NATIVEINST_ARM_32_HPP
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
address pd_location(VMReg reg) const {return NULL;}
|
address pd_location(VMReg reg) const {return NULL;}
|
||||||
|
|
||||||
address pd_location(VMReg base_reg, int slot_idx) const {
|
address pd_location(VMReg base_reg, int slot_idx) const {
|
||||||
return location(base_reg->next(slot_idx));
|
return location(base_reg->next(slot_idx), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no PD state to clear or copy:
|
// no PD state to clear or copy:
|
||||||
|
87
src/hotspot/cpu/arm/smallRegisterMap_arm.inline.hpp
Normal file
87
src/hotspot/cpu/arm/smallRegisterMap_arm.inline.hpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_ARM_SMALLREGISTERMAP_ARM_INLINE_HPP
|
||||||
|
#define CPU_ARM_SMALLREGISTERMAP_ARM_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
// Java frames don't have callee saved registers (except for rfp), so we can use a smaller RegisterMap
|
||||||
|
class SmallRegisterMap {
|
||||||
|
public:
|
||||||
|
static constexpr SmallRegisterMap* instance = nullptr;
|
||||||
|
private:
|
||||||
|
static void assert_is_rfp(VMReg r) PRODUCT_RETURN
|
||||||
|
DEBUG_ONLY({ Unimplemented(); })
|
||||||
|
public:
|
||||||
|
// as_RegisterMap is used when we didn't want to templatize and abstract over RegisterMap type to support SmallRegisterMap
|
||||||
|
// Consider enhancing SmallRegisterMap to support those cases
|
||||||
|
const RegisterMap* as_RegisterMap() const { return nullptr; }
|
||||||
|
RegisterMap* as_RegisterMap() { return nullptr; }
|
||||||
|
|
||||||
|
RegisterMap* copy_to_RegisterMap(RegisterMap* map, intptr_t* sp) const {
|
||||||
|
Unimplemented();
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallRegisterMap() {}
|
||||||
|
|
||||||
|
SmallRegisterMap(const RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address location(VMReg reg, intptr_t* sp) const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_location(VMReg reg, address loc) { assert_is_rfp(reg); }
|
||||||
|
|
||||||
|
JavaThread* thread() const {
|
||||||
|
#ifndef ASSERT
|
||||||
|
guarantee (false, "");
|
||||||
|
#endif
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update_map() const { return false; }
|
||||||
|
bool walk_cont() const { return false; }
|
||||||
|
bool include_argument_oops() const { return false; }
|
||||||
|
void set_include_argument_oops(bool f) {}
|
||||||
|
bool in_cont() const { return false; }
|
||||||
|
stackChunkHandle stack_chunk() const { return stackChunkHandle(); }
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
bool should_skip_missing() const { return false; }
|
||||||
|
VMReg find_register_spilled_here(void* p, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void print() const { print_on(tty); }
|
||||||
|
void print_on(outputStream* st) const { st->print_cr("Small register map"); }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CPU_ARM_SMALLREGISTERMAP_ARM_INLINE_HPP
|
115
src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp
Normal file
115
src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_ARM_STACKCHUNKFRAMESTREAM_ARM_INLINE_HPP
|
||||||
|
#define CPU_ARM_STACKCHUNKFRAMESTREAM_ARM_INLINE_HPP
|
||||||
|
|
||||||
|
#include "interpreter/oopMapCache.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline bool StackChunkFrameStream<frame_kind>::is_in_frame(void* p0) const {
|
||||||
|
Unimplemented();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline frame StackChunkFrameStream<frame_kind>::to_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline address StackChunkFrameStream<frame_kind>::get_pc() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::fp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::derelativize(int offset) const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::unextended_sp_for_interpreter_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
intptr_t* StackChunkFrameStream<frame_kind>::next_sp_for_interpreter_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::next_for_interpreter_frame() {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_size() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_stack_argsize() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_num_oops() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::Mixed>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::CompiledOnly>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::update_reg_map_pd(RegisterMapT* map) {}
|
||||||
|
|
||||||
|
#endif // CPU_ARM_STACKCHUNKFRAMESTREAM_ARM_INLINE_HPP
|
36
src/hotspot/cpu/arm/stackChunkOop_arm.inline.hpp
Normal file
36
src/hotspot/cpu/arm/stackChunkOop_arm.inline.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_ARM_STACKCHUNKOOP_ARM_INLINE_HPP
|
||||||
|
#define CPU_ARM_STACKCHUNKOOP_ARM_INLINE_HPP
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::relativize_frame_pd(frame& fr) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::derelativize_frame_pd(frame& fr) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_ARM_STACKCHUNKOOP_ARM_INLINE_HPP
|
@ -3039,9 +3039,9 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
}; // end class declaration
|
}; // end class declaration
|
||||||
|
|
||||||
#define UCM_TABLE_MAX_ENTRIES 32
|
#define UCM_TABLE_MAX_ENTRIES 32
|
||||||
void StubGenerator_generate(CodeBuffer* code, bool all) {
|
void StubGenerator_generate(CodeBuffer* code, int phase) {
|
||||||
if (UnsafeCopyMemory::_table == NULL) {
|
if (UnsafeCopyMemory::_table == NULL) {
|
||||||
UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES);
|
UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES);
|
||||||
}
|
}
|
||||||
StubGenerator g(code, all);
|
StubGenerator g(code, phase);
|
||||||
}
|
}
|
||||||
|
@ -728,6 +728,11 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
|||||||
// [ parameter 1 ] <--- Rlocals
|
// [ parameter 1 ] <--- Rlocals
|
||||||
//
|
//
|
||||||
|
|
||||||
|
address TemplateInterpreterGenerator::generate_Continuation_doYield_entry(void) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
|
address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
|
||||||
// Code: _aload_0, _getfield, _areturn
|
// Code: _aload_0, _getfield, _areturn
|
||||||
// parameter size = 1
|
// parameter size = 1
|
||||||
|
@ -140,6 +140,9 @@ class Argument {
|
|||||||
// shows that xlC places all float args after argument 8 on the stack AND
|
// shows that xlC places all float args after argument 8 on the stack AND
|
||||||
// in a register. This is not documented, but we follow this convention, too.
|
// in a register. This is not documented, but we follow this convention, too.
|
||||||
n_regs_not_on_stack_c = 8,
|
n_regs_not_on_stack_c = 8,
|
||||||
|
|
||||||
|
n_int_register_parameters_j = 8,
|
||||||
|
n_float_register_parameters_j = 13
|
||||||
};
|
};
|
||||||
// creation
|
// creation
|
||||||
Argument(int number) : _number(number) {}
|
Argument(int number) : _number(number) {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2019 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2019 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -1381,3 +1381,7 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
|
|||||||
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
|
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
|
||||||
fatal("vectorizedMismatch intrinsic is not implemented on this platform");
|
fatal("vectorizedMismatch intrinsic is not implemented on this platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LIRGenerator::do_continuation_doYield(Intrinsic* x) {
|
||||||
|
fatal("Continuation.doYield intrinsic is not implemented on this platform");
|
||||||
|
}
|
||||||
|
46
src/hotspot/cpu/ppc/continuationEntry_ppc.inline.hpp
Normal file
46
src/hotspot/cpu/ppc/continuationEntry_ppc.inline.hpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_PPC_CONTINUATIONENTRY_PPC_INLINE_HPP
|
||||||
|
#define CPU_PPC_CONTINUATIONENTRY_PPC_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationEntry.hpp"
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
|
|
||||||
|
inline frame ContinuationEntry::to_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationEntry::entry_fp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationEntry::update_register_map(RegisterMap* map) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_PPC_CONTINUATIONENTRY_PPC_INLINE_HPP
|
99
src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp
Normal file
99
src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_PPC_CONTINUATION_PPC_INLINE_HPP
|
||||||
|
#define CPU_PPC_CONTINUATION_PPC_INLINE_HPP
|
||||||
|
|
||||||
|
#include "oops/stackChunkOop.inline.hpp"
|
||||||
|
#include "runtime/frame.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
inline void FreezeBase::set_top_frame_metadata_pd(const frame& hf) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline frame FreezeBase::sender(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, const frame& hf) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame ThawBase::new_entry_frame() {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::set_interpreter_frame_bottom(const frame& f, intptr_t* bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& caller, bool bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::patch_pd(frame& f, const frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThawBase::patch_chunk_pd(intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::prefetch_chunk_pd(void* start, int size) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_PPC_CONTINUATION_PPC_INLINE_HPP
|
124
src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp
Normal file
124
src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp
Normal file
@ -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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_PPC_CONTINUATIONHELPER_PPC_INLINE_HPP
|
||||||
|
#define CPU_PPC_CONTINUATIONHELPER_PPC_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationHelper.hpp"
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t** link_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ContinuationHelper::frame_align_words(int size) {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::frame_align_pointer(intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline void ContinuationHelper::update_register_map(const frame& f, RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::update_register_map_with_callee(const frame& f, RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::push_pd(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void ContinuationHelper::set_anchor_to_entry_pd(JavaFrameAnchor* anchor, ContinuationEntry* cont) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
inline void ContinuationHelper::set_anchor_pd(JavaFrameAnchor* anchor, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ContinuationHelper::Frame::assert_frame_laid_out(frame f) {
|
||||||
|
Unimplemented();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline intptr_t** ContinuationHelper::Frame::callee_link_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t* real_fp(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::InterpretedFrame::return_pc_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::InterpretedFrame::patch_sender_sp(frame& f, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::Frame::return_pc_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address ContinuationHelper::Frame::real_pc(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, InterpreterOopMap* mask) { // inclusive; this will be copied with the frame
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_bottom(const frame& f) { // exclusive; this will not be copied with the frame
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_PPC_CONTINUATIONFRAMEHELPERS_PPC_INLINE_HPP
|
@ -219,27 +219,6 @@ frame frame::sender_for_interpreter_frame(RegisterMap *map) const {
|
|||||||
return frame(sender_sp(), sender_pc(), (intptr_t*)get_ijava_state()->sender_sp);
|
return frame(sender_sp(), sender_pc(), (intptr_t*)get_ijava_state()->sender_sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
frame frame::sender_for_compiled_frame(RegisterMap *map) const {
|
|
||||||
assert(map != NULL, "map must be set");
|
|
||||||
|
|
||||||
// Frame owned by compiler.
|
|
||||||
address pc = *compiled_sender_pc_addr(_cb);
|
|
||||||
frame caller(compiled_sender_sp(_cb), pc);
|
|
||||||
|
|
||||||
// Now adjust the map.
|
|
||||||
|
|
||||||
// Get the rest.
|
|
||||||
if (map->update_map()) {
|
|
||||||
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
|
||||||
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
|
||||||
if (_cb->oop_maps() != NULL) {
|
|
||||||
OopMapSet::update_register_map(this, map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return caller;
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t* frame::compiled_sender_sp(CodeBlob* cb) const {
|
intptr_t* frame::compiled_sender_sp(CodeBlob* cb) const {
|
||||||
return sender_sp();
|
return sender_sp();
|
||||||
}
|
}
|
||||||
@ -248,33 +227,6 @@ address* frame::compiled_sender_pc_addr(CodeBlob* cb) const {
|
|||||||
return sender_pc_addr();
|
return sender_pc_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
frame frame::sender_raw(RegisterMap* map) const {
|
|
||||||
// Default is we do have to follow them. The sender_for_xxx will
|
|
||||||
// update it accordingly.
|
|
||||||
map->set_include_argument_oops(false);
|
|
||||||
|
|
||||||
if (is_entry_frame()) return sender_for_entry_frame(map);
|
|
||||||
if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
|
|
||||||
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
|
||||||
|
|
||||||
if (_cb != NULL) {
|
|
||||||
return sender_for_compiled_frame(map);
|
|
||||||
}
|
|
||||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
|
||||||
// methods that exists in the core system.
|
|
||||||
return frame(sender_sp(), sender_pc());
|
|
||||||
}
|
|
||||||
|
|
||||||
frame frame::sender(RegisterMap* map) const {
|
|
||||||
frame result = sender_raw(map);
|
|
||||||
|
|
||||||
if (map->process_frames()) {
|
|
||||||
StackWatermarkSet::on_iteration(map->thread(), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void frame::patch_pc(Thread* thread, address pc) {
|
void frame::patch_pc(Thread* thread, address pc) {
|
||||||
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
||||||
if (TracePcPatching) {
|
if (TracePcPatching) {
|
||||||
@ -431,8 +383,19 @@ intptr_t *frame::initial_deoptimization_info() {
|
|||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
// This is a generic constructor which is only used by pns() in debug.cpp.
|
// This is a generic constructor which is only used by pns() in debug.cpp.
|
||||||
frame::frame(void* sp, void* fp, void* pc) : _sp((intptr_t*)sp), _unextended_sp((intptr_t*)sp) {
|
frame::frame(void* sp, void* fp, void* pc) : _sp((intptr_t*)sp),
|
||||||
|
_on_heap(false),
|
||||||
|
_unextended_sp((intptr_t*)sp) {
|
||||||
find_codeblob_and_set_pc_and_deopt_state((address)pc); // also sets _fp and adjusts _unextended_sp
|
find_codeblob_and_set_pc_and_deopt_state((address)pc); // also sets _fp and adjusts _unextended_sp
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Pointer beyond the "oldest/deepest" BasicObjectLock on stack.
|
||||||
|
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
||||||
|
return (BasicObjectLock*) get_ijava_state()->monitors;
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
||||||
|
return &interpreter_frame_tos_address()[offset];
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -379,8 +379,9 @@
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
const ImmutableOopMap* get_oop_map() const;
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
inline frame(intptr_t* sp);
|
|
||||||
inline frame(intptr_t* sp, address pc);
|
inline frame(intptr_t* sp, address pc);
|
||||||
inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp);
|
inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp);
|
||||||
|
|
||||||
@ -400,6 +401,11 @@
|
|||||||
inline void interpreter_frame_set_top_frame_sp(intptr_t* top_frame_sp);
|
inline void interpreter_frame_set_top_frame_sp(intptr_t* top_frame_sp);
|
||||||
inline void interpreter_frame_set_sender_sp(intptr_t* sender_sp);
|
inline void interpreter_frame_set_sender_sp(intptr_t* sender_sp);
|
||||||
|
|
||||||
|
inline intptr_t* interpreter_frame_last_sp() const;
|
||||||
|
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
static void update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr);
|
||||||
|
|
||||||
// Size of a monitor in bytes.
|
// Size of a monitor in bytes.
|
||||||
static int interpreter_frame_monitor_size_in_bytes();
|
static int interpreter_frame_monitor_size_in_bytes();
|
||||||
|
|
||||||
@ -413,12 +419,16 @@
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
// normal return address is 1 bundle past PC
|
// normal return address is 1 bundle past PC
|
||||||
pc_return_offset = 0
|
pc_return_offset = 0,
|
||||||
|
metadata_words = 0,
|
||||||
|
frame_alignment = 16,
|
||||||
|
// size, in words, of maximum shift in frame position due to alignment
|
||||||
|
align_wiggle = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
static jint interpreter_frame_expression_stack_direction() { return -1; }
|
static jint interpreter_frame_expression_stack_direction() { return -1; }
|
||||||
|
|
||||||
// returns the sending frame, without applying any barriers
|
// returns the sending frame, without applying any barriers
|
||||||
frame sender_raw(RegisterMap* map) const;
|
inline frame sender_raw(RegisterMap* map) const;
|
||||||
|
|
||||||
#endif // CPU_PPC_FRAME_PPC_HPP
|
#endif // CPU_PPC_FRAME_PPC_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -55,17 +55,33 @@ inline void frame::find_codeblob_and_set_pc_and_deopt_state(address pc) {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
// Initialize all fields, _unextended_sp will be adjusted in find_codeblob_and_set_pc_and_deopt_state.
|
// Initialize all fields, _unextended_sp will be adjusted in find_codeblob_and_set_pc_and_deopt_state.
|
||||||
inline frame::frame() : _sp(NULL), _pc(NULL), _cb(NULL), _deopt_state(unknown), _unextended_sp(NULL), _fp(NULL) {}
|
inline frame::frame() : _sp(NULL), _pc(NULL), _cb(NULL), _deopt_state(unknown), _on_heap(false),
|
||||||
|
#ifdef ASSERT
|
||||||
|
_frame_index(-1),
|
||||||
|
#endif
|
||||||
|
_unextended_sp(NULL), _fp(NULL) {}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* sp) : _sp(sp), _unextended_sp(sp) {
|
inline frame::frame(intptr_t* sp) : _sp(sp), _on_heap(false),
|
||||||
|
#ifdef ASSERT
|
||||||
|
_frame_index(-1),
|
||||||
|
#endif
|
||||||
|
_unextended_sp(sp) {
|
||||||
find_codeblob_and_set_pc_and_deopt_state((address)own_abi()->lr); // also sets _fp and adjusts _unextended_sp
|
find_codeblob_and_set_pc_and_deopt_state((address)own_abi()->lr); // also sets _fp and adjusts _unextended_sp
|
||||||
}
|
}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* sp, address pc) : _sp(sp), _unextended_sp(sp) {
|
inline frame::frame(intptr_t* sp, address pc) : _sp(sp), _on_heap(false),
|
||||||
|
#ifdef ASSERT
|
||||||
|
_frame_index(-1),
|
||||||
|
#endif
|
||||||
|
_unextended_sp(sp) {
|
||||||
find_codeblob_and_set_pc_and_deopt_state(pc); // also sets _fp and adjusts _unextended_sp
|
find_codeblob_and_set_pc_and_deopt_state(pc); // also sets _fp and adjusts _unextended_sp
|
||||||
}
|
}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* sp, address pc, intptr_t* unextended_sp) : _sp(sp), _unextended_sp(unextended_sp) {
|
inline frame::frame(intptr_t* sp, address pc, intptr_t* unextended_sp) : _sp(sp), _on_heap(false),
|
||||||
|
#ifdef ASSERT
|
||||||
|
_frame_index(-1),
|
||||||
|
#endif
|
||||||
|
_unextended_sp(unextended_sp) {
|
||||||
find_codeblob_and_set_pc_and_deopt_state(pc); // also sets _fp and adjusts _unextended_sp
|
find_codeblob_and_set_pc_and_deopt_state(pc); // also sets _fp and adjusts _unextended_sp
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +103,7 @@ inline bool frame::is_older(intptr_t* id) const {
|
|||||||
return this->id() > id;
|
return this->id() > id;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int frame::frame_size(RegisterMap* map) const {
|
inline int frame::frame_size() const {
|
||||||
// Stack grows towards smaller addresses on PPC64: sender is at a higher address.
|
// Stack grows towards smaller addresses on PPC64: sender is at a higher address.
|
||||||
return sender_sp() - sp();
|
return sender_sp() - sp();
|
||||||
}
|
}
|
||||||
@ -143,11 +159,6 @@ inline intptr_t* frame::interpreter_frame_mdp_addr() const {
|
|||||||
return (intptr_t*) &(get_ijava_state()->mdx);
|
return (intptr_t*) &(get_ijava_state()->mdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointer beyond the "oldest/deepest" BasicObjectLock on stack.
|
|
||||||
inline BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
|
||||||
return (BasicObjectLock*) get_ijava_state()->monitors;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
|
inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
|
||||||
return (BasicObjectLock*) get_ijava_state();
|
return (BasicObjectLock*) get_ijava_state();
|
||||||
}
|
}
|
||||||
@ -189,10 +200,6 @@ inline intptr_t* frame::interpreter_frame_tos_address() const {
|
|||||||
return ((intptr_t*) get_ijava_state()->esp) + Interpreter::stackElementWords;
|
return ((intptr_t*) get_ijava_state()->esp) + Interpreter::stackElementWords;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
|
||||||
return &interpreter_frame_tos_address()[offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int frame::interpreter_frame_monitor_size() {
|
inline int frame::interpreter_frame_monitor_size() {
|
||||||
// Number of stack slots for a monitor.
|
// Number of stack slots for a monitor.
|
||||||
return align_up(BasicObjectLock::size(), // number of stack slots
|
return align_up(BasicObjectLock::size(), // number of stack slots
|
||||||
@ -218,11 +225,103 @@ inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
||||||
return *((oop*)map->location(R3->as_VMReg()));
|
return *((oop*)map->location(R3->as_VMReg(), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
||||||
*((oop*)map->location(R3->as_VMReg())) = obj;
|
*((oop*)map->location(R3->as_VMReg(), nullptr)) = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ImmutableOopMap* frame::get_oop_map() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::compiled_frame_stack_argsize() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::interpreted_frame_oop_map(InterpreterOopMap* mask) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* frame::interpreter_frame_last_sp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::sender_sp_ret_address_offset() {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::set_unextended_sp(intptr_t* value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::offset_unextended_sp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::set_offset_unextended_sp(int value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// frame::sender
|
||||||
|
|
||||||
|
frame frame::sender(RegisterMap* map) const {
|
||||||
|
frame result = sender_raw(map);
|
||||||
|
|
||||||
|
if (map->process_frames()) {
|
||||||
|
StackWatermarkSet::on_iteration(map->thread(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame frame::sender_raw(RegisterMap* map) const {
|
||||||
|
// Default is we do have to follow them. The sender_for_xxx will
|
||||||
|
// update it accordingly.
|
||||||
|
map->set_include_argument_oops(false);
|
||||||
|
|
||||||
|
if (is_entry_frame()) return sender_for_entry_frame(map);
|
||||||
|
if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
|
||||||
|
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
||||||
|
|
||||||
|
if (_cb != NULL) return sender_for_compiled_frame(map);
|
||||||
|
|
||||||
|
// Must be native-compiled frame, i.e. the marshaling code for native
|
||||||
|
// methods that exists in the core system.
|
||||||
|
return frame(sender_sp(), sender_pc());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame frame::sender_for_compiled_frame(RegisterMap *map) const {
|
||||||
|
assert(map != NULL, "map must be set");
|
||||||
|
|
||||||
|
// Frame owned by compiler.
|
||||||
|
address pc = *compiled_sender_pc_addr(_cb);
|
||||||
|
frame caller(compiled_sender_sp(_cb), pc);
|
||||||
|
|
||||||
|
// Now adjust the map.
|
||||||
|
|
||||||
|
// Get the rest.
|
||||||
|
if (map->update_map()) {
|
||||||
|
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
||||||
|
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
||||||
|
if (_cb->oop_maps() != NULL) {
|
||||||
|
OopMapSet::update_register_map(this, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return caller;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
void frame::update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr) {
|
||||||
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CPU_PPC_FRAME_PPC_INLINE_HPP
|
#endif // CPU_PPC_FRAME_PPC_INLINE_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -121,6 +121,10 @@ void BarrierSetNMethod::disarm(nmethod* nm) {
|
|||||||
barrier->release_set_guard_value(disarmed_value());
|
barrier->release_set_guard_value(disarmed_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::arm(nmethod* nm, int arm_value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
if (!supports_entry_barrier(nm)) {
|
if (!supports_entry_barrier(nm)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -503,4 +503,35 @@ class NativeMovRegMem: public NativeInstruction {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NativePostCallNop: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
bool check() const { Unimplemented(); return false; }
|
||||||
|
int displacement() const { Unimplemented(); return 0; }
|
||||||
|
void patch(jint diff) { Unimplemented(); }
|
||||||
|
void make_deopt() { Unimplemented(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline NativePostCallNop* nativePostCallNop_at(address address) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NativeDeoptInstruction: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
address instruction_address() const { Unimplemented(); return NULL; }
|
||||||
|
address next_instruction_address() const { Unimplemented(); return NULL; }
|
||||||
|
|
||||||
|
void verify() { Unimplemented(); }
|
||||||
|
|
||||||
|
static bool is_deopt_at(address instr) {
|
||||||
|
Unimplemented();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MT-safe patching
|
||||||
|
static void insert(address code_pos) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // CPU_PPC_NATIVEINST_PPC_HPP
|
#endif // CPU_PPC_NATIVEINST_PPC_HPP
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
address pd_location(VMReg reg) const { return NULL; }
|
address pd_location(VMReg reg) const { return NULL; }
|
||||||
|
|
||||||
address pd_location(VMReg base_reg, int slot_idx) const {
|
address pd_location(VMReg base_reg, int slot_idx) const {
|
||||||
return location(base_reg->next(slot_idx));
|
return location(base_reg->next(slot_idx), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no PD state to clear or copy:
|
// no PD state to clear or copy:
|
||||||
|
87
src/hotspot/cpu/ppc/smallRegisterMap_ppc.inline.hpp
Normal file
87
src/hotspot/cpu/ppc/smallRegisterMap_ppc.inline.hpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_PPC_SMALLREGISTERMAP_PPC_INLINE_HPP
|
||||||
|
#define CPU_PPC_SMALLREGISTERMAP_PPC_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
// Java frames don't have callee saved registers (except for rfp), so we can use a smaller RegisterMap
|
||||||
|
class SmallRegisterMap {
|
||||||
|
public:
|
||||||
|
static constexpr SmallRegisterMap* instance = nullptr;
|
||||||
|
private:
|
||||||
|
static void assert_is_rfp(VMReg r) PRODUCT_RETURN
|
||||||
|
DEBUG_ONLY({ Unimplemented(); })
|
||||||
|
public:
|
||||||
|
// as_RegisterMap is used when we didn't want to templatize and abstract over RegisterMap type to support SmallRegisterMap
|
||||||
|
// Consider enhancing SmallRegisterMap to support those cases
|
||||||
|
const RegisterMap* as_RegisterMap() const { return nullptr; }
|
||||||
|
RegisterMap* as_RegisterMap() { return nullptr; }
|
||||||
|
|
||||||
|
RegisterMap* copy_to_RegisterMap(RegisterMap* map, intptr_t* sp) const {
|
||||||
|
Unimplemented();
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallRegisterMap() {}
|
||||||
|
|
||||||
|
SmallRegisterMap(const RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address location(VMReg reg, intptr_t* sp) const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_location(VMReg reg, address loc) { assert_is_rfp(reg); }
|
||||||
|
|
||||||
|
JavaThread* thread() const {
|
||||||
|
#ifndef ASSERT
|
||||||
|
guarantee (false, "");
|
||||||
|
#endif
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update_map() const { return false; }
|
||||||
|
bool walk_cont() const { return false; }
|
||||||
|
bool include_argument_oops() const { return false; }
|
||||||
|
void set_include_argument_oops(bool f) {}
|
||||||
|
bool in_cont() const { return false; }
|
||||||
|
stackChunkHandle stack_chunk() const { return stackChunkHandle(); }
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
bool should_skip_missing() const { return false; }
|
||||||
|
VMReg find_register_spilled_here(void* p, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void print() const { print_on(tty); }
|
||||||
|
void print_on(outputStream* st) const { st->print_cr("Small register map"); }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CPU_PPC_SMALLREGISTERMAP_PPC_INLINE_HPP
|
115
src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp
Normal file
115
src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_PPC_STACKCHUNKFRAMESTREAM_PPC_INLINE_HPP
|
||||||
|
#define CPU_PPC_STACKCHUNKFRAMESTREAM_PPC_INLINE_HPP
|
||||||
|
|
||||||
|
#include "interpreter/oopMapCache.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline bool StackChunkFrameStream<frame_kind>::is_in_frame(void* p0) const {
|
||||||
|
Unimplemented();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline frame StackChunkFrameStream<frame_kind>::to_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline address StackChunkFrameStream<frame_kind>::get_pc() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::fp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::derelativize(int offset) const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::unextended_sp_for_interpreter_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
intptr_t* StackChunkFrameStream<frame_kind>::next_sp_for_interpreter_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::next_for_interpreter_frame() {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_size() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_stack_argsize() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_num_oops() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::Mixed>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::CompiledOnly>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::update_reg_map_pd(RegisterMapT* map) {}
|
||||||
|
|
||||||
|
#endif // CPU_PPC_STACKCHUNKFRAMESTREAM_PPC_INLINE_HPP
|
36
src/hotspot/cpu/ppc/stackChunkOop_ppc.inline.hpp
Normal file
36
src/hotspot/cpu/ppc/stackChunkOop_ppc.inline.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_PPC_STACKCHUNKOOP_PPC_INLINE_HPP
|
||||||
|
#define CPU_PPC_STACKCHUNKOOP_PPC_INLINE_HPP
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::relativize_frame_pd(frame& fr) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::derelativize_frame_pd(frame& fr) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_PPC_STACKCHUNKOOP_PPC_INLINE_HPP
|
@ -4618,9 +4618,9 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define UCM_TABLE_MAX_ENTRIES 8
|
#define UCM_TABLE_MAX_ENTRIES 8
|
||||||
void StubGenerator_generate(CodeBuffer* code, bool all) {
|
void StubGenerator_generate(CodeBuffer* code, int phase) {
|
||||||
if (UnsafeCopyMemory::_table == NULL) {
|
if (UnsafeCopyMemory::_table == NULL) {
|
||||||
UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES);
|
UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES);
|
||||||
}
|
}
|
||||||
StubGenerator g(code, all);
|
StubGenerator g(code, phase);
|
||||||
}
|
}
|
||||||
|
@ -476,6 +476,11 @@ address TemplateInterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address TemplateInterpreterGenerator::generate_Continuation_doYield_entry(void) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Interpreter intrinsic for WeakReference.get().
|
// Interpreter intrinsic for WeakReference.get().
|
||||||
// 1. Don't push a full blown frame and go on dispatching, but fetch the value
|
// 1. Don't push a full blown frame and go on dispatching, but fetch the value
|
||||||
// into R8 and return quickly
|
// into R8 and return quickly
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||||
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
@ -301,6 +301,10 @@ void LIRGenerator::do_MonitorExit(MonitorExit* x) {
|
|||||||
monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no());
|
monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LIRGenerator::do_continuation_doYield(Intrinsic* x) {
|
||||||
|
fatal("Continuation.doYield intrinsic is not implemented on this platform");
|
||||||
|
}
|
||||||
|
|
||||||
// neg
|
// neg
|
||||||
void LIRGenerator::do_NegateOp(NegateOp* x) {
|
void LIRGenerator::do_NegateOp(NegateOp* x) {
|
||||||
LIRItem from(x->x(), this);
|
LIRItem from(x->x(), this);
|
||||||
|
46
src/hotspot/cpu/riscv/continuationEntry_riscv.inline.hpp
Normal file
46
src/hotspot/cpu/riscv/continuationEntry_riscv.inline.hpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_RISCV_CONTINUATIONENTRY_RISCV_INLINE_HPP
|
||||||
|
#define CPU_RISCV_CONTINUATIONENTRY_RISCV_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationEntry.hpp"
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
|
|
||||||
|
inline frame ContinuationEntry::to_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationEntry::entry_fp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationEntry::update_register_map(RegisterMap* map) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_RISCV_CONTINUATIONENTRY_RISCV_INLINE_HPP
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_RISCV_CONTINUATIONFREEZETHAW_RISCV_INLINE_HPP
|
||||||
|
#define CPU_RISCV_CONTINUATIONFREEZETHAW_RISCV_INLINE_HPP
|
||||||
|
|
||||||
|
#include "oops/stackChunkOop.inline.hpp"
|
||||||
|
#include "runtime/frame.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
inline void FreezeBase::set_top_frame_metadata_pd(const frame& hf) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline frame FreezeBase::sender(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, const frame& hf) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame ThawBase::new_entry_frame() {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::set_interpreter_frame_bottom(const frame& f, intptr_t* bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& caller, bool bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::patch_pd(frame& f, const frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThawBase::patch_chunk_pd(intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::prefetch_chunk_pd(void* start, int size) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_RISCV_CONTINUATIONFREEZETHAW_RISCV_INLINE_HPP
|
124
src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp
Normal file
124
src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp
Normal file
@ -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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_RISCV_CONTINUATIONHELPER_RISCV_INLINE_HPP
|
||||||
|
#define CPU_RISCV_CONTINUATIONHELPER_RISCV_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationHelper.hpp"
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t** link_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ContinuationHelper::frame_align_words(int size) {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::frame_align_pointer(intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline void ContinuationHelper::update_register_map(const frame& f, RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::update_register_map_with_callee(const frame& f, RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::push_pd(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void ContinuationHelper::set_anchor_to_entry_pd(JavaFrameAnchor* anchor, ContinuationEntry* cont) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
inline void ContinuationHelper::set_anchor_pd(JavaFrameAnchor* anchor, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ContinuationHelper::Frame::assert_frame_laid_out(frame f) {
|
||||||
|
Unimplemented();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline intptr_t** ContinuationHelper::Frame::callee_link_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t* real_fp(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::InterpretedFrame::return_pc_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::InterpretedFrame::patch_sender_sp(frame& f, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::Frame::return_pc_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address ContinuationHelper::Frame::real_pc(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, InterpreterOopMap* mask) { // inclusive; this will be copied with the frame
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_bottom(const frame& f) { // exclusive; this will not be copied with the frame
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_RISCV_CONTINUATIONFRAMEHELPERS_RISCV_INLINE_HPP
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
||||||
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
@ -282,11 +282,6 @@ bool frame::is_interpreted_frame() const {
|
|||||||
return Interpreter::contains(pc());
|
return Interpreter::contains(pc());
|
||||||
}
|
}
|
||||||
|
|
||||||
int frame::frame_size(RegisterMap* map) const {
|
|
||||||
frame sender = this->sender(map);
|
|
||||||
return sender.sp() - sp();
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t* frame::entry_frame_argument_at(int offset) const {
|
intptr_t* frame::entry_frame_argument_at(int offset) const {
|
||||||
// convert offset to index to deal with tsi
|
// convert offset to index to deal with tsi
|
||||||
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
||||||
@ -394,32 +389,12 @@ void frame::adjust_unextended_sp() {
|
|||||||
// If the sender PC is a deoptimization point, get the original PC.
|
// If the sender PC is a deoptimization point, get the original PC.
|
||||||
if (sender_cm->is_deopt_entry(_pc) ||
|
if (sender_cm->is_deopt_entry(_pc) ||
|
||||||
sender_cm->is_deopt_mh_entry(_pc)) {
|
sender_cm->is_deopt_mh_entry(_pc)) {
|
||||||
DEBUG_ONLY(verify_deopt_original_pc(sender_cm, _unextended_sp));
|
verify_deopt_original_pc(sender_cm, _unextended_sp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// frame::update_map_with_saved_link
|
|
||||||
void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) {
|
|
||||||
// The interpreter and compiler(s) always save fp in a known
|
|
||||||
// location on entry. We must record where that location is
|
|
||||||
// so that if fp was live on callout from c2 we can find
|
|
||||||
// the saved copy no matter what it called.
|
|
||||||
|
|
||||||
// Since the interpreter always saves fp if we record where it is then
|
|
||||||
// we don't have to always save fp on entry and exit to c2 compiled
|
|
||||||
// code, on entry will be enough.
|
|
||||||
assert(map != NULL, "map must be set");
|
|
||||||
map->set_location(::fp->as_VMReg(), (address) link_addr);
|
|
||||||
// this is weird "H" ought to be at a higher address however the
|
|
||||||
// oopMaps seems to have the "H" regs at the same address and the
|
|
||||||
// vanilla register.
|
|
||||||
map->set_location(::fp->as_VMReg()->next(), (address) link_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// frame::sender_for_interpreter_frame
|
// frame::sender_for_interpreter_frame
|
||||||
frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
||||||
@ -440,80 +415,6 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
|||||||
return frame(sender_sp, unextended_sp, link(), sender_pc());
|
return frame(sender_sp, unextended_sp, link(), sender_pc());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// frame::sender_for_compiled_frame
|
|
||||||
frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
|
||||||
// we cannot rely upon the last fp having been saved to the thread
|
|
||||||
// in C2 code but it will have been pushed onto the stack. so we
|
|
||||||
// have to find it relative to the unextended sp
|
|
||||||
|
|
||||||
assert(_cb->frame_size() >= 0, "must have non-zero frame size");
|
|
||||||
intptr_t* l_sender_sp = unextended_sp() + _cb->frame_size();
|
|
||||||
intptr_t* unextended_sp = l_sender_sp;
|
|
||||||
|
|
||||||
// the return_address is always the word on the stack
|
|
||||||
address sender_pc = (address) *(l_sender_sp + frame::return_addr_offset);
|
|
||||||
|
|
||||||
intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp + frame::link_offset);
|
|
||||||
|
|
||||||
assert(map != NULL, "map must be set");
|
|
||||||
if (map->update_map()) {
|
|
||||||
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
|
||||||
// For C1, the runtime stub might not have oop maps, so set this flag
|
|
||||||
// outside of update_register_map.
|
|
||||||
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
|
||||||
if (_cb->oop_maps() != NULL) {
|
|
||||||
OopMapSet::update_register_map(this, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since the prolog does the save and restore of FP there is no
|
|
||||||
// oopmap for it so we must fill in its location as if there was
|
|
||||||
// an oopmap entry since if our caller was compiled code there
|
|
||||||
// could be live jvm state in it.
|
|
||||||
update_map_with_saved_link(map, saved_fp_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return frame(l_sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// frame::sender_raw
|
|
||||||
frame frame::sender_raw(RegisterMap* map) const {
|
|
||||||
// Default is we done have to follow them. The sender_for_xxx will
|
|
||||||
// update it accordingly
|
|
||||||
assert(map != NULL, "map must be set");
|
|
||||||
map->set_include_argument_oops(false);
|
|
||||||
|
|
||||||
if (is_entry_frame()) {
|
|
||||||
return sender_for_entry_frame(map);
|
|
||||||
}
|
|
||||||
if (is_interpreted_frame()) {
|
|
||||||
return sender_for_interpreter_frame(map);
|
|
||||||
}
|
|
||||||
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
|
||||||
|
|
||||||
// This test looks odd: why is it not is_compiled_frame() ? That's
|
|
||||||
// because stubs also have OOP maps.
|
|
||||||
if (_cb != NULL) {
|
|
||||||
return sender_for_compiled_frame(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
|
||||||
// methods that exists in the core system.
|
|
||||||
return frame(sender_sp(), link(), sender_pc());
|
|
||||||
}
|
|
||||||
|
|
||||||
frame frame::sender(RegisterMap* map) const {
|
|
||||||
frame result = sender_raw(map);
|
|
||||||
|
|
||||||
if (map->process_frames()) {
|
|
||||||
StackWatermarkSet::on_iteration(map->thread(), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
||||||
assert(is_interpreted_frame(), "Not an interpreted frame");
|
assert(is_interpreted_frame(), "Not an interpreted frame");
|
||||||
// These are reasonable sanity checks
|
// These are reasonable sanity checks
|
||||||
@ -651,24 +552,11 @@ intptr_t *frame::initial_deoptimization_info() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr_t* frame::real_fp() const {
|
|
||||||
if (_cb != NULL) {
|
|
||||||
// use the frame size if valid
|
|
||||||
int size = _cb->frame_size();
|
|
||||||
if (size > 0) {
|
|
||||||
return unextended_sp() + size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else rely on fp()
|
|
||||||
assert(!is_compiled_frame(), "unknown compiled frame size");
|
|
||||||
return fp();
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef DESCRIBE_FP_OFFSET
|
#undef DESCRIBE_FP_OFFSET
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
// This is a generic constructor which is only used by pns() in debug.cpp.
|
// This is a generic constructor which is only used by pns() in debug.cpp.
|
||||||
frame::frame(void* ptr_sp, void* ptr_fp, void* pc) {
|
frame::frame(void* ptr_sp, void* ptr_fp, void* pc) : _on_heap(false) {
|
||||||
init((intptr_t*)ptr_sp, (intptr_t*)ptr_fp, (address)pc);
|
init((intptr_t*)ptr_sp, (intptr_t*)ptr_fp, (address)pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -137,7 +137,14 @@
|
|||||||
entry_frame_call_wrapper_offset = -10,
|
entry_frame_call_wrapper_offset = -10,
|
||||||
|
|
||||||
// we don't need a save area
|
// we don't need a save area
|
||||||
arg_reg_save_area_bytes = 0
|
arg_reg_save_area_bytes = 0,
|
||||||
|
|
||||||
|
// size, in words, of frame metadata (e.g. pc and link)
|
||||||
|
metadata_words = sender_sp_offset,
|
||||||
|
// in bytes
|
||||||
|
frame_alignment = 16,
|
||||||
|
// size, in words, of maximum shift in frame position due to alignment
|
||||||
|
align_wiggle = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
intptr_t ptr_at(int offset) const {
|
intptr_t ptr_at(int offset) const {
|
||||||
@ -170,6 +177,8 @@
|
|||||||
static void verify_deopt_original_pc( CompiledMethod* nm, intptr_t* unextended_sp);
|
static void verify_deopt_original_pc( CompiledMethod* nm, intptr_t* unextended_sp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const ImmutableOopMap* get_oop_map() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
@ -190,8 +199,8 @@
|
|||||||
// expression stack tos if we are nested in a java call
|
// expression stack tos if we are nested in a java call
|
||||||
intptr_t* interpreter_frame_last_sp() const;
|
intptr_t* interpreter_frame_last_sp() const;
|
||||||
|
|
||||||
// helper to update a map with callee-saved RBP
|
template <typename RegisterMapT>
|
||||||
static void update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr);
|
static void update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr);
|
||||||
|
|
||||||
// deoptimization support
|
// deoptimization support
|
||||||
void interpreter_frame_set_last_sp(intptr_t* last_sp);
|
void interpreter_frame_set_last_sp(intptr_t* last_sp);
|
||||||
@ -199,6 +208,6 @@
|
|||||||
static jint interpreter_frame_expression_stack_direction() { return -1; }
|
static jint interpreter_frame_expression_stack_direction() { return -1; }
|
||||||
|
|
||||||
// returns the sending frame, without applying any barriers
|
// returns the sending frame, without applying any barriers
|
||||||
frame sender_raw(RegisterMap* map) const;
|
inline frame sender_raw(RegisterMap* map) const;
|
||||||
|
|
||||||
#endif // CPU_RISCV_FRAME_RISCV_HPP
|
#endif // CPU_RISCV_FRAME_RISCV_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||||
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
@ -41,6 +41,8 @@ inline frame::frame() {
|
|||||||
_fp = NULL;
|
_fp = NULL;
|
||||||
_cb = NULL;
|
_cb = NULL;
|
||||||
_deopt_state = unknown;
|
_deopt_state = unknown;
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spin;
|
static int spin;
|
||||||
@ -63,6 +65,9 @@ inline void frame::init(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) {
|
|||||||
} else {
|
} else {
|
||||||
_deopt_state = not_deoptimized;
|
_deopt_state = not_deoptimized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) {
|
inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) {
|
||||||
@ -89,6 +94,13 @@ inline frame::frame(intptr_t* ptr_sp, intptr_t* unextended_sp, intptr_t* ptr_fp,
|
|||||||
} else {
|
} else {
|
||||||
_deopt_state = not_deoptimized;
|
_deopt_state = not_deoptimized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame::frame(intptr_t* ptr_sp) {
|
||||||
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp) {
|
inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp) {
|
||||||
@ -119,6 +131,9 @@ inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp) {
|
|||||||
} else {
|
} else {
|
||||||
_deopt_state = not_deoptimized;
|
_deopt_state = not_deoptimized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_on_heap = false;
|
||||||
|
DEBUG_ONLY(_frame_index = -1;)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
@ -150,6 +165,38 @@ inline intptr_t* frame::link_or_null() const {
|
|||||||
|
|
||||||
inline intptr_t* frame::unextended_sp() const { return _unextended_sp; }
|
inline intptr_t* frame::unextended_sp() const { return _unextended_sp; }
|
||||||
|
|
||||||
|
inline void frame::set_unextended_sp(intptr_t* value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::offset_unextended_sp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::set_offset_unextended_sp(int value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* frame::real_fp() const {
|
||||||
|
if (_cb != NULL) {
|
||||||
|
// use the frame size if valid
|
||||||
|
int size = _cb->frame_size();
|
||||||
|
if (size > 0) {
|
||||||
|
return unextended_sp() + size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// else rely on fp()
|
||||||
|
assert(!is_compiled_frame(), "unknown compiled frame size");
|
||||||
|
return fp();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::frame_size() const {
|
||||||
|
return is_interpreted_frame()
|
||||||
|
? sender_sp() - sp()
|
||||||
|
: cb()->frame_size();
|
||||||
|
}
|
||||||
|
|
||||||
// Return address
|
// Return address
|
||||||
inline address* frame::sender_pc_addr() const { return (address*) addr_at(return_addr_offset); }
|
inline address* frame::sender_pc_addr() const { return (address*) addr_at(return_addr_offset); }
|
||||||
inline address frame::sender_pc() const { return *sender_pc_addr(); }
|
inline address frame::sender_pc() const { return *sender_pc_addr(); }
|
||||||
@ -160,7 +207,7 @@ inline intptr_t** frame::interpreter_frame_locals_addr() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline intptr_t* frame::interpreter_frame_last_sp() const {
|
inline intptr_t* frame::interpreter_frame_last_sp() const {
|
||||||
return *(intptr_t**)addr_at(interpreter_frame_last_sp_offset);
|
return (intptr_t*)at(interpreter_frame_last_sp_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline intptr_t* frame::interpreter_frame_bcp_addr() const {
|
inline intptr_t* frame::interpreter_frame_bcp_addr() const {
|
||||||
@ -233,16 +280,130 @@ inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
|
|||||||
PRAGMA_DIAG_PUSH
|
PRAGMA_DIAG_PUSH
|
||||||
PRAGMA_NONNULL_IGNORED
|
PRAGMA_NONNULL_IGNORED
|
||||||
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
||||||
oop* result_adr = (oop *)map->location(x10->as_VMReg());
|
oop* result_adr = (oop *)map->location(x10->as_VMReg(), nullptr);
|
||||||
guarantee(result_adr != NULL, "bad register save location");
|
guarantee(result_adr != NULL, "bad register save location");
|
||||||
return (*result_adr);
|
return (*result_adr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
||||||
oop* result_adr = (oop *)map->location(x10->as_VMReg());
|
oop* result_adr = (oop *)map->location(x10->as_VMReg(), nullptr);
|
||||||
guarantee(result_adr != NULL, "bad register save location");
|
guarantee(result_adr != NULL, "bad register save location");
|
||||||
*result_adr = obj;
|
*result_adr = obj;
|
||||||
}
|
}
|
||||||
PRAGMA_DIAG_POP
|
PRAGMA_DIAG_POP
|
||||||
|
|
||||||
|
inline const ImmutableOopMap* frame::get_oop_map() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::compiled_frame_stack_argsize() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::interpreted_frame_oop_map(InterpreterOopMap* mask) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::sender_sp_ret_address_offset() {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// frame::sender
|
||||||
|
frame frame::sender(RegisterMap* map) const {
|
||||||
|
frame result = sender_raw(map);
|
||||||
|
|
||||||
|
if (map->process_frames()) {
|
||||||
|
StackWatermarkSet::on_iteration(map->thread(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// frame::sender_raw
|
||||||
|
frame frame::sender_raw(RegisterMap* map) const {
|
||||||
|
// Default is we done have to follow them. The sender_for_xxx will
|
||||||
|
// update it accordingly
|
||||||
|
assert(map != NULL, "map must be set");
|
||||||
|
map->set_include_argument_oops(false);
|
||||||
|
|
||||||
|
if (is_entry_frame()) {
|
||||||
|
return sender_for_entry_frame(map);
|
||||||
|
}
|
||||||
|
if (is_interpreted_frame()) {
|
||||||
|
return sender_for_interpreter_frame(map);
|
||||||
|
}
|
||||||
|
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
||||||
|
|
||||||
|
// This test looks odd: why is it not is_compiled_frame() ? That's
|
||||||
|
// because stubs also have OOP maps.
|
||||||
|
if (_cb != NULL) {
|
||||||
|
return sender_for_compiled_frame(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be native-compiled frame, i.e. the marshaling code for native
|
||||||
|
// methods that exists in the core system.
|
||||||
|
return frame(sender_sp(), link(), sender_pc());
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// frame::sender_for_compiled_frame
|
||||||
|
frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
||||||
|
// we cannot rely upon the last fp having been saved to the thread
|
||||||
|
// in C2 code but it will have been pushed onto the stack. so we
|
||||||
|
// have to find it relative to the unextended sp
|
||||||
|
|
||||||
|
assert(_cb->frame_size() >= 0, "must have non-zero frame size");
|
||||||
|
intptr_t* l_sender_sp = unextended_sp() + _cb->frame_size();
|
||||||
|
intptr_t* unextended_sp = l_sender_sp;
|
||||||
|
|
||||||
|
// the return_address is always the word on the stack
|
||||||
|
address sender_pc = (address) *(l_sender_sp + frame::return_addr_offset);
|
||||||
|
|
||||||
|
intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp + frame::link_offset);
|
||||||
|
|
||||||
|
assert(map != NULL, "map must be set");
|
||||||
|
if (map->update_map()) {
|
||||||
|
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
||||||
|
// For C1, the runtime stub might not have oop maps, so set this flag
|
||||||
|
// outside of update_register_map.
|
||||||
|
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
||||||
|
if (_cb->oop_maps() != NULL) {
|
||||||
|
OopMapSet::update_register_map(this, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the prolog does the save and restore of FP there is no
|
||||||
|
// oopmap for it so we must fill in its location as if there was
|
||||||
|
// an oopmap entry since if our caller was compiled code there
|
||||||
|
// could be live jvm state in it.
|
||||||
|
update_map_with_saved_link(map, saved_fp_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame(l_sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// frame::update_map_with_saved_link
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
void frame::update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr) {
|
||||||
|
// The interpreter and compiler(s) always save fp in a known
|
||||||
|
// location on entry. We must record where that location is
|
||||||
|
// so that if fp was live on callout from c2 we can find
|
||||||
|
// the saved copy no matter what it called.
|
||||||
|
|
||||||
|
// Since the interpreter always saves fp if we record where it is then
|
||||||
|
// we don't have to always save fp on entry and exit to c2 compiled
|
||||||
|
// code, on entry will be enough.
|
||||||
|
assert(map != NULL, "map must be set");
|
||||||
|
map->set_location(::fp->as_VMReg(), (address) link_addr);
|
||||||
|
// this is weird "H" ought to be at a higher address however the
|
||||||
|
// oopMaps seems to have the "H" regs at the same address and the
|
||||||
|
// vanilla register.
|
||||||
|
map->set_location(::fp->as_VMReg()->next(), (address) link_addr);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // CPU_RISCV_FRAME_RISCV_INLINE_HPP
|
#endif // CPU_RISCV_FRAME_RISCV_INLINE_HPP
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -29,6 +29,7 @@
|
|||||||
#include "gc/shared/barrierSetNMethod.hpp"
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
#include "logging/log.hpp"
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/registerMap.hpp"
|
#include "runtime/registerMap.hpp"
|
||||||
#include "runtime/thread.hpp"
|
#include "runtime/thread.hpp"
|
||||||
@ -161,6 +162,10 @@ void BarrierSetNMethod::disarm(nmethod* nm) {
|
|||||||
barrier->set_value(disarmed_value());
|
barrier->set_value(disarmed_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::arm(nmethod* nm, int arm_value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
if (!supports_entry_barrier(nm)) {
|
if (!supports_entry_barrier(nm)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved.
|
||||||
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
@ -569,4 +569,35 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NativePostCallNop: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
bool check() const { Unimplemented(); return false; }
|
||||||
|
int displacement() const { Unimplemented(); return 0; }
|
||||||
|
void patch(jint diff) { Unimplemented(); }
|
||||||
|
void make_deopt() { Unimplemented(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline NativePostCallNop* nativePostCallNop_at(address address) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NativeDeoptInstruction: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
address instruction_address() const { Unimplemented(); return NULL; }
|
||||||
|
address next_instruction_address() const { Unimplemented(); return NULL; }
|
||||||
|
|
||||||
|
void verify() { Unimplemented(); }
|
||||||
|
|
||||||
|
static bool is_deopt_at(address instr) {
|
||||||
|
Unimplemented();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MT-safe patching
|
||||||
|
static void insert(address code_pos) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // CPU_RISCV_NATIVEINST_RISCV_HPP
|
#endif // CPU_RISCV_NATIVEINST_RISCV_HPP
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
* Copyright (c) 2021, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -33,13 +33,13 @@ address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const {
|
|||||||
int base_reg_enc = (base_reg->value() - ConcreteRegisterImpl::max_fpr) /
|
int base_reg_enc = (base_reg->value() - ConcreteRegisterImpl::max_fpr) /
|
||||||
VectorRegisterImpl::max_slots_per_register;
|
VectorRegisterImpl::max_slots_per_register;
|
||||||
intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size;
|
intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size;
|
||||||
address base_location = location(base_reg);
|
address base_location = location(base_reg, nullptr);
|
||||||
if (base_location != NULL) {
|
if (base_location != NULL) {
|
||||||
return base_location + offset_in_bytes;
|
return base_location + offset_in_bytes;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return location(base_reg->next(slot_idx));
|
return location(base_reg->next(slot_idx), nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
87
src/hotspot/cpu/riscv/smallRegisterMap_riscv.inline.hpp
Normal file
87
src/hotspot/cpu/riscv/smallRegisterMap_riscv.inline.hpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_RISCV_SMALLREGISTERMAP_RISCV_INLINE_HPP
|
||||||
|
#define CPU_RISCV_SMALLREGISTERMAP_RISCV_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
// Java frames don't have callee saved registers (except for rfp), so we can use a smaller RegisterMap
|
||||||
|
class SmallRegisterMap {
|
||||||
|
public:
|
||||||
|
static constexpr SmallRegisterMap* instance = nullptr;
|
||||||
|
private:
|
||||||
|
static void assert_is_rfp(VMReg r) PRODUCT_RETURN
|
||||||
|
DEBUG_ONLY({ Unimplemented(); })
|
||||||
|
public:
|
||||||
|
// as_RegisterMap is used when we didn't want to templatize and abstract over RegisterMap type to support SmallRegisterMap
|
||||||
|
// Consider enhancing SmallRegisterMap to support those cases
|
||||||
|
const RegisterMap* as_RegisterMap() const { return nullptr; }
|
||||||
|
RegisterMap* as_RegisterMap() { return nullptr; }
|
||||||
|
|
||||||
|
RegisterMap* copy_to_RegisterMap(RegisterMap* map, intptr_t* sp) const {
|
||||||
|
Unimplemented();
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallRegisterMap() {}
|
||||||
|
|
||||||
|
SmallRegisterMap(const RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address location(VMReg reg, intptr_t* sp) const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_location(VMReg reg, address loc) { assert_is_rfp(reg); }
|
||||||
|
|
||||||
|
JavaThread* thread() const {
|
||||||
|
#ifndef ASSERT
|
||||||
|
guarantee (false, "");
|
||||||
|
#endif
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update_map() const { return false; }
|
||||||
|
bool walk_cont() const { return false; }
|
||||||
|
bool include_argument_oops() const { return false; }
|
||||||
|
void set_include_argument_oops(bool f) {}
|
||||||
|
bool in_cont() const { return false; }
|
||||||
|
stackChunkHandle stack_chunk() const { return stackChunkHandle(); }
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
bool should_skip_missing() const { return false; }
|
||||||
|
VMReg find_register_spilled_here(void* p, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void print() const { print_on(tty); }
|
||||||
|
void print_on(outputStream* st) const { st->print_cr("Small register map"); }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CPU_RISCV_SMALLREGISTERMAP_RISCV_INLINE_HPP
|
115
src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp
Normal file
115
src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_RISCV_STACKCHUNKFRAMESTREAM_RISCV_INLINE_HPP
|
||||||
|
#define CPU_RISCV_STACKCHUNKFRAMESTREAM_RISCV_INLINE_HPP
|
||||||
|
|
||||||
|
#include "interpreter/oopMapCache.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline bool StackChunkFrameStream<frame_kind>::is_in_frame(void* p0) const {
|
||||||
|
Unimplemented();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline frame StackChunkFrameStream<frame_kind>::to_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline address StackChunkFrameStream<frame_kind>::get_pc() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::fp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::derelativize(int offset) const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::unextended_sp_for_interpreter_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
intptr_t* StackChunkFrameStream<frame_kind>::next_sp_for_interpreter_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::next_for_interpreter_frame() {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_size() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_stack_argsize() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_num_oops() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::Mixed>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::CompiledOnly>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::update_reg_map_pd(RegisterMapT* map) {}
|
||||||
|
|
||||||
|
#endif // CPU_RISCV_STACKCHUNKFRAMESTREAM_RISCV_INLINE_HPP
|
36
src/hotspot/cpu/riscv/stackChunkOop_riscv.inline.hpp
Normal file
36
src/hotspot/cpu/riscv/stackChunkOop_riscv.inline.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_RISCV_STACKCHUNKOOP_RISCV_INLINE_HPP
|
||||||
|
#define CPU_RISCV_STACKCHUNKOOP_RISCV_INLINE_HPP
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::relativize_frame_pd(frame& fr) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::derelativize_frame_pd(frame& fr) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_RISCV_STACKCHUNKOOP_RISCV_INLINE_HPP
|
@ -3810,10 +3810,10 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
}; // end class declaration
|
}; // end class declaration
|
||||||
|
|
||||||
#define UCM_TABLE_MAX_ENTRIES 8
|
#define UCM_TABLE_MAX_ENTRIES 8
|
||||||
void StubGenerator_generate(CodeBuffer* code, bool all) {
|
void StubGenerator_generate(CodeBuffer* code, int phase) {
|
||||||
if (UnsafeCopyMemory::_table == NULL) {
|
if (UnsafeCopyMemory::_table == NULL) {
|
||||||
UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES);
|
UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
StubGenerator g(code, all);
|
StubGenerator g(code, phase);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
||||||
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
@ -797,6 +797,11 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
|||||||
|
|
||||||
// End of helpers
|
// End of helpers
|
||||||
|
|
||||||
|
address TemplateInterpreterGenerator::generate_Continuation_doYield_entry(void) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Various method entries
|
// Various method entries
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -392,7 +392,10 @@ class Argument {
|
|||||||
// Only 5 registers may contain integer parameters.
|
// Only 5 registers may contain integer parameters.
|
||||||
n_register_parameters = 5,
|
n_register_parameters = 5,
|
||||||
// Can have up to 4 floating registers.
|
// Can have up to 4 floating registers.
|
||||||
n_float_register_parameters = 4
|
n_float_register_parameters = 4,
|
||||||
|
|
||||||
|
n_int_register_parameters_j = n_register_parameters,
|
||||||
|
n_float_register_parameters_j = n_float_register_parameters
|
||||||
};
|
};
|
||||||
|
|
||||||
// creation
|
// creation
|
||||||
|
@ -1183,3 +1183,7 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
|
|||||||
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
|
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
|
||||||
fatal("vectorizedMismatch intrinsic is not implemented on this platform");
|
fatal("vectorizedMismatch intrinsic is not implemented on this platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LIRGenerator::do_continuation_doYield(Intrinsic* x) {
|
||||||
|
fatal("Continuation.doYield intrinsic is not implemented on this platform");
|
||||||
|
}
|
||||||
|
46
src/hotspot/cpu/s390/continuationEntry_s390.inline.hpp
Normal file
46
src/hotspot/cpu/s390/continuationEntry_s390.inline.hpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_S390_CONTINUATIONENTRY_S390_INLINE_HPP
|
||||||
|
#define CPU_S390_CONTINUATIONENTRY_S390_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationEntry.hpp"
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
|
|
||||||
|
inline frame ContinuationEntry::to_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationEntry::entry_fp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationEntry::update_register_map(RegisterMap* map) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_S390_CONTINUATIONENTRY_S390_INLINE_HPP
|
98
src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp
Normal file
98
src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_S390_CONTINUATION_S390_INLINE_HPP
|
||||||
|
#define CPU_S390_CONTINUATION_S390_INLINE_HPP
|
||||||
|
|
||||||
|
#include "oops/stackChunkOop.inline.hpp"
|
||||||
|
#include "runtime/frame.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
|
||||||
|
inline void FreezeBase::set_top_frame_metadata_pd(const frame& hf) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline frame FreezeBase::sender(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, const frame& hf) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame ThawBase::new_entry_frame() {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::set_interpreter_frame_bottom(const frame& f, intptr_t* bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& caller, bool bottom) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::patch_pd(frame& f, const frame& caller) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThawBase::patch_chunk_pd(intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::prefetch_chunk_pd(void* start, int size) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_S390_CONTINUATION_S390_INLINE_HPP
|
125
src/hotspot/cpu/s390/continuationHelper_s390.inline.hpp
Normal file
125
src/hotspot/cpu/s390/continuationHelper_s390.inline.hpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_S390_CONTINUATIONHELPER_S390_INLINE_HPP
|
||||||
|
#define CPU_S390_CONTINUATIONHELPER_S390_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationHelper.hpp"
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t** link_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ContinuationHelper::frame_align_words(int size) {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::frame_align_pointer(intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline void ContinuationHelper::update_register_map(const frame& f, RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::update_register_map_with_callee(const frame& f, RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::push_pd(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::set_anchor_to_entry_pd(JavaFrameAnchor* anchor, ContinuationEntry* cont) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
inline void ContinuationHelper::set_anchor_pd(JavaFrameAnchor* anchor, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ContinuationHelper::Frame::assert_frame_laid_out(frame f) {
|
||||||
|
Unimplemented();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline intptr_t** ContinuationHelper::Frame::callee_link_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t* real_fp(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::InterpretedFrame::return_pc_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::InterpretedFrame::patch_sender_sp(frame& f, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::Frame::return_pc_address(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address ContinuationHelper::Frame::real_pc(const frame& f) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, InterpreterOopMap* mask) { // inclusive; this will be copied with the frame
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_bottom(const frame& f) { // exclusive; this will not be copied with the frame
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_S390_CONTINUATIONHELPER_S390_INLINE_HPP
|
@ -230,27 +230,6 @@ frame frame::sender_for_interpreter_frame(RegisterMap *map) const {
|
|||||||
return frame(sender_sp(), sender_pc(), (intptr_t*)(ijava_state()->sender_sp));
|
return frame(sender_sp(), sender_pc(), (intptr_t*)(ijava_state()->sender_sp));
|
||||||
}
|
}
|
||||||
|
|
||||||
frame frame::sender_for_compiled_frame(RegisterMap *map) const {
|
|
||||||
assert(map != NULL, "map must be set");
|
|
||||||
// Frame owned by compiler.
|
|
||||||
|
|
||||||
address pc = *compiled_sender_pc_addr(_cb);
|
|
||||||
frame caller(compiled_sender_sp(_cb), pc);
|
|
||||||
|
|
||||||
// Now adjust the map.
|
|
||||||
|
|
||||||
// Get the rest.
|
|
||||||
if (map->update_map()) {
|
|
||||||
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
|
||||||
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
|
||||||
if (_cb->oop_maps() != NULL) {
|
|
||||||
OopMapSet::update_register_map(this, map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return caller;
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t* frame::compiled_sender_sp(CodeBlob* cb) const {
|
intptr_t* frame::compiled_sender_sp(CodeBlob* cb) const {
|
||||||
return sender_sp();
|
return sender_sp();
|
||||||
}
|
}
|
||||||
@ -259,26 +238,6 @@ address* frame::compiled_sender_pc_addr(CodeBlob* cb) const {
|
|||||||
return sender_pc_addr();
|
return sender_pc_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
frame frame::sender(RegisterMap* map) const {
|
|
||||||
// Default is we don't have to follow them. The sender_for_xxx will
|
|
||||||
// update it accordingly.
|
|
||||||
map->set_include_argument_oops(false);
|
|
||||||
|
|
||||||
if (is_entry_frame()) {
|
|
||||||
return sender_for_entry_frame(map);
|
|
||||||
}
|
|
||||||
if (is_interpreted_frame()) {
|
|
||||||
return sender_for_interpreter_frame(map);
|
|
||||||
}
|
|
||||||
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
|
||||||
if (_cb != NULL) {
|
|
||||||
return sender_for_compiled_frame(map);
|
|
||||||
}
|
|
||||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
|
||||||
// methods that exists in the core system.
|
|
||||||
return frame(sender_sp(), sender_pc());
|
|
||||||
}
|
|
||||||
|
|
||||||
void frame::patch_pc(Thread* thread, address pc) {
|
void frame::patch_pc(Thread* thread, address pc) {
|
||||||
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
||||||
if (TracePcPatching) {
|
if (TracePcPatching) {
|
||||||
@ -680,3 +639,13 @@ intptr_t *frame::initial_deoptimization_info() {
|
|||||||
// Used to reset the saved FP.
|
// Used to reset the saved FP.
|
||||||
return fp();
|
return fp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pointer beyond the "oldest/deepest" BasicObjectLock on stack.
|
||||||
|
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
||||||
|
return interpreter_frame_monitors();
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
||||||
|
return &interpreter_frame_tos_address()[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -461,11 +461,11 @@
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
inline void find_codeblob_and_set_pc_and_deopt_state(address pc);
|
inline void find_codeblob_and_set_pc_and_deopt_state(address pc);
|
||||||
|
const ImmutableOopMap* get_oop_map() const;
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline frame(intptr_t* sp);
|
|
||||||
// To be used, if sp was not extended to match callee's calling convention.
|
// To be used, if sp was not extended to match callee's calling convention.
|
||||||
inline frame(intptr_t* sp, address pc);
|
inline frame(intptr_t* sp, address pc);
|
||||||
inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp);
|
inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp);
|
||||||
@ -486,6 +486,10 @@
|
|||||||
address* sender_pc_addr(void) const;
|
address* sender_pc_addr(void) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
inline intptr_t* interpreter_frame_last_sp() const;
|
||||||
|
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
static void update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr);
|
||||||
|
|
||||||
// Additional interface for interpreter frames:
|
// Additional interface for interpreter frames:
|
||||||
static int interpreter_frame_interpreterstate_size_in_bytes();
|
static int interpreter_frame_interpreterstate_size_in_bytes();
|
||||||
@ -550,6 +554,10 @@
|
|||||||
//
|
//
|
||||||
// Normal return address is the instruction following the branch.
|
// Normal return address is the instruction following the branch.
|
||||||
pc_return_offset = 0,
|
pc_return_offset = 0,
|
||||||
|
metadata_words = 0,
|
||||||
|
frame_alignment = 16,
|
||||||
|
// size, in words, of maximum shift in frame position due to alignment
|
||||||
|
align_wiggle = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
static jint interpreter_frame_expression_stack_direction() { return -1; }
|
static jint interpreter_frame_expression_stack_direction() { return -1; }
|
||||||
|
@ -54,24 +54,44 @@ inline void frame::find_codeblob_and_set_pc_and_deopt_state(address pc) {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
// Initialize all fields, _unextended_sp will be adjusted in find_codeblob_and_set_pc_and_deopt_state.
|
// Initialize all fields, _unextended_sp will be adjusted in find_codeblob_and_set_pc_and_deopt_state.
|
||||||
inline frame::frame() : _sp(NULL), _pc(NULL), _cb(NULL), _deopt_state(unknown), _unextended_sp(NULL), _fp(NULL) {}
|
inline frame::frame() : _sp(NULL), _pc(NULL), _cb(NULL), _deopt_state(unknown), _on_heap(false),
|
||||||
|
#ifdef ASSERT
|
||||||
|
_frame_index(-1),
|
||||||
|
#endif
|
||||||
|
_unextended_sp(NULL), _fp(NULL) {}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* sp) : _sp(sp), _unextended_sp(sp) {
|
inline frame::frame(intptr_t* sp) : _sp(sp), _on_heap(false),
|
||||||
|
#ifdef ASSERT
|
||||||
|
_frame_index(-1),
|
||||||
|
#endif
|
||||||
|
_unextended_sp(sp) {
|
||||||
find_codeblob_and_set_pc_and_deopt_state((address)own_abi()->return_pc);
|
find_codeblob_and_set_pc_and_deopt_state((address)own_abi()->return_pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* sp, address pc) : _sp(sp), _unextended_sp(sp) {
|
inline frame::frame(intptr_t* sp, address pc) : _sp(sp), _on_heap(false),
|
||||||
|
#ifdef ASSERT
|
||||||
|
_frame_index(-1),
|
||||||
|
#endif
|
||||||
|
_unextended_sp(sp) {
|
||||||
find_codeblob_and_set_pc_and_deopt_state(pc); // Also sets _fp and adjusts _unextended_sp.
|
find_codeblob_and_set_pc_and_deopt_state(pc); // Also sets _fp and adjusts _unextended_sp.
|
||||||
}
|
}
|
||||||
|
|
||||||
inline frame::frame(intptr_t* sp, address pc, intptr_t* unextended_sp) : _sp(sp), _unextended_sp(unextended_sp) {
|
inline frame::frame(intptr_t* sp, address pc, intptr_t* unextended_sp) : _sp(sp), _on_heap(false),
|
||||||
|
#ifdef ASSERT
|
||||||
|
_frame_index(-1),
|
||||||
|
#endif
|
||||||
|
_unextended_sp(unextended_sp) {
|
||||||
find_codeblob_and_set_pc_and_deopt_state(pc); // Also sets _fp and adjusts _unextended_sp.
|
find_codeblob_and_set_pc_and_deopt_state(pc); // Also sets _fp and adjusts _unextended_sp.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic constructor. Used by pns() in debug.cpp only
|
// Generic constructor. Used by pns() in debug.cpp only
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
inline frame::frame(void* sp, void* pc, void* unextended_sp) :
|
inline frame::frame(void* sp, void* pc, void* unextended_sp) :
|
||||||
_sp((intptr_t*)sp), _pc(NULL), _cb(NULL), _unextended_sp((intptr_t*)unextended_sp) {
|
_sp((intptr_t*)sp), _pc(NULL), _cb(NULL), _on_heap(false),
|
||||||
|
#ifdef ASSERT
|
||||||
|
_frame_index(-1),
|
||||||
|
#endif
|
||||||
|
_unextended_sp((intptr_t*)unextended_sp) {
|
||||||
find_codeblob_and_set_pc_and_deopt_state((address)pc); // Also sets _fp and adjusts _unextended_sp.
|
find_codeblob_and_set_pc_and_deopt_state((address)pc); // Also sets _fp and adjusts _unextended_sp.
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -119,7 +139,7 @@ inline bool frame::is_older(intptr_t* id) const {
|
|||||||
return this->id() > id;
|
return this->id() > id;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int frame::frame_size(RegisterMap* map) const {
|
inline int frame::frame_size() const {
|
||||||
// Stack grows towards smaller addresses on z/Linux: sender is at a higher address.
|
// Stack grows towards smaller addresses on z/Linux: sender is at a higher address.
|
||||||
return sender_sp() - sp();
|
return sender_sp() - sp();
|
||||||
}
|
}
|
||||||
@ -176,11 +196,6 @@ inline intptr_t* frame::interpreter_frame_expression_stack() const {
|
|||||||
return (intptr_t*)interpreter_frame_monitor_end() - 1;
|
return (intptr_t*)interpreter_frame_monitor_end() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
|
||||||
return &interpreter_frame_tos_address()[offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// monitor elements
|
// monitor elements
|
||||||
|
|
||||||
// End is lower in memory than begin, and beginning element is oldest element.
|
// End is lower in memory than begin, and beginning element is oldest element.
|
||||||
@ -229,10 +244,6 @@ inline BasicObjectLock * frame::interpreter_frame_monitor_begin() const {
|
|||||||
return (BasicObjectLock*)ijava_state();
|
return (BasicObjectLock*)ijava_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline BasicObjectLock * frame::interpreter_frame_monitor_end() const {
|
|
||||||
return interpreter_frame_monitors();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* monitors) {
|
inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* monitors) {
|
||||||
interpreter_frame_set_monitors((BasicObjectLock *)monitors);
|
interpreter_frame_set_monitors((BasicObjectLock *)monitors);
|
||||||
}
|
}
|
||||||
@ -281,15 +292,100 @@ inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
inline oop frame::saved_oop_result(RegisterMap* map) const {
|
||||||
return *((oop*) map->location(Z_R2->as_VMReg())); // R2 is return register.
|
return *((oop*) map->location(Z_R2->as_VMReg(), nullptr)); // R2 is return register.
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
||||||
*((oop*) map->location(Z_R2->as_VMReg())) = obj; // R2 is return register.
|
*((oop*) map->location(Z_R2->as_VMReg(), nullptr)) = obj; // R2 is return register.
|
||||||
}
|
}
|
||||||
|
|
||||||
inline intptr_t* frame::real_fp() const {
|
inline intptr_t* frame::real_fp() const {
|
||||||
return fp();
|
return fp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const ImmutableOopMap* frame::get_oop_map() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::compiled_frame_stack_argsize() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::interpreted_frame_oop_map(InterpreterOopMap* mask) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* frame::interpreter_frame_last_sp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::sender_sp_ret_address_offset() {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::set_unextended_sp(intptr_t* value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int frame::offset_unextended_sp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void frame::set_offset_unextended_sp(int value) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// frame::sender
|
||||||
|
|
||||||
|
inline frame frame::sender(RegisterMap* map) const {
|
||||||
|
// Default is we don't have to follow them. The sender_for_xxx will
|
||||||
|
// update it accordingly.
|
||||||
|
map->set_include_argument_oops(false);
|
||||||
|
|
||||||
|
if (is_entry_frame()) {
|
||||||
|
return sender_for_entry_frame(map);
|
||||||
|
}
|
||||||
|
if (is_interpreted_frame()) {
|
||||||
|
return sender_for_interpreter_frame(map);
|
||||||
|
}
|
||||||
|
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
||||||
|
if (_cb != NULL) return sender_for_compiled_frame(map);
|
||||||
|
|
||||||
|
// Must be native-compiled frame, i.e. the marshaling code for native
|
||||||
|
// methods that exists in the core system.
|
||||||
|
return frame(sender_sp(), sender_pc());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline frame frame::sender_for_compiled_frame(RegisterMap *map) const {
|
||||||
|
assert(map != NULL, "map must be set");
|
||||||
|
// Frame owned by compiler.
|
||||||
|
|
||||||
|
address pc = *compiled_sender_pc_addr(_cb);
|
||||||
|
frame caller(compiled_sender_sp(_cb), pc);
|
||||||
|
|
||||||
|
// Now adjust the map.
|
||||||
|
|
||||||
|
// Get the rest.
|
||||||
|
if (map->update_map()) {
|
||||||
|
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
||||||
|
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
||||||
|
if (_cb->oop_maps() != NULL) {
|
||||||
|
OopMapSet::update_register_map(this, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return caller;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
void frame::update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
#endif // CPU_S390_FRAME_S390_INLINE_HPP
|
#endif // CPU_S390_FRAME_S390_INLINE_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -654,4 +654,35 @@ class NativeGeneralJump: public NativeInstruction {
|
|||||||
void verify() PRODUCT_RETURN;
|
void verify() PRODUCT_RETURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NativePostCallNop: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
bool check() const { Unimplemented(); return false; }
|
||||||
|
int displacement() const { Unimplemented(); return 0; }
|
||||||
|
void patch(jint diff) { Unimplemented(); }
|
||||||
|
void make_deopt() { Unimplemented(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline NativePostCallNop* nativePostCallNop_at(address address) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NativeDeoptInstruction: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
address instruction_address() const { Unimplemented(); return NULL; }
|
||||||
|
address next_instruction_address() const { Unimplemented(); return NULL; }
|
||||||
|
|
||||||
|
void verify() { Unimplemented(); }
|
||||||
|
|
||||||
|
static bool is_deopt_at(address instr) {
|
||||||
|
Unimplemented();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MT-safe patching
|
||||||
|
static void insert(address code_pos) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // CPU_S390_NATIVEINST_S390_HPP
|
#endif // CPU_S390_NATIVEINST_S390_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -37,7 +37,7 @@
|
|||||||
address pd_location(VMReg reg) const {return NULL;}
|
address pd_location(VMReg reg) const {return NULL;}
|
||||||
|
|
||||||
address pd_location(VMReg base_reg, int slot_idx) const {
|
address pd_location(VMReg base_reg, int slot_idx) const {
|
||||||
return location(base_reg->next(slot_idx));
|
return location(base_reg->next(slot_idx), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No PD state to clear or copy.
|
// No PD state to clear or copy.
|
||||||
|
87
src/hotspot/cpu/s390/smallRegisterMap_s390.inline.hpp
Normal file
87
src/hotspot/cpu/s390/smallRegisterMap_s390.inline.hpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_S390_SMALLREGISTERMAP_S390_INLINE_HPP
|
||||||
|
#define CPU_S390_SMALLREGISTERMAP_S390_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
// Java frames don't have callee saved registers (except for rfp), so we can use a smaller RegisterMap
|
||||||
|
class SmallRegisterMap {
|
||||||
|
public:
|
||||||
|
static constexpr SmallRegisterMap* instance = nullptr;
|
||||||
|
private:
|
||||||
|
static void assert_is_rfp(VMReg r) PRODUCT_RETURN
|
||||||
|
DEBUG_ONLY({ Unimplemented(); })
|
||||||
|
public:
|
||||||
|
// as_RegisterMap is used when we didn't want to templatize and abstract over RegisterMap type to support SmallRegisterMap
|
||||||
|
// Consider enhancing SmallRegisterMap to support those cases
|
||||||
|
const RegisterMap* as_RegisterMap() const { return nullptr; }
|
||||||
|
RegisterMap* as_RegisterMap() { return nullptr; }
|
||||||
|
|
||||||
|
RegisterMap* copy_to_RegisterMap(RegisterMap* map, intptr_t* sp) const {
|
||||||
|
Unimplemented();
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallRegisterMap() {}
|
||||||
|
|
||||||
|
SmallRegisterMap(const RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address location(VMReg reg, intptr_t* sp) const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_location(VMReg reg, address loc) { assert_is_rfp(reg); }
|
||||||
|
|
||||||
|
JavaThread* thread() const {
|
||||||
|
#ifndef ASSERT
|
||||||
|
guarantee (false, "");
|
||||||
|
#endif
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update_map() const { return false; }
|
||||||
|
bool walk_cont() const { return false; }
|
||||||
|
bool include_argument_oops() const { return false; }
|
||||||
|
void set_include_argument_oops(bool f) {}
|
||||||
|
bool in_cont() const { return false; }
|
||||||
|
stackChunkHandle stack_chunk() const { return stackChunkHandle(); }
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
bool should_skip_missing() const { return false; }
|
||||||
|
VMReg find_register_spilled_here(void* p, intptr_t* sp) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void print() const { print_on(tty); }
|
||||||
|
void print_on(outputStream* st) const { st->print_cr("Small register map"); }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CPU_S390_SMALLREGISTERMAP_S390_INLINE_HPP
|
115
src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp
Normal file
115
src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_S390_STACKCHUNKFRAMESTREAM_S390_INLINE_HPP
|
||||||
|
#define CPU_S390_STACKCHUNKFRAMESTREAM_S390_INLINE_HPP
|
||||||
|
|
||||||
|
#include "interpreter/oopMapCache.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline bool StackChunkFrameStream<frame_kind>::is_in_frame(void* p0) const {
|
||||||
|
Unimplemented();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline frame StackChunkFrameStream<frame_kind>::to_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline address StackChunkFrameStream<frame_kind>::get_pc() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::fp() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::derelativize(int offset) const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline intptr_t* StackChunkFrameStream<frame_kind>::unextended_sp_for_interpreter_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
intptr_t* StackChunkFrameStream<frame_kind>::next_sp_for_interpreter_frame() const {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::next_for_interpreter_frame() {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_size() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_stack_argsize() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
inline int StackChunkFrameStream<frame_kind>::interpreter_frame_num_oops() const {
|
||||||
|
Unimplemented();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::Mixed>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
template<>
|
||||||
|
inline void StackChunkFrameStream<ChunkFrames::CompiledOnly>::update_reg_map_pd(RegisterMap* map) {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ChunkFrames frame_kind>
|
||||||
|
template <typename RegisterMapT>
|
||||||
|
inline void StackChunkFrameStream<frame_kind>::update_reg_map_pd(RegisterMapT* map) {}
|
||||||
|
|
||||||
|
#endif // CPU_S390_STACKCHUNKFRAMESTREAM_S390_INLINE_HPP
|
36
src/hotspot/cpu/s390/stackChunkOop_s390.inline.hpp
Normal file
36
src/hotspot/cpu/s390/stackChunkOop_s390.inline.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_S390_STACKCHUNKOOP_S390_INLINE_HPP
|
||||||
|
#define CPU_S390_STACKCHUNKOOP_S390_INLINE_HPP
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::relativize_frame_pd(frame& fr) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void stackChunkOopDesc::derelativize_frame_pd(frame& fr) const {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_S390_STACKCHUNKOOP_S390_INLINE_HPP
|
@ -3014,6 +3014,6 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void StubGenerator_generate(CodeBuffer* code, bool all) {
|
void StubGenerator_generate(CodeBuffer* code, int phase) {
|
||||||
StubGenerator g(code, all);
|
StubGenerator g(code, phase);
|
||||||
}
|
}
|
||||||
|
@ -482,6 +482,11 @@ address TemplateInterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
return __ addr_at(entry_offset);
|
return __ addr_at(entry_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address TemplateInterpreterGenerator::generate_Continuation_doYield_entry(void) {
|
||||||
|
Unimplemented();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
|
address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
|
||||||
// Inputs:
|
// Inputs:
|
||||||
// Z_ARG1 - receiver
|
// Z_ARG1 - receiver
|
||||||
|
@ -49,7 +49,9 @@ class Argument {
|
|||||||
n_int_register_parameters_j = 6, // j_rarg0, j_rarg1, ...
|
n_int_register_parameters_j = 6, // j_rarg0, j_rarg1, ...
|
||||||
n_float_register_parameters_j = 8 // j_farg0, j_farg1, ...
|
n_float_register_parameters_j = 8 // j_farg0, j_farg1, ...
|
||||||
#else
|
#else
|
||||||
n_register_parameters = 0 // 0 registers used to pass arguments
|
n_register_parameters = 0, // 0 registers used to pass arguments
|
||||||
|
n_int_register_parameters_j = 0,
|
||||||
|
n_float_register_parameters_j = 0
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -438,7 +438,7 @@ int LIR_Assembler::emit_unwind_handler() {
|
|||||||
|
|
||||||
// Fetch the exception from TLS and clear out exception related thread state
|
// Fetch the exception from TLS and clear out exception related thread state
|
||||||
Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread);
|
Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread);
|
||||||
NOT_LP64(__ get_thread(rsi));
|
NOT_LP64(__ get_thread(thread));
|
||||||
__ movptr(rax, Address(thread, JavaThread::exception_oop_offset()));
|
__ movptr(rax, Address(thread, JavaThread::exception_oop_offset()));
|
||||||
__ movptr(Address(thread, JavaThread::exception_oop_offset()), (intptr_t)NULL_WORD);
|
__ movptr(Address(thread, JavaThread::exception_oop_offset()), (intptr_t)NULL_WORD);
|
||||||
__ movptr(Address(thread, JavaThread::exception_pc_offset()), (intptr_t)NULL_WORD);
|
__ movptr(Address(thread, JavaThread::exception_pc_offset()), (intptr_t)NULL_WORD);
|
||||||
@ -460,6 +460,8 @@ int LIR_Assembler::emit_unwind_handler() {
|
|||||||
__ unlock_object(rdi, rsi, rax, *stub->entry());
|
__ unlock_object(rdi, rsi, rax, *stub->entry());
|
||||||
}
|
}
|
||||||
__ bind(*stub->continuation());
|
__ bind(*stub->continuation());
|
||||||
|
NOT_LP64(__ get_thread(thread);)
|
||||||
|
__ dec_held_monitor_count(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compilation()->env()->dtrace_method_probes()) {
|
if (compilation()->env()->dtrace_method_probes()) {
|
||||||
@ -2864,6 +2866,7 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
|
|||||||
"must be aligned");
|
"must be aligned");
|
||||||
__ call(AddressLiteral(op->addr(), rtype));
|
__ call(AddressLiteral(op->addr(), rtype));
|
||||||
add_call_info(code_offset(), op->info());
|
add_call_info(code_offset(), op->info());
|
||||||
|
__ post_call_nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2872,6 +2875,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
|
|||||||
add_call_info(code_offset(), op->info());
|
add_call_info(code_offset(), op->info());
|
||||||
assert((__ offset() - NativeCall::instruction_size + NativeCall::displacement_offset) % BytesPerWord == 0,
|
assert((__ offset() - NativeCall::instruction_size + NativeCall::displacement_offset) % BytesPerWord == 0,
|
||||||
"must be aligned");
|
"must be aligned");
|
||||||
|
__ post_call_nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3507,7 +3511,38 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
|||||||
} else {
|
} else {
|
||||||
Unimplemented();
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
if (op->code() == lir_lock) {
|
||||||
|
// If deoptimization happens in Runtime1::monitorenter, inc_held_monitor_count after backing from slowpath
|
||||||
|
// will be skipped. Solution is
|
||||||
|
// 1. Increase only in fastpath
|
||||||
|
// 2. Runtime1::monitorenter increase count after locking
|
||||||
|
#ifndef _LP64
|
||||||
|
Register thread = rsi;
|
||||||
|
__ push(thread);
|
||||||
|
__ get_thread(thread);
|
||||||
|
#else
|
||||||
|
Register thread = r15_thread;
|
||||||
|
#endif
|
||||||
|
__ inc_held_monitor_count(thread);
|
||||||
|
#ifndef _LP64
|
||||||
|
__ pop(thread);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
__ bind(*op->stub()->continuation());
|
__ bind(*op->stub()->continuation());
|
||||||
|
if (op->code() == lir_unlock) {
|
||||||
|
// unlock in slowpath is JRT_Leaf stub, no deoptimization can happen
|
||||||
|
#ifndef _LP64
|
||||||
|
Register thread = rsi;
|
||||||
|
__ push(thread);
|
||||||
|
__ get_thread(thread);
|
||||||
|
#else
|
||||||
|
Register thread = r15_thread;
|
||||||
|
#endif
|
||||||
|
__ dec_held_monitor_count(thread);
|
||||||
|
#ifndef _LP64
|
||||||
|
__ pop(thread);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
|
void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
|
||||||
@ -3868,6 +3903,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* arg
|
|||||||
if (info != NULL) {
|
if (info != NULL) {
|
||||||
add_call_info_here(info);
|
add_call_info_here(info);
|
||||||
}
|
}
|
||||||
|
__ post_call_nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -336,6 +336,17 @@ void LIRGenerator::do_MonitorExit(MonitorExit* x) {
|
|||||||
monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no());
|
monitor_exit(obj_temp, lock, syncTempOpr(), LIR_OprFact::illegalOpr, x->monitor_no());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LIRGenerator::do_continuation_doYield(Intrinsic* x) {
|
||||||
|
BasicTypeList signature(0);
|
||||||
|
CallingConvention* cc = frame_map()->java_calling_convention(&signature, true);
|
||||||
|
|
||||||
|
const LIR_Opr result_reg = result_register_for(x->type());
|
||||||
|
address entry = StubRoutines::cont_doYield();
|
||||||
|
LIR_Opr result = rlock_result(x);
|
||||||
|
CodeEmitInfo* info = state_for(x, x->state());
|
||||||
|
__ call_runtime(entry, LIR_OprFact::illegalOpr, result_reg, cc->args(), info);
|
||||||
|
__ move(result_reg, result);
|
||||||
|
}
|
||||||
|
|
||||||
// _ineg, _lneg, _fneg, _dneg
|
// _ineg, _lneg, _fneg, _dneg
|
||||||
void LIRGenerator::do_NegateOp(NegateOp* x) {
|
void LIRGenerator::do_NegateOp(NegateOp* x) {
|
||||||
@ -362,7 +373,6 @@ void LIRGenerator::do_NegateOp(NegateOp* x) {
|
|||||||
set_result(x, round_item(reg));
|
set_result(x, round_item(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// for _fadd, _fmul, _fsub, _fdiv, _frem
|
// for _fadd, _fmul, _fsub, _fdiv, _frem
|
||||||
// _dadd, _dmul, _dsub, _ddiv, _drem
|
// _dadd, _dmul, _dsub, _ddiv, _drem
|
||||||
void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
|
void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
|
||||||
|
50
src/hotspot/cpu/x86/continuationEntry_x86.inline.hpp
Normal file
50
src/hotspot/cpu/x86/continuationEntry_x86.inline.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_X86_CONTINUATIONENTRY_X86_INLINE_HPP
|
||||||
|
#define CPU_X86_CONTINUATIONENTRY_X86_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationEntry.hpp"
|
||||||
|
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
#include "utilities/macros.hpp"
|
||||||
|
|
||||||
|
inline frame ContinuationEntry::to_frame() const {
|
||||||
|
static CodeBlob* cb = CodeCache::find_blob_fast(entry_pc());
|
||||||
|
assert(cb != nullptr, "");
|
||||||
|
assert(cb->as_compiled_method()->method()->is_continuation_enter_intrinsic(), "");
|
||||||
|
return frame(entry_sp(), entry_sp(), entry_fp(), entry_pc(), cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationEntry::entry_fp() const {
|
||||||
|
return (intptr_t*)((address)this + size());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationEntry::update_register_map(RegisterMap* map) const {
|
||||||
|
intptr_t** fp = (intptr_t**)(bottom_sender_sp() - frame::sender_sp_offset);
|
||||||
|
frame::update_map_with_saved_link(map, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_X86_CONTINUATIONENTRY_X86_INLINE_HPP
|
289
src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp
Normal file
289
src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_X86_CONTINUATIONFREEZETHAW_X86_INLINE_HPP
|
||||||
|
#define CPU_X86_CONTINUATIONFREEZETHAW_X86_INLINE_HPP
|
||||||
|
|
||||||
|
#include "code/codeBlob.inline.hpp"
|
||||||
|
#include "oops/stackChunkOop.inline.hpp"
|
||||||
|
#include "runtime/frame.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
|
||||||
|
inline void patch_callee_link(const frame& f, intptr_t* fp) {
|
||||||
|
*ContinuationHelper::Frame::callee_link_address(f) = fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void patch_callee_link_relative(const frame& f, intptr_t* fp) {
|
||||||
|
intptr_t* la = (intptr_t*)ContinuationHelper::Frame::callee_link_address(f);
|
||||||
|
intptr_t new_value = fp - la;
|
||||||
|
*la = new_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////// Freeze
|
||||||
|
|
||||||
|
// Fast path
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
|
||||||
|
// copy the spilled rbp from the heap to the stack
|
||||||
|
*(frame_sp - frame::sender_sp_offset) = *(heap_sp - frame::sender_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slow path
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline frame FreezeBase::sender(const frame& f) {
|
||||||
|
assert(FKind::is_instance(f), "");
|
||||||
|
if (FKind::interpreted) {
|
||||||
|
return frame(f.sender_sp(), f.interpreter_frame_sender_sp(), f.link(), f.sender_pc());
|
||||||
|
}
|
||||||
|
intptr_t** link_addr = link_address<FKind>(f);
|
||||||
|
|
||||||
|
intptr_t* sender_sp = (intptr_t*)(link_addr + frame::sender_sp_offset); // f.unextended_sp() + (fsize/wordSize); //
|
||||||
|
address sender_pc = (address) *(sender_sp-1);
|
||||||
|
assert(sender_sp != f.sp(), "must have changed");
|
||||||
|
|
||||||
|
int slot = 0;
|
||||||
|
CodeBlob* sender_cb = CodeCache::find_blob_and_oopmap(sender_pc, slot);
|
||||||
|
return sender_cb != nullptr
|
||||||
|
? frame(sender_sp, sender_sp, *link_addr, sender_pc, sender_cb,
|
||||||
|
slot == -1 ? nullptr : sender_cb->oop_map_for_slot(slot, sender_pc), false)
|
||||||
|
: frame(sender_sp, sender_sp, *link_addr, sender_pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
|
||||||
|
assert(FKind::is_instance(f), "");
|
||||||
|
assert(!caller.is_interpreted_frame()
|
||||||
|
|| caller.unextended_sp() == (intptr_t*)caller.at(frame::interpreter_frame_last_sp_offset), "");
|
||||||
|
|
||||||
|
intptr_t *sp, *fp; // sp is really our unextended_sp
|
||||||
|
if (FKind::interpreted) {
|
||||||
|
assert((intptr_t*)f.at(frame::interpreter_frame_last_sp_offset) == nullptr
|
||||||
|
|| f.unextended_sp() == (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset), "");
|
||||||
|
int locals = f.interpreter_frame_method()->max_locals();
|
||||||
|
// If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set
|
||||||
|
// the chunk's argsize in finalize_freeze and make room for it above the unextended_sp
|
||||||
|
bool overlap_caller = caller.is_interpreted_frame() || caller.is_empty();
|
||||||
|
fp = caller.unextended_sp() - (locals + frame::sender_sp_offset) + (overlap_caller ? ContinuationHelper::InterpretedFrame::stack_argsize(f) : 0);
|
||||||
|
sp = fp - (f.fp() - f.unextended_sp());
|
||||||
|
assert(sp <= fp, "");
|
||||||
|
assert(fp <= caller.unextended_sp(), "");
|
||||||
|
caller.set_sp(fp + frame::sender_sp_offset);
|
||||||
|
|
||||||
|
assert(_cont.tail()->is_in_chunk(sp), "");
|
||||||
|
|
||||||
|
frame hf(sp, sp, fp, f.pc(), nullptr, nullptr, true /* on_heap */);
|
||||||
|
*hf.addr_at(frame::interpreter_frame_locals_offset) = frame::sender_sp_offset + locals - 1;
|
||||||
|
return hf;
|
||||||
|
} else {
|
||||||
|
// We need to re-read fp out of the frame because it may be an oop and we might have
|
||||||
|
// had a safepoint in finalize_freeze, after constructing f.
|
||||||
|
fp = *(intptr_t**)(f.sp() - frame::sender_sp_offset);
|
||||||
|
|
||||||
|
int fsize = FKind::size(f);
|
||||||
|
sp = caller.unextended_sp() - fsize;
|
||||||
|
if (caller.is_interpreted_frame()) {
|
||||||
|
// If the caller is interpreted, our stackargs are not supposed to overlap with it
|
||||||
|
// so we make more room by moving sp down by argsize
|
||||||
|
int argsize = FKind::stack_argsize(f);
|
||||||
|
sp -= argsize;
|
||||||
|
}
|
||||||
|
caller.set_sp(sp + fsize);
|
||||||
|
|
||||||
|
assert(_cont.tail()->is_in_chunk(sp), "");
|
||||||
|
|
||||||
|
return frame(sp, sp, fp, f.pc(), nullptr, nullptr, true /* on_heap */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
|
||||||
|
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
|
||||||
|
intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset);
|
||||||
|
if (real_unextended_sp != nullptr) {
|
||||||
|
f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void relativize_one(intptr_t* const vfp, intptr_t* const hfp, int offset) {
|
||||||
|
assert(*(hfp + offset) == *(vfp + offset), "");
|
||||||
|
intptr_t* addr = hfp + offset;
|
||||||
|
intptr_t value = *(intptr_t**)addr - vfp;
|
||||||
|
*addr = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, const frame& hf) {
|
||||||
|
intptr_t* vfp = f.fp();
|
||||||
|
intptr_t* hfp = hf.fp();
|
||||||
|
assert(hfp == hf.unextended_sp() + (f.fp() - f.unextended_sp()), "");
|
||||||
|
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0)
|
||||||
|
|| (f.unextended_sp() == f.sp()), "");
|
||||||
|
assert(f.fp() > (intptr_t*)f.at(frame::interpreter_frame_initial_sp_offset), "");
|
||||||
|
|
||||||
|
// We compute the locals as below rather than relativize the value in the frame because then we can use the same
|
||||||
|
// code on AArch64, which has an added complication (see this method in continuation_aarch64.inline.hpp)
|
||||||
|
|
||||||
|
// at(frame::interpreter_frame_last_sp_offset) can be NULL at safepoint preempts
|
||||||
|
*hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp();
|
||||||
|
*hf.addr_at(frame::interpreter_frame_locals_offset) = frame::sender_sp_offset + f.interpreter_frame_method()->max_locals() - 1;
|
||||||
|
|
||||||
|
relativize_one(vfp, hfp, frame::interpreter_frame_initial_sp_offset); // == block_top == block_bottom
|
||||||
|
|
||||||
|
assert((hf.fp() - hf.unextended_sp()) == (f.fp() - f.unextended_sp()), "");
|
||||||
|
assert(hf.unextended_sp() == (intptr_t*)hf.at(frame::interpreter_frame_last_sp_offset), "");
|
||||||
|
assert(hf.unextended_sp() <= (intptr_t*)hf.at(frame::interpreter_frame_initial_sp_offset), "");
|
||||||
|
assert(hf.fp() > (intptr_t*)hf.at(frame::interpreter_frame_initial_sp_offset), "");
|
||||||
|
assert(hf.fp() <= (intptr_t*)hf.at(frame::interpreter_frame_locals_offset), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::set_top_frame_metadata_pd(const frame& hf) {
|
||||||
|
stackChunkOop chunk = _cont.tail();
|
||||||
|
assert(chunk->is_in_chunk(hf.sp() - 1), "");
|
||||||
|
assert(chunk->is_in_chunk(hf.sp() - frame::sender_sp_offset), "");
|
||||||
|
|
||||||
|
address frame_pc = hf.pc();
|
||||||
|
|
||||||
|
*(hf.sp() - 1) = (intptr_t)hf.pc();
|
||||||
|
|
||||||
|
intptr_t* fp_addr = hf.sp() - frame::sender_sp_offset;
|
||||||
|
*fp_addr = hf.is_interpreted_frame() ? (intptr_t)(hf.fp() - fp_addr)
|
||||||
|
: (intptr_t)hf.fp();
|
||||||
|
assert(frame_pc == ContinuationHelper::Frame::real_pc(hf), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
|
||||||
|
if (caller.is_interpreted_frame()) {
|
||||||
|
assert(!caller.is_empty(), "");
|
||||||
|
patch_callee_link_relative(caller, caller.fp());
|
||||||
|
} else {
|
||||||
|
// If we're the bottom-most frame frozen in this freeze, the caller might have stayed frozen in the chunk,
|
||||||
|
// and its oop-containing fp fixed. We've now just overwritten it, so we must patch it back to its value
|
||||||
|
// as read from the chunk.
|
||||||
|
patch_callee_link(caller, caller.fp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////// Thaw
|
||||||
|
|
||||||
|
// Fast path
|
||||||
|
|
||||||
|
inline void ThawBase::prefetch_chunk_pd(void* start, int size) {
|
||||||
|
size <<= LogBytesPerWord;
|
||||||
|
Prefetch::read(start, size);
|
||||||
|
Prefetch::read(start, size - 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThawBase::patch_chunk_pd(intptr_t* sp) {
|
||||||
|
intptr_t* fp = _cont.entryFP();
|
||||||
|
*(intptr_t**)(sp - frame::sender_sp_offset) = fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slow path
|
||||||
|
|
||||||
|
inline frame ThawBase::new_entry_frame() {
|
||||||
|
intptr_t* sp = _cont.entrySP();
|
||||||
|
return frame(sp, sp, _cont.entryFP(), _cont.entryPC()); // TODO PERF: This finds code blob and computes deopt state
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) {
|
||||||
|
assert(FKind::is_instance(hf), "");
|
||||||
|
// The values in the returned frame object will be written into the callee's stack in patch.
|
||||||
|
|
||||||
|
if (FKind::interpreted) {
|
||||||
|
intptr_t* heap_sp = hf.unextended_sp();
|
||||||
|
const int fsize = ContinuationHelper::InterpretedFrame::frame_bottom(hf) - hf.unextended_sp();
|
||||||
|
const int locals = hf.interpreter_frame_method()->max_locals();
|
||||||
|
intptr_t* frame_sp = caller.unextended_sp() - fsize;
|
||||||
|
intptr_t* fp = frame_sp + (hf.fp() - heap_sp);
|
||||||
|
DEBUG_ONLY(intptr_t* unextended_sp = fp + *hf.addr_at(frame::interpreter_frame_last_sp_offset);)
|
||||||
|
assert(frame_sp == unextended_sp, "");
|
||||||
|
caller.set_sp(fp + frame::sender_sp_offset);
|
||||||
|
frame f(frame_sp, frame_sp, fp, hf.pc());
|
||||||
|
// it's set again later in set_interpreter_frame_bottom, but we need to set the locals now so that
|
||||||
|
// we could call ContinuationHelper::InterpretedFrame::frame_bottom
|
||||||
|
intptr_t offset = *hf.addr_at(frame::interpreter_frame_locals_offset);
|
||||||
|
assert((int)offset == frame::sender_sp_offset + locals - 1, "");
|
||||||
|
// derelativize locals
|
||||||
|
*(intptr_t**)f.addr_at(frame::interpreter_frame_locals_offset) = fp + offset;
|
||||||
|
return f;
|
||||||
|
} else {
|
||||||
|
int fsize = FKind::size(hf);
|
||||||
|
intptr_t* frame_sp = caller.unextended_sp() - fsize;
|
||||||
|
if (bottom || caller.is_interpreted_frame()) {
|
||||||
|
int argsize = hf.compiled_frame_stack_argsize();
|
||||||
|
|
||||||
|
fsize += argsize;
|
||||||
|
frame_sp -= argsize;
|
||||||
|
caller.set_sp(caller.sp() - argsize);
|
||||||
|
assert(caller.sp() == frame_sp + (fsize-argsize), "");
|
||||||
|
|
||||||
|
frame_sp = align(hf, frame_sp, caller, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(hf.cb() != nullptr, "");
|
||||||
|
assert(hf.oop_map() != nullptr, "");
|
||||||
|
intptr_t* fp;
|
||||||
|
if (PreserveFramePointer) {
|
||||||
|
// we need to recreate a "real" frame pointer, pointing into the stack
|
||||||
|
fp = frame_sp + FKind::size(hf) - frame::sender_sp_offset;
|
||||||
|
} else {
|
||||||
|
// we need to re-read fp because it may be an oop and we might have fixed the frame.
|
||||||
|
fp = *(intptr_t**)(hf.sp() - frame::sender_sp_offset);
|
||||||
|
}
|
||||||
|
return frame(frame_sp, frame_sp, fp, hf.pc(), hf.cb(), hf.oop_map(), false); // TODO PERF : this computes deopt state; is it necessary?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& caller, bool bottom) {
|
||||||
|
#ifdef _LP64
|
||||||
|
if (((intptr_t)frame_sp & 0xf) != 0) {
|
||||||
|
assert(caller.is_interpreted_frame() || (bottom && hf.compiled_frame_stack_argsize() % 2 != 0), "");
|
||||||
|
frame_sp--;
|
||||||
|
caller.set_sp(caller.sp() - 1);
|
||||||
|
}
|
||||||
|
assert(is_aligned(frame_sp, frame::frame_alignment), "");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return frame_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::patch_pd(frame& f, const frame& caller) {
|
||||||
|
patch_callee_link(caller, caller.fp());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void derelativize_one(intptr_t* const fp, int offset) {
|
||||||
|
intptr_t* addr = fp + offset;
|
||||||
|
*addr = (intptr_t)(fp + *addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
|
||||||
|
intptr_t* vfp = f.fp();
|
||||||
|
|
||||||
|
derelativize_one(vfp, frame::interpreter_frame_last_sp_offset);
|
||||||
|
derelativize_one(vfp, frame::interpreter_frame_initial_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ThawBase::set_interpreter_frame_bottom(const frame& f, intptr_t* bottom) {
|
||||||
|
*(intptr_t**)f.addr_at(frame::interpreter_frame_locals_offset) = bottom - 1;
|
||||||
|
}
|
||||||
|
#endif // CPU_X86_CONTINUATIONFREEZE_THAW_X86_INLINE_HPP
|
139
src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp
Normal file
139
src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_X86_CONTINUATIONHELPER_X86_INLINE_HPP
|
||||||
|
#define CPU_X86_CONTINUATIONHELPER_X86_INLINE_HPP
|
||||||
|
|
||||||
|
#include "runtime/continuationHelper.hpp"
|
||||||
|
|
||||||
|
#include "runtime/continuationEntry.inline.hpp"
|
||||||
|
#include "runtime/frame.inline.hpp"
|
||||||
|
#include "runtime/registerMap.hpp"
|
||||||
|
#include "utilities/macros.hpp"
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
static inline intptr_t** link_address(const frame& f) {
|
||||||
|
assert(FKind::is_instance(f), "");
|
||||||
|
return FKind::interpreted
|
||||||
|
? (intptr_t**)(f.fp() + frame::link_offset)
|
||||||
|
: (intptr_t**)(f.unextended_sp() + f.cb()->frame_size() - frame::sender_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ContinuationHelper::frame_align_words(int size) {
|
||||||
|
#ifdef _LP64
|
||||||
|
return size & 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::frame_align_pointer(intptr_t* sp) {
|
||||||
|
#ifdef _LP64
|
||||||
|
sp = align_down(sp, frame::frame_alignment);
|
||||||
|
#endif
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FKind>
|
||||||
|
inline void ContinuationHelper::update_register_map(const frame& f, RegisterMap* map) {
|
||||||
|
frame::update_map_with_saved_link(map, link_address<FKind>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::update_register_map_with_callee(const frame& f, RegisterMap* map) {
|
||||||
|
frame::update_map_with_saved_link(map, ContinuationHelper::Frame::callee_link_address(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::push_pd(const frame& f) {
|
||||||
|
*(intptr_t**)(f.sp() - frame::sender_sp_offset) = f.fp();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::set_anchor_to_entry_pd(JavaFrameAnchor* anchor, ContinuationEntry* entry) {
|
||||||
|
anchor->set_last_Java_fp(entry->entry_fp());
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
inline void ContinuationHelper::set_anchor_pd(JavaFrameAnchor* anchor, intptr_t* sp) {
|
||||||
|
intptr_t* fp = *(intptr_t**)(sp - frame::sender_sp_offset);
|
||||||
|
anchor->set_last_Java_fp(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ContinuationHelper::Frame::assert_frame_laid_out(frame f) {
|
||||||
|
intptr_t* sp = f.sp();
|
||||||
|
address pc = *(address*)(sp - frame::sender_sp_ret_address_offset());
|
||||||
|
intptr_t* fp = *(intptr_t**)(sp - frame::sender_sp_offset);
|
||||||
|
assert(f.raw_pc() == pc, "f.ra_pc: " INTPTR_FORMAT " actual: " INTPTR_FORMAT, p2i(f.raw_pc()), p2i(pc));
|
||||||
|
assert(f.fp() == fp, "f.fp: " INTPTR_FORMAT " actual: " INTPTR_FORMAT, p2i(f.fp()), p2i(fp));
|
||||||
|
return f.raw_pc() == pc && f.fp() == fp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline intptr_t** ContinuationHelper::Frame::callee_link_address(const frame& f) {
|
||||||
|
return (intptr_t**)(f.sp() - frame::sender_sp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::Frame::return_pc_address(const frame& f) {
|
||||||
|
return (address*)(f.real_fp() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address* ContinuationHelper::InterpretedFrame::return_pc_address(const frame& f) {
|
||||||
|
return (address*)(f.fp() + frame::return_addr_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::InterpretedFrame::patch_sender_sp(frame& f, intptr_t* sp) {
|
||||||
|
assert(f.is_interpreted_frame(), "");
|
||||||
|
intptr_t* la = f.addr_at(frame::interpreter_frame_sender_sp_offset);
|
||||||
|
*la = f.is_heap_frame() ? (intptr_t)(sp - f.fp()) : (intptr_t)sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline address ContinuationHelper::Frame::real_pc(const frame& f) {
|
||||||
|
address* pc_addr = &(((address*) f.sp())[-1]);
|
||||||
|
return *pc_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
|
||||||
|
address* pc_addr = &(((address*) f.sp())[-1]);
|
||||||
|
*pc_addr = pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, InterpreterOopMap* mask) { // inclusive; this will be copied with the frame
|
||||||
|
// interpreter_frame_last_sp_offset, points to unextended_sp includes arguments in the frame
|
||||||
|
// interpreter_frame_initial_sp_offset excludes expression stack slots
|
||||||
|
int expression_stack_sz = expression_stack_size(f, mask);
|
||||||
|
intptr_t* res = *(intptr_t**)f.addr_at(frame::interpreter_frame_initial_sp_offset) - expression_stack_sz;
|
||||||
|
assert(res == (intptr_t*)f.interpreter_frame_monitor_end() - expression_stack_sz, "");
|
||||||
|
assert(res >= f.unextended_sp(),
|
||||||
|
"res: " INTPTR_FORMAT " initial_sp: " INTPTR_FORMAT " last_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " expression_stack_size: %d",
|
||||||
|
p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at(frame::interpreter_frame_last_sp_offset), p2i(f.unextended_sp()), expression_stack_sz);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_bottom(const frame& f) { // exclusive; this will not be copied with the frame
|
||||||
|
return (intptr_t*)f.at(frame::interpreter_frame_locals_offset) + 1; // exclusive, so we add 1 word
|
||||||
|
}
|
||||||
|
|
||||||
|
inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) {
|
||||||
|
return f.unextended_sp() + (callee_interpreted ? callee_argsize : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_X86_CONTINUATIONHELPER_X86_INLINE_HPP
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -31,6 +31,7 @@
|
|||||||
#include "oops/method.hpp"
|
#include "oops/method.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/methodHandles.hpp"
|
#include "prims/methodHandles.hpp"
|
||||||
|
#include "runtime/continuation.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
@ -54,6 +55,9 @@ void RegisterMap::check_location_valid() {
|
|||||||
// Profiling/safepoint support
|
// Profiling/safepoint support
|
||||||
|
|
||||||
bool frame::safe_for_sender(JavaThread *thread) {
|
bool frame::safe_for_sender(JavaThread *thread) {
|
||||||
|
if (is_heap_frame()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
address sp = (address)_sp;
|
address sp = (address)_sp;
|
||||||
address fp = (address)_fp;
|
address fp = (address)_fp;
|
||||||
address unextended_sp = (address)_unextended_sp;
|
address unextended_sp = (address)_unextended_sp;
|
||||||
@ -146,6 +150,12 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
|||||||
saved_fp = (intptr_t*) *(sender_sp - frame::sender_sp_offset);
|
saved_fp = (intptr_t*) *(sender_sp - frame::sender_sp_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Continuation::is_return_barrier_entry(sender_pc)) {
|
||||||
|
// If our sender_pc is the return barrier, then our "real" sender is the continuation entry
|
||||||
|
frame s = Continuation::continuation_bottom_sender(thread, *this, sender_sp);
|
||||||
|
sender_sp = s.sp();
|
||||||
|
sender_pc = s.pc();
|
||||||
|
}
|
||||||
|
|
||||||
// If the potential sender is the interpreter then we can do some more checking
|
// If the potential sender is the interpreter then we can do some more checking
|
||||||
if (Interpreter::contains(sender_pc)) {
|
if (Interpreter::contains(sender_pc)) {
|
||||||
@ -261,32 +271,39 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
|||||||
void frame::patch_pc(Thread* thread, address pc) {
|
void frame::patch_pc(Thread* thread, address pc) {
|
||||||
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
||||||
address* pc_addr = &(((address*) sp())[-1]);
|
address* pc_addr = &(((address*) sp())[-1]);
|
||||||
|
|
||||||
if (TracePcPatching) {
|
if (TracePcPatching) {
|
||||||
tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
|
tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
|
||||||
p2i(pc_addr), p2i(*pc_addr), p2i(pc));
|
p2i(pc_addr), p2i(*pc_addr), p2i(pc));
|
||||||
}
|
}
|
||||||
// Either the return address is the original one or we are going to
|
// Either the return address is the original one or we are going to
|
||||||
// patch in the same address that's already there.
|
// patch in the same address that's already there.
|
||||||
assert(_pc == *pc_addr || pc == *pc_addr, "must be");
|
|
||||||
|
assert(!Continuation::is_return_barrier_entry(*pc_addr), "return barrier");
|
||||||
|
|
||||||
|
assert(_pc == *pc_addr || pc == *pc_addr || *pc_addr == 0, "");
|
||||||
|
DEBUG_ONLY(address old_pc = _pc;)
|
||||||
*pc_addr = pc;
|
*pc_addr = pc;
|
||||||
|
_pc = pc; // must be set before call to get_deopt_original_pc
|
||||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||||
if (original_pc != NULL) {
|
if (original_pc != NULL) {
|
||||||
assert(original_pc == _pc, "expected original PC to be stored before patching");
|
assert(original_pc == old_pc, "expected original PC to be stored before patching");
|
||||||
_deopt_state = is_deoptimized;
|
_deopt_state = is_deoptimized;
|
||||||
// leave _pc as is
|
_pc = original_pc;
|
||||||
} else {
|
} else {
|
||||||
_deopt_state = not_deoptimized;
|
_deopt_state = not_deoptimized;
|
||||||
_pc = pc;
|
|
||||||
}
|
}
|
||||||
}
|
assert(!is_compiled_frame() || !_cb->as_compiled_method()->is_deopt_entry(_pc), "must be");
|
||||||
|
|
||||||
bool frame::is_interpreted_frame() const {
|
#ifdef ASSERT
|
||||||
return Interpreter::contains(pc());
|
{
|
||||||
}
|
frame f(this->sp(), this->unextended_sp(), this->fp(), pc);
|
||||||
|
assert(f.is_deoptimized_frame() == this->is_deoptimized_frame() && f.pc() == this->pc() && f.raw_pc() == this->raw_pc(),
|
||||||
int frame::frame_size(RegisterMap* map) const {
|
"must be (f.is_deoptimized_frame(): %d this->is_deoptimized_frame(): %d "
|
||||||
frame sender = this->sender(map);
|
"f.pc(): " INTPTR_FORMAT " this->pc(): " INTPTR_FORMAT " f.raw_pc(): " INTPTR_FORMAT " this->raw_pc(): " INTPTR_FORMAT ")",
|
||||||
return sender.sp() - sp();
|
f.is_deoptimized_frame(), this->is_deoptimized_frame(), p2i(f.pc()), p2i(this->pc()), p2i(f.raw_pc()), p2i(this->raw_pc()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr_t* frame::entry_frame_argument_at(int offset) const {
|
intptr_t* frame::entry_frame_argument_at(int offset) const {
|
||||||
@ -316,10 +333,10 @@ BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
||||||
BasicObjectLock* result = (BasicObjectLock*) *addr_at(interpreter_frame_monitor_block_top_offset);
|
BasicObjectLock* result = (BasicObjectLock*) at(interpreter_frame_monitor_block_top_offset);
|
||||||
// make sure the pointer points inside the frame
|
// make sure the pointer points inside the frame
|
||||||
assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer");
|
assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer");
|
||||||
assert((intptr_t*) result < fp(), "monitor end should be strictly below the frame pointer");
|
assert((intptr_t*) result < fp(), "monitor end should be strictly below the frame pointer: result: " INTPTR_FORMAT " fp: " INTPTR_FORMAT, p2i(result), p2i(fp()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +414,7 @@ void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp
|
|||||||
|
|
||||||
address original_pc = nm->get_original_pc(&fr);
|
address original_pc = nm->get_original_pc(&fr);
|
||||||
assert(nm->insts_contains_inclusive(original_pc),
|
assert(nm->insts_contains_inclusive(original_pc),
|
||||||
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
|
"original PC must be in the main code section of the the compiled method (or must be immediately following it) original_pc: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " name: %s", p2i(original_pc), p2i(unextended_sp), nm->name());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -422,30 +439,6 @@ void frame::adjust_unextended_sp() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// frame::update_map_with_saved_link
|
|
||||||
void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) {
|
|
||||||
// The interpreter and compiler(s) always save EBP/RBP in a known
|
|
||||||
// location on entry. We must record where that location is
|
|
||||||
// so this if EBP/RBP was live on callout from c2 we can find
|
|
||||||
// the saved copy no matter what it called.
|
|
||||||
|
|
||||||
// Since the interpreter always saves EBP/RBP if we record where it is then
|
|
||||||
// we don't have to always save EBP/RBP on entry and exit to c2 compiled
|
|
||||||
// code, on entry will be enough.
|
|
||||||
map->set_location(rbp->as_VMReg(), (address) link_addr);
|
|
||||||
#ifdef AMD64
|
|
||||||
// this is weird "H" ought to be at a higher address however the
|
|
||||||
// oopMaps seems to have the "H" regs at the same address and the
|
|
||||||
// vanilla register.
|
|
||||||
// XXXX make this go away
|
|
||||||
if (true) {
|
|
||||||
map->set_location(rbp->as_VMReg()->next(), (address) link_addr);
|
|
||||||
}
|
|
||||||
#endif // AMD64
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// frame::sender_for_interpreter_frame
|
// frame::sender_for_interpreter_frame
|
||||||
frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
||||||
@ -455,6 +448,7 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
|||||||
|
|
||||||
// This is the sp before any possible extension (adapter/locals).
|
// This is the sp before any possible extension (adapter/locals).
|
||||||
intptr_t* unextended_sp = interpreter_frame_sender_sp();
|
intptr_t* unextended_sp = interpreter_frame_sender_sp();
|
||||||
|
intptr_t* sender_fp = link();
|
||||||
|
|
||||||
#if COMPILER2_OR_JVMCI
|
#if COMPILER2_OR_JVMCI
|
||||||
if (map->update_map()) {
|
if (map->update_map()) {
|
||||||
@ -462,75 +456,17 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
|||||||
}
|
}
|
||||||
#endif // COMPILER2_OR_JVMCI
|
#endif // COMPILER2_OR_JVMCI
|
||||||
|
|
||||||
return frame(sender_sp, unextended_sp, link(), sender_pc());
|
address sender_pc = this->sender_pc();
|
||||||
}
|
|
||||||
|
|
||||||
|
if (Continuation::is_return_barrier_entry(sender_pc)) {
|
||||||
//------------------------------------------------------------------------------
|
if (map->walk_cont()) { // about to walk into an h-stack
|
||||||
// frame::sender_for_compiled_frame
|
return Continuation::top_frame(*this, map);
|
||||||
frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
} else {
|
||||||
assert(map != NULL, "map must be set");
|
return Continuation::continuation_bottom_sender(map->thread(), *this, sender_sp);
|
||||||
|
}
|
||||||
// frame owned by optimizing compiler
|
|
||||||
assert(_cb->frame_size() >= 0, "must have non-zero frame size");
|
|
||||||
intptr_t* sender_sp = unextended_sp() + _cb->frame_size();
|
|
||||||
intptr_t* unextended_sp = sender_sp;
|
|
||||||
|
|
||||||
// On Intel the return_address is always the word on the stack
|
|
||||||
address sender_pc = (address) *(sender_sp-1);
|
|
||||||
|
|
||||||
// This is the saved value of EBP which may or may not really be an FP.
|
|
||||||
// It is only an FP if the sender is an interpreter frame (or C1?).
|
|
||||||
intptr_t** saved_fp_addr = (intptr_t**) (sender_sp - frame::sender_sp_offset);
|
|
||||||
|
|
||||||
if (map->update_map()) {
|
|
||||||
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
|
||||||
// For C1, the runtime stub might not have oop maps, so set this flag
|
|
||||||
// outside of update_register_map.
|
|
||||||
map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
|
|
||||||
if (_cb->oop_maps() != NULL) {
|
|
||||||
OopMapSet::update_register_map(this, map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since the prolog does the save and restore of EBP there is no oopmap
|
return frame(sender_sp, unextended_sp, sender_fp, sender_pc);
|
||||||
// for it so we must fill in its location as if there was an oopmap entry
|
|
||||||
// since if our caller was compiled code there could be live jvm state in it.
|
|
||||||
update_map_with_saved_link(map, saved_fp_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(sender_sp != sp(), "must have changed");
|
|
||||||
return frame(sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// frame::sender_raw
|
|
||||||
frame frame::sender_raw(RegisterMap* map) const {
|
|
||||||
// Default is we done have to follow them. The sender_for_xxx will
|
|
||||||
// update it accordingly
|
|
||||||
map->set_include_argument_oops(false);
|
|
||||||
|
|
||||||
if (is_entry_frame()) return sender_for_entry_frame(map);
|
|
||||||
if (is_optimized_entry_frame()) return sender_for_optimized_entry_frame(map);
|
|
||||||
if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
|
|
||||||
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
|
|
||||||
|
|
||||||
if (_cb != NULL) {
|
|
||||||
return sender_for_compiled_frame(map);
|
|
||||||
}
|
|
||||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
|
||||||
// methods that exists in the core system.
|
|
||||||
return frame(sender_sp(), link(), sender_pc());
|
|
||||||
}
|
|
||||||
|
|
||||||
frame frame::sender(RegisterMap* map) const {
|
|
||||||
frame result = sender_raw(map);
|
|
||||||
|
|
||||||
if (map->process_frames()) {
|
|
||||||
StackWatermarkSet::on_iteration(map->thread(), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
||||||
@ -651,7 +587,6 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result)
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
||||||
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
|
||||||
return &interpreter_frame_tos_address()[index];
|
return &interpreter_frame_tos_address()[index];
|
||||||
@ -660,7 +595,7 @@ intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
|||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
|
||||||
#define DESCRIBE_FP_OFFSET(name) \
|
#define DESCRIBE_FP_OFFSET(name) \
|
||||||
values.describe(frame_no, fp() + frame::name##_offset, #name)
|
values.describe(frame_no, fp() + frame::name##_offset, #name, 1)
|
||||||
|
|
||||||
void frame::describe_pd(FrameValues& values, int frame_no) {
|
void frame::describe_pd(FrameValues& values, int frame_no) {
|
||||||
if (is_interpreted_frame()) {
|
if (is_interpreted_frame()) {
|
||||||
@ -683,7 +618,16 @@ void frame::describe_pd(FrameValues& values, int frame_no) {
|
|||||||
}
|
}
|
||||||
#endif // AMD64
|
#endif // AMD64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intptr_t* ret_pc_loc = sp() - return_addr_offset;
|
||||||
|
address ret_pc = *(address*)ret_pc_loc;
|
||||||
|
if (Continuation::is_return_barrier_entry(ret_pc))
|
||||||
|
values.describe(frame_no, ret_pc_loc, "return address (return barrier)");
|
||||||
|
else
|
||||||
|
values.describe(frame_no, ret_pc_loc, err_msg("return address for #%d", frame_no));
|
||||||
|
values.describe(frame_no, sp() - sender_sp_offset, err_msg("saved fp for #%d", frame_no), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !PRODUCT
|
#endif // !PRODUCT
|
||||||
|
|
||||||
intptr_t *frame::initial_deoptimization_info() {
|
intptr_t *frame::initial_deoptimization_info() {
|
||||||
@ -691,19 +635,6 @@ intptr_t *frame::initial_deoptimization_info() {
|
|||||||
return fp();
|
return fp();
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr_t* frame::real_fp() const {
|
|
||||||
if (_cb != NULL) {
|
|
||||||
// use the frame size if valid
|
|
||||||
int size = _cb->frame_size();
|
|
||||||
if (size > 0) {
|
|
||||||
return unextended_sp() + size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else rely on fp()
|
|
||||||
assert(! is_compiled_frame(), "unknown compiled frame size");
|
|
||||||
return fp();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
// This is a generic constructor which is only used by pns() in debug.cpp.
|
// This is a generic constructor which is only used by pns() in debug.cpp.
|
||||||
frame::frame(void* sp, void* fp, void* pc) {
|
frame::frame(void* sp, void* fp, void* pc) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user