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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
9 #include "src/full-codegen.h" | 9 #include "src/full-codegen.h" |
10 #include "src/safepoint-table.h" | 10 #include "src/safepoint-table.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 if (deopt_data->Pc(i)->value() == -1) continue; | 42 if (deopt_data->Pc(i)->value() == -1) continue; |
43 | 43 |
44 Address call_address = code_start_address + deopt_data->Pc(i)->value(); | 44 Address call_address = code_start_address + deopt_data->Pc(i)->value(); |
45 Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY); | 45 Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY); |
46 | 46 |
47 PatchingAssembler patcher(call_address, patch_size() / kInstructionSize); | 47 PatchingAssembler patcher(call_address, patch_size() / kInstructionSize); |
48 patcher.ldr_pcrel(ip0, (2 * kInstructionSize) >> kLoadLiteralScaleLog2); | 48 patcher.ldr_pcrel(ip0, (2 * kInstructionSize) >> kLoadLiteralScaleLog2); |
49 patcher.blr(ip0); | 49 patcher.blr(ip0); |
50 patcher.dc64(reinterpret_cast<intptr_t>(deopt_entry)); | 50 patcher.dc64(reinterpret_cast<intptr_t>(deopt_entry)); |
51 | 51 |
52 ASSERT((prev_call_address == NULL) || | 52 DCHECK((prev_call_address == NULL) || |
53 (call_address >= prev_call_address + patch_size())); | 53 (call_address >= prev_call_address + patch_size())); |
54 ASSERT(call_address + patch_size() <= code->instruction_end()); | 54 DCHECK(call_address + patch_size() <= code->instruction_end()); |
55 #ifdef DEBUG | 55 #ifdef DEBUG |
56 prev_call_address = call_address; | 56 prev_call_address = call_address; |
57 #endif | 57 #endif |
58 } | 58 } |
59 } | 59 } |
60 | 60 |
61 | 61 |
62 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 62 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
63 // Set the register values. The values are not important as there are no | 63 // Set the register values. The values are not important as there are no |
64 // callee saved registers in JavaScript frames, so all registers are | 64 // callee saved registers in JavaScript frames, so all registers are |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 __ Push(x7); | 243 __ Push(x7); |
244 __ Bind(&inner_loop_header); | 244 __ Bind(&inner_loop_header); |
245 __ Cbnz(x3, &inner_push_loop); | 245 __ Cbnz(x3, &inner_push_loop); |
246 | 246 |
247 __ Add(x0, x0, kPointerSize); | 247 __ Add(x0, x0, kPointerSize); |
248 __ Bind(&outer_loop_header); | 248 __ Bind(&outer_loop_header); |
249 __ Cmp(x0, x1); | 249 __ Cmp(x0, x1); |
250 __ B(lt, &outer_push_loop); | 250 __ B(lt, &outer_push_loop); |
251 | 251 |
252 __ Ldr(x1, MemOperand(x4, Deoptimizer::input_offset())); | 252 __ Ldr(x1, MemOperand(x4, Deoptimizer::input_offset())); |
253 ASSERT(!saved_fp_registers.IncludesAliasOf(crankshaft_fp_scratch) && | 253 DCHECK(!saved_fp_registers.IncludesAliasOf(crankshaft_fp_scratch) && |
254 !saved_fp_registers.IncludesAliasOf(fp_zero) && | 254 !saved_fp_registers.IncludesAliasOf(fp_zero) && |
255 !saved_fp_registers.IncludesAliasOf(fp_scratch)); | 255 !saved_fp_registers.IncludesAliasOf(fp_scratch)); |
256 int src_offset = FrameDescription::double_registers_offset(); | 256 int src_offset = FrameDescription::double_registers_offset(); |
257 while (!saved_fp_registers.IsEmpty()) { | 257 while (!saved_fp_registers.IsEmpty()) { |
258 const CPURegister reg = saved_fp_registers.PopLowestIndex(); | 258 const CPURegister reg = saved_fp_registers.PopLowestIndex(); |
259 __ Ldr(reg, MemOperand(x1, src_offset)); | 259 __ Ldr(reg, MemOperand(x1, src_offset)); |
260 src_offset += kDoubleSize; | 260 src_offset += kDoubleSize; |
261 } | 261 } |
262 | 262 |
263 // Push state from the last output frame. | 263 // Push state from the last output frame. |
264 __ Ldr(x6, MemOperand(current_frame, FrameDescription::state_offset())); | 264 __ Ldr(x6, MemOperand(current_frame, FrameDescription::state_offset())); |
265 __ Push(x6); | 265 __ Push(x6); |
266 | 266 |
267 // TODO(all): ARM copies a lot (if not all) of the last output frame onto the | 267 // TODO(all): ARM copies a lot (if not all) of the last output frame onto the |
268 // stack, then pops it all into registers. Here, we try to load it directly | 268 // stack, then pops it all into registers. Here, we try to load it directly |
269 // into the relevant registers. Is this correct? If so, we should improve the | 269 // into the relevant registers. Is this correct? If so, we should improve the |
270 // ARM code. | 270 // ARM code. |
271 | 271 |
272 // TODO(all): This code needs to be revisited, We probably don't need to | 272 // TODO(all): This code needs to be revisited, We probably don't need to |
273 // restore all the registers as fullcodegen does not keep live values in | 273 // restore all the registers as fullcodegen does not keep live values in |
274 // registers (note that at least fp must be restored though). | 274 // registers (note that at least fp must be restored though). |
275 | 275 |
276 // Restore registers from the last output frame. | 276 // Restore registers from the last output frame. |
277 // Note that lr is not in the list of saved_registers and will be restored | 277 // Note that lr is not in the list of saved_registers and will be restored |
278 // later. We can use it to hold the address of last output frame while | 278 // later. We can use it to hold the address of last output frame while |
279 // reloading the other registers. | 279 // reloading the other registers. |
280 ASSERT(!saved_registers.IncludesAliasOf(lr)); | 280 DCHECK(!saved_registers.IncludesAliasOf(lr)); |
281 Register last_output_frame = lr; | 281 Register last_output_frame = lr; |
282 __ Mov(last_output_frame, current_frame); | 282 __ Mov(last_output_frame, current_frame); |
283 | 283 |
284 // We don't need to restore x7 as it will be clobbered later to hold the | 284 // We don't need to restore x7 as it will be clobbered later to hold the |
285 // continuation address. | 285 // continuation address. |
286 Register continuation = x7; | 286 Register continuation = x7; |
287 saved_registers.Remove(continuation); | 287 saved_registers.Remove(continuation); |
288 | 288 |
289 while (!saved_registers.IsEmpty()) { | 289 while (!saved_registers.IsEmpty()) { |
290 // TODO(all): Look for opportunities to optimize this by using ldp. | 290 // TODO(all): Look for opportunities to optimize this by using ldp. |
(...skipping 22 matching lines...) Expand all Loading... |
313 | 313 |
314 // Create a sequence of deoptimization entries. | 314 // Create a sequence of deoptimization entries. |
315 // Note that registers are still live when jumping to an entry. | 315 // Note that registers are still live when jumping to an entry. |
316 Label done; | 316 Label done; |
317 { | 317 { |
318 InstructionAccurateScope scope(masm()); | 318 InstructionAccurateScope scope(masm()); |
319 | 319 |
320 // The number of entry will never exceed kMaxNumberOfEntries. | 320 // The number of entry will never exceed kMaxNumberOfEntries. |
321 // As long as kMaxNumberOfEntries is a valid 16 bits immediate you can use | 321 // As long as kMaxNumberOfEntries is a valid 16 bits immediate you can use |
322 // a movz instruction to load the entry id. | 322 // a movz instruction to load the entry id. |
323 ASSERT(is_uint16(Deoptimizer::kMaxNumberOfEntries)); | 323 DCHECK(is_uint16(Deoptimizer::kMaxNumberOfEntries)); |
324 | 324 |
325 for (int i = 0; i < count(); i++) { | 325 for (int i = 0; i < count(); i++) { |
326 int start = masm()->pc_offset(); | 326 int start = masm()->pc_offset(); |
327 USE(start); | 327 USE(start); |
328 __ movz(entry_id, i); | 328 __ movz(entry_id, i); |
329 __ b(&done); | 329 __ b(&done); |
330 ASSERT(masm()->pc_offset() - start == table_entry_size_); | 330 DCHECK(masm()->pc_offset() - start == table_entry_size_); |
331 } | 331 } |
332 } | 332 } |
333 __ Bind(&done); | 333 __ Bind(&done); |
334 __ Push(entry_id); | 334 __ Push(entry_id); |
335 } | 335 } |
336 | 336 |
337 | 337 |
338 void FrameDescription::SetCallerPc(unsigned offset, intptr_t value) { | 338 void FrameDescription::SetCallerPc(unsigned offset, intptr_t value) { |
339 SetFrameSlot(offset, value); | 339 SetFrameSlot(offset, value); |
340 } | 340 } |
341 | 341 |
342 | 342 |
343 void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) { | 343 void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) { |
344 SetFrameSlot(offset, value); | 344 SetFrameSlot(offset, value); |
345 } | 345 } |
346 | 346 |
347 | 347 |
348 void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { | 348 void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { |
349 // No out-of-line constant pool support. | 349 // No out-of-line constant pool support. |
350 UNREACHABLE(); | 350 UNREACHABLE(); |
351 } | 351 } |
352 | 352 |
353 | 353 |
354 #undef __ | 354 #undef __ |
355 | 355 |
356 } } // namespace v8::internal | 356 } } // namespace v8::internal |
OLD | NEW |