Commit 2afe66c5 authored by Junliang Yan's avatar Junliang Yan Committed by Commit Bot

PPC/s390: [Deopt] Remove jump table in prologue of deopt entries.

Port 4ab96a9a

Original Commit Message:

    Remove the use of a jump table in the prologue of the deopt entries
    and instead pass the bailout id explicitly in a register when calling
    the deopt entry routine from optimized code. This unifies the logic
    with the way the Arm64 code works. It saves the following amount of
    memory in code stubs:

     - arm:  384KB
     - ia32: 480KB
     - x64:  240KB

    This could be offset by a slight increase in the size of optimized code
    for loading the immediate, however this impact should be minimal and
    will scale with the maximum number of bailout ids (e.g., the size of
    code will increase by one instruction per bailout id on Arm, therefore
    ~98,000 bailouts will be needed before the overhead is greater than
    the current fixed table size).

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

Change-Id: Id5762334b21e6a91e5ce44b7db1e38ace9147372
Reviewed-on: https://chromium-review.googlesource.com/c/1406026
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Reviewed-by: 's avatarJoran Siu <joransiu@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#58752}
parent e2d44ede
......@@ -162,11 +162,6 @@ bool RelocInfo::IsInConstantPool() {
return false;
}
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind);
}
uint32_t RelocInfo::wasm_call_tag() const {
DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
return static_cast<uint32_t>(
......
......@@ -11,17 +11,14 @@
namespace v8 {
namespace internal {
const int Deoptimizer::table_entry_size_ = 8;
#define __ masm->
// This code tries to be close to ia32 code so that any changes can be
// easily ported.
void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
Isolate* isolate, int count,
Isolate* isolate,
DeoptimizeKind deopt_kind) {
NoRootArrayScope no_root_array(masm);
GenerateDeoptimizationEntriesPrologue(masm, count);
// Unlike on ARM we don't save all the registers, just the useful ones.
// For the rest, there are gaps on the stack, so the offsets remain the same.
......@@ -67,15 +64,14 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
const int kSavedRegistersAreaSize =
(kNumberOfRegisters * kPointerSize) + kDoubleRegsSize + kFloatRegsSize;
// Get the bailout id from the stack.
__ LoadP(r5, MemOperand(sp, kSavedRegistersAreaSize));
// Get the bailout id is passed as r29 by the caller.
__ mr(r5, r29);
// Get the address of the location in the code object (r6) (return
// address for lazy deoptimization) and compute the fp-to-sp delta in
// register r7.
__ mflr(r6);
// Correct one word for bailout id.
__ addi(r7, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
__ addi(r7, sp, Operand(kSavedRegistersAreaSize));
__ sub(r7, fp, r7);
// Allocate a new deoptimizer object.
......@@ -131,8 +127,9 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
__ lfs(d0, MemOperand(sp, src_offset));
__ stfs(d0, MemOperand(r4, dst_offset));
}
// Remove the bailout id and the saved registers from the stack.
__ addi(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
// Remove the saved registers from the stack.
__ addi(sp, sp, Operand(kSavedRegistersAreaSize));
// Compute a pointer to the unwinding limit in register r5; that is
// the first stack slot not part of the input frame.
......@@ -229,24 +226,6 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
__ stop("Unreachable.");
}
void Deoptimizer::GenerateDeoptimizationEntriesPrologue(MacroAssembler* masm,
int count) {
Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
// Create a sequence of deoptimization entries.
// Note that registers are still live when jumping to an entry.
Label done;
for (int i = 0; i < count; i++) {
int start = masm->pc_offset();
USE(start);
__ li(ip, Operand(i));
__ b(&done);
DCHECK(masm->pc_offset() - start == table_entry_size_);
}
__ bind(&done);
__ push(ip);
}
bool Deoptimizer::PadTopOfStackRegister() { return false; }
void FrameDescription::SetCallerPc(unsigned offset, intptr_t value) {
......
......@@ -3134,6 +3134,16 @@ void TurboAssembler::StoreReturnAddressAndCall(Register target) {
SizeOfCodeGeneratedSince(&start_call));
}
void TurboAssembler::CallForDeoptimization(Address target, int deopt_id) {
NoRootArrayScope no_root_array(this);
// Save the deopt id in r29 (we don't need the roots array from now on).
DCHECK_LE(deopt_id, 0xFFFF);
mov(r29, Operand(deopt_id));
Call(target, RelocInfo::RUNTIME_ENTRY);
}
} // namespace internal
} // namespace v8
......
......@@ -417,13 +417,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void JumpCodeObject(Register code_object) override;
void CallBuiltinPointer(Register builtin_pointer) override;
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
USE(deopt_id);
Call(target, rmode);
}
void CallForDeoptimization(Address target, int deopt_id);
// Emit code to discard a non-negative number of pointer-sized elements
// from the stack, clobbering only the sp register.
......
......@@ -274,11 +274,6 @@ bool RelocInfo::IsCodedSpecially() {
bool RelocInfo::IsInConstantPool() { return false; }
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind);
}
uint32_t RelocInfo::wasm_call_tag() const {
DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
return static_cast<uint32_t>(
......
......@@ -10,19 +10,14 @@
namespace v8 {
namespace internal {
// LAY + LGHI/LHI + BRCL
const int Deoptimizer::table_entry_size_ = 16;
#define __ masm->
// This code tries to be close to ia32 code so that any changes can be
// easily ported.
void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
Isolate* isolate, int count,
Isolate* isolate,
DeoptimizeKind deopt_kind) {
NoRootArrayScope no_root_array(masm);
Label deopt_table_entry;
GenerateDeoptimizationEntriesPrologue(masm, count);
// Save all the registers onto the stack
const int kNumberOfRegisters = Register::kNumRegisters;
......@@ -54,15 +49,15 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
__ lay(sp, MemOperand(sp, -kNumberOfRegisters * kPointerSize));
__ StoreMultipleP(r0, sp, MemOperand(sp)); // Save all 16 registers
__ mov(ip, Operand(ExternalReference::Create(
__ mov(r1, Operand(ExternalReference::Create(
IsolateAddressId::kCEntryFPAddress, isolate)));
__ StoreP(fp, MemOperand(ip));
__ StoreP(fp, MemOperand(r1));
const int kSavedRegistersAreaSize =
(kNumberOfRegisters * kPointerSize) + kDoubleRegsSize + kFloatRegsSize;
// Get the bailout id from the stack.
__ LoadP(r4, MemOperand(sp, kSavedRegistersAreaSize));
// The bailout id is passed using r10
__ LoadRR(r4, r10);
// Cleanse the Return address for 31-bit
__ CleanseP(r14);
......@@ -71,7 +66,8 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
// address for lazy deoptimization) and compute the fp-to-sp delta in
// register r6.
__ LoadRR(r5, r14);
__ la(r6, MemOperand(sp, kSavedRegistersAreaSize + (1 * kPointerSize)));
__ la(r6, MemOperand(sp, kSavedRegistersAreaSize));
__ SubP(r6, fp, r6);
// Allocate a new deoptimizer object.
......@@ -138,8 +134,9 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
__ LoadFloat32(d0, MemOperand(sp, src_offset));
__ StoreFloat32(d0, MemOperand(r3, dst_offset));
}
// Remove the bailout id and the saved registers from the stack.
__ la(sp, MemOperand(sp, kSavedRegistersAreaSize + (1 * kPointerSize)));
// Remove the saved registers from the stack.
__ la(sp, MemOperand(sp, kSavedRegistersAreaSize));
// Compute a pointer to the unwinding limit in register r4; that is
// the first stack slot not part of the input frame.
......@@ -191,7 +188,7 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
__ b(&inner_loop_header, Label::kNear);
__ bind(&inner_push_loop);
__ AddP(r5, Operand(-sizeof(intptr_t)));
__ SubP(r5, Operand(sizeof(intptr_t)));
__ AddP(r8, r4, r5);
__ LoadP(r8, MemOperand(r8, FrameDescription::frame_content_offset()));
__ push(r8);
......@@ -234,25 +231,6 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
__ stop("Unreachable.");
}
void Deoptimizer::GenerateDeoptimizationEntriesPrologue(MacroAssembler* masm,
int count) {
// Create a sequence of deoptimization entries. Note that any
// registers may be still live.
Label done;
for (int i = 0; i < count; i++) {
int start = masm->pc_offset();
USE(start);
__ lay(sp, MemOperand(sp, -kPointerSize));
__ LoadImmP(ip, Operand(i));
__ b(&done);
int end = masm->pc_offset();
USE(end);
DCHECK(masm->pc_offset() - start == table_entry_size_);
}
__ bind(&done);
__ StoreP(ip, MemOperand(sp));
}
bool Deoptimizer::PadTopOfStackRegister() { return false; }
void FrameDescription::SetCallerPc(unsigned offset, intptr_t value) {
......
......@@ -4476,6 +4476,15 @@ void TurboAssembler::StoreReturnAddressAndCall(Register target) {
bind(&return_label);
}
void TurboAssembler::CallForDeoptimization(Address target, int deopt_id) {
NoRootArrayScope no_root_array(this);
// Save the deopt id in r10 (we don't need the roots array from now on).
DCHECK_LE(deopt_id, 0xFFFF);
lghi(r10, Operand(deopt_id));
Call(target, RelocInfo::RUNTIME_ENTRY);
}
} // namespace internal
} // namespace v8
......
......@@ -159,11 +159,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void Ret() { b(r14); }
void Ret(Condition cond) { b(cond, r14); }
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
USE(deopt_id);
Call(target, rmode);
}
void CallForDeoptimization(Address target, int deopt_id);
// Emit code to discard a non-negative number of pointer-sized elements
// from the stack, clobbering only the sp register.
......
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