| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/api.h" | 5 #include "src/api.h" |
| 6 #include "src/arm64/assembler-arm64-inl.h" | 6 #include "src/arm64/assembler-arm64-inl.h" |
| 7 #include "src/arm64/frames-arm64.h" | 7 #include "src/arm64/frames-arm64.h" |
| 8 #include "src/arm64/macro-assembler-arm64-inl.h" | 8 #include "src/arm64/macro-assembler-arm64-inl.h" |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/deoptimizer.h" | 10 #include "src/deoptimizer.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 | 90 |
| 91 #define __ masm()-> | 91 #define __ masm()-> |
| 92 | 92 |
| 93 void Deoptimizer::TableEntryGenerator::Generate() { | 93 void Deoptimizer::TableEntryGenerator::Generate() { |
| 94 GeneratePrologue(); | 94 GeneratePrologue(); |
| 95 | 95 |
| 96 // TODO(all): This code needs to be revisited. We probably only need to save | 96 // TODO(all): This code needs to be revisited. We probably only need to save |
| 97 // caller-saved registers here. Callee-saved registers can be stored directly | 97 // caller-saved registers here. Callee-saved registers can be stored directly |
| 98 // in the input frame. | 98 // in the input frame. |
| 99 | 99 |
| 100 // Save all allocatable floating point registers. | 100 // Save all allocatable double registers. |
| 101 CPURegList saved_fp_registers( | 101 CPURegList saved_double_registers( |
| 102 CPURegister::kFPRegister, kDRegSizeInBits, | 102 CPURegister::kFPRegister, kDRegSizeInBits, |
| 103 RegisterConfiguration::Crankshaft()->allocatable_double_codes_mask()); | 103 RegisterConfiguration::Crankshaft()->allocatable_double_codes_mask()); |
| 104 __ PushCPURegList(saved_fp_registers); | 104 __ PushCPURegList(saved_double_registers); |
| 105 |
| 106 // Save all allocatable float registers. |
| 107 CPURegList saved_float_registers( |
| 108 CPURegister::kFPRegister, kSRegSizeInBits, |
| 109 RegisterConfiguration::Crankshaft()->allocatable_float_codes_mask()); |
| 110 __ PushCPURegList(saved_float_registers); |
| 105 | 111 |
| 106 // We save all the registers expcept jssp, sp and lr. | 112 // We save all the registers expcept jssp, sp and lr. |
| 107 CPURegList saved_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 27); | 113 CPURegList saved_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 27); |
| 108 saved_registers.Combine(fp); | 114 saved_registers.Combine(fp); |
| 109 __ PushCPURegList(saved_registers); | 115 __ PushCPURegList(saved_registers); |
| 110 | 116 |
| 111 __ Mov(x3, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 117 __ Mov(x3, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
| 112 __ Str(fp, MemOperand(x3)); | 118 __ Str(fp, MemOperand(x3)); |
| 113 | 119 |
| 114 const int kSavedRegistersAreaSize = | 120 const int kSavedRegistersAreaSize = |
| 115 (saved_registers.Count() * kXRegSize) + | 121 (saved_registers.Count() * kXRegSize) + |
| 116 (saved_fp_registers.Count() * kDRegSize); | 122 (saved_double_registers.Count() * kDRegSize) + |
| 123 (saved_float_registers.Count() * kSRegSize); |
| 117 | 124 |
| 118 // Floating point registers are saved on the stack above core registers. | 125 // Floating point registers are saved on the stack above core registers. |
| 119 const int kFPRegistersOffset = saved_registers.Count() * kXRegSize; | 126 const int kFloatRegistersOffset = saved_registers.Count() * kXRegSize; |
| 127 const int kDoubleRegistersOffset = |
| 128 kFloatRegistersOffset + saved_float_registers.Count() * kSRegSize; |
| 120 | 129 |
| 121 // Get the bailout id from the stack. | 130 // Get the bailout id from the stack. |
| 122 Register bailout_id = x2; | 131 Register bailout_id = x2; |
| 123 __ Peek(bailout_id, kSavedRegistersAreaSize); | 132 __ Peek(bailout_id, kSavedRegistersAreaSize); |
| 124 | 133 |
| 125 Register code_object = x3; | 134 Register code_object = x3; |
| 126 Register fp_to_sp = x4; | 135 Register fp_to_sp = x4; |
| 127 // Get the address of the location in the code object. This is the return | 136 // Get the address of the location in the code object. This is the return |
| 128 // address for lazy deoptimization. | 137 // address for lazy deoptimization. |
| 129 __ Mov(code_object, lr); | 138 __ Mov(code_object, lr); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 // Copy core registers into the input frame. | 170 // Copy core registers into the input frame. |
| 162 CPURegList copy_to_input = saved_registers; | 171 CPURegList copy_to_input = saved_registers; |
| 163 for (int i = 0; i < saved_registers.Count(); i++) { | 172 for (int i = 0; i < saved_registers.Count(); i++) { |
| 164 __ Peek(x2, i * kPointerSize); | 173 __ Peek(x2, i * kPointerSize); |
| 165 CPURegister current_reg = copy_to_input.PopLowestIndex(); | 174 CPURegister current_reg = copy_to_input.PopLowestIndex(); |
| 166 int offset = (current_reg.code() * kPointerSize) + | 175 int offset = (current_reg.code() * kPointerSize) + |
| 167 FrameDescription::registers_offset(); | 176 FrameDescription::registers_offset(); |
| 168 __ Str(x2, MemOperand(x1, offset)); | 177 __ Str(x2, MemOperand(x1, offset)); |
| 169 } | 178 } |
| 170 | 179 |
| 171 // Copy FP registers to the input frame. | 180 // Copy double registers to the input frame. |
| 172 CPURegList copy_fp_to_input = saved_fp_registers; | 181 CPURegList copy_double_to_input = saved_double_registers; |
| 173 for (int i = 0; i < saved_fp_registers.Count(); i++) { | 182 for (int i = 0; i < saved_double_registers.Count(); i++) { |
| 174 int src_offset = kFPRegistersOffset + (i * kDoubleSize); | 183 int src_offset = kDoubleRegistersOffset + (i * kDoubleSize); |
| 175 __ Peek(x2, src_offset); | 184 __ Peek(x2, src_offset); |
| 176 CPURegister reg = copy_fp_to_input.PopLowestIndex(); | 185 CPURegister reg = copy_double_to_input.PopLowestIndex(); |
| 177 int dst_offset = FrameDescription::double_registers_offset() + | 186 int dst_offset = FrameDescription::double_registers_offset() + |
| 178 (reg.code() * kDoubleSize); | 187 (reg.code() * kDoubleSize); |
| 179 __ Str(x2, MemOperand(x1, dst_offset)); | 188 __ Str(x2, MemOperand(x1, dst_offset)); |
| 180 } | 189 } |
| 181 | 190 |
| 191 // Copy float registers to the input frame. |
| 192 CPURegList copy_float_to_input = saved_float_registers; |
| 193 for (int i = 0; i < saved_float_registers.Count(); i++) { |
| 194 int src_offset = kFloatRegistersOffset + (i * kFloatSize); |
| 195 __ Peek(w2, src_offset); |
| 196 CPURegister reg = copy_float_to_input.PopLowestIndex(); |
| 197 int dst_offset = |
| 198 FrameDescription::float_registers_offset() + (reg.code() * kFloatSize); |
| 199 __ Str(w2, MemOperand(x1, dst_offset)); |
| 200 } |
| 201 |
| 182 // Remove the bailout id and the saved registers from the stack. | 202 // Remove the bailout id and the saved registers from the stack. |
| 183 __ Drop(1 + (kSavedRegistersAreaSize / kXRegSize)); | 203 __ Drop(1 + (kSavedRegistersAreaSize / kXRegSize)); |
| 184 | 204 |
| 185 // Compute a pointer to the unwinding limit in register x2; that is | 205 // Compute a pointer to the unwinding limit in register x2; that is |
| 186 // the first stack slot not part of the input frame. | 206 // the first stack slot not part of the input frame. |
| 187 Register unwind_limit = x2; | 207 Register unwind_limit = x2; |
| 188 __ Ldr(unwind_limit, MemOperand(x1, FrameDescription::frame_size_offset())); | 208 __ Ldr(unwind_limit, MemOperand(x1, FrameDescription::frame_size_offset())); |
| 189 __ Add(unwind_limit, unwind_limit, __ StackPointer()); | 209 __ Add(unwind_limit, unwind_limit, __ StackPointer()); |
| 190 | 210 |
| 191 // Unwind the stack down to - but not including - the unwinding | 211 // Unwind the stack down to - but not including - the unwinding |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 __ Push(x7); | 257 __ Push(x7); |
| 238 __ Bind(&inner_loop_header); | 258 __ Bind(&inner_loop_header); |
| 239 __ Cbnz(x3, &inner_push_loop); | 259 __ Cbnz(x3, &inner_push_loop); |
| 240 | 260 |
| 241 __ Add(x0, x0, kPointerSize); | 261 __ Add(x0, x0, kPointerSize); |
| 242 __ Bind(&outer_loop_header); | 262 __ Bind(&outer_loop_header); |
| 243 __ Cmp(x0, x1); | 263 __ Cmp(x0, x1); |
| 244 __ B(lt, &outer_push_loop); | 264 __ B(lt, &outer_push_loop); |
| 245 | 265 |
| 246 __ Ldr(x1, MemOperand(x4, Deoptimizer::input_offset())); | 266 __ Ldr(x1, MemOperand(x4, Deoptimizer::input_offset())); |
| 247 DCHECK(!saved_fp_registers.IncludesAliasOf(crankshaft_fp_scratch) && | 267 DCHECK(!saved_double_registers.IncludesAliasOf(crankshaft_fp_scratch) && |
| 248 !saved_fp_registers.IncludesAliasOf(fp_zero) && | 268 !saved_double_registers.IncludesAliasOf(fp_zero) && |
| 249 !saved_fp_registers.IncludesAliasOf(fp_scratch)); | 269 !saved_double_registers.IncludesAliasOf(fp_scratch)); |
| 250 while (!saved_fp_registers.IsEmpty()) { | 270 while (!saved_double_registers.IsEmpty()) { |
| 251 const CPURegister reg = saved_fp_registers.PopLowestIndex(); | 271 const CPURegister reg = saved_double_registers.PopLowestIndex(); |
| 252 int src_offset = FrameDescription::double_registers_offset() + | 272 int src_offset = FrameDescription::double_registers_offset() + |
| 253 (reg.code() * kDoubleSize); | 273 (reg.code() * kDoubleSize); |
| 254 __ Ldr(reg, MemOperand(x1, src_offset)); | 274 __ Ldr(reg, MemOperand(x1, src_offset)); |
| 255 } | 275 } |
| 256 | 276 |
| 257 // Push state from the last output frame. | 277 // Push state from the last output frame. |
| 258 __ Ldr(x6, MemOperand(current_frame, FrameDescription::state_offset())); | 278 __ Ldr(x6, MemOperand(current_frame, FrameDescription::state_offset())); |
| 259 __ Push(x6); | 279 __ Push(x6); |
| 260 | 280 |
| 261 // TODO(all): ARM copies a lot (if not all) of the last output frame onto the | 281 // TODO(all): ARM copies a lot (if not all) of the last output frame onto the |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { | 362 void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { |
| 343 // No embedded constant pool support. | 363 // No embedded constant pool support. |
| 344 UNREACHABLE(); | 364 UNREACHABLE(); |
| 345 } | 365 } |
| 346 | 366 |
| 347 | 367 |
| 348 #undef __ | 368 #undef __ |
| 349 | 369 |
| 350 } // namespace internal | 370 } // namespace internal |
| 351 } // namespace v8 | 371 } // namespace v8 |
| OLD | NEW |