Commit 2713a83b authored by Junliang Yan's avatar Junliang Yan Committed by Commit Bot

PPC/s390: [nojit] Migrate DirectCEntryStub to a builtin

Port bec0234f

Original Commit Message:

    been converted to builtins themselves and are thus immovable.

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

Change-Id: I5e08b7a894ab72647028735521d7851b15ef5f12
Reviewed-on: https://chromium-review.googlesource.com/c/1363566Reviewed-by: 's avatarJoran Siu <joransiu@ca.ibm.com>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#58097}
parent 134c67ef
......@@ -2978,7 +2978,6 @@ v8_source_set("v8_base") {
"src/ppc/assembler-ppc.cc",
"src/ppc/assembler-ppc.h",
"src/ppc/code-stubs-ppc.cc",
"src/ppc/code-stubs-ppc.h",
"src/ppc/codegen-ppc.cc",
"src/ppc/constants-ppc.cc",
"src/ppc/constants-ppc.h",
......@@ -3009,7 +3008,6 @@ v8_source_set("v8_base") {
"src/s390/assembler-s390.cc",
"src/s390/assembler-s390.h",
"src/s390/code-stubs-s390.cc",
"src/s390/code-stubs-s390.h",
"src/s390/codegen-s390.cc",
"src/s390/constants-s390.cc",
"src/s390/constants-s390.h",
......
......@@ -2403,20 +2403,7 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
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 * 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 - kInstrSize,
__ SizeOfCodeGeneratedSince(&start_call));
__ StoreReturnAddressAndCall(target);
// If return value is on the stack, pop it to registers.
if (needs_return_buffer) {
......@@ -2885,11 +2872,7 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
__ PopSafepointRegisters();
}
// Native call returns to the DirectCEntry stub which redirects to the
// return address pushed on stack (could have moved after GC).
// DirectCEntry stub itself is generated early and never moves.
DirectCEntryStub stub(isolate);
stub.GenerateCall(masm, scratch);
__ StoreReturnAddressAndCall(scratch);
if (FLAG_log_timer_events) {
FrameScope frame(masm, StackFrame::MANUAL);
......@@ -3192,6 +3175,11 @@ void Builtins::Generate_CallApiGetter(MacroAssembler* masm) {
return_value_operand);
}
void Builtins::Generate_DirectCEntry(MacroAssembler* masm) {
// Unused.
__ stop(0);
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -2406,24 +2406,7 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
// 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));
}
__ StoreReturnAddressAndCall(r7);
// If return value is on the stack, pop it to registers.
if (needs_return_buffer) {
......@@ -2869,11 +2852,7 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
__ PopSafepointRegisters();
}
// Native call returns to the DirectCEntry stub which redirects to the
// return address pushed on stack (could have moved after GC).
// DirectCEntry stub itself is generated early and never moves.
DirectCEntryStub stub(isolate);
stub.GenerateCall(masm, scratch);
__ StoreReturnAddressAndCall(scratch);
if (FLAG_log_timer_events) {
FrameScope frame(masm, StackFrame::MANUAL);
......@@ -3174,6 +3153,11 @@ void Builtins::Generate_CallApiGetter(MacroAssembler* masm) {
return_value_operand);
}
void Builtins::Generate_DirectCEntry(MacroAssembler* masm) {
// Unused.
__ stop(0);
}
#undef __
} // namespace internal
......
......@@ -21,8 +21,6 @@
#include "src/regexp/regexp-macro-assembler.h"
#include "src/runtime/runtime.h"
#include "src/ppc/code-stubs-ppc.h" // Cannot be the first include.
namespace v8 {
namespace internal {
......@@ -174,55 +172,6 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ blr();
}
// This stub is paired with DirectCEntryStub::GenerateCall
void DirectCEntryStub::Generate(MacroAssembler* masm) {
// Place the return address on the stack, making the call
// GC safe. The RegExp backend also relies on this.
__ mflr(r0);
__ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
if (ABI_USES_FUNCTION_DESCRIPTORS && FLAG_embedded_builtins) {
// AIX/PPC64BE Linux use a function descriptor;
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize));
__ LoadP(ip, MemOperand(ip, 0)); // Instruction address
}
__ Call(ip); // Call the C++ function.
__ LoadP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
__ mtlr(r0);
__ blr();
}
void DirectCEntryStub::GenerateCall(MacroAssembler* masm, Register target) {
if (FLAG_embedded_builtins) {
if (masm->root_array_available() &&
isolate()->ShouldLoadConstantsFromRootList()) {
// This is basically an inlined version of Call(Handle<Code>) that loads
// the code object into lr instead of ip.
DCHECK_NE(ip, target);
__ IndirectLoadConstant(ip, GetCode());
__ addi(r0, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Move(ip, target);
__ Call(r0);
return;
}
}
if (ABI_USES_FUNCTION_DESCRIPTORS && !FLAG_embedded_builtins) {
// AIX/PPC64BE Linux use a function descriptor.
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize));
__ LoadP(ip, MemOperand(target, 0)); // Instruction address
} else {
// ip needs to be set for DirectCEentryStub::Generate, and also
// for ABI_CALL_VIA_IP.
__ Move(ip, target);
}
intptr_t code = reinterpret_cast<intptr_t>(GetCode().location());
__ mov(r0, Operand(code, RelocInfo::CODE_TARGET));
__ Call(r0); // Call the stub.
}
#undef __
} // namespace internal
} // namespace v8
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_PPC_CODE_STUBS_PPC_H_
#define V8_PPC_CODE_STUBS_PPC_H_
namespace v8 {
namespace internal {
// Trampoline stub to call into native code. To call safely into native code
// in the presence of compacting GC (which can move code objects) we need to
// keep the code which called into native pinned in the memory. Currently the
// simplest approach is to generate such stub early enough so it can never be
// moved by GC
class DirectCEntryStub : public PlatformCodeStub {
public:
explicit DirectCEntryStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
void GenerateCall(MacroAssembler* masm, Register target);
private:
Movability NeedsImmovableCode() override { return kImmovable; }
DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
DEFINE_PLATFORM_CODE_STUB(DirectCEntry, PlatformCodeStub);
};
} // namespace internal
} // namespace v8
#endif // V8_PPC_CODE_STUBS_PPC_H_
......@@ -3044,6 +3044,25 @@ void TurboAssembler::JumpIfLessThan(Register x, int32_t y, Label* dest) {
blt(dest);
}
void TurboAssembler::StoreReturnAddressAndCall(Register target) {
// This generates the final instruction sequence for calls to C functions
// once an exit frame has been constructed.
//
// Note that this assumes the caller code (i.e. the Code object currently
// being generated) is immovable or that the callee function cannot trigger
// GC, since the callee function will return to it.
Label start_call;
static constexpr int after_call_offset = 5 * kInstrSize;
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 - kInstrSize,
__ SizeOfCodeGeneratedSince(&start_call));
}
} // namespace internal
} // namespace v8
......
......@@ -652,6 +652,11 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
#endif
}
// Generates an instruction sequence s.t. the return address points to the
// instruction following the call.
// The return address on the stack is used by frame iteration.
void StoreReturnAddressAndCall(Register target);
void ResetSpeculationPoisonRegister();
private:
......
......@@ -13,6 +13,7 @@
#include "src/macro-assembler.h"
#include "src/regexp/regexp-macro-assembler.h"
#include "src/regexp/regexp-stack.h"
#include "src/snapshot/embedded-data.h"
#include "src/unicode.h"
namespace v8 {
......@@ -1091,6 +1092,9 @@ void RegExpMacroAssemblerPPC::WriteStackPointerToRegister(int reg) {
// Private methods:
void RegExpMacroAssemblerPPC::CallCheckStackGuardState(Register scratch) {
DCHECK(!isolate()->ShouldLoadConstantsFromRootList());
DCHECK(!masm_->options().isolate_independent_code);
int frame_alignment = masm_->ActivationFrameAlignment();
int stack_space = kNumRequiredStackFrameSlots;
int stack_passed_arguments = 1; // space for return address pointer
......@@ -1125,8 +1129,7 @@ void RegExpMacroAssemblerPPC::CallCheckStackGuardState(Register scratch) {
ExternalReference stack_guard_check =
ExternalReference::re_check_stack_guard_state(isolate());
__ mov(ip, Operand(stack_guard_check));
DirectCEntryStub stub(isolate());
stub.GenerateCall(masm_, ip);
__ StoreReturnAddressAndCall(ip);
// Restore the stack pointer
stack_space = kNumRequiredStackFrameSlots + stack_passed_arguments;
......
......@@ -13,6 +13,7 @@
#include "src/macro-assembler.h"
#include "src/regexp/regexp-macro-assembler.h"
#include "src/regexp/regexp-stack.h"
#include "src/snapshot/embedded-data.h"
#include "src/regexp/s390/regexp-macro-assembler-s390.h"
#include "src/unicode.h"
......@@ -1071,7 +1072,10 @@ void RegExpMacroAssemblerS390::WriteStackPointerToRegister(int reg) {
// Private methods:
void RegExpMacroAssemblerS390::CallCheckStackGuardState(Register scratch) {
static const int num_arguments = 3;
DCHECK(!isolate()->ShouldLoadConstantsFromRootList());
DCHECK(!masm_->options().isolate_independent_code);
static constexpr int num_arguments = 3;
__ PrepareCallCFunction(num_arguments, scratch);
// RegExp code frame pointer.
__ LoadRR(r4, frame_pointer());
......@@ -1081,7 +1085,17 @@ void RegExpMacroAssemblerS390::CallCheckStackGuardState(Register scratch) {
__ lay(r2, MemOperand(sp, kStackFrameRASlot * kPointerSize));
ExternalReference stack_guard_check =
ExternalReference::re_check_stack_guard_state(isolate());
CallCFunctionUsingStub(stack_guard_check, num_arguments);
__ mov(ip, Operand(stack_guard_check));
__ StoreReturnAddressAndCall(ip);
if (base::OS::ActivationFrameAlignment() > kPointerSize) {
__ LoadP(sp, MemOperand(sp, (kNumRequiredStackFrameSlots * kPointerSize)));
} else {
__ la(sp, MemOperand(sp, (kNumRequiredStackFrameSlots * kPointerSize)));
}
__ mov(code_pointer(), Operand(masm_->CodeObject()));
}
// Helper function for reading a value out of a stack frame.
......
......@@ -20,8 +20,6 @@
#include "src/regexp/regexp-macro-assembler.h"
#include "src/runtime/runtime.h"
#include "src/s390/code-stubs-s390.h" // Cannot be the first include.
namespace v8 {
namespace internal {
......@@ -208,39 +206,6 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ b(r14);
}
// This stub is paired with DirectCEntryStub::GenerateCall
void DirectCEntryStub::Generate(MacroAssembler* masm) {
__ CleanseP(r14);
__ b(ip); // Callee will return to R14 directly
}
void DirectCEntryStub::GenerateCall(MacroAssembler* masm, Register target) {
if (FLAG_embedded_builtins) {
if (masm->root_array_available() &&
isolate()->ShouldLoadConstantsFromRootList()) {
// This is basically an inlined version of Call(Handle<Code>) that loads
// the code object into lr instead of ip.
__ Move(ip, target);
__ IndirectLoadConstant(r1, GetCode());
__ AddP(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Call(r1);
return;
}
}
#if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
// Native AIX/S390X Linux use a function descriptor.
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize));
__ LoadP(target, MemOperand(target, 0)); // Instruction address
#else
// ip needs to be set for DirectCEentryStub::Generate, and also
// for ABI_CALL_VIA_IP.
__ Move(ip, target);
#endif
__ call(GetCode(), RelocInfo::CODE_TARGET); // Call the stub.
}
#undef __
} // namespace internal
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_S390_CODE_STUBS_S390_H_
#define V8_S390_CODE_STUBS_S390_H_
namespace v8 {
namespace internal {
// Trampoline stub to call into native code. To call safely into native code
// in the presence of compacting GC (which can move code objects) we need to
// keep the code which called into native pinned in the memory. Currently the
// simplest approach is to generate such stub early enough so it can never be
// moved by GC
class DirectCEntryStub : public PlatformCodeStub {
public:
explicit DirectCEntryStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
void GenerateCall(MacroAssembler* masm, Register target);
private:
Movability NeedsImmovableCode() override { return kImmovable; }
DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
DEFINE_PLATFORM_CODE_STUB(DirectCEntry, PlatformCodeStub);
};
} // namespace internal
} // namespace v8
#endif // V8_S390_CODE_STUBS_S390_H_
......@@ -4416,6 +4416,24 @@ void TurboAssembler::JumpIfLessThan(Register x, int32_t y, Label* dest) {
blt(dest);
}
void TurboAssembler::StoreReturnAddressAndCall(Register target) {
// This generates the final instruction sequence for calls to C functions
// once an exit frame has been constructed.
//
// Note that this assumes the caller code (i.e. the Code object currently
// being generated) is immovable or that the callee function cannot trigger
// GC, since the callee function will return to it.
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.
b(target);
bind(&return_label);
}
} // namespace internal
} // namespace v8
......
......@@ -1008,6 +1008,11 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void ComputeCodeStartAddress(Register dst);
void LoadPC(Register dst);
// Generates an instruction sequence s.t. the return address points to the
// instruction following the call.
// The return address on the stack is used by frame iteration.
void StoreReturnAddressAndCall(Register target);
private:
static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
......
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