OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 } | 300 } |
301 | 301 |
302 | 302 |
303 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 303 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
304 intptr_t deopt_reason, | 304 intptr_t deopt_reason, |
305 uword saved_registers_address); | 305 uword saved_registers_address); |
306 | 306 |
307 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); | 307 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); |
308 | 308 |
309 | 309 |
| 310 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. |
310 // This stub translates optimized frame into unoptimized frame. The optimized | 311 // This stub translates optimized frame into unoptimized frame. The optimized |
311 // frame can contain values in registers and on stack, the unoptimized | 312 // frame can contain values in registers and on stack, the unoptimized |
312 // frame contains all values on stack. | 313 // frame contains all values on stack. |
313 // Deoptimization occurs in following steps: | 314 // Deoptimization occurs in following steps: |
314 // - Push all registers that can contain values. | 315 // - Push all registers that can contain values. |
315 // - Call C routine to copy the stack and saved registers into temporary buffer. | 316 // - Call C routine to copy the stack and saved registers into temporary buffer. |
316 // - Adjust caller's frame to correct unoptimized frame size. | 317 // - Adjust caller's frame to correct unoptimized frame size. |
317 // - Fill the unoptimized frame. | 318 // - Fill the unoptimized frame. |
318 // - Materialize objects that require allocation (e.g. Double instances). | 319 // - Materialize objects that require allocation (e.g. Double instances). |
319 // GC can occur only after frame is fully rewritten. | 320 // GC can occur only after frame is fully rewritten. |
320 // Stack after EnterFrame(0) below: | 321 // Stack after EnterDartFrame(0) below: |
321 // +------------------+ | 322 // +------------------+ |
322 // | Saved FP | <- TOS | 323 // | PC marker | <- TOS |
| 324 // +------------------+ |
| 325 // | Saved FP | <- FP of stub |
323 // +------------------+ | 326 // +------------------+ |
324 // | return-address | (deoptimization point) | 327 // | return-address | (deoptimization point) |
325 // +------------------+ | 328 // +------------------+ |
326 // | optimized frame | | 329 // | ... | <- SP of optimized frame |
327 // | ... | | |
328 // | 330 // |
329 // Parts of the code cannot GC, part of the code can GC. | 331 // Parts of the code cannot GC, part of the code can GC. |
330 static void GenerateDeoptimizationSequence(Assembler* assembler, | 332 static void GenerateDeoptimizationSequence(Assembler* assembler, |
331 bool preserve_rax) { | 333 bool preserve_result) { |
332 __ EnterFrame(0); | 334 // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. |
| 335 __ EnterDartFrame(0); |
333 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry | 336 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
334 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. | 337 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
335 const intptr_t saved_rax_offset_from_ebp = -(kNumberOfCpuRegisters - RAX); | 338 const intptr_t saved_result_slot_from_fp = |
336 // Result in EAX is preserved as part of pushing all registers below. | 339 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX); |
| 340 // Result in RAX is preserved as part of pushing all registers below. |
337 | 341 |
338 // Push registers in their enumeration order: lowest register number at | 342 // Push registers in their enumeration order: lowest register number at |
339 // lowest address. | 343 // lowest address. |
340 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { | 344 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { |
341 __ pushq(static_cast<Register>(i)); | 345 __ pushq(static_cast<Register>(i)); |
342 } | 346 } |
343 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); | 347 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); |
344 intptr_t offset = 0; | 348 intptr_t offset = 0; |
345 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 349 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
346 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 350 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
347 __ movups(Address(RSP, offset), xmm_reg); | 351 __ movups(Address(RSP, offset), xmm_reg); |
348 offset += kFpuRegisterSize; | 352 offset += kFpuRegisterSize; |
349 } | 353 } |
350 | 354 |
351 __ movq(RDI, RSP); // Pass address of saved registers block. | 355 __ movq(RDI, RSP); // Pass address of saved registers block. |
352 __ ReserveAlignedFrameSpace(0); | 356 __ ReserveAlignedFrameSpace(0); |
353 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); | 357 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); |
354 // Result (RAX) is stack-size (FP - SP) in bytes, incl. the return address. | 358 // Result (RAX) is stack-size (FP - SP) in bytes. |
355 | 359 |
356 if (preserve_rax) { | 360 if (preserve_result) { |
357 // Restore result into RBX temporarily. | 361 // Restore result into RBX temporarily. |
358 __ movq(RBX, Address(RBP, saved_rax_offset_from_ebp * kWordSize)); | 362 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); |
359 } | 363 } |
360 | 364 |
361 __ LeaveFrame(); | 365 __ LeaveFrame(); |
362 __ popq(RCX); // Preserve return address. | 366 __ popq(RCX); // Preserve return address. |
363 __ movq(RSP, RBP); | 367 __ movq(RSP, RBP); // Discard optimized frame. |
364 __ subq(RSP, RAX); | 368 __ subq(RSP, RAX); // Reserve space for deoptimized frame. |
365 __ movq(Address(RSP, 0), RCX); | 369 __ pushq(RCX); // Restore return address. |
366 | 370 |
367 __ EnterFrame(0); | 371 // Leaf runtime function DeoptimizeFillFrame expects a Dart frame. |
368 __ movq(RCX, RSP); // Get last FP address. | 372 __ EnterDartFrame(0); |
369 if (preserve_rax) { | 373 if (preserve_result) { |
370 __ pushq(RBX); // Preserve result. | 374 __ pushq(RBX); // Preserve result as first local. |
371 } | 375 } |
372 __ ReserveAlignedFrameSpace(0); | 376 __ ReserveAlignedFrameSpace(0); |
373 __ movq(RDI, RCX); // Set up argument 1 last_fp. | 377 __ movq(RDI, RBP); // Pass last FP as parameter in RDI. |
374 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); | 378 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); |
375 // Result (RAX) is our FP. | 379 if (preserve_result) { |
376 if (preserve_rax) { | |
377 // Restore result into RBX. | 380 // Restore result into RBX. |
378 __ movq(RBX, Address(RBP, -1 * kWordSize)); | 381 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); |
379 } | 382 } |
380 // Code above cannot cause GC. | 383 // Code above cannot cause GC. |
381 __ LeaveFrame(); | 384 __ LeaveFrame(); |
382 __ movq(RBP, RAX); | |
383 | 385 |
384 // Frame is fully rewritten at this point and it is safe to perform a GC. | 386 // Frame is fully rewritten at this point and it is safe to perform a GC. |
385 // Materialize any objects that were deferred by FillFrame because they | 387 // Materialize any objects that were deferred by FillFrame because they |
386 // require allocation. | 388 // require allocation. |
387 __ EnterStubFrame(); | 389 __ EnterStubFrame(); |
388 if (preserve_rax) { | 390 if (preserve_result) { |
389 __ pushq(RBX); // Preserve result, it will be GC-d here. | 391 __ pushq(RBX); // Preserve result, it will be GC-d here. |
390 } | 392 } |
391 __ pushq(Immediate(Smi::RawValue(0))); // Space for the result. | 393 __ pushq(Immediate(Smi::RawValue(0))); // Space for the result. |
392 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry); | 394 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry); |
393 // Result tells stub how many bytes to remove from the expression stack | 395 // Result tells stub how many bytes to remove from the expression stack |
394 // of the bottom-most frame. They were used as materialization arguments. | 396 // of the bottom-most frame. They were used as materialization arguments. |
395 __ popq(RBX); | 397 __ popq(RBX); |
396 __ SmiUntag(RBX); | 398 __ SmiUntag(RBX); |
397 if (preserve_rax) { | 399 if (preserve_result) { |
398 __ popq(RAX); // Restore result. | 400 __ popq(RAX); // Restore result. |
399 } | 401 } |
400 __ LeaveFrame(); | 402 __ LeaveFrame(); |
401 | 403 |
402 __ popq(RCX); // Pop return address. | 404 __ popq(RCX); // Pop return address. |
403 __ addq(RSP, RBX); // Remove materialization arguments. | 405 __ addq(RSP, RBX); // Remove materialization arguments. |
404 __ pushq(RCX); // Push return address. | 406 __ pushq(RCX); // Push return address. |
405 __ ret(); | 407 __ ret(); |
406 } | 408 } |
407 | 409 |
(...skipping 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2090 __ cmpq(left, right); | 2092 __ cmpq(left, right); |
2091 __ Bind(&done); | 2093 __ Bind(&done); |
2092 __ popq(right); | 2094 __ popq(right); |
2093 __ popq(left); | 2095 __ popq(left); |
2094 __ ret(); | 2096 __ ret(); |
2095 } | 2097 } |
2096 | 2098 |
2097 } // namespace dart | 2099 } // namespace dart |
2098 | 2100 |
2099 #endif // defined TARGET_ARCH_X64 | 2101 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |