Commit f7f18b0f authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[nojit] Explicitly pass the root register value to JSEntry

In preparation for converting JSEntry into a builtin. The root register
used to be initialized by an embedded external reference, which is not
isolate-independent. Pass in its value explicitly instead.

Tbr: clemensh@chromium.org
Bug: v8:7777
Change-Id: If9d20cb193af175bd1cf58e5826bdf6f397869ad
Reviewed-on: https://chromium-review.googlesource.com/c/1363139Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58065}
parent a0858cf0
......@@ -28,15 +28,26 @@ namespace internal {
#define __ ACCESS_MASM(masm)
// Called with the native C calling convention. The corresponding function
// signature is:
//
// using JSEntryFunction = GeneratedCode<Object*(
// Object * new_target, Object * target, Object * receiver, int argc,
// Object*** args, Address root_register_value)>;
void JSEntryStub::Generate(MacroAssembler* masm) {
// r0: code entry
// r1: function
// r2: receiver
// r3: argc
// [sp+0]: argv
// [sp + 0 * kSystemPointerSize]: argv
// [sp + 1 * kSystemPointerSize]: root register value
Label invoke, handler_entry, exit;
static constexpr int kPushedStackSpace =
(kNumCalleeSaved + 1) * kPointerSize +
kNumDoubleCalleeSaved * kDoubleSize;
{
NoRootArrayScope no_root_array(masm);
......@@ -50,7 +61,11 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// Set up the reserved register for 0.0.
__ vmov(kDoubleRegZero, Double(0.0));
__ InitializeRootRegister();
// Initialize the root register.
// C calling convention. The sixth argument is passed on the stack.
static constexpr int kOffsetToRootRegisterValue =
kPushedStackSpace + EntryFrameConstants::kRootRegisterValueOffset;
__ ldr(kRootRegister, MemOperand(sp, kOffsetToRootRegisterValue));
}
// Get address of argv, see stm above.
......@@ -60,9 +75,9 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// r3: argc
// Set up argv in r4.
int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize;
__ ldr(r4, MemOperand(sp, offset_to_argv));
static constexpr int kOffsetToArgv =
kPushedStackSpace + EntryFrameConstants::kArgvOffset;
__ ldr(r4, MemOperand(sp, kOffsetToArgv));
// Push a frame with special values setup to mark it as an entry frame.
// r0: code entry
......
......@@ -13,8 +13,14 @@ namespace internal {
class EntryFrameConstants : public AllStatic {
public:
// This is the offset to where JSEntry pushes the current value of
// Isolate::c_entry_fp onto the stack.
static constexpr int kCallerFPOffset =
-(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize);
// Stack offsets for arguments passed to JSEntry.
static constexpr int kArgvOffset = +0 * kSystemPointerSize;
static constexpr int kRootRegisterValueOffset = +1 * kSystemPointerSize;
};
class ExitFrameConstants : public TypedFrameConstants {
......
......@@ -27,14 +27,20 @@ namespace internal {
#define __ ACCESS_MASM(masm)
// This is the entry point from C++. 5 arguments are provided in x0-x4.
// See use of the JSEntryFunction for example in src/execution.cc.
// Called with the native C calling convention. The corresponding function
// signature is:
//
// using JSEntryFunction = GeneratedCode<Object*(
// Object * new_target, Object * target, Object * receiver, int argc,
// Object*** args, Address root_register_value)>;
//
// Input:
// x0: code entry.
// x1: function.
// x2: receiver.
// x3: argc.
// x4: argv.
// x5: root register value.
// Output:
// x0: result.
void JSEntryStub::Generate(MacroAssembler* masm) {
......@@ -54,8 +60,9 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// Set up the reserved register for 0.0.
__ Fmov(fp_zero, 0.0);
// Initialize the root array register
__ InitializeRootRegister();
// Initialize the root register.
// C calling convention. The sixth argument is passed in x5.
__ Mov(kRootRegister, x5);
}
// Build an entry frame (see layout below).
......
......@@ -35,6 +35,8 @@ namespace internal {
//
class EntryFrameConstants : public AllStatic {
public:
// This is the offset to where JSEntry pushes the current value of
// Isolate::c_entry_fp onto the stack.
static constexpr int kCallerFPOffset = -3 * kPointerSize;
static constexpr int kFixedFrameSize = 6 * kPointerSize;
};
......
......@@ -118,9 +118,9 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(
// Placeholder for return value.
Object* value = nullptr;
using JSEntryFunction =
GeneratedCode<Object*(Object * new_target, Object * target,
Object * receiver, int argc, Object*** args)>;
using JSEntryFunction = GeneratedCode<Object*(
Object * new_target, Object * target, Object * receiver, int argc,
Object*** args, Address root_register_value)>;
Handle<Code> code;
switch (execution_target) {
......@@ -154,7 +154,8 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(
PrintDeserializedCodeInfo(Handle<JSFunction>::cast(target));
}
RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kJS_Execution);
value = stub_entry.Call(orig_func, func, recv, argc, argv);
value = stub_entry.Call(orig_func, func, recv, argc, argv,
isolate->isolate_data()->isolate_root());
}
#ifdef VERIFY_HEAP
......
......@@ -25,6 +25,12 @@ namespace internal {
#define __ ACCESS_MASM(masm)
// Called with the native C calling convention. The corresponding function
// signature is:
//
// using JSEntryFunction = GeneratedCode<Object*(
// Object * new_target, Object * target, Object * receiver, int argc,
// Object*** args, Address root_register_value)>;
void JSEntryStub::Generate(MacroAssembler* masm) {
Label invoke, handler_entry, exit;
Label not_outermost_js, not_outermost_js_2;
......@@ -48,7 +54,10 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ push(esi);
__ push(ebx);
__ InitializeRootRegister();
// Initialize the root register based on the given Isolate* argument.
// C calling convention. The sixth argument is passed on the stack.
__ mov(kRootRegister,
Operand(ebp, EntryFrameConstants::kRootRegisterValueOffset));
}
// Save copies of the top frame descriptor on the stack.
......
......@@ -13,6 +13,8 @@ namespace internal {
class EntryFrameConstants : public AllStatic {
public:
// This is the offset to where JSEntry pushes the current value of
// Isolate::c_entry_fp onto the stack.
static constexpr int kCallerFPOffset = -6 * kPointerSize;
static constexpr int kNewTargetArgOffset = +2 * kPointerSize;
......@@ -20,6 +22,7 @@ class EntryFrameConstants : public AllStatic {
static constexpr int kReceiverArgOffset = +4 * kPointerSize;
static constexpr int kArgcOffset = +5 * kPointerSize;
static constexpr int kArgvOffset = +6 * kPointerSize;
static constexpr int kRootRegisterValueOffset = +7 * kPointerSize;
};
class ExitFrameConstants : public TypedFrameConstants {
......
......@@ -1560,7 +1560,7 @@ Object* Isolate::UnwindAndFindHandler() {
switch (frame->type()) {
case StackFrame::ENTRY:
case StackFrame::CONSTRUCT_ENTRY: {
// For JSEntryStub frames we always have a handler.
// For JSEntry frames we always have a handler.
StackHandler* handler = frame->top_handler();
// Restore the next handler.
......
......@@ -1298,10 +1298,9 @@ MaybeHandle<Object> ErrorUtils::MakeGenericError(
Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
FrameSkipMode mode) {
if (FLAG_clear_exceptions_on_js_entry) {
// This function used to be implemented in JavaScript, and JSEntryStub
// clears
// any pending exceptions - so whenever we'd call this from C++, pending
// exceptions would be cleared. Preserve this behavior.
// This function used to be implemented in JavaScript, and JSEntry
// clears any pending exceptions - so whenever we'd call this from C++,
// pending exceptions would be cleared. Preserve this behavior.
isolate->clear_pending_exception();
}
......
......@@ -24,10 +24,19 @@ namespace internal {
#define __ ACCESS_MASM(masm)
// Called with the native C calling convention. The corresponding function
// signature is:
//
// using JSEntryFunction = GeneratedCode<Object*(
// Object * new_target, Object * target, Object * receiver, int argc,
// Object*** args, Address root_register_value)>;
void JSEntryStub::Generate(MacroAssembler* masm) {
Label invoke, handler_entry, exit;
Isolate* isolate = masm->isolate();
static constexpr int kPushedStackSpace =
(kNumCalleeSaved + 1) * kPointerSize + kNumCalleeSavedFPU * kDoubleSize;
{
NoRootArrayScope no_root_array(masm);
......@@ -38,8 +47,9 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// a3: argc
//
// Stack:
// 4 args slots
// args
// 4 arg slots
// argv
// root register value
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved | ra.bit());
......@@ -49,14 +59,18 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// Set up the reserved register for 0.0.
__ Move(kDoubleRegZero, 0.0);
__ InitializeRootRegister();
// Initialize the root register.
// C calling convention. The sixth argument is passed on the stack.
static constexpr int kOffsetToRootRegisterValue =
kPushedStackSpace + kCArgsSlotsSize +
EntryFrameConstants::kRootRegisterValueOffset;
__ lw(kRootRegister, MemOperand(sp, kOffsetToRootRegisterValue));
}
// Load argv in s0 register.
int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
offset_to_argv += kNumCalleeSavedFPU * kDoubleSize;
__ lw(s0, MemOperand(sp, offset_to_argv + kCArgsSlotsSize));
static constexpr int kOffsetToArgv =
kPushedStackSpace + kCArgsSlotsSize + EntryFrameConstants::kArgvOffset;
__ lw(s0, MemOperand(sp, kOffsetToArgv));
// We build an EntryFrame.
__ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used.
......
......@@ -13,8 +13,14 @@ namespace internal {
class EntryFrameConstants : public AllStatic {
public:
// This is the offset to where JSEntry pushes the current value of
// Isolate::c_entry_fp onto the stack.
static constexpr int kCallerFPOffset =
-(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize);
// Stack offsets for arguments passed to JSEntry.
static constexpr int kArgvOffset = +0 * kSystemPointerSize;
static constexpr int kRootRegisterValueOffset = +1 * kSystemPointerSize;
};
class ExitFrameConstants : public TypedFrameConstants {
......
......@@ -23,6 +23,12 @@ namespace internal {
#define __ ACCESS_MASM(masm)
// Called with the native C calling convention. The corresponding function
// signature is:
//
// using JSEntryFunction = GeneratedCode<Object*(
// Object * new_target, Object * target, Object * receiver, int argc,
// Object*** args, Address root_register_value)>;
void JSEntryStub::Generate(MacroAssembler* masm) {
Label invoke, handler_entry, exit;
Isolate* isolate = masm->isolate();
......@@ -36,11 +42,11 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// a1: function
// a2: receiver
// a3: argc
// a4 (a4): on mips64
// a4: argv
// a5: root register value
//
// Stack:
// 0 arg slots on mips64 (4 args slots on mips)
// args -- in a4/a4 on mips64, on stack on mips
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved | ra.bit());
......@@ -50,12 +56,14 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// Set up the reserved register for 0.0.
__ Move(kDoubleRegZero, 0.0);
// Load argv in s0 register.
__ mov(s0, a4); // 5th parameter in mips64 a4 (a4) register.
__ InitializeRootRegister();
// Initialize the root register.
// C calling convention. The sixth argument is passed in a5.
__ mov(kRootRegister, a5);
}
// Load argv in s0.
__ mov(s0, a4); // The 5th argument is passed in a4.
// We build an EntryFrame.
__ li(a7, Operand(-1)); // Push a bad frame pointer to fail if it is used.
StackFrame::Type marker = type();
......
......@@ -13,6 +13,8 @@ namespace internal {
class EntryFrameConstants : public AllStatic {
public:
// This is the offset to where JSEntry pushes the current value of
// Isolate::c_entry_fp onto the stack.
static constexpr int kCallerFPOffset =
-(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize);
};
......
......@@ -2793,9 +2793,9 @@ class ThreadImpl {
maybe_retval.is_null() ? " with exception" : "");
if (maybe_retval.is_null()) {
// JSEntryStub may through a stack overflow before we actually get to wasm
// code or back to the interpreter, meaning the thread-in-wasm flag won't
// be cleared.
// JSEntry may throw a stack overflow before we actually get to wasm code
// or back to the interpreter, meaning the thread-in-wasm flag won't be
// cleared.
if (trap_handler::IsThreadInWasm()) {
trap_handler::ClearThreadInWasm();
}
......
......@@ -27,6 +27,12 @@ namespace internal {
#define __ ACCESS_MASM(masm)
// Called with the native C calling convention. The corresponding function
// signature is:
//
// using JSEntryFunction = GeneratedCode<Object*(
// Object * new_target, Object * target, Object * receiver, int argc,
// Object*** args, Address root_register_value)>;
void JSEntryStub::Generate(MacroAssembler* masm) {
Label invoke, handler_entry, exit;
Label not_outermost_js, not_outermost_js_2;
......@@ -55,7 +61,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ pushq(rbx);
#ifdef _WIN64
// On Win64 XMM6-XMM15 are callee-save
// On Win64 XMM6-XMM15 are callee-save.
__ subp(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize));
__ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0), xmm6);
__ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1), xmm7);
......@@ -67,9 +73,22 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7), xmm13);
__ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8), xmm14);
__ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9), xmm15);
STATIC_ASSERT(EntryFrameConstants::kCalleeSaveXMMRegisters == 10);
STATIC_ASSERT(EntryFrameConstants::kXMMRegistersBlockSize ==
EntryFrameConstants::kXMMRegisterSize *
EntryFrameConstants::kCalleeSaveXMMRegisters);
#endif
__ InitializeRootRegister();
#ifdef _WIN64
// Initialize the root register.
// C calling convention. The sixth argument is passed on the stack.
__ movp(kRootRegister,
Operand(rbp, EntryFrameConstants::kRootRegisterValueOffset));
#else
// Initialize the root register.
// C calling convention. The sixth argument is passed in r9.
__ movp(kRootRegister, r9);
#endif
}
// Save copies of the top frame descriptor on the stack.
......
......@@ -18,13 +18,25 @@ class EntryFrameConstants : public AllStatic {
static constexpr int kXMMRegisterSize = 16;
static constexpr int kXMMRegistersBlockSize =
kXMMRegisterSize * kCalleeSaveXMMRegisters;
// This is the offset to where JSEntry pushes the current value of
// Isolate::c_entry_fp onto the stack.
// On x64, there are 7 pushq() and 3 Push() calls between setting up rbp and
// pushing the c_entry_fp, plus we manually allocate kXMMRegistersBlockSize
// bytes on the stack.
static constexpr int kCallerFPOffset =
-3 * kPointerSize + -7 * kRegisterSize - kXMMRegistersBlockSize;
// Stack offsets for arguments passed to JSEntry.
static constexpr int kArgvOffset = 6 * kPointerSize;
static constexpr int kRootRegisterValueOffset = 7 * kPointerSize;
#else
// We have 3 Push and 5 pushq in the JSEntryStub::GenerateBody.
// This is the offset to where JSEntry pushes the current value of
// Isolate::c_entry_fp onto the stack.
// On x64, there are 5 pushq() and 3 Push() calls between setting up rbp and
// pushing the c_entry_fp.
static constexpr int kCallerFPOffset = -3 * kPointerSize + -5 * kRegisterSize;
#endif
static constexpr int kArgvOffset = 6 * kPointerSize;
};
class ExitFrameConstants : public TypedFrameConstants {
......
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