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 |