OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/codegen.h" | 5 #include "src/codegen.h" |
6 #include "src/deoptimizer.h" | 6 #include "src/deoptimizer.h" |
7 #include "src/full-codegen/full-codegen.h" | 7 #include "src/full-codegen/full-codegen.h" |
8 #include "src/register-configuration.h" | |
9 #include "src/safepoint-table.h" | 8 #include "src/safepoint-table.h" |
10 | 9 |
11 namespace v8 { | 10 namespace v8 { |
12 namespace internal { | 11 namespace internal { |
13 | 12 |
14 | 13 |
15 int Deoptimizer::patch_size() { | 14 int Deoptimizer::patch_size() { |
16 const int kCallInstructionSizeInWords = 6; | 15 const int kCallInstructionSizeInWords = 6; |
17 return kCallInstructionSizeInWords * Assembler::kInstrSize; | 16 return kCallInstructionSizeInWords * Assembler::kInstrSize; |
18 } | 17 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 81 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
83 // Set the register values. The values are not important as there are no | 82 // Set the register values. The values are not important as there are no |
84 // callee saved registers in JavaScript frames, so all registers are | 83 // callee saved registers in JavaScript frames, so all registers are |
85 // spilled. Registers fp and sp are set to the correct values though. | 84 // spilled. Registers fp and sp are set to the correct values though. |
86 | 85 |
87 for (int i = 0; i < Register::kNumRegisters; i++) { | 86 for (int i = 0; i < Register::kNumRegisters; i++) { |
88 input_->SetRegister(i, i * 4); | 87 input_->SetRegister(i, i * 4); |
89 } | 88 } |
90 input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 89 input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
91 input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 90 input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
92 for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) { | 91 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { |
93 input_->SetDoubleRegister(i, 0.0); | 92 input_->SetDoubleRegister(i, 0.0); |
94 } | 93 } |
95 | 94 |
96 // Fill the frame content from the actual data on the frame. | 95 // Fill the frame content from the actual data on the frame. |
97 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 96 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
98 input_->SetFrameSlot(i, Memory::uint64_at(tos + i)); | 97 input_->SetFrameSlot(i, Memory::uint64_at(tos + i)); |
99 } | 98 } |
100 } | 99 } |
101 | 100 |
102 | 101 |
(...skipping 30 matching lines...) Expand all Loading... |
133 void Deoptimizer::TableEntryGenerator::Generate() { | 132 void Deoptimizer::TableEntryGenerator::Generate() { |
134 GeneratePrologue(); | 133 GeneratePrologue(); |
135 | 134 |
136 // Unlike on ARM we don't save all the registers, just the useful ones. | 135 // Unlike on ARM we don't save all the registers, just the useful ones. |
137 // For the rest, there are gaps on the stack, so the offsets remain the same. | 136 // For the rest, there are gaps on the stack, so the offsets remain the same. |
138 const int kNumberOfRegisters = Register::kNumRegisters; | 137 const int kNumberOfRegisters = Register::kNumRegisters; |
139 | 138 |
140 RegList restored_regs = kJSCallerSaved | kCalleeSaved; | 139 RegList restored_regs = kJSCallerSaved | kCalleeSaved; |
141 RegList saved_regs = restored_regs | sp.bit() | ra.bit(); | 140 RegList saved_regs = restored_regs | sp.bit() | ra.bit(); |
142 | 141 |
143 const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kMaxNumRegisters; | 142 const int kDoubleRegsSize = |
| 143 kDoubleSize * FPURegister::kMaxNumAllocatableRegisters; |
144 | 144 |
145 // Save all FPU registers before messing with them. | 145 // Save all FPU registers before messing with them. |
146 __ Dsubu(sp, sp, Operand(kDoubleRegsSize)); | 146 __ Dsubu(sp, sp, Operand(kDoubleRegsSize)); |
147 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); | 147 for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) { |
148 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 148 FPURegister fpu_reg = FPURegister::FromAllocationIndex(i); |
149 int code = config->GetAllocatableDoubleCode(i); | 149 int offset = i * kDoubleSize; |
150 const DoubleRegister fpu_reg = DoubleRegister::from_code(code); | |
151 int offset = code * kDoubleSize; | |
152 __ sdc1(fpu_reg, MemOperand(sp, offset)); | 150 __ sdc1(fpu_reg, MemOperand(sp, offset)); |
153 } | 151 } |
154 | 152 |
155 // Push saved_regs (needed to populate FrameDescription::registers_). | 153 // Push saved_regs (needed to populate FrameDescription::registers_). |
156 // Leave gaps for other registers. | 154 // Leave gaps for other registers. |
157 __ Dsubu(sp, sp, kNumberOfRegisters * kPointerSize); | 155 __ Dsubu(sp, sp, kNumberOfRegisters * kPointerSize); |
158 for (int16_t i = kNumberOfRegisters - 1; i >= 0; i--) { | 156 for (int16_t i = kNumberOfRegisters - 1; i >= 0; i--) { |
159 if ((saved_regs & (1 << i)) != 0) { | 157 if ((saved_regs & (1 << i)) != 0) { |
160 __ sd(ToRegister(i), MemOperand(sp, kPointerSize * i)); | 158 __ sd(ToRegister(i), MemOperand(sp, kPointerSize * i)); |
161 } | 159 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 __ sd(a2, MemOperand(a1, offset)); | 214 __ sd(a2, MemOperand(a1, offset)); |
217 } else if (FLAG_debug_code) { | 215 } else if (FLAG_debug_code) { |
218 __ li(a2, kDebugZapValue); | 216 __ li(a2, kDebugZapValue); |
219 __ sd(a2, MemOperand(a1, offset)); | 217 __ sd(a2, MemOperand(a1, offset)); |
220 } | 218 } |
221 } | 219 } |
222 | 220 |
223 int double_regs_offset = FrameDescription::double_registers_offset(); | 221 int double_regs_offset = FrameDescription::double_registers_offset(); |
224 // Copy FPU registers to | 222 // Copy FPU registers to |
225 // double_registers_[DoubleRegister::kNumAllocatableRegisters] | 223 // double_registers_[DoubleRegister::kNumAllocatableRegisters] |
226 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 224 for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) { |
227 int code = config->GetAllocatableDoubleCode(i); | 225 int dst_offset = i * kDoubleSize + double_regs_offset; |
228 int dst_offset = code * kDoubleSize + double_regs_offset; | 226 int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize; |
229 int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize; | |
230 __ ldc1(f0, MemOperand(sp, src_offset)); | 227 __ ldc1(f0, MemOperand(sp, src_offset)); |
231 __ sdc1(f0, MemOperand(a1, dst_offset)); | 228 __ sdc1(f0, MemOperand(a1, dst_offset)); |
232 } | 229 } |
233 | 230 |
234 // Remove the bailout id and the saved registers from the stack. | 231 // Remove the bailout id and the saved registers from the stack. |
235 __ Daddu(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); | 232 __ Daddu(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); |
236 | 233 |
237 // Compute a pointer to the unwinding limit in register a2; that is | 234 // Compute a pointer to the unwinding limit in register a2; that is |
238 // the first stack slot not part of the input frame. | 235 // the first stack slot not part of the input frame. |
239 __ ld(a2, MemOperand(a1, FrameDescription::frame_size_offset())); | 236 __ ld(a2, MemOperand(a1, FrameDescription::frame_size_offset())); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 __ ld(a7, MemOperand(a6, FrameDescription::frame_content_offset())); | 282 __ ld(a7, MemOperand(a6, FrameDescription::frame_content_offset())); |
286 __ push(a7); | 283 __ push(a7); |
287 __ bind(&inner_loop_header); | 284 __ bind(&inner_loop_header); |
288 __ BranchShort(&inner_push_loop, ne, a3, Operand(zero_reg)); | 285 __ BranchShort(&inner_push_loop, ne, a3, Operand(zero_reg)); |
289 | 286 |
290 __ Daddu(a4, a4, Operand(kPointerSize)); | 287 __ Daddu(a4, a4, Operand(kPointerSize)); |
291 __ bind(&outer_loop_header); | 288 __ bind(&outer_loop_header); |
292 __ BranchShort(&outer_push_loop, lt, a4, Operand(a1)); | 289 __ BranchShort(&outer_push_loop, lt, a4, Operand(a1)); |
293 | 290 |
294 __ ld(a1, MemOperand(a0, Deoptimizer::input_offset())); | 291 __ ld(a1, MemOperand(a0, Deoptimizer::input_offset())); |
295 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 292 for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) { |
296 int code = config->GetAllocatableDoubleCode(i); | 293 const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i); |
297 const DoubleRegister fpu_reg = DoubleRegister::from_code(code); | 294 int src_offset = i * kDoubleSize + double_regs_offset; |
298 int src_offset = code * kDoubleSize + double_regs_offset; | |
299 __ ldc1(fpu_reg, MemOperand(a1, src_offset)); | 295 __ ldc1(fpu_reg, MemOperand(a1, src_offset)); |
300 } | 296 } |
301 | 297 |
302 // Push state, pc, and continuation from the last output frame. | 298 // Push state, pc, and continuation from the last output frame. |
303 __ ld(a6, MemOperand(a2, FrameDescription::state_offset())); | 299 __ ld(a6, MemOperand(a2, FrameDescription::state_offset())); |
304 __ push(a6); | 300 __ push(a6); |
305 | 301 |
306 __ ld(a6, MemOperand(a2, FrameDescription::pc_offset())); | 302 __ ld(a6, MemOperand(a2, FrameDescription::pc_offset())); |
307 __ push(a6); | 303 __ push(a6); |
308 __ ld(a6, MemOperand(a2, FrameDescription::continuation_offset())); | 304 __ ld(a6, MemOperand(a2, FrameDescription::continuation_offset())); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 // No embedded constant pool support. | 404 // No embedded constant pool support. |
409 UNREACHABLE(); | 405 UNREACHABLE(); |
410 } | 406 } |
411 | 407 |
412 | 408 |
413 #undef __ | 409 #undef __ |
414 | 410 |
415 | 411 |
416 } // namespace internal | 412 } // namespace internal |
417 } // namespace v8 | 413 } // namespace v8 |
OLD | NEW |