| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 const int Deoptimizer::table_entry_size_ = 8; | 14 const int Deoptimizer::table_entry_size_ = 8; |
| 14 | 15 |
| 15 | 16 |
| 16 int Deoptimizer::patch_size() { | 17 int Deoptimizer::patch_size() { |
| 17 #if V8_TARGET_ARCH_PPC64 | 18 #if V8_TARGET_ARCH_PPC64 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 // spilled. Registers fp and sp are set to the correct values though. | 93 // spilled. Registers fp and sp are set to the correct values though. |
| 93 // We ensure the values are Smis to avoid confusing the garbage | 94 // We ensure the values are Smis to avoid confusing the garbage |
| 94 // collector in the event that any values are retreived and stored | 95 // collector in the event that any values are retreived and stored |
| 95 // elsewhere. | 96 // elsewhere. |
| 96 | 97 |
| 97 for (int i = 0; i < Register::kNumRegisters; i++) { | 98 for (int i = 0; i < Register::kNumRegisters; i++) { |
| 98 input_->SetRegister(i, reinterpret_cast<intptr_t>(Smi::FromInt(i))); | 99 input_->SetRegister(i, reinterpret_cast<intptr_t>(Smi::FromInt(i))); |
| 99 } | 100 } |
| 100 input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 101 input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
| 101 input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 102 input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
| 102 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { | 103 for (int i = 0; i < DoubleRegister::kNumRegisters; i++) { |
| 103 input_->SetDoubleRegister(i, 0.0); | 104 input_->SetDoubleRegister(i, 0.0); |
| 104 } | 105 } |
| 105 | 106 |
| 106 // Fill the frame content from the actual data on the frame. | 107 // Fill the frame content from the actual data on the frame. |
| 107 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 108 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
| 108 input_->SetFrameSlot( | 109 input_->SetFrameSlot( |
| 109 i, reinterpret_cast<intptr_t>(Memory::Address_at(tos + i))); | 110 i, reinterpret_cast<intptr_t>(Memory::Address_at(tos + i))); |
| 110 } | 111 } |
| 111 } | 112 } |
| 112 | 113 |
| 113 | 114 |
| 114 void Deoptimizer::SetPlatformCompiledStubRegisters( | 115 void Deoptimizer::SetPlatformCompiledStubRegisters( |
| 115 FrameDescription* output_frame, CodeStubDescriptor* descriptor) { | 116 FrameDescription* output_frame, CodeStubDescriptor* descriptor) { |
| 116 ApiFunction function(descriptor->deoptimization_handler()); | 117 ApiFunction function(descriptor->deoptimization_handler()); |
| 117 ExternalReference xref(&function, ExternalReference::BUILTIN_CALL, isolate_); | 118 ExternalReference xref(&function, ExternalReference::BUILTIN_CALL, isolate_); |
| 118 intptr_t handler = reinterpret_cast<intptr_t>(xref.address()); | 119 intptr_t handler = reinterpret_cast<intptr_t>(xref.address()); |
| 119 int params = descriptor->GetHandlerParameterCount(); | 120 int params = descriptor->GetHandlerParameterCount(); |
| 120 output_frame->SetRegister(r3.code(), params); | 121 output_frame->SetRegister(r3.code(), params); |
| 121 output_frame->SetRegister(r4.code(), handler); | 122 output_frame->SetRegister(r4.code(), handler); |
| 122 } | 123 } |
| 123 | 124 |
| 124 | 125 |
| 125 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { | 126 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { |
| 126 for (int i = 0; i < DoubleRegister::kMaxNumRegisters; ++i) { | 127 for (int i = 0; i < DoubleRegister::kNumRegisters; ++i) { |
| 127 double double_value = input_->GetDoubleRegister(i); | 128 double double_value = input_->GetDoubleRegister(i); |
| 128 output_frame->SetDoubleRegister(i, double_value); | 129 output_frame->SetDoubleRegister(i, double_value); |
| 129 } | 130 } |
| 130 } | 131 } |
| 131 | 132 |
| 132 | 133 |
| 133 bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { | 134 bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { |
| 134 // There is no dynamic alignment padding on PPC in the input frame. | 135 // There is no dynamic alignment padding on PPC in the input frame. |
| 135 return false; | 136 return false; |
| 136 } | 137 } |
| 137 | 138 |
| 138 | 139 |
| 139 #define __ masm()-> | 140 #define __ masm()-> |
| 140 | 141 |
| 141 // This code tries to be close to ia32 code so that any changes can be | 142 // This code tries to be close to ia32 code so that any changes can be |
| 142 // easily ported. | 143 // easily ported. |
| 143 void Deoptimizer::TableEntryGenerator::Generate() { | 144 void Deoptimizer::TableEntryGenerator::Generate() { |
| 144 GeneratePrologue(); | 145 GeneratePrologue(); |
| 145 | 146 |
| 146 // Unlike on ARM we don't save all the registers, just the useful ones. | 147 // Unlike on ARM we don't save all the registers, just the useful ones. |
| 147 // For the rest, there are gaps on the stack, so the offsets remain the same. | 148 // For the rest, there are gaps on the stack, so the offsets remain the same. |
| 148 const int kNumberOfRegisters = Register::kNumRegisters; | 149 const int kNumberOfRegisters = Register::kNumRegisters; |
| 149 | 150 |
| 150 RegList restored_regs = kJSCallerSaved | kCalleeSaved; | 151 RegList restored_regs = kJSCallerSaved | kCalleeSaved; |
| 151 RegList saved_regs = restored_regs | sp.bit(); | 152 RegList saved_regs = restored_regs | sp.bit(); |
| 152 | 153 |
| 153 const int kDoubleRegsSize = | 154 const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters; |
| 154 kDoubleSize * DoubleRegister::kMaxNumAllocatableRegisters; | |
| 155 | 155 |
| 156 // Save all FPU registers before messing with them. | 156 // Save all double registers before messing with them. |
| 157 __ subi(sp, sp, Operand(kDoubleRegsSize)); | 157 __ subi(sp, sp, Operand(kDoubleRegsSize)); |
| 158 for (int i = 0; i < DoubleRegister::kMaxNumAllocatableRegisters; ++i) { | 158 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); |
| 159 DoubleRegister fpu_reg = DoubleRegister::FromAllocationIndex(i); | 159 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
| 160 int offset = i * kDoubleSize; | 160 int code = config->GetAllocatableDoubleCode(i); |
| 161 __ stfd(fpu_reg, MemOperand(sp, offset)); | 161 const DoubleRegister dreg = DoubleRegister::from_code(code); |
| 162 int offset = code * kDoubleSize; |
| 163 __ stfd(dreg, MemOperand(sp, offset)); |
| 162 } | 164 } |
| 163 | 165 |
| 164 // Push saved_regs (needed to populate FrameDescription::registers_). | 166 // Push saved_regs (needed to populate FrameDescription::registers_). |
| 165 // Leave gaps for other registers. | 167 // Leave gaps for other registers. |
| 166 __ subi(sp, sp, Operand(kNumberOfRegisters * kPointerSize)); | 168 __ subi(sp, sp, Operand(kNumberOfRegisters * kPointerSize)); |
| 167 for (int16_t i = kNumberOfRegisters - 1; i >= 0; i--) { | 169 for (int16_t i = kNumberOfRegisters - 1; i >= 0; i--) { |
| 168 if ((saved_regs & (1 << i)) != 0) { | 170 if ((saved_regs & (1 << i)) != 0) { |
| 169 __ StoreP(ToRegister(i), MemOperand(sp, kPointerSize * i)); | 171 __ StoreP(ToRegister(i), MemOperand(sp, kPointerSize * i)); |
| 170 } | 172 } |
| 171 } | 173 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 | 210 |
| 209 // Copy core registers into FrameDescription::registers_[kNumRegisters]. | 211 // Copy core registers into FrameDescription::registers_[kNumRegisters]. |
| 210 DCHECK(Register::kNumRegisters == kNumberOfRegisters); | 212 DCHECK(Register::kNumRegisters == kNumberOfRegisters); |
| 211 for (int i = 0; i < kNumberOfRegisters; i++) { | 213 for (int i = 0; i < kNumberOfRegisters; i++) { |
| 212 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 214 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
| 213 __ LoadP(r5, MemOperand(sp, i * kPointerSize)); | 215 __ LoadP(r5, MemOperand(sp, i * kPointerSize)); |
| 214 __ StoreP(r5, MemOperand(r4, offset)); | 216 __ StoreP(r5, MemOperand(r4, offset)); |
| 215 } | 217 } |
| 216 | 218 |
| 217 int double_regs_offset = FrameDescription::double_registers_offset(); | 219 int double_regs_offset = FrameDescription::double_registers_offset(); |
| 218 // Copy VFP registers to | 220 // Copy double registers to |
| 219 // double_registers_[DoubleRegister::kNumAllocatableRegisters] | 221 // double_registers_[DoubleRegister::kNumRegisters] |
| 220 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) { | 222 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
| 221 int dst_offset = i * kDoubleSize + double_regs_offset; | 223 int code = config->GetAllocatableDoubleCode(i); |
| 222 int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize; | 224 int dst_offset = code * kDoubleSize + double_regs_offset; |
| 225 int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize; |
| 223 __ lfd(d0, MemOperand(sp, src_offset)); | 226 __ lfd(d0, MemOperand(sp, src_offset)); |
| 224 __ stfd(d0, MemOperand(r4, dst_offset)); | 227 __ stfd(d0, MemOperand(r4, dst_offset)); |
| 225 } | 228 } |
| 226 | 229 |
| 227 // Remove the bailout id and the saved registers from the stack. | 230 // Remove the bailout id and the saved registers from the stack. |
| 228 __ addi(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); | 231 __ addi(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); |
| 229 | 232 |
| 230 // Compute a pointer to the unwinding limit in register r5; that is | 233 // Compute a pointer to the unwinding limit in register r5; that is |
| 231 // the first stack slot not part of the input frame. | 234 // the first stack slot not part of the input frame. |
| 232 __ LoadP(r5, MemOperand(r4, FrameDescription::frame_size_offset())); | 235 __ LoadP(r5, MemOperand(r4, FrameDescription::frame_size_offset())); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 __ bind(&inner_loop_header); | 287 __ bind(&inner_loop_header); |
| 285 __ cmpi(r6, Operand::Zero()); | 288 __ cmpi(r6, Operand::Zero()); |
| 286 __ bne(&inner_push_loop); // test for gt? | 289 __ bne(&inner_push_loop); // test for gt? |
| 287 | 290 |
| 288 __ addi(r7, r7, Operand(kPointerSize)); | 291 __ addi(r7, r7, Operand(kPointerSize)); |
| 289 __ bind(&outer_loop_header); | 292 __ bind(&outer_loop_header); |
| 290 __ cmp(r7, r4); | 293 __ cmp(r7, r4); |
| 291 __ blt(&outer_push_loop); | 294 __ blt(&outer_push_loop); |
| 292 | 295 |
| 293 __ LoadP(r4, MemOperand(r3, Deoptimizer::input_offset())); | 296 __ LoadP(r4, MemOperand(r3, Deoptimizer::input_offset())); |
| 294 for (int i = 0; i < DoubleRegister::kMaxNumAllocatableRegisters; ++i) { | 297 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
| 295 const DoubleRegister dreg = DoubleRegister::FromAllocationIndex(i); | 298 int code = config->GetAllocatableDoubleCode(i); |
| 296 int src_offset = i * kDoubleSize + double_regs_offset; | 299 const DoubleRegister dreg = DoubleRegister::from_code(code); |
| 300 int src_offset = code * kDoubleSize + double_regs_offset; |
| 297 __ lfd(dreg, MemOperand(r4, src_offset)); | 301 __ lfd(dreg, MemOperand(r4, src_offset)); |
| 298 } | 302 } |
| 299 | 303 |
| 300 // Push state, pc, and continuation from the last output frame. | 304 // Push state, pc, and continuation from the last output frame. |
| 301 __ LoadP(r9, MemOperand(r5, FrameDescription::state_offset())); | 305 __ LoadP(r9, MemOperand(r5, FrameDescription::state_offset())); |
| 302 __ push(r9); | 306 __ push(r9); |
| 303 __ LoadP(r9, MemOperand(r5, FrameDescription::pc_offset())); | 307 __ LoadP(r9, MemOperand(r5, FrameDescription::pc_offset())); |
| 304 __ push(r9); | 308 __ push(r9); |
| 305 __ LoadP(r9, MemOperand(r5, FrameDescription::continuation_offset())); | 309 __ LoadP(r9, MemOperand(r5, FrameDescription::continuation_offset())); |
| 306 __ push(r9); | 310 __ push(r9); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 | 359 |
| 356 void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { | 360 void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { |
| 357 DCHECK(FLAG_enable_embedded_constant_pool); | 361 DCHECK(FLAG_enable_embedded_constant_pool); |
| 358 SetFrameSlot(offset, value); | 362 SetFrameSlot(offset, value); |
| 359 } | 363 } |
| 360 | 364 |
| 361 | 365 |
| 362 #undef __ | 366 #undef __ |
| 363 } // namespace internal | 367 } // namespace internal |
| 364 } // namespace v8 | 368 } // namespace v8 |
| OLD | NEW |