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" |
8 #include "src/safepoint-table.h" | 9 #include "src/safepoint-table.h" |
9 | 10 |
10 namespace v8 { | 11 namespace v8 { |
11 namespace internal { | 12 namespace internal { |
12 | 13 |
13 | 14 |
14 int Deoptimizer::patch_size() { | 15 int Deoptimizer::patch_size() { |
15 const int kCallInstructionSizeInWords = 4; | 16 const int kCallInstructionSizeInWords = 4; |
16 return kCallInstructionSizeInWords * Assembler::kInstrSize; | 17 return kCallInstructionSizeInWords * Assembler::kInstrSize; |
17 } | 18 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 82 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
82 // Set the register values. The values are not important as there are no | 83 // Set the register values. The values are not important as there are no |
83 // callee saved registers in JavaScript frames, so all registers are | 84 // callee saved registers in JavaScript frames, so all registers are |
84 // spilled. Registers fp and sp are set to the correct values though. | 85 // spilled. Registers fp and sp are set to the correct values though. |
85 | 86 |
86 for (int i = 0; i < Register::kNumRegisters; i++) { | 87 for (int i = 0; i < Register::kNumRegisters; i++) { |
87 input_->SetRegister(i, i * 4); | 88 input_->SetRegister(i, i * 4); |
88 } | 89 } |
89 input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 90 input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
90 input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 91 input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
91 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { | 92 for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) { |
92 input_->SetDoubleRegister(i, 0.0); | 93 input_->SetDoubleRegister(i, 0.0); |
93 } | 94 } |
94 | 95 |
95 // Fill the frame content from the actual data on the frame. | 96 // Fill the frame content from the actual data on the frame. |
96 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 97 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
97 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); | 98 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); |
98 } | 99 } |
99 } | 100 } |
100 | 101 |
101 | 102 |
(...skipping 30 matching lines...) Expand all Loading... |
132 void Deoptimizer::TableEntryGenerator::Generate() { | 133 void Deoptimizer::TableEntryGenerator::Generate() { |
133 GeneratePrologue(); | 134 GeneratePrologue(); |
134 | 135 |
135 // Unlike on ARM we don't save all the registers, just the useful ones. | 136 // Unlike on ARM we don't save all the registers, just the useful ones. |
136 // For the rest, there are gaps on the stack, so the offsets remain the same. | 137 // For the rest, there are gaps on the stack, so the offsets remain the same. |
137 const int kNumberOfRegisters = Register::kNumRegisters; | 138 const int kNumberOfRegisters = Register::kNumRegisters; |
138 | 139 |
139 RegList restored_regs = kJSCallerSaved | kCalleeSaved; | 140 RegList restored_regs = kJSCallerSaved | kCalleeSaved; |
140 RegList saved_regs = restored_regs | sp.bit() | ra.bit(); | 141 RegList saved_regs = restored_regs | sp.bit() | ra.bit(); |
141 | 142 |
142 const int kDoubleRegsSize = | 143 const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kMaxNumRegisters; |
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 __ Subu(sp, sp, Operand(kDoubleRegsSize)); | 146 __ Subu(sp, sp, Operand(kDoubleRegsSize)); |
147 for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) { | 147 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); |
148 FPURegister fpu_reg = FPURegister::FromAllocationIndex(i); | 148 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
149 int offset = i * kDoubleSize; | 149 int code = config->GetAllocatableDoubleCode(i); |
| 150 const DoubleRegister fpu_reg = DoubleRegister::from_code(code); |
| 151 int offset = code * kDoubleSize; |
150 __ sdc1(fpu_reg, MemOperand(sp, offset)); | 152 __ sdc1(fpu_reg, MemOperand(sp, offset)); |
151 } | 153 } |
152 | 154 |
153 // Push saved_regs (needed to populate FrameDescription::registers_). | 155 // Push saved_regs (needed to populate FrameDescription::registers_). |
154 // Leave gaps for other registers. | 156 // Leave gaps for other registers. |
155 __ Subu(sp, sp, kNumberOfRegisters * kPointerSize); | 157 __ Subu(sp, sp, kNumberOfRegisters * kPointerSize); |
156 for (int16_t i = kNumberOfRegisters - 1; i >= 0; i--) { | 158 for (int16_t i = kNumberOfRegisters - 1; i >= 0; i--) { |
157 if ((saved_regs & (1 << i)) != 0) { | 159 if ((saved_regs & (1 << i)) != 0) { |
158 __ sw(ToRegister(i), MemOperand(sp, kPointerSize * i)); | 160 __ sw(ToRegister(i), MemOperand(sp, kPointerSize * i)); |
159 } | 161 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 __ sw(a2, MemOperand(a1, offset)); | 210 __ sw(a2, MemOperand(a1, offset)); |
209 } else if (FLAG_debug_code) { | 211 } else if (FLAG_debug_code) { |
210 __ li(a2, kDebugZapValue); | 212 __ li(a2, kDebugZapValue); |
211 __ sw(a2, MemOperand(a1, offset)); | 213 __ sw(a2, MemOperand(a1, offset)); |
212 } | 214 } |
213 } | 215 } |
214 | 216 |
215 int double_regs_offset = FrameDescription::double_registers_offset(); | 217 int double_regs_offset = FrameDescription::double_registers_offset(); |
216 // Copy FPU registers to | 218 // Copy FPU registers to |
217 // double_registers_[DoubleRegister::kNumAllocatableRegisters] | 219 // double_registers_[DoubleRegister::kNumAllocatableRegisters] |
218 for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) { | 220 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
219 int dst_offset = i * kDoubleSize + double_regs_offset; | 221 int code = config->GetAllocatableDoubleCode(i); |
220 int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize; | 222 int dst_offset = code * kDoubleSize + double_regs_offset; |
| 223 int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize; |
221 __ ldc1(f0, MemOperand(sp, src_offset)); | 224 __ ldc1(f0, MemOperand(sp, src_offset)); |
222 __ sdc1(f0, MemOperand(a1, dst_offset)); | 225 __ sdc1(f0, MemOperand(a1, dst_offset)); |
223 } | 226 } |
224 | 227 |
225 // Remove the bailout id and the saved registers from the stack. | 228 // Remove the bailout id and the saved registers from the stack. |
226 __ Addu(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); | 229 __ Addu(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); |
227 | 230 |
228 // Compute a pointer to the unwinding limit in register a2; that is | 231 // Compute a pointer to the unwinding limit in register a2; that is |
229 // the first stack slot not part of the input frame. | 232 // the first stack slot not part of the input frame. |
230 __ lw(a2, MemOperand(a1, FrameDescription::frame_size_offset())); | 233 __ lw(a2, MemOperand(a1, FrameDescription::frame_size_offset())); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 __ lw(t3, MemOperand(t2, FrameDescription::frame_content_offset())); | 280 __ lw(t3, MemOperand(t2, FrameDescription::frame_content_offset())); |
278 __ push(t3); | 281 __ push(t3); |
279 __ bind(&inner_loop_header); | 282 __ bind(&inner_loop_header); |
280 __ BranchShort(&inner_push_loop, ne, a3, Operand(zero_reg)); | 283 __ BranchShort(&inner_push_loop, ne, a3, Operand(zero_reg)); |
281 | 284 |
282 __ Addu(t0, t0, Operand(kPointerSize)); | 285 __ Addu(t0, t0, Operand(kPointerSize)); |
283 __ bind(&outer_loop_header); | 286 __ bind(&outer_loop_header); |
284 __ BranchShort(&outer_push_loop, lt, t0, Operand(a1)); | 287 __ BranchShort(&outer_push_loop, lt, t0, Operand(a1)); |
285 | 288 |
286 __ lw(a1, MemOperand(a0, Deoptimizer::input_offset())); | 289 __ lw(a1, MemOperand(a0, Deoptimizer::input_offset())); |
287 for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) { | 290 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
288 const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i); | 291 int code = config->GetAllocatableDoubleCode(i); |
289 int src_offset = i * kDoubleSize + double_regs_offset; | 292 const DoubleRegister fpu_reg = DoubleRegister::from_code(code); |
| 293 int src_offset = code * kDoubleSize + double_regs_offset; |
290 __ ldc1(fpu_reg, MemOperand(a1, src_offset)); | 294 __ ldc1(fpu_reg, MemOperand(a1, src_offset)); |
291 } | 295 } |
292 | 296 |
293 // Push state, pc, and continuation from the last output frame. | 297 // Push state, pc, and continuation from the last output frame. |
294 __ lw(t2, MemOperand(a2, FrameDescription::state_offset())); | 298 __ lw(t2, MemOperand(a2, FrameDescription::state_offset())); |
295 __ push(t2); | 299 __ push(t2); |
296 | 300 |
297 __ lw(t2, MemOperand(a2, FrameDescription::pc_offset())); | 301 __ lw(t2, MemOperand(a2, FrameDescription::pc_offset())); |
298 __ push(t2); | 302 __ push(t2); |
299 __ lw(t2, MemOperand(a2, FrameDescription::continuation_offset())); | 303 __ lw(t2, MemOperand(a2, FrameDescription::continuation_offset())); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 // No embedded constant pool support. | 403 // No embedded constant pool support. |
400 UNREACHABLE(); | 404 UNREACHABLE(); |
401 } | 405 } |
402 | 406 |
403 | 407 |
404 #undef __ | 408 #undef __ |
405 | 409 |
406 | 410 |
407 } // namespace internal | 411 } // namespace internal |
408 } // namespace v8 | 412 } // namespace v8 |
OLD | NEW |