Commit 9b243c9a authored by Junliang Yan's avatar Junliang Yan Committed by V8 LUCI CQ

s390x: [baseline] port Generate_BaselineOutOfLinePrologue

Change-Id: I8cd279059800567a81d8586944c8ed4c0ef9fa92
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3279101Reviewed-by: 's avatarMilad Fa <mfarazma@redhat.com>
Commit-Queue: Junliang Yan <junyan@redhat.com>
Cr-Commit-Position: refs/heads/main@{#77879}
parent e9c531b7
......@@ -1345,6 +1345,171 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
TailCallOptimizedCodeSlot(masm, optimized_code_entry, r8);
}
// Read off the optimization state in the feedback vector and check if there
// is optimized code or a optimization marker that needs to be processed.
static void LoadOptimizationStateAndJumpIfNeedsProcessing(
MacroAssembler* masm, Register optimization_state, Register feedback_vector,
Label* has_optimized_code_or_marker) {
ASM_CODE_COMMENT(masm);
USE(LoadOptimizationStateAndJumpIfNeedsProcessing);
DCHECK(!AreAliased(optimization_state, feedback_vector));
__ LoadU32(optimization_state,
FieldMemOperand(feedback_vector, FeedbackVector::kFlagsOffset));
CHECK(
is_uint16(FeedbackVector::kHasOptimizedCodeOrCompileOptimizedMarkerMask));
__ tmll(
optimization_state,
Operand(FeedbackVector::kHasOptimizedCodeOrCompileOptimizedMarkerMask));
__ b(Condition(7), has_optimized_code_or_marker);
}
#if ENABLE_SPARKPLUG
// static
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
// UseScratchRegisterScope temps(masm);
// Need a few extra registers
// temps.Include(r8, r9);
auto descriptor =
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
Register closure = descriptor.GetRegisterParameter(
BaselineOutOfLinePrologueDescriptor::kClosure);
// Load the feedback vector from the closure.
Register feedback_vector = ip;
__ LoadTaggedPointerField(
feedback_vector,
FieldMemOperand(closure, JSFunction::kFeedbackCellOffset));
__ LoadTaggedPointerField(
feedback_vector, FieldMemOperand(feedback_vector, Cell::kValueOffset));
if (FLAG_debug_code) {
Register scratch = r1;
__ CompareObjectType(feedback_vector, scratch, scratch,
FEEDBACK_VECTOR_TYPE);
__ Assert(eq, AbortReason::kExpectedFeedbackVector);
}
// Check for an optimization marker.
Label has_optimized_code_or_marker;
Register optimization_state = r9;
{
LoadOptimizationStateAndJumpIfNeedsProcessing(
masm, optimization_state, feedback_vector,
&has_optimized_code_or_marker);
}
// Increment invocation count for the function.
{
Register invocation_count = r1;
__ LoadU64(invocation_count,
FieldMemOperand(feedback_vector,
FeedbackVector::kInvocationCountOffset));
__ AddU64(invocation_count, Operand(1));
__ StoreU64(invocation_count,
FieldMemOperand(feedback_vector,
FeedbackVector::kInvocationCountOffset));
}
FrameScope frame_scope(masm, StackFrame::MANUAL);
{
ASM_CODE_COMMENT_STRING(masm, "Frame Setup");
// Normally the first thing we'd do here is Push(lr, fp), but we already
// entered the frame in BaselineCompiler::Prologue, as we had to use the
// value lr before the call to this BaselineOutOfLinePrologue builtin.
Register callee_context = descriptor.GetRegisterParameter(
BaselineOutOfLinePrologueDescriptor::kCalleeContext);
Register callee_js_function = descriptor.GetRegisterParameter(
BaselineOutOfLinePrologueDescriptor::kClosure);
__ Push(callee_context, callee_js_function);
DCHECK_EQ(callee_js_function, kJavaScriptCallTargetRegister);
DCHECK_EQ(callee_js_function, kJSFunctionRegister);
Register argc = descriptor.GetRegisterParameter(
BaselineOutOfLinePrologueDescriptor::kJavaScriptCallArgCount);
// We'll use the bytecode for both code age/OSR resetting, and pushing onto
// the frame, so load it into a register.
Register bytecodeArray = descriptor.GetRegisterParameter(
BaselineOutOfLinePrologueDescriptor::kInterpreterBytecodeArray);
// Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset
// are 8-bit fields next to each other, so we could just optimize by writing
// a 16-bit. These static asserts guard our assumption is valid.
STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset ==
BytecodeArray::kOsrLoopNestingLevelOffset + kCharSize);
STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0);
{
Register scratch = r0;
__ mov(scratch, Operand(0));
__ StoreU16(scratch,
FieldMemOperand(bytecodeArray,
BytecodeArray::kOsrLoopNestingLevelOffset));
}
__ Push(argc, bytecodeArray);
// Baseline code frames store the feedback vector where interpreter would
// store the bytecode offset.
if (FLAG_debug_code) {
Register scratch = r1;
__ CompareObjectType(feedback_vector, scratch, scratch,
FEEDBACK_VECTOR_TYPE);
__ Assert(eq, AbortReason::kExpectedFeedbackVector);
}
__ Push(feedback_vector);
}
Label call_stack_guard;
Register frame_size = descriptor.GetRegisterParameter(
BaselineOutOfLinePrologueDescriptor::kStackFrameSize);
{
ASM_CODE_COMMENT_STRING(masm, "Stack/interrupt check");
// Stack check. This folds the checks for both the interrupt stack limit
// check and the real stack limit into one by just checking for the
// interrupt limit. The interrupt limit is either equal to the real stack
// limit or tighter. By ensuring we have space until that limit after
// building the frame we can quickly precheck both at once.
Register sp_minus_frame_size = r1;
Register interrupt_limit = r0;
__ SubS64(sp_minus_frame_size, sp, frame_size);
__ LoadStackLimit(interrupt_limit, StackLimitKind::kInterruptStackLimit);
__ CmpU64(sp_minus_frame_size, interrupt_limit);
__ blt(&call_stack_guard);
}
// Do "fast" return to the caller pc in lr.
__ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
__ Ret();
__ bind(&has_optimized_code_or_marker);
{
ASM_CODE_COMMENT_STRING(masm, "Optimized marker check");
// Drop the frame created by the baseline call.
__ Pop(r14, fp);
MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(masm, optimization_state,
feedback_vector);
__ Trap();
}
__ bind(&call_stack_guard);
{
ASM_CODE_COMMENT_STRING(masm, "Stack/interrupt call");
FrameScope frame_scope(masm, StackFrame::INTERNAL);
// Save incoming new target or generator
__ Push(kJavaScriptCallNewTargetRegister);
__ SmiTag(frame_size);
__ Push(frame_size);
__ CallRuntime(Runtime::kStackGuardWithGap);
__ Pop(kJavaScriptCallNewTargetRegister);
}
__ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
__ Ret();
}
#endif
// Generate code for entering a JS function with the interpreter.
// On entry to the function the receiver and arguments have been pushed on the
// stack left to right.
......
......@@ -5553,6 +5553,22 @@ STORE_LANE_LIST(STORE_LANE)
#undef CAN_LOAD_STORE_REVERSE
#undef IS_BIG_ENDIAN
void MacroAssembler::LoadStackLimit(Register destination, StackLimitKind kind) {
ASM_CODE_COMMENT(this);
DCHECK(root_array_available());
Isolate* isolate = this->isolate();
ExternalReference limit =
kind == StackLimitKind::kRealStackLimit
? ExternalReference::address_of_real_jslimit(isolate)
: ExternalReference::address_of_jslimit(isolate);
DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit));
intptr_t offset =
TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit);
CHECK(is_int32(offset));
LoadU64(destination, MemOperand(kRootRegister, offset));
}
#undef kScratchDoubleReg
} // namespace internal
......
......@@ -1267,6 +1267,7 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
public:
using TurboAssembler::TurboAssembler;
void LoadStackLimit(Register destination, StackLimitKind kind);
// It assumes that the arguments are located below the stack pointer.
// argc is the number of arguments not including the receiver.
// TODO(victorgomes): Remove this function once we stick with the reversed
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment