Commit 65c11d39 authored by Junliang Yan's avatar Junliang Yan Committed by Commit Bot

PPC/s390: [nojit] Migrate JSEntry variants to builtins

Port b89d4249

Original Commit Message:

    This migrates the JSEntryStub to three dedicated builtins:

    JSEntry
    JSConstructEntry
    JSRunMicrotasksEntry

    correct macro assembler method to load and store external references
    through the kRootRegister).
    kRootRegister is initialized, so we first reserve the slot and later
    load its value.

R=jgruber@chromium.org, joransiu@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=
LOG=N

Change-Id: Ib84feca5e88d032307b5fab42377c56d074faf7f
Reviewed-on: https://chromium-review.googlesource.com/c/1393296Reviewed-by: 's avatarJoran Siu <joransiu@ca.ibm.com>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#58503}
parent 554dcb70
......@@ -533,6 +533,195 @@ void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
__ CallRuntime(Runtime::kThrowConstructedNonConstructable);
}
namespace {
// 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 Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
Builtins::Name entry_trampoline) {
// r3: code entry
// r4: function
// r5: receiver
// r6: argc
// [sp+0]: argv
Label invoke, handler_entry, exit;
// Called from C
__ function_descriptor();
{
NoRootArrayScope no_root_array(masm);
// PPC LINUX ABI:
// preserve LR in pre-reserved slot in caller's frame
__ mflr(r0);
__ StoreP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved);
// Save callee-saved double registers.
__ MultiPushDoubles(kCalleeSavedDoubles);
// Set up the reserved register for 0.0.
__ LoadDoubleLiteral(kDoubleRegZero, Double(0.0), r0);
// Initialize the root register.
// C calling convention. The sixth argument is passed in r8.
__ mr(kRootRegister, r8);
}
// Push a frame with special values setup to mark it as an entry frame.
// r3: code entry
// r4: function
// r5: receiver
// r6: argc
// r7: argv
__ li(r0, Operand(-1)); // Push a bad frame pointer to fail if it is used.
__ push(r0);
if (FLAG_enable_embedded_constant_pool) {
__ li(kConstantPoolRegister, Operand::Zero());
__ push(kConstantPoolRegister);
}
__ mov(r0, Operand(StackFrame::TypeToMarker(type)));
__ push(r0);
__ push(r0);
// Save copies of the top frame descriptor on the stack.
__ Move(r8, ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, masm->isolate()));
__ LoadP(r0, MemOperand(r8));
__ push(r0);
// Set up frame pointer for the frame to be pushed.
__ addi(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
// If this is the outermost JS call, set js_entry_sp value.
Label non_outermost_js;
ExternalReference js_entry_sp =
ExternalReference::Create(IsolateAddressId::kJSEntrySPAddress,
masm->isolate());
__ Move(r8, js_entry_sp);
__ LoadP(r9, MemOperand(r8));
__ cmpi(r9, Operand::Zero());
__ bne(&non_outermost_js);
__ StoreP(fp, MemOperand(r8));
__ mov(ip, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
Label cont;
__ b(&cont);
__ bind(&non_outermost_js);
__ mov(ip, Operand(StackFrame::INNER_JSENTRY_FRAME));
__ bind(&cont);
__ push(ip); // frame-type
// Jump to a faked try block that does the invoke, with a faked catch
// block that sets the pending exception.
__ b(&invoke);
// Block literal pool emission whilst taking the position of the handler
// entry. This avoids making the assumption that literal pools are always
// emitted after an instruction is emitted, rather than before.
{
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
__ bind(&handler_entry);
// Store the current pc as the handler offset. It's used later to create the
// handler table.
masm->isolate()->builtins()->SetJSEntryHandlerOffset(handler_entry.pos());
// Caught exception: Store result (exception) in the pending exception
// field in the JSEnv and return a failure sentinel. Coming in here the
// fp will be invalid because the PushStackHandler below sets it to 0 to
// signal the existence of the JSEntry frame.
__ Move(ip,
ExternalReference::Create(IsolateAddressId::kPendingExceptionAddress,
masm->isolate()));
}
__ StoreP(r3, MemOperand(ip));
__ LoadRoot(r3, RootIndex::kException);
__ b(&exit);
// Invoke: Link this frame into the handler chain.
__ bind(&invoke);
// Must preserve r3-r7.
__ PushStackHandler();
// If an exception not caught by another handler occurs, this handler
// returns control to the code after the b(&invoke) above, which
// restores all kCalleeSaved registers (including cp and fp) to their
// saved values before returning a failure to C.
// Invoke the function by calling through JS entry trampoline builtin.
// Notice that we cannot store a reference to the trampoline code directly in
// this stub, because runtime stubs are not traversed when doing GC.
// Expected registers by Builtins::JSEntryTrampoline
// r3: code entry
// r4: function
// r5: receiver
// r6: argc
// r7: argv
//
// Invoke the function by calling through JS entry trampoline builtin and
// pop the faked function when we return.
Handle<Code> trampoline_code =
masm->isolate()->builtins()->builtin_handle(entry_trampoline);
__ Call(trampoline_code, RelocInfo::CODE_TARGET);
// Unlink this frame from the handler chain.
__ PopStackHandler();
__ bind(&exit); // r3 holds result
// Check if the current stack frame is marked as the outermost JS frame.
Label non_outermost_js_2;
__ pop(r8);
__ cmpi(r8, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ bne(&non_outermost_js_2);
__ mov(r9, Operand::Zero());
__ Move(r8, js_entry_sp);
__ StoreP(r9, MemOperand(r8));
__ bind(&non_outermost_js_2);
// Restore the top frame descriptors from the stack.
__ pop(r6);
__ Move(ip, ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, masm->isolate()));
__ StoreP(r6, MemOperand(ip));
// Reset the stack to the callee saved registers.
__ addi(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
// Restore callee-saved double registers.
__ MultiPopDoubles(kCalleeSavedDoubles);
// Restore callee-saved registers.
__ MultiPop(kCalleeSaved);
// Return
__ LoadP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
__ mtlr(r0);
__ blr();
}
} // namespace
void Builtins::Generate_JSEntry(MacroAssembler* masm) {
Generate_JSEntryVariant(masm, StackFrame::ENTRY,
Builtins::kJSEntryTrampoline);
}
void Builtins::Generate_JSConstructEntry(MacroAssembler* masm) {
Generate_JSEntryVariant(masm, StackFrame::CONSTRUCT_ENTRY,
Builtins::kJSConstructEntryTrampoline);
}
void Builtins::Generate_JSRunMicrotasksEntry(MacroAssembler* masm) {
Generate_JSEntryVariant(masm, StackFrame::ENTRY, Builtins::kRunMicrotasks);
}
// Clobbers r5; preserves all other registers.
static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc) {
// Check the stack for overflow. We are not trying to catch
......
......@@ -533,6 +533,227 @@ void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
__ CallRuntime(Runtime::kThrowConstructedNonConstructable);
}
namespace {
// 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 Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
Builtins::Name entry_trampoline) {
// r2: code entry
// r3: function
// r4: receiver
// r5: argc
// r6: argv
// [sp + 20 * kSystemPointerSize]: root register value
Label invoke, handler_entry, exit;
static constexpr int kPushedStackSpace =
(kNumCalleeSaved + 2) * kPointerSize +
kNumCalleeSavedDoubles * kDoubleSize;
{
NoRootArrayScope no_root_array(masm);
// saving floating point registers
// 64bit ABI requires f8 to f15 be saved
// http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html
__ lay(sp, MemOperand(sp, -8 * kDoubleSize));
__ std(d8, MemOperand(sp));
__ std(d9, MemOperand(sp, 1 * kDoubleSize));
__ std(d10, MemOperand(sp, 2 * kDoubleSize));
__ std(d11, MemOperand(sp, 3 * kDoubleSize));
__ std(d12, MemOperand(sp, 4 * kDoubleSize));
__ std(d13, MemOperand(sp, 5 * kDoubleSize));
__ std(d14, MemOperand(sp, 6 * kDoubleSize));
__ std(d15, MemOperand(sp, 7 * kDoubleSize));
// zLinux ABI
// Incoming parameters:
// r2: code entry
// r3: function
// r4: receiver
// r5: argc
// r6: argv
// [sp + 20 * kSystemPointerSize]: root register value
// Requires us to save the callee-preserved registers r6-r13
// General convention is to also save r14 (return addr) and
// sp/r15 as well in a single STM/STMG
__ lay(sp, MemOperand(sp, -10 * kPointerSize));
__ StoreMultipleP(r6, sp, MemOperand(sp, 0));
// Initialize the root register.
// C calling convention. The sixth argument is passed on the stack.
static constexpr int kOffsetToRootRegisterValue =
kPushedStackSpace + EntryFrameConstants::kRootRegisterValueOffset;
__ LoadP(kRootRegister, MemOperand(sp, kOffsetToRootRegisterValue));
}
// save r6 to r1
__ LoadRR(r1, r6);
// Push a frame with special values setup to mark it as an entry frame.
// Bad FP (-1)
// SMI Marker
// SMI Marker
// kCEntryFPAddress
// Frame type
__ lay(sp, MemOperand(sp, -5 * kPointerSize));
// Push a bad frame pointer to fail if it is used.
__ LoadImmP(r9, Operand(-1));
__ mov(r8, Operand(StackFrame::TypeToMarker(type)));
__ mov(r7, Operand(StackFrame::TypeToMarker(type)));
// Save copies of the top frame descriptor on the stack.
__ Move(r6, ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, masm->isolate()));
__ LoadP(r6, MemOperand(r6));
__ StoreMultipleP(r6, r9, MemOperand(sp, kPointerSize));
// Set up frame pointer for the frame to be pushed.
// Need to add kPointerSize, because sp has one extra
// frame already for the frame type being pushed later.
__ lay(fp, MemOperand(
sp, -EntryFrameConstants::kCallerFPOffset + kPointerSize));
// restore r6
__ LoadRR(r6, r1);
// If this is the outermost JS call, set js_entry_sp value.
Label non_outermost_js;
ExternalReference js_entry_sp =
ExternalReference::Create(IsolateAddressId::kJSEntrySPAddress,
masm->isolate());
__ Move(r7, js_entry_sp);
__ LoadAndTestP(r8, MemOperand(r7));
__ bne(&non_outermost_js, Label::kNear);
__ StoreP(fp, MemOperand(r7));
__ Load(ip, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
Label cont;
__ b(&cont, Label::kNear);
__ bind(&non_outermost_js);
__ Load(ip, Operand(StackFrame::INNER_JSENTRY_FRAME));
__ bind(&cont);
__ StoreP(ip, MemOperand(sp)); // frame-type
// Jump to a faked try block that does the invoke, with a faked catch
// block that sets the pending exception.
__ b(&invoke, Label::kNear);
__ bind(&handler_entry);
// Store the current pc as the handler offset. It's used later to create the
// handler table.
masm->isolate()->builtins()->SetJSEntryHandlerOffset(handler_entry.pos());
// Caught exception: Store result (exception) in the pending exception
// field in the JSEnv and return a failure sentinel. Coming in here the
// fp will be invalid because the PushStackHandler below sets it to 0 to
// signal the existence of the JSEntry frame.
__ Move(ip, ExternalReference::Create(
IsolateAddressId::kPendingExceptionAddress, masm->isolate()));
__ StoreP(r2, MemOperand(ip));
__ LoadRoot(r2, RootIndex::kException);
__ b(&exit, Label::kNear);
// Invoke: Link this frame into the handler chain.
__ bind(&invoke);
// Must preserve r2-r6.
__ PushStackHandler();
// If an exception not caught by another handler occurs, this handler
// returns control to the code after the b(&invoke) above, which
// restores all kCalleeSaved registers (including cp and fp) to their
// saved values before returning a failure to C.
// Invoke the function by calling through JS entry trampoline builtin.
// Notice that we cannot store a reference to the trampoline code directly in
// this stub, because runtime stubs are not traversed when doing GC.
// Expected registers by Builtins::JSEntryTrampoline
// r2: code entry
// r3: function
// r4: receiver
// r5: argc
// r6: argv
//
// Invoke the function by calling through JS entry trampoline builtin and
// pop the faked function when we return.
Handle<Code> trampoline_code =
masm->isolate()->builtins()->builtin_handle(entry_trampoline);
__ Call(trampoline_code, RelocInfo::CODE_TARGET);
// Unlink this frame from the handler chain.
__ PopStackHandler();
__ bind(&exit); // r2 holds result
// Check if the current stack frame is marked as the outermost JS frame.
Label non_outermost_js_2;
__ pop(r7);
__ CmpP(r7, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ bne(&non_outermost_js_2, Label::kNear);
__ mov(r8, Operand::Zero());
__ Move(r7, js_entry_sp);
__ StoreP(r8, MemOperand(r7));
__ bind(&non_outermost_js_2);
// Restore the top frame descriptors from the stack.
__ pop(r5);
__ Move(ip, ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, masm->isolate()));
__ StoreP(r5, MemOperand(ip));
// Reset the stack to the callee saved registers.
__ lay(sp, MemOperand(sp, -EntryFrameConstants::kCallerFPOffset));
// Reload callee-saved preserved regs, return address reg (r14) and sp
__ LoadMultipleP(r6, sp, MemOperand(sp, 0));
__ la(sp, MemOperand(sp, 10 * kPointerSize));
// saving floating point registers
#if V8_TARGET_ARCH_S390X
// 64bit ABI requires f8 to f15 be saved
__ ld(d8, MemOperand(sp));
__ ld(d9, MemOperand(sp, 1 * kDoubleSize));
__ ld(d10, MemOperand(sp, 2 * kDoubleSize));
__ ld(d11, MemOperand(sp, 3 * kDoubleSize));
__ ld(d12, MemOperand(sp, 4 * kDoubleSize));
__ ld(d13, MemOperand(sp, 5 * kDoubleSize));
__ ld(d14, MemOperand(sp, 6 * kDoubleSize));
__ ld(d15, MemOperand(sp, 7 * kDoubleSize));
__ la(sp, MemOperand(sp, 8 * kDoubleSize));
#else
// 31bit ABI requires you to store f4 and f6:
// http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN417
__ ld(d4, MemOperand(sp));
__ ld(d6, MemOperand(sp, kDoubleSize));
__ la(sp, MemOperand(sp, 2 * kDoubleSize));
#endif
__ b(r14);
}
} // namespace
void Builtins::Generate_JSEntry(MacroAssembler* masm) {
Generate_JSEntryVariant(masm, StackFrame::ENTRY,
Builtins::kJSEntryTrampoline);
}
void Builtins::Generate_JSConstructEntry(MacroAssembler* masm) {
Generate_JSEntryVariant(masm, StackFrame::CONSTRUCT_ENTRY,
Builtins::kJSConstructEntryTrampoline);
}
void Builtins::Generate_JSRunMicrotasksEntry(MacroAssembler* masm) {
Generate_JSEntryVariant(masm, StackFrame::ENTRY, Builtins::kRunMicrotasks);
}
// Clobbers r4; preserves all other registers.
static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc) {
// Check the stack for overflow. We are not trying to catch
......
......@@ -24,157 +24,6 @@
namespace v8 {
namespace internal {
#define __ ACCESS_MASM(masm)
void JSEntryStub::Generate(MacroAssembler* masm) {
// r3: code entry
// r4: function
// r5: receiver
// r6: argc
// [sp+0]: argv
Label invoke, handler_entry, exit;
// Called from C
__ function_descriptor();
{
NoRootArrayScope no_root_array(masm);
// PPC LINUX ABI:
// preserve LR in pre-reserved slot in caller's frame
__ mflr(r0);
__ StoreP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved);
// Save callee-saved double registers.
__ MultiPushDoubles(kCalleeSavedDoubles);
// Set up the reserved register for 0.0.
__ LoadDoubleLiteral(kDoubleRegZero, Double(0.0), r0);
// Initialize the root register.
// C calling convention. The sixth argument is passed in r8.
__ mr(kRootRegister, r8);
}
// Push a frame with special values setup to mark it as an entry frame.
// r3: code entry
// r4: function
// r5: receiver
// r6: argc
// r7: argv
__ li(r0, Operand(-1)); // Push a bad frame pointer to fail if it is used.
__ push(r0);
if (FLAG_enable_embedded_constant_pool) {
__ li(kConstantPoolRegister, Operand::Zero());
__ push(kConstantPoolRegister);
}
StackFrame::Type marker = type();
__ mov(r0, Operand(StackFrame::TypeToMarker(marker)));
__ push(r0);
__ push(r0);
// Save copies of the top frame descriptor on the stack.
__ mov(r8, Operand(ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, isolate())));
__ LoadP(r0, MemOperand(r8));
__ push(r0);
// Set up frame pointer for the frame to be pushed.
__ addi(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
// If this is the outermost JS call, set js_entry_sp value.
Label non_outermost_js;
ExternalReference js_entry_sp =
ExternalReference::Create(IsolateAddressId::kJSEntrySPAddress, isolate());
__ mov(r8, Operand(js_entry_sp));
__ LoadP(r9, MemOperand(r8));
__ cmpi(r9, Operand::Zero());
__ bne(&non_outermost_js);
__ StoreP(fp, MemOperand(r8));
__ mov(ip, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
Label cont;
__ b(&cont);
__ bind(&non_outermost_js);
__ mov(ip, Operand(StackFrame::INNER_JSENTRY_FRAME));
__ bind(&cont);
__ push(ip); // frame-type
// Jump to a faked try block that does the invoke, with a faked catch
// block that sets the pending exception.
__ b(&invoke);
__ bind(&handler_entry);
handler_offset_ = handler_entry.pos();
// Caught exception: Store result (exception) in the pending exception
// field in the JSEnv and return a failure sentinel. Coming in here the
// fp will be invalid because the PushStackHandler below sets it to 0 to
// signal the existence of the JSEntry frame.
__ mov(ip, Operand(ExternalReference::Create(
IsolateAddressId::kPendingExceptionAddress, isolate())));
__ StoreP(r3, MemOperand(ip));
__ LoadRoot(r3, RootIndex::kException);
__ b(&exit);
// Invoke: Link this frame into the handler chain.
__ bind(&invoke);
// Must preserve r3-r7.
__ PushStackHandler();
// If an exception not caught by another handler occurs, this handler
// returns control to the code after the b(&invoke) above, which
// restores all kCalleeSaved registers (including cp and fp) to their
// saved values before returning a failure to C.
// Invoke the function by calling through JS entry trampoline builtin.
// Notice that we cannot store a reference to the trampoline code directly in
// this stub, because runtime stubs are not traversed when doing GC.
// Expected registers by Builtins::JSEntryTrampoline
// r3: code entry
// r4: function
// r5: receiver
// r6: argc
// r7: argv
__ Call(EntryTrampoline(), RelocInfo::CODE_TARGET);
// Unlink this frame from the handler chain.
__ PopStackHandler();
__ bind(&exit); // r3 holds result
// Check if the current stack frame is marked as the outermost JS frame.
Label non_outermost_js_2;
__ pop(r8);
__ cmpi(r8, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ bne(&non_outermost_js_2);
__ mov(r9, Operand::Zero());
__ mov(r8, Operand(js_entry_sp));
__ StoreP(r9, MemOperand(r8));
__ bind(&non_outermost_js_2);
// Restore the top frame descriptors from the stack.
__ pop(r6);
__ mov(ip, Operand(ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, isolate())));
__ StoreP(r6, MemOperand(ip));
// Reset the stack to the callee saved registers.
__ addi(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
// Restore callee-saved double registers.
__ MultiPopDoubles(kCalleeSavedDoubles);
// Restore callee-saved registers.
__ MultiPop(kCalleeSaved);
// Return
__ LoadP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
__ mtlr(r0);
__ blr();
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -1421,8 +1421,8 @@ void MacroAssembler::PushStackHandler() {
// Link the current handler as the next handler.
// Preserve r3-r7.
mov(r8, Operand(ExternalReference::Create(IsolateAddressId::kHandlerAddress,
isolate())));
Move(r8, ExternalReference::Create(IsolateAddressId::kHandlerAddress,
isolate()));
LoadP(r0, MemOperand(r8));
push(r0);
......@@ -1436,8 +1436,8 @@ void MacroAssembler::PopStackHandler() {
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
pop(r4);
mov(ip, Operand(ExternalReference::Create(IsolateAddressId::kHandlerAddress,
isolate())));
Move(ip, ExternalReference::Create(IsolateAddressId::kHandlerAddress,
isolate()));
StoreP(r4, MemOperand(ip));
Drop(1); // Drop padding.
......
......@@ -23,203 +23,6 @@
namespace v8 {
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) {
// r2: code entry
// r3: function
// r4: receiver
// r5: argc
// r6: argv
// [sp + 20 * kSystemPointerSize]: root register value
Label invoke, handler_entry, exit;
static constexpr int kPushedStackSpace =
(kNumCalleeSaved + 2) * kPointerSize +
kNumCalleeSavedDoubles * kDoubleSize;
{
NoRootArrayScope no_root_array(masm);
// saving floating point registers
// 64bit ABI requires f8 to f15 be saved
// http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html
__ lay(sp, MemOperand(sp, -8 * kDoubleSize));
__ std(d8, MemOperand(sp));
__ std(d9, MemOperand(sp, 1 * kDoubleSize));
__ std(d10, MemOperand(sp, 2 * kDoubleSize));
__ std(d11, MemOperand(sp, 3 * kDoubleSize));
__ std(d12, MemOperand(sp, 4 * kDoubleSize));
__ std(d13, MemOperand(sp, 5 * kDoubleSize));
__ std(d14, MemOperand(sp, 6 * kDoubleSize));
__ std(d15, MemOperand(sp, 7 * kDoubleSize));
// zLinux ABI
// Incoming parameters:
// r2: code entry
// r3: function
// r4: receiver
// r5: argc
// r6: argv
// [sp + 20 * kSystemPointerSize]: root register value
// Requires us to save the callee-preserved registers r6-r13
// General convention is to also save r14 (return addr) and
// sp/r15 as well in a single STM/STMG
__ lay(sp, MemOperand(sp, -10 * kPointerSize));
__ StoreMultipleP(r6, sp, MemOperand(sp, 0));
// Initialize the root register.
// C calling convention. The sixth argument is passed on the stack.
static constexpr int kOffsetToRootRegisterValue =
kPushedStackSpace + EntryFrameConstants::kRootRegisterValueOffset;
__ LoadP(kRootRegister, MemOperand(sp, kOffsetToRootRegisterValue));
}
// save r6 to r1
__ LoadRR(r1, r6);
// Push a frame with special values setup to mark it as an entry frame.
// Bad FP (-1)
// SMI Marker
// SMI Marker
// kCEntryFPAddress
// Frame type
__ lay(sp, MemOperand(sp, -5 * kPointerSize));
// Push a bad frame pointer to fail if it is used.
__ LoadImmP(r9, Operand(-1));
StackFrame::Type marker = type();
__ Load(r8, Operand(StackFrame::TypeToMarker(marker)));
__ Load(r7, Operand(StackFrame::TypeToMarker(marker)));
// Save copies of the top frame descriptor on the stack.
__ mov(r6, Operand(ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, isolate())));
__ LoadP(r6, MemOperand(r6));
__ StoreMultipleP(r6, r9, MemOperand(sp, kPointerSize));
// Set up frame pointer for the frame to be pushed.
// Need to add kPointerSize, because sp has one extra
// frame already for the frame type being pushed later.
__ lay(fp, MemOperand(
sp, -EntryFrameConstants::kCallerFPOffset + kPointerSize));
// restore r6
__ LoadRR(r6, r1);
// If this is the outermost JS call, set js_entry_sp value.
Label non_outermost_js;
ExternalReference js_entry_sp =
ExternalReference::Create(IsolateAddressId::kJSEntrySPAddress, isolate());
__ mov(r7, Operand(js_entry_sp));
__ LoadAndTestP(r8, MemOperand(r7));
__ bne(&non_outermost_js, Label::kNear);
__ StoreP(fp, MemOperand(r7));
__ Load(ip, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
Label cont;
__ b(&cont, Label::kNear);
__ bind(&non_outermost_js);
__ Load(ip, Operand(StackFrame::INNER_JSENTRY_FRAME));
__ bind(&cont);
__ StoreP(ip, MemOperand(sp)); // frame-type
// Jump to a faked try block that does the invoke, with a faked catch
// block that sets the pending exception.
__ b(&invoke, Label::kNear);
__ bind(&handler_entry);
handler_offset_ = handler_entry.pos();
// Caught exception: Store result (exception) in the pending exception
// field in the JSEnv and return a failure sentinel. Coming in here the
// fp will be invalid because the PushStackHandler below sets it to 0 to
// signal the existence of the JSEntry frame.
__ mov(ip, Operand(ExternalReference::Create(
IsolateAddressId::kPendingExceptionAddress, isolate())));
__ StoreP(r2, MemOperand(ip));
__ LoadRoot(r2, RootIndex::kException);
__ b(&exit, Label::kNear);
// Invoke: Link this frame into the handler chain.
__ bind(&invoke);
// Must preserve r2-r6.
__ PushStackHandler();
// If an exception not caught by another handler occurs, this handler
// returns control to the code after the b(&invoke) above, which
// restores all kCalleeSaved registers (including cp and fp) to their
// saved values before returning a failure to C.
// Invoke the function by calling through JS entry trampoline builtin.
// Notice that we cannot store a reference to the trampoline code directly in
// this stub, because runtime stubs are not traversed when doing GC.
// Expected registers by Builtins::JSEntryTrampoline
// r2: code entry
// r3: function
// r4: receiver
// r5: argc
// r6: argv
__ Call(EntryTrampoline(), RelocInfo::CODE_TARGET);
// Unlink this frame from the handler chain.
__ PopStackHandler();
__ bind(&exit); // r2 holds result
// Check if the current stack frame is marked as the outermost JS frame.
Label non_outermost_js_2;
__ pop(r7);
__ CmpP(r7, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ bne(&non_outermost_js_2, Label::kNear);
__ mov(r8, Operand::Zero());
__ mov(r7, Operand(js_entry_sp));
__ StoreP(r8, MemOperand(r7));
__ bind(&non_outermost_js_2);
// Restore the top frame descriptors from the stack.
__ pop(r5);
__ mov(ip, Operand(ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, isolate())));
__ StoreP(r5, MemOperand(ip));
// Reset the stack to the callee saved registers.
__ lay(sp, MemOperand(sp, -EntryFrameConstants::kCallerFPOffset));
// Reload callee-saved preserved regs, return address reg (r14) and sp
__ LoadMultipleP(r6, sp, MemOperand(sp, 0));
__ la(sp, MemOperand(sp, 10 * kPointerSize));
// saving floating point registers
#if V8_TARGET_ARCH_S390X
// 64bit ABI requires f8 to f15 be saved
__ ld(d8, MemOperand(sp));
__ ld(d9, MemOperand(sp, 1 * kDoubleSize));
__ ld(d10, MemOperand(sp, 2 * kDoubleSize));
__ ld(d11, MemOperand(sp, 3 * kDoubleSize));
__ ld(d12, MemOperand(sp, 4 * kDoubleSize));
__ ld(d13, MemOperand(sp, 5 * kDoubleSize));
__ ld(d14, MemOperand(sp, 6 * kDoubleSize));
__ ld(d15, MemOperand(sp, 7 * kDoubleSize));
__ la(sp, MemOperand(sp, 8 * kDoubleSize));
#else
// 31bit ABI requires you to store f4 and f6:
// http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN417
__ ld(d4, MemOperand(sp));
__ ld(d6, MemOperand(sp, kDoubleSize));
__ la(sp, MemOperand(sp, 2 * kDoubleSize));
#endif
__ b(r14);
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -1485,8 +1485,8 @@ void MacroAssembler::PushStackHandler() {
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
// Link the current handler as the next handler.
mov(r7, Operand(ExternalReference::Create(IsolateAddressId::kHandlerAddress,
isolate())));
Move(r7, ExternalReference::Create(IsolateAddressId::kHandlerAddress,
isolate()));
// Buy the full stack frame for 5 slots.
lay(sp, MemOperand(sp, -StackHandlerConstants::kSize));
......@@ -1508,8 +1508,8 @@ void MacroAssembler::PopStackHandler() {
// Pop the Next Handler into r3 and store it into Handler Address reference.
Pop(r3);
mov(ip, Operand(ExternalReference::Create(IsolateAddressId::kHandlerAddress,
isolate())));
Move(ip, ExternalReference::Create(IsolateAddressId::kHandlerAddress,
isolate()));
StoreP(r3, MemOperand(ip));
Drop(1); // Drop padding.
......
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