PPC/s390: [builtins] Convert CEntry/GetProperty/StringAdd stubs to builtins
Port d8131cd63a
Original Commit Message:
Stubs and builtins are very similar. The main differences are that
stubs can be parameterized and may be generated at runtime, whereas
builtins are generated at mksnapshot-time and shipped with the snapshot
(or embedded into the binary).
My main motivation for these conversions is that we can generate
faster calls and jumps to (embedded) builtins callees from (embedded)
builtin callers. Instead of going through the builtins constants table
indirection, we can simply do a pc-relative call/jump.
This also unlocks other refactorings, e.g. removal of
CallRuntimeDelayed.
R=jgruber@chromium.org, joransiu@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=
LOG=N
Change-Id: I193e4275470d492912a7d0f8523c3b8c29f1b146
Reviewed-on: https://chromium-review.googlesource.com/1050732
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Reviewed-by: Joran Siu <joransiu@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#53081}
This commit is contained in:
parent
e084eea628
commit
7ff35bd542
@ -5,6 +5,7 @@
|
||||
#if V8_TARGET_ARCH_PPC
|
||||
|
||||
#include "src/assembler-inl.h"
|
||||
#include "src/code-factory.h"
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/deoptimizer.h"
|
||||
@ -52,7 +53,7 @@ void AdaptorWithExitFrameType(MacroAssembler* masm,
|
||||
// ordinary functions).
|
||||
__ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
|
||||
|
||||
// CEntryStub expects r3 to contain the number of arguments including the
|
||||
// CEntry expects r3 to contain the number of arguments including the
|
||||
// receiver and the extra arguments.
|
||||
__ addi(r3, r3,
|
||||
Operand(BuiltinExitFrameConstants::kNumExtraArgsWithReceiver));
|
||||
@ -67,9 +68,10 @@ void AdaptorWithExitFrameType(MacroAssembler* masm,
|
||||
// JumpToExternalReference. We have already loaded entry point to r15
|
||||
// in Generate_adaptor.
|
||||
__ mr(r4, r15);
|
||||
CEntryStub stub(masm->isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
|
||||
exit_frame_type == Builtins::BUILTIN_EXIT);
|
||||
__ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
|
||||
Handle<Code> code =
|
||||
CodeFactory::CEntry(masm->isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
|
||||
exit_frame_type == Builtins::BUILTIN_EXIT);
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -2664,7 +2666,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ Push(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// Initialize the JavaScript context with 0. CEntry will use it to
|
||||
// set the current context on the isolate.
|
||||
__ LoadSmiLiteral(cp, Smi::kZero);
|
||||
__ CallRuntime(Runtime::kWasmCompileLazy);
|
||||
@ -2681,6 +2683,199 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ Jump(r11);
|
||||
}
|
||||
|
||||
void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
|
||||
SaveFPRegsMode save_doubles, ArgvMode argv_mode,
|
||||
bool builtin_exit_frame) {
|
||||
// Called from JavaScript; parameters are on stack as if calling JS function.
|
||||
// r3: number of arguments including receiver
|
||||
// r4: pointer to builtin function
|
||||
// fp: frame pointer (restored after C call)
|
||||
// sp: stack pointer (restored as callee's sp after C call)
|
||||
// cp: current context (C callee-saved)
|
||||
//
|
||||
// If argv_mode == kArgvInRegister:
|
||||
// r5: pointer to the first argument
|
||||
ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
||||
|
||||
__ mr(r15, r4);
|
||||
|
||||
if (argv_mode == kArgvInRegister) {
|
||||
// Move argv into the correct register.
|
||||
__ mr(r4, r5);
|
||||
} else {
|
||||
// Compute the argv pointer.
|
||||
__ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2));
|
||||
__ add(r4, r4, sp);
|
||||
__ subi(r4, r4, Operand(kPointerSize));
|
||||
}
|
||||
|
||||
// Enter the exit frame that transitions from JavaScript to C++.
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
|
||||
// Need at least one extra slot for return address location.
|
||||
int arg_stack_space = 1;
|
||||
|
||||
// Pass buffer for return value on stack if necessary
|
||||
bool needs_return_buffer =
|
||||
(result_size == 2 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS);
|
||||
if (needs_return_buffer) {
|
||||
arg_stack_space += result_size;
|
||||
}
|
||||
|
||||
__ EnterExitFrame(
|
||||
save_doubles, arg_stack_space,
|
||||
builtin_exit_frame ? StackFrame::BUILTIN_EXIT : StackFrame::EXIT);
|
||||
|
||||
// Store a copy of argc in callee-saved registers for later.
|
||||
__ mr(r14, r3);
|
||||
|
||||
// r3, r14: number of arguments including receiver (C callee-saved)
|
||||
// r4: pointer to the first argument
|
||||
// r15: pointer to builtin function (C callee-saved)
|
||||
|
||||
// Result returned in registers or stack, depending on result size and ABI.
|
||||
|
||||
Register isolate_reg = r5;
|
||||
if (needs_return_buffer) {
|
||||
// The return value is a non-scalar value.
|
||||
// Use frame storage reserved by calling function to pass return
|
||||
// buffer as implicit first argument.
|
||||
__ mr(r5, r4);
|
||||
__ mr(r4, r3);
|
||||
__ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
|
||||
isolate_reg = r6;
|
||||
}
|
||||
|
||||
// Call C built-in.
|
||||
__ Move(isolate_reg, ExternalReference::isolate_address(masm->isolate()));
|
||||
|
||||
Register target = r15;
|
||||
if (ABI_USES_FUNCTION_DESCRIPTORS) {
|
||||
// AIX/PPC64BE Linux use a function descriptor.
|
||||
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize));
|
||||
__ LoadP(ip, MemOperand(r15, 0)); // Instruction address
|
||||
target = ip;
|
||||
} else if (ABI_CALL_VIA_IP) {
|
||||
__ Move(ip, r15);
|
||||
target = ip;
|
||||
}
|
||||
|
||||
// To let the GC traverse the return address of the exit frames, we need to
|
||||
// know where the return address is. The CEntryStub is unmovable, so
|
||||
// we can store the address on the stack to be able to find it again and
|
||||
// we never have to restore it, because it will not change.
|
||||
Label start_call;
|
||||
constexpr int after_call_offset = 5 * Assembler::kInstrSize;
|
||||
DCHECK_NE(r7, target);
|
||||
__ LoadPC(r7);
|
||||
__ bind(&start_call);
|
||||
__ addi(r7, r7, Operand(after_call_offset));
|
||||
__ StoreP(r7, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
|
||||
__ Call(target);
|
||||
DCHECK_EQ(after_call_offset - Assembler::kInstrSize,
|
||||
__ SizeOfCodeGeneratedSince(&start_call));
|
||||
|
||||
// If return value is on the stack, pop it to registers.
|
||||
if (needs_return_buffer) {
|
||||
__ LoadP(r4, MemOperand(r3, kPointerSize));
|
||||
__ LoadP(r3, MemOperand(r3));
|
||||
}
|
||||
|
||||
// Check result for exception sentinel.
|
||||
Label exception_returned;
|
||||
__ CompareRoot(r3, Heap::kExceptionRootIndex);
|
||||
__ beq(&exception_returned);
|
||||
|
||||
// Check that there is no pending exception, otherwise we
|
||||
// should have returned the exception sentinel.
|
||||
if (FLAG_debug_code) {
|
||||
Label okay;
|
||||
ExternalReference pending_exception_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingExceptionAddress, masm->isolate());
|
||||
|
||||
__ Move(r6, pending_exception_address);
|
||||
__ LoadP(r6, MemOperand(r6));
|
||||
__ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
|
||||
// Cannot use check here as it attempts to generate call into runtime.
|
||||
__ beq(&okay);
|
||||
__ stop("Unexpected pending exception");
|
||||
__ bind(&okay);
|
||||
}
|
||||
|
||||
// Exit C frame and return.
|
||||
// r3:r4: result
|
||||
// sp: stack pointer
|
||||
// fp: frame pointer
|
||||
Register argc = argv_mode == kArgvInRegister
|
||||
// We don't want to pop arguments so set argc to no_reg.
|
||||
? no_reg
|
||||
// r14: still holds argc (callee-saved).
|
||||
: r14;
|
||||
__ LeaveExitFrame(save_doubles, argc);
|
||||
__ blr();
|
||||
|
||||
// Handling of exception.
|
||||
__ bind(&exception_returned);
|
||||
|
||||
ExternalReference pending_handler_context_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerContextAddress, masm->isolate());
|
||||
ExternalReference pending_handler_entrypoint_address =
|
||||
ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerEntrypointAddress, masm->isolate());
|
||||
ExternalReference pending_handler_constant_pool_address =
|
||||
ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerConstantPoolAddress,
|
||||
masm->isolate());
|
||||
ExternalReference pending_handler_fp_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerFPAddress, masm->isolate());
|
||||
ExternalReference pending_handler_sp_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerSPAddress, masm->isolate());
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set r3 to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler =
|
||||
ExternalReference::Create(Runtime::kUnwindAndFindExceptionHandler);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, 0, r3);
|
||||
__ li(r3, Operand::Zero());
|
||||
__ li(r4, Operand::Zero());
|
||||
__ Move(r5, ExternalReference::isolate_address(masm->isolate()));
|
||||
__ CallCFunction(find_handler, 3);
|
||||
}
|
||||
|
||||
// Retrieve the handler context, SP and FP.
|
||||
__ Move(cp, pending_handler_context_address);
|
||||
__ LoadP(cp, MemOperand(cp));
|
||||
__ Move(sp, pending_handler_sp_address);
|
||||
__ LoadP(sp, MemOperand(sp));
|
||||
__ Move(fp, pending_handler_fp_address);
|
||||
__ LoadP(fp, MemOperand(fp));
|
||||
|
||||
// If the handler is a JS frame, restore the context to the frame. Note that
|
||||
// the context will be set to (cp == 0) for non-JS frames.
|
||||
Label skip;
|
||||
__ cmpi(cp, Operand::Zero());
|
||||
__ beq(&skip);
|
||||
__ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
__ bind(&skip);
|
||||
|
||||
// Reset the masking register.
|
||||
if (FLAG_branch_load_poisoning) {
|
||||
__ ResetSpeculationPoisonRegister();
|
||||
}
|
||||
|
||||
// Compute the handler entry address and jump to it.
|
||||
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
|
||||
__ Move(ip, pending_handler_entrypoint_address);
|
||||
__ LoadP(ip, MemOperand(ip));
|
||||
if (FLAG_enable_embedded_constant_pool) {
|
||||
__ Move(kConstantPoolRegister, pending_handler_constant_pool_address);
|
||||
__ LoadP(kConstantPoolRegister, MemOperand(kConstantPoolRegister));
|
||||
}
|
||||
__ Jump(ip);
|
||||
}
|
||||
|
||||
void Builtins::Generate_DoubleToI(MacroAssembler* masm) {
|
||||
Label out_of_range, only_low, negate, done, fastpath_done;
|
||||
Register result_reg = r3;
|
||||
|
@ -5,6 +5,7 @@
|
||||
#if V8_TARGET_ARCH_S390
|
||||
|
||||
#include "src/assembler-inl.h"
|
||||
#include "src/code-factory.h"
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/deoptimizer.h"
|
||||
@ -52,7 +53,7 @@ void AdaptorWithExitFrameType(MacroAssembler* masm,
|
||||
// ordinary functions).
|
||||
__ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
|
||||
|
||||
// CEntryStub expects r2 to contain the number of arguments including the
|
||||
// CEntry expects r2 to contain the number of arguments including the
|
||||
// receiver and the extra arguments.
|
||||
__ AddP(r2, r2,
|
||||
Operand(BuiltinExitFrameConstants::kNumExtraArgsWithReceiver));
|
||||
@ -67,9 +68,10 @@ void AdaptorWithExitFrameType(MacroAssembler* masm,
|
||||
// JumpToExternalReference. We have already loaded entry point to r7
|
||||
// in Generate_adaptor.
|
||||
__ LoadRR(r3, r7);
|
||||
CEntryStub stub(masm->isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
|
||||
exit_frame_type == Builtins::BUILTIN_EXIT);
|
||||
__ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
|
||||
Handle<Code> code =
|
||||
CodeFactory::CEntry(masm->isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
|
||||
exit_frame_type == Builtins::BUILTIN_EXIT);
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -2672,7 +2674,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ Push(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// Initialize the JavaScript context with 0. CEntry will use it to
|
||||
// set the current context on the isolate.
|
||||
__ LoadSmiLiteral(cp, Smi::kZero);
|
||||
__ CallRuntime(Runtime::kWasmCompileLazy);
|
||||
@ -2689,6 +2691,186 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ Jump(ip);
|
||||
}
|
||||
|
||||
void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
|
||||
SaveFPRegsMode save_doubles, ArgvMode argv_mode,
|
||||
bool builtin_exit_frame) {
|
||||
// Called from JavaScript; parameters are on stack as if calling JS function.
|
||||
// r2: number of arguments including receiver
|
||||
// r3: pointer to builtin function
|
||||
// fp: frame pointer (restored after C call)
|
||||
// sp: stack pointer (restored as callee's sp after C call)
|
||||
// cp: current context (C callee-saved)
|
||||
//
|
||||
// If argv_mode == kArgvInRegister:
|
||||
// r4: pointer to the first argument
|
||||
ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
||||
|
||||
__ LoadRR(r7, r3);
|
||||
|
||||
if (argv_mode == kArgvInRegister) {
|
||||
// Move argv into the correct register.
|
||||
__ LoadRR(r3, r4);
|
||||
} else {
|
||||
// Compute the argv pointer.
|
||||
__ ShiftLeftP(r3, r2, Operand(kPointerSizeLog2));
|
||||
__ lay(r3, MemOperand(r3, sp, -kPointerSize));
|
||||
}
|
||||
|
||||
// Enter the exit frame that transitions from JavaScript to C++.
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
|
||||
// Need at least one extra slot for return address location.
|
||||
int arg_stack_space = 1;
|
||||
|
||||
// Pass buffer for return value on stack if necessary
|
||||
bool needs_return_buffer =
|
||||
result_size == 2 && !ABI_RETURNS_OBJECTPAIR_IN_REGS;
|
||||
if (needs_return_buffer) {
|
||||
arg_stack_space += result_size;
|
||||
}
|
||||
|
||||
#if V8_TARGET_ARCH_S390X
|
||||
// 64-bit linux pass Argument object by reference not value
|
||||
arg_stack_space += 2;
|
||||
#endif
|
||||
|
||||
__ EnterExitFrame(
|
||||
save_doubles, arg_stack_space,
|
||||
builtin_exit_frame ? StackFrame::BUILTIN_EXIT : StackFrame::EXIT);
|
||||
|
||||
// Store a copy of argc, argv in callee-saved registers for later.
|
||||
__ LoadRR(r6, r2);
|
||||
__ LoadRR(r8, r3);
|
||||
// r2, r6: number of arguments including receiver (C callee-saved)
|
||||
// r3, r8: pointer to the first argument
|
||||
// r7: pointer to builtin function (C callee-saved)
|
||||
|
||||
// Result returned in registers or stack, depending on result size and ABI.
|
||||
|
||||
Register isolate_reg = r4;
|
||||
if (needs_return_buffer) {
|
||||
// The return value is 16-byte non-scalar value.
|
||||
// Use frame storage reserved by calling function to pass return
|
||||
// buffer as implicit first argument in R2. Shfit original parameters
|
||||
// by one register each.
|
||||
__ LoadRR(r4, r3);
|
||||
__ LoadRR(r3, r2);
|
||||
__ la(r2, MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize));
|
||||
isolate_reg = r5;
|
||||
}
|
||||
// Call C built-in.
|
||||
__ Move(isolate_reg, ExternalReference::isolate_address(masm->isolate()));
|
||||
|
||||
Register target = r7;
|
||||
|
||||
// To let the GC traverse the return address of the exit frames, we need to
|
||||
// know where the return address is. The CEntryStub is unmovable, so
|
||||
// we can store the address on the stack to be able to find it again and
|
||||
// we never have to restore it, because it will not change.
|
||||
{
|
||||
Label return_label;
|
||||
__ larl(r14, &return_label); // Generate the return addr of call later.
|
||||
__ StoreP(r14, MemOperand(sp, kStackFrameRASlot * kPointerSize));
|
||||
|
||||
// zLinux ABI requires caller's frame to have sufficient space for callee
|
||||
// preserved regsiter save area.
|
||||
// __ lay(sp, MemOperand(sp, -kCalleeRegisterSaveAreaSize));
|
||||
__ b(target);
|
||||
__ bind(&return_label);
|
||||
// __ la(sp, MemOperand(sp, +kCalleeRegisterSaveAreaSize));
|
||||
}
|
||||
|
||||
// If return value is on the stack, pop it to registers.
|
||||
if (needs_return_buffer) {
|
||||
__ LoadP(r3, MemOperand(r2, kPointerSize));
|
||||
__ LoadP(r2, MemOperand(r2));
|
||||
}
|
||||
|
||||
// Check result for exception sentinel.
|
||||
Label exception_returned;
|
||||
__ CompareRoot(r2, Heap::kExceptionRootIndex);
|
||||
__ beq(&exception_returned, Label::kNear);
|
||||
|
||||
// Check that there is no pending exception, otherwise we
|
||||
// should have returned the exception sentinel.
|
||||
if (FLAG_debug_code) {
|
||||
Label okay;
|
||||
ExternalReference pending_exception_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingExceptionAddress, masm->isolate());
|
||||
__ Move(r1, pending_exception_address);
|
||||
__ LoadP(r1, MemOperand(r1));
|
||||
__ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
|
||||
// Cannot use check here as it attempts to generate call into runtime.
|
||||
__ beq(&okay, Label::kNear);
|
||||
__ stop("Unexpected pending exception");
|
||||
__ bind(&okay);
|
||||
}
|
||||
|
||||
// Exit C frame and return.
|
||||
// r2:r3: result
|
||||
// sp: stack pointer
|
||||
// fp: frame pointer
|
||||
Register argc = argv_mode == kArgvInRegister
|
||||
// We don't want to pop arguments so set argc to no_reg.
|
||||
? no_reg
|
||||
// r6: still holds argc (callee-saved).
|
||||
: r6;
|
||||
__ LeaveExitFrame(save_doubles, argc);
|
||||
__ b(r14);
|
||||
|
||||
// Handling of exception.
|
||||
__ bind(&exception_returned);
|
||||
|
||||
ExternalReference pending_handler_context_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerContextAddress, masm->isolate());
|
||||
ExternalReference pending_handler_entrypoint_address =
|
||||
ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerEntrypointAddress, masm->isolate());
|
||||
ExternalReference pending_handler_fp_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerFPAddress, masm->isolate());
|
||||
ExternalReference pending_handler_sp_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerSPAddress, masm->isolate());
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set r3 to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler =
|
||||
ExternalReference::Create(Runtime::kUnwindAndFindExceptionHandler);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, 0, r2);
|
||||
__ LoadImmP(r2, Operand::Zero());
|
||||
__ LoadImmP(r3, Operand::Zero());
|
||||
__ Move(r4, ExternalReference::isolate_address(masm->isolate()));
|
||||
__ CallCFunction(find_handler, 3);
|
||||
}
|
||||
|
||||
// Retrieve the handler context, SP and FP.
|
||||
__ Move(cp, pending_handler_context_address);
|
||||
__ LoadP(cp, MemOperand(cp));
|
||||
__ Move(sp, pending_handler_sp_address);
|
||||
__ LoadP(sp, MemOperand(sp));
|
||||
__ Move(fp, pending_handler_fp_address);
|
||||
__ LoadP(fp, MemOperand(fp));
|
||||
|
||||
// If the handler is a JS frame, restore the context to the frame. Note that
|
||||
// the context will be set to (cp == 0) for non-JS frames.
|
||||
Label skip;
|
||||
__ CmpP(cp, Operand::Zero());
|
||||
__ beq(&skip, Label::kNear);
|
||||
__ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
__ bind(&skip);
|
||||
|
||||
// Reset the masking register.
|
||||
if (FLAG_branch_load_poisoning) {
|
||||
__ ResetSpeculationPoisonRegister();
|
||||
}
|
||||
|
||||
// Compute the handler entry address and jump to it.
|
||||
__ Move(r3, pending_handler_entrypoint_address);
|
||||
__ LoadP(r3, MemOperand(r3));
|
||||
__ Jump(r3);
|
||||
}
|
||||
|
||||
void Builtins::Generate_DoubleToI(MacroAssembler* masm) {
|
||||
Label out_of_range, only_low, negate, done, fastpath_done;
|
||||
Register result_reg = r2;
|
||||
|
@ -36,217 +36,11 @@ void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kNewArray);
|
||||
}
|
||||
|
||||
Movability CEntryStub::NeedsImmovableCode() { return kImmovable; }
|
||||
|
||||
void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
|
||||
CEntryStub::GenerateAheadOfTime(isolate);
|
||||
CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
|
||||
StoreFastElementStub::GenerateAheadOfTime(isolate);
|
||||
}
|
||||
|
||||
|
||||
void CodeStub::GenerateFPStubs(Isolate* isolate) {
|
||||
// Generate if not already in cache.
|
||||
SaveFPRegsMode mode = kSaveFPRegs;
|
||||
CEntryStub(isolate, 1, mode).GetCode();
|
||||
}
|
||||
|
||||
|
||||
void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
|
||||
CEntryStub stub(isolate, 1, kDontSaveFPRegs);
|
||||
stub.GetCode();
|
||||
CEntryStub save_doubles(isolate, 1, kSaveFPRegs);
|
||||
save_doubles.GetCode();
|
||||
}
|
||||
|
||||
|
||||
void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
// Called from JavaScript; parameters are on stack as if calling JS function.
|
||||
// r3: number of arguments including receiver
|
||||
// r4: pointer to builtin function
|
||||
// fp: frame pointer (restored after C call)
|
||||
// sp: stack pointer (restored as callee's sp after C call)
|
||||
// cp: current context (C callee-saved)
|
||||
//
|
||||
// If argv_in_register():
|
||||
// r5: pointer to the first argument
|
||||
ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
||||
|
||||
__ mr(r15, r4);
|
||||
|
||||
if (argv_in_register()) {
|
||||
// Move argv into the correct register.
|
||||
__ mr(r4, r5);
|
||||
} else {
|
||||
// Compute the argv pointer.
|
||||
__ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2));
|
||||
__ add(r4, r4, sp);
|
||||
__ subi(r4, r4, Operand(kPointerSize));
|
||||
}
|
||||
|
||||
// Enter the exit frame that transitions from JavaScript to C++.
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
|
||||
// Need at least one extra slot for return address location.
|
||||
int arg_stack_space = 1;
|
||||
|
||||
// Pass buffer for return value on stack if necessary
|
||||
bool needs_return_buffer =
|
||||
(result_size() == 2 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS);
|
||||
if (needs_return_buffer) {
|
||||
arg_stack_space += result_size();
|
||||
}
|
||||
|
||||
__ EnterExitFrame(save_doubles(), arg_stack_space, is_builtin_exit()
|
||||
? StackFrame::BUILTIN_EXIT
|
||||
: StackFrame::EXIT);
|
||||
|
||||
// Store a copy of argc in callee-saved registers for later.
|
||||
__ mr(r14, r3);
|
||||
|
||||
// r3, r14: number of arguments including receiver (C callee-saved)
|
||||
// r4: pointer to the first argument
|
||||
// r15: pointer to builtin function (C callee-saved)
|
||||
|
||||
// Result returned in registers or stack, depending on result size and ABI.
|
||||
|
||||
Register isolate_reg = r5;
|
||||
if (needs_return_buffer) {
|
||||
// The return value is a non-scalar value.
|
||||
// Use frame storage reserved by calling function to pass return
|
||||
// buffer as implicit first argument.
|
||||
__ mr(r5, r4);
|
||||
__ mr(r4, r3);
|
||||
__ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
|
||||
isolate_reg = r6;
|
||||
}
|
||||
|
||||
// Call C built-in.
|
||||
__ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate())));
|
||||
|
||||
Register target = r15;
|
||||
if (ABI_USES_FUNCTION_DESCRIPTORS) {
|
||||
// AIX/PPC64BE Linux use a function descriptor.
|
||||
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize));
|
||||
__ LoadP(ip, MemOperand(r15, 0)); // Instruction address
|
||||
target = ip;
|
||||
} else if (ABI_CALL_VIA_IP) {
|
||||
__ Move(ip, r15);
|
||||
target = ip;
|
||||
}
|
||||
|
||||
// To let the GC traverse the return address of the exit frames, we need to
|
||||
// know where the return address is. The CEntryStub is unmovable, so
|
||||
// we can store the address on the stack to be able to find it again and
|
||||
// we never have to restore it, because it will not change.
|
||||
Label after_call;
|
||||
__ mov_label_addr(r0, &after_call);
|
||||
__ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
|
||||
__ Call(target);
|
||||
__ bind(&after_call);
|
||||
|
||||
// If return value is on the stack, pop it to registers.
|
||||
if (needs_return_buffer) {
|
||||
__ LoadP(r4, MemOperand(r3, kPointerSize));
|
||||
__ LoadP(r3, MemOperand(r3));
|
||||
}
|
||||
|
||||
// Check result for exception sentinel.
|
||||
Label exception_returned;
|
||||
__ CompareRoot(r3, Heap::kExceptionRootIndex);
|
||||
__ beq(&exception_returned);
|
||||
|
||||
// Check that there is no pending exception, otherwise we
|
||||
// should have returned the exception sentinel.
|
||||
if (FLAG_debug_code) {
|
||||
Label okay;
|
||||
ExternalReference pending_exception_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingExceptionAddress, isolate());
|
||||
|
||||
__ mov(r6, Operand(pending_exception_address));
|
||||
__ LoadP(r6, MemOperand(r6));
|
||||
__ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
|
||||
// Cannot use check here as it attempts to generate call into runtime.
|
||||
__ beq(&okay);
|
||||
__ stop("Unexpected pending exception");
|
||||
__ bind(&okay);
|
||||
}
|
||||
|
||||
// Exit C frame and return.
|
||||
// r3:r4: result
|
||||
// sp: stack pointer
|
||||
// fp: frame pointer
|
||||
Register argc = argv_in_register()
|
||||
// We don't want to pop arguments so set argc to no_reg.
|
||||
? no_reg
|
||||
// r14: still holds argc (callee-saved).
|
||||
: r14;
|
||||
__ LeaveExitFrame(save_doubles(), argc);
|
||||
__ blr();
|
||||
|
||||
// Handling of exception.
|
||||
__ bind(&exception_returned);
|
||||
|
||||
ExternalReference pending_handler_context_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerContextAddress, isolate());
|
||||
ExternalReference pending_handler_entrypoint_address =
|
||||
ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerEntrypointAddress, isolate());
|
||||
ExternalReference pending_handler_constant_pool_address =
|
||||
ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerConstantPoolAddress, isolate());
|
||||
ExternalReference pending_handler_fp_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerFPAddress, isolate());
|
||||
ExternalReference pending_handler_sp_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerSPAddress, isolate());
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set r3 to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler =
|
||||
ExternalReference::Create(Runtime::kUnwindAndFindExceptionHandler);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, 0, r3);
|
||||
__ li(r3, Operand::Zero());
|
||||
__ li(r4, Operand::Zero());
|
||||
__ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
|
||||
__ CallCFunction(find_handler, 3);
|
||||
}
|
||||
|
||||
// Retrieve the handler context, SP and FP.
|
||||
__ mov(cp, Operand(pending_handler_context_address));
|
||||
__ LoadP(cp, MemOperand(cp));
|
||||
__ mov(sp, Operand(pending_handler_sp_address));
|
||||
__ LoadP(sp, MemOperand(sp));
|
||||
__ mov(fp, Operand(pending_handler_fp_address));
|
||||
__ LoadP(fp, MemOperand(fp));
|
||||
|
||||
// If the handler is a JS frame, restore the context to the frame. Note that
|
||||
// the context will be set to (cp == 0) for non-JS frames.
|
||||
Label skip;
|
||||
__ cmpi(cp, Operand::Zero());
|
||||
__ beq(&skip);
|
||||
__ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
__ bind(&skip);
|
||||
|
||||
// Reset the masking register.
|
||||
if (FLAG_branch_load_poisoning) {
|
||||
__ ResetSpeculationPoisonRegister();
|
||||
}
|
||||
|
||||
// Compute the handler entry address and jump to it.
|
||||
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
|
||||
__ mov(ip, Operand(pending_handler_entrypoint_address));
|
||||
__ LoadP(ip, MemOperand(ip));
|
||||
if (FLAG_enable_embedded_constant_pool) {
|
||||
__ mov(kConstantPoolRegister,
|
||||
Operand(pending_handler_constant_pool_address));
|
||||
__ LoadP(kConstantPoolRegister, MemOperand(kConstantPoolRegister));
|
||||
}
|
||||
__ Jump(ip);
|
||||
}
|
||||
|
||||
|
||||
void JSEntryStub::Generate(MacroAssembler* masm) {
|
||||
// r3: code entry
|
||||
// r4: function
|
||||
|
@ -253,12 +253,6 @@ void BinaryOpDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void StringAddDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {r4, r3};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void ArgumentAdaptorDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "src/bootstrapper.h"
|
||||
#include "src/builtins/constants-table-builder.h"
|
||||
#include "src/callable.h"
|
||||
#include "src/code-factory.h"
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/external-reference-table.h"
|
||||
@ -1060,7 +1061,7 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
|
||||
StoreP(kConstantPoolRegister,
|
||||
MemOperand(fp, ExitFrameConstants::kConstantPoolOffset));
|
||||
}
|
||||
mov(r8, Operand(CodeObject()));
|
||||
Move(r8, CodeObject());
|
||||
StoreP(r8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
|
||||
|
||||
// Save the frame pointer and the context in top.
|
||||
@ -1684,13 +1685,13 @@ void TurboAssembler::CallRuntimeDelayed(Zone* zone, Runtime::FunctionId fid,
|
||||
// smarter.
|
||||
mov(r3, Operand(f->nargs));
|
||||
Move(r4, ExternalReference::Create(f));
|
||||
CallStubDelayed(new (zone) CEntryStub(nullptr,
|
||||
#if V8_TARGET_ARCH_PPC64
|
||||
f->result_size,
|
||||
Handle<Code> code =
|
||||
CodeFactory::CEntry(isolate(), f->result_size, save_doubles);
|
||||
#else
|
||||
1,
|
||||
Handle<Code> code = CodeFactory::CEntry(isolate(), 1, save_doubles);
|
||||
#endif
|
||||
save_doubles));
|
||||
Call(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
|
||||
@ -1708,14 +1709,13 @@ void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
|
||||
// smarter.
|
||||
mov(r3, Operand(num_arguments));
|
||||
Move(r4, ExternalReference::Create(f));
|
||||
CEntryStub stub(isolate(),
|
||||
#if V8_TARGET_ARCH_PPC64
|
||||
f->result_size,
|
||||
Handle<Code> code =
|
||||
CodeFactory::CEntry(isolate(), f->result_size, save_doubles);
|
||||
#else
|
||||
1,
|
||||
Handle<Code> code = CodeFactory::CEntry(isolate(), 1, save_doubles);
|
||||
#endif
|
||||
save_doubles);
|
||||
CallStub(&stub);
|
||||
Call(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
|
||||
@ -1731,9 +1731,9 @@ void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
|
||||
void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
|
||||
bool builtin_exit_frame) {
|
||||
Move(r4, builtin);
|
||||
CEntryStub stub(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
|
||||
builtin_exit_frame);
|
||||
Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
|
||||
Handle<Code> code = CodeFactory::CEntry(isolate(), 1, kDontSaveFPRegs,
|
||||
kArgvOnStack, builtin_exit_frame);
|
||||
Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
void MacroAssembler::JumpToInstructionStream(Address entry) {
|
||||
|
@ -35,204 +35,11 @@ void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kNewArray);
|
||||
}
|
||||
|
||||
Movability CEntryStub::NeedsImmovableCode() { return kImmovable; }
|
||||
|
||||
void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
|
||||
CEntryStub::GenerateAheadOfTime(isolate);
|
||||
CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
|
||||
StoreFastElementStub::GenerateAheadOfTime(isolate);
|
||||
}
|
||||
|
||||
void CodeStub::GenerateFPStubs(Isolate* isolate) {
|
||||
SaveFPRegsMode mode = kSaveFPRegs;
|
||||
CEntryStub(isolate, 1, mode).GetCode();
|
||||
}
|
||||
|
||||
void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
|
||||
CEntryStub stub(isolate, 1, kDontSaveFPRegs);
|
||||
stub.GetCode();
|
||||
CEntryStub save_doubles(isolate, 1, kSaveFPRegs);
|
||||
save_doubles.GetCode();
|
||||
}
|
||||
|
||||
void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
// Called from JavaScript; parameters are on stack as if calling JS function.
|
||||
// r2: number of arguments including receiver
|
||||
// r3: pointer to builtin function
|
||||
// fp: frame pointer (restored after C call)
|
||||
// sp: stack pointer (restored as callee's sp after C call)
|
||||
// cp: current context (C callee-saved)
|
||||
//
|
||||
// If argv_in_register():
|
||||
// r4: pointer to the first argument
|
||||
ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
||||
|
||||
__ LoadRR(r7, r3);
|
||||
|
||||
if (argv_in_register()) {
|
||||
// Move argv into the correct register.
|
||||
__ LoadRR(r3, r4);
|
||||
} else {
|
||||
// Compute the argv pointer.
|
||||
__ ShiftLeftP(r3, r2, Operand(kPointerSizeLog2));
|
||||
__ lay(r3, MemOperand(r3, sp, -kPointerSize));
|
||||
}
|
||||
|
||||
// Enter the exit frame that transitions from JavaScript to C++.
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
|
||||
// Need at least one extra slot for return address location.
|
||||
int arg_stack_space = 1;
|
||||
|
||||
// Pass buffer for return value on stack if necessary
|
||||
bool needs_return_buffer =
|
||||
result_size() == 2 && !ABI_RETURNS_OBJECTPAIR_IN_REGS;
|
||||
if (needs_return_buffer) {
|
||||
arg_stack_space += result_size();
|
||||
}
|
||||
|
||||
#if V8_TARGET_ARCH_S390X
|
||||
// 64-bit linux pass Argument object by reference not value
|
||||
arg_stack_space += 2;
|
||||
#endif
|
||||
|
||||
__ EnterExitFrame(save_doubles(), arg_stack_space, is_builtin_exit()
|
||||
? StackFrame::BUILTIN_EXIT
|
||||
: StackFrame::EXIT);
|
||||
|
||||
// Store a copy of argc, argv in callee-saved registers for later.
|
||||
__ LoadRR(r6, r2);
|
||||
__ LoadRR(r8, r3);
|
||||
// r2, r6: number of arguments including receiver (C callee-saved)
|
||||
// r3, r8: pointer to the first argument
|
||||
// r7: pointer to builtin function (C callee-saved)
|
||||
|
||||
// Result returned in registers or stack, depending on result size and ABI.
|
||||
|
||||
Register isolate_reg = r4;
|
||||
if (needs_return_buffer) {
|
||||
// The return value is 16-byte non-scalar value.
|
||||
// Use frame storage reserved by calling function to pass return
|
||||
// buffer as implicit first argument in R2. Shfit original parameters
|
||||
// by one register each.
|
||||
__ LoadRR(r4, r3);
|
||||
__ LoadRR(r3, r2);
|
||||
__ la(r2, MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize));
|
||||
isolate_reg = r5;
|
||||
}
|
||||
// Call C built-in.
|
||||
__ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate())));
|
||||
|
||||
Register target = r7;
|
||||
|
||||
// To let the GC traverse the return address of the exit frames, we need to
|
||||
// know where the return address is. The CEntryStub is unmovable, so
|
||||
// we can store the address on the stack to be able to find it again and
|
||||
// we never have to restore it, because it will not change.
|
||||
{
|
||||
Label return_label;
|
||||
__ larl(r14, &return_label); // Generate the return addr of call later.
|
||||
__ StoreP(r14, MemOperand(sp, kStackFrameRASlot * kPointerSize));
|
||||
|
||||
// zLinux ABI requires caller's frame to have sufficient space for callee
|
||||
// preserved regsiter save area.
|
||||
// __ lay(sp, MemOperand(sp, -kCalleeRegisterSaveAreaSize));
|
||||
__ b(target);
|
||||
__ bind(&return_label);
|
||||
// __ la(sp, MemOperand(sp, +kCalleeRegisterSaveAreaSize));
|
||||
}
|
||||
|
||||
// If return value is on the stack, pop it to registers.
|
||||
if (needs_return_buffer) {
|
||||
__ LoadP(r3, MemOperand(r2, kPointerSize));
|
||||
__ LoadP(r2, MemOperand(r2));
|
||||
}
|
||||
|
||||
// Check result for exception sentinel.
|
||||
Label exception_returned;
|
||||
__ CompareRoot(r2, Heap::kExceptionRootIndex);
|
||||
__ beq(&exception_returned, Label::kNear);
|
||||
|
||||
// Check that there is no pending exception, otherwise we
|
||||
// should have returned the exception sentinel.
|
||||
if (FLAG_debug_code) {
|
||||
Label okay;
|
||||
ExternalReference pending_exception_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingExceptionAddress, isolate());
|
||||
__ mov(r1, Operand(pending_exception_address));
|
||||
__ LoadP(r1, MemOperand(r1));
|
||||
__ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
|
||||
// Cannot use check here as it attempts to generate call into runtime.
|
||||
__ beq(&okay, Label::kNear);
|
||||
__ stop("Unexpected pending exception");
|
||||
__ bind(&okay);
|
||||
}
|
||||
|
||||
// Exit C frame and return.
|
||||
// r2:r3: result
|
||||
// sp: stack pointer
|
||||
// fp: frame pointer
|
||||
Register argc = argv_in_register()
|
||||
// We don't want to pop arguments so set argc to no_reg.
|
||||
? no_reg
|
||||
// r6: still holds argc (callee-saved).
|
||||
: r6;
|
||||
__ LeaveExitFrame(save_doubles(), argc);
|
||||
__ b(r14);
|
||||
|
||||
// Handling of exception.
|
||||
__ bind(&exception_returned);
|
||||
|
||||
ExternalReference pending_handler_context_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerContextAddress, isolate());
|
||||
ExternalReference pending_handler_entrypoint_address =
|
||||
ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerEntrypointAddress, isolate());
|
||||
ExternalReference pending_handler_fp_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerFPAddress, isolate());
|
||||
ExternalReference pending_handler_sp_address = ExternalReference::Create(
|
||||
IsolateAddressId::kPendingHandlerSPAddress, isolate());
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set r3 to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler =
|
||||
ExternalReference::Create(Runtime::kUnwindAndFindExceptionHandler);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, 0, r2);
|
||||
__ LoadImmP(r2, Operand::Zero());
|
||||
__ LoadImmP(r3, Operand::Zero());
|
||||
__ mov(r4, Operand(ExternalReference::isolate_address(isolate())));
|
||||
__ CallCFunction(find_handler, 3);
|
||||
}
|
||||
|
||||
// Retrieve the handler context, SP and FP.
|
||||
__ mov(cp, Operand(pending_handler_context_address));
|
||||
__ LoadP(cp, MemOperand(cp));
|
||||
__ mov(sp, Operand(pending_handler_sp_address));
|
||||
__ LoadP(sp, MemOperand(sp));
|
||||
__ mov(fp, Operand(pending_handler_fp_address));
|
||||
__ LoadP(fp, MemOperand(fp));
|
||||
|
||||
// If the handler is a JS frame, restore the context to the frame. Note that
|
||||
// the context will be set to (cp == 0) for non-JS frames.
|
||||
Label skip;
|
||||
__ CmpP(cp, Operand::Zero());
|
||||
__ beq(&skip, Label::kNear);
|
||||
__ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
__ bind(&skip);
|
||||
|
||||
// Reset the masking register.
|
||||
if (FLAG_branch_load_poisoning) {
|
||||
__ ResetSpeculationPoisonRegister();
|
||||
}
|
||||
|
||||
// Compute the handler entry address and jump to it.
|
||||
__ mov(r3, Operand(pending_handler_entrypoint_address));
|
||||
__ LoadP(r3, MemOperand(r3));
|
||||
__ Jump(r3);
|
||||
}
|
||||
|
||||
void JSEntryStub::Generate(MacroAssembler* masm) {
|
||||
// r2: code entry
|
||||
// r3: function
|
||||
|
@ -247,12 +247,6 @@ void BinaryOpDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void StringAddDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {r3, r2};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void ArgumentAdaptorDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "src/bootstrapper.h"
|
||||
#include "src/builtins/constants-table-builder.h"
|
||||
#include "src/callable.h"
|
||||
#include "src/code-factory.h"
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/external-reference-table.h"
|
||||
@ -1084,7 +1085,7 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
|
||||
if (emit_debug_code()) {
|
||||
StoreP(MemOperand(fp, ExitFrameConstants::kSPOffset), Operand::Zero(), r1);
|
||||
}
|
||||
mov(r1, Operand(CodeObject()));
|
||||
Move(r1, CodeObject());
|
||||
StoreP(r1, MemOperand(fp, ExitFrameConstants::kCodeOffset));
|
||||
|
||||
// Save the frame pointer and the context in top.
|
||||
@ -1155,14 +1156,14 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
|
||||
StoreP(MemOperand(ip), Operand(0, RelocInfo::NONE), r0);
|
||||
|
||||
// Restore current context from top and clear it in debug mode.
|
||||
mov(ip, Operand(ExternalReference::Create(IsolateAddressId::kContextAddress,
|
||||
isolate())));
|
||||
Move(ip,
|
||||
ExternalReference::Create(IsolateAddressId::kContextAddress, isolate()));
|
||||
LoadP(cp, MemOperand(ip));
|
||||
|
||||
#ifdef DEBUG
|
||||
mov(r1, Operand(Context::kInvalidContext));
|
||||
mov(ip, Operand(ExternalReference::Create(IsolateAddressId::kContextAddress,
|
||||
isolate())));
|
||||
Move(ip,
|
||||
ExternalReference::Create(IsolateAddressId::kContextAddress, isolate()));
|
||||
StoreP(r1, MemOperand(ip));
|
||||
#endif
|
||||
|
||||
@ -1584,13 +1585,14 @@ void TurboAssembler::CallRuntimeDelayed(Zone* zone, Runtime::FunctionId fid,
|
||||
const Runtime::Function* f = Runtime::FunctionForId(fid);
|
||||
mov(r2, Operand(f->nargs));
|
||||
Move(r3, ExternalReference::Create(f));
|
||||
CallStubDelayed(new (zone) CEntryStub(nullptr,
|
||||
|
||||
#if V8_TARGET_ARCH_S390X
|
||||
f->result_size,
|
||||
Handle<Code> code =
|
||||
CodeFactory::CEntry(isolate(), f->result_size, save_doubles);
|
||||
#else
|
||||
1,
|
||||
Handle<Code> code = CodeFactory::CEntry(isolate(), 1, save_doubles);
|
||||
#endif
|
||||
save_doubles));
|
||||
Call(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
|
||||
@ -1608,14 +1610,14 @@ void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
|
||||
// smarter.
|
||||
mov(r2, Operand(num_arguments));
|
||||
Move(r3, ExternalReference::Create(f));
|
||||
CEntryStub stub(isolate(),
|
||||
#if V8_TARGET_ARCH_S390X
|
||||
f->result_size,
|
||||
Handle<Code> code =
|
||||
CodeFactory::CEntry(isolate(), f->result_size, save_doubles);
|
||||
#else
|
||||
1,
|
||||
Handle<Code> code = CodeFactory::CEntry(isolate(), 1, save_doubles);
|
||||
#endif
|
||||
save_doubles);
|
||||
CallStub(&stub);
|
||||
|
||||
Call(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
|
||||
@ -1630,9 +1632,9 @@ void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
|
||||
void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
|
||||
bool builtin_exit_frame) {
|
||||
Move(r3, builtin);
|
||||
CEntryStub stub(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
|
||||
builtin_exit_frame);
|
||||
Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
|
||||
Handle<Code> code = CodeFactory::CEntry(isolate(), 1, kDontSaveFPRegs,
|
||||
kArgvOnStack, builtin_exit_frame);
|
||||
Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
void MacroAssembler::JumpToInstructionStream(Address entry) {
|
||||
|
Loading…
Reference in New Issue
Block a user