Commit 798ffc9d authored by jarin's avatar jarin Committed by Commit bot

[deoptimizer] Fill the single precision registers in the deoptimizer entry stub.

BUG=v8:6077

Review-Url: https://codereview.chromium.org/2765323002
Cr-Commit-Position: refs/heads/master@{#44035}
parent 760c56bd
......@@ -121,6 +121,7 @@ void Deoptimizer::TableEntryGenerator::Generate() {
RegList restored_regs = kJSCallerSaved | kCalleeSaved | ip.bit();
const int kDoubleRegsSize = kDoubleSize * DwVfpRegister::kMaxNumRegisters;
const int kFloatRegsSize = kFloatSize * SwVfpRegister::kMaxNumRegisters;
// Save all allocatable VFP registers before messing with them.
DCHECK(kDoubleRegZero.code() == 14);
......@@ -139,6 +140,12 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ vstm(db_w, sp, d16, d31, ne);
__ sub(sp, sp, Operand(16 * kDoubleSize), LeaveCC, eq);
__ vstm(db_w, sp, d0, d15);
// Push registers s0-s15, and possibly s16-s31, on the stack.
// If s16-s31 are not pushed, decrease the stack pointer instead.
__ vstm(db_w, sp, s16, s31, ne);
__ sub(sp, sp, Operand(16 * kFloatSize), LeaveCC, eq);
__ vstm(db_w, sp, s0, s15);
}
// Push all 16 registers (needed to populate FrameDescription::registers_).
......@@ -150,7 +157,7 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ str(fp, MemOperand(ip));
const int kSavedRegistersAreaSize =
(kNumberOfRegisters * kPointerSize) + kDoubleRegsSize;
(kNumberOfRegisters * kPointerSize) + kDoubleRegsSize + kFloatRegsSize;
// Get the bailout id from the stack.
__ ldr(r2, MemOperand(sp, kSavedRegistersAreaSize));
......@@ -203,11 +210,23 @@ void Deoptimizer::TableEntryGenerator::Generate() {
for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
int code = config->GetAllocatableDoubleCode(i);
int dst_offset = code * kDoubleSize + double_regs_offset;
int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize;
int src_offset =
code * kDoubleSize + kNumberOfRegisters * kPointerSize + kFloatRegsSize;
__ vldr(d0, sp, src_offset);
__ vstr(d0, r1, dst_offset);
}
// Copy VFP registers to
// float_registers_[FloatRegister::kMaxNumAllocatableRegisters]
int float_regs_offset = FrameDescription::float_registers_offset();
for (int i = 0; i < config->num_allocatable_float_registers(); ++i) {
int code = config->GetAllocatableFloatCode(i);
int dst_offset = code * kFloatSize + float_regs_offset;
int src_offset = code * kFloatSize + kNumberOfRegisters * kPointerSize;
__ ldr(r2, MemOperand(sp, src_offset));
__ str(r2, MemOperand(r1, dst_offset));
}
// Remove the bailout id and the saved registers from the stack.
__ add(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
......
......@@ -97,11 +97,17 @@ void Deoptimizer::TableEntryGenerator::Generate() {
// caller-saved registers here. Callee-saved registers can be stored directly
// in the input frame.
// Save all allocatable floating point registers.
CPURegList saved_fp_registers(
// Save all allocatable double registers.
CPURegList saved_double_registers(
CPURegister::kFPRegister, kDRegSizeInBits,
RegisterConfiguration::Crankshaft()->allocatable_double_codes_mask());
__ PushCPURegList(saved_fp_registers);
__ PushCPURegList(saved_double_registers);
// Save all allocatable float registers.
CPURegList saved_float_registers(
CPURegister::kFPRegister, kSRegSizeInBits,
RegisterConfiguration::Crankshaft()->allocatable_float_codes_mask());
__ PushCPURegList(saved_float_registers);
// We save all the registers expcept jssp, sp and lr.
CPURegList saved_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 27);
......@@ -113,10 +119,13 @@ void Deoptimizer::TableEntryGenerator::Generate() {
const int kSavedRegistersAreaSize =
(saved_registers.Count() * kXRegSize) +
(saved_fp_registers.Count() * kDRegSize);
(saved_double_registers.Count() * kDRegSize) +
(saved_float_registers.Count() * kSRegSize);
// Floating point registers are saved on the stack above core registers.
const int kFPRegistersOffset = saved_registers.Count() * kXRegSize;
const int kFloatRegistersOffset = saved_registers.Count() * kXRegSize;
const int kDoubleRegistersOffset =
kFloatRegistersOffset + saved_float_registers.Count() * kSRegSize;
// Get the bailout id from the stack.
Register bailout_id = x2;
......@@ -168,17 +177,28 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ Str(x2, MemOperand(x1, offset));
}
// Copy FP registers to the input frame.
CPURegList copy_fp_to_input = saved_fp_registers;
for (int i = 0; i < saved_fp_registers.Count(); i++) {
int src_offset = kFPRegistersOffset + (i * kDoubleSize);
// Copy double registers to the input frame.
CPURegList copy_double_to_input = saved_double_registers;
for (int i = 0; i < saved_double_registers.Count(); i++) {
int src_offset = kDoubleRegistersOffset + (i * kDoubleSize);
__ Peek(x2, src_offset);
CPURegister reg = copy_fp_to_input.PopLowestIndex();
CPURegister reg = copy_double_to_input.PopLowestIndex();
int dst_offset = FrameDescription::double_registers_offset() +
(reg.code() * kDoubleSize);
__ Str(x2, MemOperand(x1, dst_offset));
}
// Copy float registers to the input frame.
CPURegList copy_float_to_input = saved_float_registers;
for (int i = 0; i < saved_float_registers.Count(); i++) {
int src_offset = kFloatRegistersOffset + (i * kFloatSize);
__ Peek(w2, src_offset);
CPURegister reg = copy_float_to_input.PopLowestIndex();
int dst_offset =
FrameDescription::float_registers_offset() + (reg.code() * kFloatSize);
__ Str(w2, MemOperand(x1, dst_offset));
}
// Remove the bailout id and the saved registers from the stack.
__ Drop(1 + (kSavedRegistersAreaSize / kXRegSize));
......@@ -244,11 +264,11 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ B(lt, &outer_push_loop);
__ Ldr(x1, MemOperand(x4, Deoptimizer::input_offset()));
DCHECK(!saved_fp_registers.IncludesAliasOf(crankshaft_fp_scratch) &&
!saved_fp_registers.IncludesAliasOf(fp_zero) &&
!saved_fp_registers.IncludesAliasOf(fp_scratch));
while (!saved_fp_registers.IsEmpty()) {
const CPURegister reg = saved_fp_registers.PopLowestIndex();
DCHECK(!saved_double_registers.IncludesAliasOf(crankshaft_fp_scratch) &&
!saved_double_registers.IncludesAliasOf(fp_zero) &&
!saved_double_registers.IncludesAliasOf(fp_scratch));
while (!saved_double_registers.IsEmpty()) {
const CPURegister reg = saved_double_registers.PopLowestIndex();
int src_offset = FrameDescription::double_registers_offset() +
(reg.code() * kDoubleSize);
__ Ldr(reg, MemOperand(x1, src_offset));
......
......@@ -816,6 +816,10 @@ class FrameDescription {
return OFFSET_OF(FrameDescription, register_values_.double_registers_);
}
static int float_registers_offset() {
return OFFSET_OF(FrameDescription, register_values_.float_registers_);
}
static int frame_size_offset() {
return offsetof(FrameDescription, frame_size_);
}
......
......@@ -204,13 +204,23 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ movsd(Operand(esp, offset), xmm_reg);
}
STATIC_ASSERT(kFloatSize == kPointerSize);
const int kFloatRegsSize = kFloatSize * XMMRegister::kMaxNumRegisters;
__ sub(esp, Immediate(kFloatRegsSize));
for (int i = 0; i < config->num_allocatable_float_registers(); ++i) {
int code = config->GetAllocatableFloatCode(i);
XMMRegister xmm_reg = XMMRegister::from_code(code);
int offset = code * kFloatSize;
__ movss(Operand(esp, offset), xmm_reg);
}
__ pushad();
ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
__ mov(Operand::StaticVariable(c_entry_fp_address), ebp);
const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize +
kDoubleRegsSize;
const int kSavedRegistersAreaSize =
kNumberOfRegisters * kPointerSize + kDoubleRegsSize + kFloatRegsSize;
// Get the bailout id from the stack.
__ mov(ebx, Operand(esp, kSavedRegistersAreaSize));
......@@ -253,6 +263,13 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ pop(Operand(ebx, offset));
}
int float_regs_offset = FrameDescription::float_registers_offset();
// Fill in the float input registers.
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
int dst_offset = i * kFloatSize + float_regs_offset;
__ pop(Operand(ebx, dst_offset));
}
int double_regs_offset = FrameDescription::double_registers_offset();
// Fill in the double input registers.
for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
......
......@@ -67,6 +67,9 @@ class V8_EXPORT_PRIVATE RegisterConfiguration {
int32_t allocatable_double_codes_mask() const {
return allocatable_double_codes_mask_;
}
int32_t allocatable_float_codes_mask() const {
return allocatable_float_codes_mask_;
}
int GetAllocatableGeneralCode(int index) const {
return allocatable_general_codes_[index];
}
......
......@@ -125,6 +125,16 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ Movsd(Operand(rsp, offset), xmm_reg);
}
const int kFloatRegsSize = kFloatSize * XMMRegister::kMaxNumRegisters;
__ subp(rsp, Immediate(kFloatRegsSize));
for (int i = 0; i < config->num_allocatable_float_registers(); ++i) {
int code = config->GetAllocatableFloatCode(i);
XMMRegister xmm_reg = XMMRegister::from_code(code);
int offset = code * kFloatSize;
__ Movss(Operand(rsp, offset), xmm_reg);
}
// We push all registers onto the stack, even though we do not need
// to restore all later.
for (int i = 0; i < kNumberOfRegisters; i++) {
......@@ -132,8 +142,8 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ pushq(r);
}
const int kSavedRegistersAreaSize = kNumberOfRegisters * kRegisterSize +
kDoubleRegsSize;
const int kSavedRegistersAreaSize =
kNumberOfRegisters * kRegisterSize + kDoubleRegsSize + kFloatRegsSize;
__ Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp);
......@@ -190,6 +200,16 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ PopQuad(Operand(rbx, offset));
}
// Fill in the float input registers.
int float_regs_offset = FrameDescription::float_registers_offset();
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
int src_offset = i * kFloatSize;
int dst_offset = i * kFloatSize + float_regs_offset;
__ movl(rcx, Operand(rsp, src_offset));
__ movl(Operand(rbx, dst_offset), rcx);
}
__ addp(rsp, Immediate(kFloatRegsSize));
// Fill in the double input registers.
int double_regs_offset = FrameDescription::double_registers_offset();
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
......
// Copyright 2017 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.
// Flags: --allow-natives-syntax
var f32 = new Float32Array(20);
function foo(f32, deopt) {
var f0 = f32[0];
var f1 = f32[1];
var f2 = f32[2];
var f3 = f32[3];
var f4 = f32[4];
var f5 = f32[5];
var f6 = f32[6];
var f7 = f32[7];
var f8 = f32[8];
var f9 = f32[9];
var f10 = f32[10];
var f11 = f32[11];
var f12 = f32[12];
var f13 = f32[13];
var f14 = f32[14];
var f15 = f32[15];
var f16 = f32[16];
var f17 = f32[17];
var f18 = f32[18];
var f19 = f32[19];
// Side effect to force the deopt after the store.
f32[0] = f1 - 1;
// Here we deopt once we warm up with numbers, but then we
// pass a string as {deopt}.
return deopt + f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 +
f12 + f13 + f14 + f15 + f16 + f17 + f18 + f19;
}
var s = "";
for (var i = 0; i < f32.length; i++) {
f32[i] = i;
s += i;
}
foo(f32, 0);
foo(f32, 0);
%OptimizeFunctionOnNextCall(foo);
assertEquals("x" + s, foo(f32, "x"));
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