| 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 |