| 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 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 } | 323 } |
| 324 | 324 |
| 325 | 325 |
| 326 // Input parameters: | 326 // Input parameters: |
| 327 // RBX: ic-data. | 327 // RBX: ic-data. |
| 328 // R10: arguments descriptor array. | 328 // R10: arguments descriptor array. |
| 329 // Note: The receiver object is the first argument to the function being | 329 // Note: The receiver object is the first argument to the function being |
| 330 // called, the stub accesses the receiver from this location directly | 330 // called, the stub accesses the receiver from this location directly |
| 331 // when trying to resolve the call. | 331 // when trying to resolve the call. |
| 332 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { | 332 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
| 333 __ EnterStubFrame(); | 333 __ EnterStubFrame(true); |
| 334 | 334 |
| 335 const Immediate& raw_null = | 335 const Immediate& raw_null = |
| 336 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 336 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 337 __ pushq(raw_null); // Space for the return value. | 337 __ pushq(raw_null); // Space for the return value. |
| 338 | 338 |
| 339 // Push the receiver as an argument. Load the smi-tagged argument | 339 // Push the receiver as an argument. Load the smi-tagged argument |
| 340 // count into R13 to index the receiver in the stack. There are | 340 // count into R13 to index the receiver in the stack. There are |
| 341 // three words (null, stub's pc marker, saved fp) above the return | 341 // four words (null, stub's pc marker, saved pp, saved fp) above the return |
| 342 // address. | 342 // address. |
| 343 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 343 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 344 __ pushq(Address(RSP, R13, TIMES_4, (3 * kWordSize))); | 344 __ pushq(Address(RSP, R13, TIMES_4, (4 * kWordSize))); |
| 345 | 345 |
| 346 __ pushq(RBX); // Pass IC data object. | 346 __ pushq(RBX); // Pass IC data object. |
| 347 __ pushq(R10); // Pass arguments descriptor array. | 347 __ pushq(R10); // Pass arguments descriptor array. |
| 348 | 348 |
| 349 // Pass the call's arguments array. | 349 // Pass the call's arguments array. |
| 350 __ movq(R10, R13); // Smi-tagged arguments array length. | 350 __ movq(R10, R13); // Smi-tagged arguments array length. |
| 351 PushArgumentsArray(assembler); | 351 PushArgumentsArray(assembler); |
| 352 | 352 |
| 353 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry); | 353 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry); |
| 354 | 354 |
| 355 // Remove arguments. | 355 // Remove arguments. |
| 356 __ Drop(4); | 356 __ Drop(4); |
| 357 __ popq(RAX); // Get result into RAX. | 357 __ popq(RAX); // Get result into RAX. |
| 358 __ LeaveFrame(); | 358 __ LeaveFrame(true); |
| 359 __ ret(); | 359 __ ret(); |
| 360 } | 360 } |
| 361 | 361 |
| 362 | 362 |
| 363 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 363 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 364 intptr_t deopt_reason, | 364 intptr_t deopt_reason, |
| 365 uword saved_registers_address); | 365 uword saved_registers_address); |
| 366 | 366 |
| 367 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); | 367 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); |
| 368 | 368 |
| 369 | 369 |
| 370 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. | 370 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. |
| 371 // This stub translates optimized frame into unoptimized frame. The optimized | 371 // This stub translates optimized frame into unoptimized frame. The optimized |
| 372 // frame can contain values in registers and on stack, the unoptimized | 372 // frame can contain values in registers and on stack, the unoptimized |
| 373 // frame contains all values on stack. | 373 // frame contains all values on stack. |
| 374 // Deoptimization occurs in following steps: | 374 // Deoptimization occurs in following steps: |
| 375 // - Push all registers that can contain values. | 375 // - Push all registers that can contain values. |
| 376 // - Call C routine to copy the stack and saved registers into temporary buffer. | 376 // - Call C routine to copy the stack and saved registers into temporary buffer. |
| 377 // - Adjust caller's frame to correct unoptimized frame size. | 377 // - Adjust caller's frame to correct unoptimized frame size. |
| 378 // - Fill the unoptimized frame. | 378 // - Fill the unoptimized frame. |
| 379 // - Materialize objects that require allocation (e.g. Double instances). | 379 // - Materialize objects that require allocation (e.g. Double instances). |
| 380 // GC can occur only after frame is fully rewritten. | 380 // GC can occur only after frame is fully rewritten. |
| 381 // Stack after EnterDartFrame(0) below: | 381 // Stack after EnterDartFrame(0) below: |
| 382 // +------------------+ | 382 // +------------------+ |
| 383 // | Saved PP | <- PP |
| 384 // +------------------+ |
| 383 // | PC marker | <- TOS | 385 // | PC marker | <- TOS |
| 384 // +------------------+ | 386 // +------------------+ |
| 385 // | Saved FP | <- FP of stub | 387 // | Saved FP | <- FP of stub |
| 386 // +------------------+ | 388 // +------------------+ |
| 387 // | return-address | (deoptimization point) | 389 // | return-address | (deoptimization point) |
| 388 // +------------------+ | 390 // +------------------+ |
| 389 // | ... | <- SP of optimized frame | 391 // | ... | <- SP of optimized frame |
| 390 // | 392 // |
| 391 // Parts of the code cannot GC, part of the code can GC. | 393 // Parts of the code cannot GC, part of the code can GC. |
| 392 static void GenerateDeoptimizationSequence(Assembler* assembler, | 394 static void GenerateDeoptimizationSequence(Assembler* assembler, |
| 393 bool preserve_result) { | 395 bool preserve_result) { |
| 394 // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. | 396 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| 395 __ EnterDartFrame(0); | 397 // is no need to set the correct PC marker or load PP, since they get patched. |
| 398 __ EnterFrame(0); |
| 399 __ pushq(Immediate(0)); |
| 400 __ pushq(PP); |
| 401 |
| 396 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry | 402 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
| 397 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. | 403 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
| 398 const intptr_t saved_result_slot_from_fp = | 404 const intptr_t saved_result_slot_from_fp = |
| 399 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX); | 405 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX); |
| 400 // Result in RAX is preserved as part of pushing all registers below. | 406 // Result in RAX is preserved as part of pushing all registers below. |
| 401 | 407 |
| 402 // Push registers in their enumeration order: lowest register number at | 408 // Push registers in their enumeration order: lowest register number at |
| 403 // lowest address. | 409 // lowest address. |
| 404 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { | 410 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { |
| 405 __ pushq(static_cast<Register>(i)); | 411 __ pushq(static_cast<Register>(i)); |
| 406 } | 412 } |
| 407 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); | 413 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); |
| 408 intptr_t offset = 0; | 414 intptr_t offset = 0; |
| 409 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 415 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 410 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 416 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 411 __ movups(Address(RSP, offset), xmm_reg); | 417 __ movups(Address(RSP, offset), xmm_reg); |
| 412 offset += kFpuRegisterSize; | 418 offset += kFpuRegisterSize; |
| 413 } | 419 } |
| 414 | 420 |
| 415 __ movq(RDI, RSP); // Pass address of saved registers block. | 421 __ movq(RDI, RSP); // Pass address of saved registers block. |
| 416 __ ReserveAlignedFrameSpace(0); | 422 __ ReserveAlignedFrameSpace(0); |
| 417 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); | 423 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); |
| 418 // Result (RAX) is stack-size (FP - SP) in bytes. | 424 // Result (RAX) is stack-size (FP - SP) in bytes. |
| 419 | 425 |
| 420 if (preserve_result) { | 426 if (preserve_result) { |
| 421 // Restore result into RBX temporarily. | 427 // Restore result into RBX temporarily. |
| 422 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); | 428 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); |
| 423 } | 429 } |
| 424 | 430 |
| 425 __ LeaveFrame(); | 431 __ LeaveFrame(true); |
| 426 __ popq(RCX); // Preserve return address. | 432 __ popq(RCX); // Preserve return address. |
| 427 __ movq(RSP, RBP); // Discard optimized frame. | 433 __ movq(RSP, RBP); // Discard optimized frame. |
| 428 __ subq(RSP, RAX); // Reserve space for deoptimized frame. | 434 __ subq(RSP, RAX); // Reserve space for deoptimized frame. |
| 429 __ pushq(RCX); // Restore return address. | 435 __ pushq(RCX); // Restore return address. |
| 430 | 436 |
| 431 // Leaf runtime function DeoptimizeFillFrame expects a Dart frame. | 437 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| 432 __ EnterDartFrame(0); | 438 // is no need to set the correct PC marker or load PP, since they get patched. |
| 439 __ EnterFrame(0); |
| 440 __ pushq(Immediate(0)); |
| 441 __ pushq(PP); |
| 442 |
| 433 if (preserve_result) { | 443 if (preserve_result) { |
| 434 __ pushq(RBX); // Preserve result as first local. | 444 __ pushq(RBX); // Preserve result as first local. |
| 435 } | 445 } |
| 436 __ ReserveAlignedFrameSpace(0); | 446 __ ReserveAlignedFrameSpace(0); |
| 437 __ movq(RDI, RBP); // Pass last FP as parameter in RDI. | 447 __ movq(RDI, RBP); // Pass last FP as parameter in RDI. |
| 438 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); | 448 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); |
| 439 if (preserve_result) { | 449 if (preserve_result) { |
| 440 // Restore result into RBX. | 450 // Restore result into RBX. |
| 441 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); | 451 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); |
| 442 } | 452 } |
| 443 // Code above cannot cause GC. | 453 // Code above cannot cause GC. |
| 444 __ LeaveFrame(); | 454 __ LeaveFrame(true); |
| 445 | 455 |
| 446 // Frame is fully rewritten at this point and it is safe to perform a GC. | 456 // Frame is fully rewritten at this point and it is safe to perform a GC. |
| 447 // Materialize any objects that were deferred by FillFrame because they | 457 // Materialize any objects that were deferred by FillFrame because they |
| 448 // require allocation. | 458 // require allocation. |
| 449 __ EnterStubFrame(); | 459 __ EnterStubFrame(); |
| 450 if (preserve_result) { | 460 if (preserve_result) { |
| 451 __ pushq(RBX); // Preserve result, it will be GC-d here. | 461 __ pushq(RBX); // Preserve result, it will be GC-d here. |
| 452 } | 462 } |
| 453 __ pushq(Immediate(Smi::RawValue(0))); // Space for the result. | 463 __ pushq(Immediate(Smi::RawValue(0))); // Space for the result. |
| 454 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry); | 464 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 479 GenerateDeoptimizationSequence(assembler, true); // Preserve RAX. | 489 GenerateDeoptimizationSequence(assembler, true); // Preserve RAX. |
| 480 } | 490 } |
| 481 | 491 |
| 482 | 492 |
| 483 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 493 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 484 GenerateDeoptimizationSequence(assembler, false); // Don't preserve RAX. | 494 GenerateDeoptimizationSequence(assembler, false); // Don't preserve RAX. |
| 485 } | 495 } |
| 486 | 496 |
| 487 | 497 |
| 488 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 498 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
| 489 __ EnterStubFrame(); | 499 __ EnterStubFrame(true); |
| 490 // Load the receiver into RAX. The argument count in the arguments | 500 // Load the receiver into RAX. The argument count in the arguments |
| 491 // descriptor in R10 is a smi. | 501 // descriptor in R10 is a smi. |
| 492 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 502 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 493 // Two words (saved fp, stub's pc marker) in the stack above the return | 503 // Three words (saved pp, saved fp, stub's pc marker) |
| 494 // address. | 504 // in the stack above the return address. |
| 495 __ movq(RAX, Address(RSP, RAX, TIMES_4, 2 * kWordSize)); | 505 __ movq(RAX, Address(RSP, RAX, TIMES_4, |
| 506 kSavedAboveReturnAddress * kWordSize)); |
| 496 // Preserve IC data and arguments descriptor. | 507 // Preserve IC data and arguments descriptor. |
| 497 __ pushq(RBX); | 508 __ pushq(RBX); |
| 498 __ pushq(R10); | 509 __ pushq(R10); |
| 499 | 510 |
| 500 const Immediate& raw_null = | 511 const Immediate& raw_null = |
| 501 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); | 512 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); |
| 502 __ pushq(raw_null); // Space for the result of the runtime call. | 513 __ pushq(raw_null); // Space for the result of the runtime call. |
| 503 __ pushq(RAX); // Receiver. | 514 __ pushq(RAX); // Receiver. |
| 504 __ pushq(RBX); // IC data. | 515 __ pushq(RBX); // IC data. |
| 505 __ pushq(R10); // Arguments descriptor. | 516 __ pushq(R10); // Arguments descriptor. |
| 506 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry); | 517 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry); |
| 507 // Discard arguments. | 518 // Discard arguments. |
| 508 __ popq(RAX); | 519 __ popq(RAX); |
| 509 __ popq(RAX); | 520 __ popq(RAX); |
| 510 __ popq(RAX); | 521 __ popq(RAX); |
| 511 __ popq(RAX); // Return value from the runtime call (instructions). | 522 __ popq(RAX); // Return value from the runtime call (instructions). |
| 512 __ popq(R10); // Restore arguments descriptor. | 523 __ popq(R10); // Restore arguments descriptor. |
| 513 __ popq(RBX); // Restore IC data. | 524 __ popq(RBX); // Restore IC data. |
| 514 __ LeaveFrame(); | 525 __ LeaveFrame(true); |
| 515 | 526 |
| 516 Label lookup; | 527 Label lookup; |
| 517 __ cmpq(RAX, raw_null); | 528 __ cmpq(RAX, raw_null); |
| 518 __ j(EQUAL, &lookup, Assembler::kNearJump); | 529 __ j(EQUAL, &lookup, Assembler::kNearJump); |
| 519 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 530 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 520 __ jmp(RAX); | 531 __ jmp(RAX); |
| 521 | 532 |
| 522 __ Bind(&lookup); | 533 __ Bind(&lookup); |
| 523 __ jmp(&StubCode::InstanceFunctionLookupLabel()); | 534 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
| 524 } | 535 } |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 | 765 |
| 755 // Called when invoking Dart code from C++ (VM code). | 766 // Called when invoking Dart code from C++ (VM code). |
| 756 // Input parameters: | 767 // Input parameters: |
| 757 // RSP : points to return address. | 768 // RSP : points to return address. |
| 758 // RDI : entrypoint of the Dart function to call. | 769 // RDI : entrypoint of the Dart function to call. |
| 759 // RSI : arguments descriptor array. | 770 // RSI : arguments descriptor array. |
| 760 // RDX : arguments array. | 771 // RDX : arguments array. |
| 761 // RCX : new context containing the current isolate pointer. | 772 // RCX : new context containing the current isolate pointer. |
| 762 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | 773 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
| 763 // Save frame pointer coming in. | 774 // Save frame pointer coming in. |
| 764 __ EnterFrame(0); | 775 __ EnterStubFrame(); |
| 765 | 776 |
| 766 // Save arguments descriptor array and new context. | 777 // Save arguments descriptor array and new context. |
| 767 const intptr_t kArgumentsDescOffset = -1 * kWordSize; | 778 const intptr_t kArgumentsDescOffset = -2 * kWordSize; |
| 768 __ pushq(RSI); | 779 __ pushq(RSI); |
| 769 const intptr_t kNewContextOffset = -2 * kWordSize; | 780 const intptr_t kNewContextOffset = -3 * kWordSize; |
| 770 __ pushq(RCX); | 781 __ pushq(RCX); |
| 771 | 782 |
| 772 // Save C++ ABI callee-saved registers. | 783 // Save C++ ABI callee-saved registers. |
| 773 __ pushq(RBX); | 784 __ pushq(RBX); |
| 774 __ pushq(R12); | 785 __ pushq(R12); |
| 775 __ pushq(R13); | 786 __ pushq(R13); |
| 776 __ pushq(R14); | 787 __ pushq(R14); |
| 777 __ pushq(R15); | 788 __ pushq(R15); |
| 778 | 789 |
| 779 // The new Context structure contains a pointer to the current Isolate | 790 // The new Context structure contains a pointer to the current Isolate |
| 780 // structure. Cache the Context pointer in the CTX register so that it is | 791 // structure. Cache the Context pointer in the CTX register so that it is |
| 781 // available in generated code and calls to Isolate::Current() need not be | 792 // available in generated code and calls to Isolate::Current() need not be |
| 782 // done. The assumption is that this register will never be clobbered by | 793 // done. The assumption is that this register will never be clobbered by |
| 783 // compiled or runtime stub code. | 794 // compiled or runtime stub code. |
| 784 | 795 |
| 785 // Cache the new Context pointer into CTX while executing Dart code. | 796 // Cache the new Context pointer into CTX while executing Dart code. |
| 786 __ movq(CTX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle)); | 797 __ movq(CTX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 787 | 798 |
| 788 // Load Isolate pointer from Context structure into R8. | 799 // Load Isolate pointer from Context structure into R8. |
| 789 __ movq(R8, FieldAddress(CTX, Context::isolate_offset())); | 800 __ movq(R8, FieldAddress(CTX, Context::isolate_offset())); |
| 790 | 801 |
| 791 // Save the top exit frame info. Use RAX as a temporary register. | 802 // Save the top exit frame info. Use RAX as a temporary register. |
| 792 // StackFrameIterator reads the top exit frame info saved in this frame. | 803 // StackFrameIterator reads the top exit frame info saved in this frame. |
| 793 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the | 804 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the |
| 794 // code below. | 805 // code below. |
| 795 ASSERT(kExitLinkSlotFromEntryFp == -8); | 806 ASSERT(kExitLinkSlotFromEntryFp == -9); |
| 796 __ movq(RAX, Address(R8, Isolate::top_exit_frame_info_offset())); | 807 __ movq(RAX, Address(R8, Isolate::top_exit_frame_info_offset())); |
| 797 __ pushq(RAX); | 808 __ pushq(RAX); |
| 798 __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 809 __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 799 | 810 |
| 800 // Save the old Context pointer. Use RAX as a temporary register. | 811 // Save the old Context pointer. Use RAX as a temporary register. |
| 801 // Note that VisitObjectPointers will find this saved Context pointer during | 812 // Note that VisitObjectPointers will find this saved Context pointer during |
| 802 // GC marking, since it traverses any information between SP and | 813 // GC marking, since it traverses any information between SP and |
| 803 // FP - kExitLinkSlotFromEntryFp * kWordSize. | 814 // FP - kExitLinkSlotFromEntryFp * kWordSize. |
| 804 // EntryFrame::SavedContext reads the context saved in this frame. | 815 // EntryFrame::SavedContext reads the context saved in this frame. |
| 805 // The constant kSavedContextSlotFromEntryFp must be kept in sync with | 816 // The constant kSavedContextSlotFromEntryFp must be kept in sync with |
| 806 // the code below. | 817 // the code below. |
| 807 ASSERT(kSavedContextSlotFromEntryFp == -9); | 818 ASSERT(kSavedContextSlotFromEntryFp == -10); |
| 808 __ movq(RAX, Address(R8, Isolate::top_context_offset())); | 819 __ movq(RAX, Address(R8, Isolate::top_context_offset())); |
| 809 __ pushq(RAX); | 820 __ pushq(RAX); |
| 810 | 821 |
| 811 // Load arguments descriptor array into R10, which is passed to Dart code. | 822 // Load arguments descriptor array into R10, which is passed to Dart code. |
| 812 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle)); | 823 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle)); |
| 813 | 824 |
| 814 // Load number of arguments into RBX. | 825 // Load number of arguments into RBX. |
| 815 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 826 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 816 __ SmiUntag(RBX); | 827 __ SmiUntag(RBX); |
| 817 | 828 |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1210 __ addq(RAX, Immediate(kHeapObjectTag)); | 1221 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 1211 __ ret(); | 1222 __ ret(); |
| 1212 | 1223 |
| 1213 __ Bind(&slow_case); | 1224 __ Bind(&slow_case); |
| 1214 } | 1225 } |
| 1215 if (is_cls_parameterized) { | 1226 if (is_cls_parameterized) { |
| 1216 __ movq(RAX, Address(RSP, kObjectTypeArgumentsOffset)); | 1227 __ movq(RAX, Address(RSP, kObjectTypeArgumentsOffset)); |
| 1217 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); | 1228 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); |
| 1218 } | 1229 } |
| 1219 // Create a stub frame. | 1230 // Create a stub frame. |
| 1220 __ EnterStubFrame(); | 1231 __ EnterStubFrame(true); |
| 1221 __ pushq(raw_null); // Setup space on stack for return value. | 1232 __ pushq(raw_null); // Setup space on stack for return value. |
| 1222 __ PushObject(cls); // Push class of object to be allocated. | 1233 __ PushObject(cls); // Push class of object to be allocated. |
| 1223 if (is_cls_parameterized) { | 1234 if (is_cls_parameterized) { |
| 1224 __ pushq(RAX); // Push type arguments of object to be allocated. | 1235 __ pushq(RAX); // Push type arguments of object to be allocated. |
| 1225 __ pushq(RDX); // Push type arguments of instantiator. | 1236 __ pushq(RDX); // Push type arguments of instantiator. |
| 1226 } else { | 1237 } else { |
| 1227 __ pushq(raw_null); // Push null type arguments. | 1238 __ pushq(raw_null); // Push null type arguments. |
| 1228 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1239 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 1229 } | 1240 } |
| 1230 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. | 1241 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. |
| 1231 __ popq(RAX); // Pop argument (instantiator). | 1242 __ popq(RAX); // Pop argument (instantiator). |
| 1232 __ popq(RAX); // Pop argument (type arguments of object). | 1243 __ popq(RAX); // Pop argument (type arguments of object). |
| 1233 __ popq(RAX); // Pop argument (class of object). | 1244 __ popq(RAX); // Pop argument (class of object). |
| 1234 __ popq(RAX); // Pop result (newly allocated object). | 1245 __ popq(RAX); // Pop result (newly allocated object). |
| 1235 // RAX: new object | 1246 // RAX: new object |
| 1236 // Restore the frame pointer. | 1247 // Restore the frame pointer. |
| 1237 __ LeaveFrame(); | 1248 __ LeaveFrame(true); |
| 1238 __ ret(); | 1249 __ ret(); |
| 1239 } | 1250 } |
| 1240 | 1251 |
| 1241 | 1252 |
| 1242 // Called for inline allocation of closures. | 1253 // Called for inline allocation of closures. |
| 1243 // Input parameters: | 1254 // Input parameters: |
| 1244 // RSP + 16 : receiver (null if not an implicit instance closure). | 1255 // RSP + 16 : receiver (null if not an implicit instance closure). |
| 1245 // RSP + 8 : type arguments object (null if class is not parameterized). | 1256 // RSP + 8 : type arguments object (null if class is not parameterized). |
| 1246 // RSP : points to return address. | 1257 // RSP : points to return address. |
| 1247 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 1258 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
| 1248 const Function& func) { | 1259 const Function& func) { |
| 1249 const Immediate& raw_null = | 1260 const Immediate& raw_null = |
| 1250 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1261 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1251 ASSERT(func.IsClosureFunction()); | 1262 ASSERT(func.IsClosureFunction()); |
| 1252 ASSERT(!func.IsImplicitStaticClosureFunction()); | 1263 ASSERT(!func.IsImplicitStaticClosureFunction()); |
| 1253 const bool is_implicit_instance_closure = | 1264 const bool is_implicit_instance_closure = |
| 1254 func.IsImplicitInstanceClosureFunction(); | 1265 func.IsImplicitInstanceClosureFunction(); |
| 1255 const Class& cls = Class::ZoneHandle(func.signature_class()); | 1266 const Class& cls = Class::ZoneHandle(func.signature_class()); |
| 1256 const bool has_type_arguments = cls.HasTypeArguments(); | 1267 const bool has_type_arguments = cls.HasTypeArguments(); |
| 1257 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; | 1268 |
| 1258 const intptr_t kReceiverOffset = 2 * kWordSize; | 1269 __ EnterStubFrame(true); // Uses pool pointer to refer to function. |
| 1270 const intptr_t kTypeArgumentsOffset = 4 * kWordSize; |
| 1271 const intptr_t kReceiverOffset = 5 * kWordSize; |
| 1259 const intptr_t closure_size = Closure::InstanceSize(); | 1272 const intptr_t closure_size = Closure::InstanceSize(); |
| 1260 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. | 1273 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. |
| 1261 if (FLAG_inline_alloc && | 1274 if (FLAG_inline_alloc && |
| 1262 Heap::IsAllocatableInNewSpace(closure_size + context_size)) { | 1275 Heap::IsAllocatableInNewSpace(closure_size + context_size)) { |
| 1263 Label slow_case; | 1276 Label slow_case; |
| 1264 Heap* heap = Isolate::Current()->heap(); | 1277 Heap* heap = Isolate::Current()->heap(); |
| 1265 __ movq(RAX, Immediate(heap->TopAddress())); | 1278 __ movq(RAX, Immediate(heap->TopAddress())); |
| 1266 __ movq(RAX, Address(RAX, 0)); | 1279 __ movq(RAX, Address(RAX, 0)); |
| 1267 __ leaq(R13, Address(RAX, closure_size)); | 1280 __ leaq(R13, Address(RAX, closure_size)); |
| 1268 if (is_implicit_instance_closure) { | 1281 if (is_implicit_instance_closure) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1333 __ movq(Address(RAX, Closure::context_offset()), CTX); | 1346 __ movq(Address(RAX, Closure::context_offset()), CTX); |
| 1334 } | 1347 } |
| 1335 | 1348 |
| 1336 // Set the type arguments field in the newly allocated closure. | 1349 // Set the type arguments field in the newly allocated closure. |
| 1337 __ movq(R10, Address(RSP, kTypeArgumentsOffset)); | 1350 __ movq(R10, Address(RSP, kTypeArgumentsOffset)); |
| 1338 __ movq(Address(RAX, Closure::type_arguments_offset()), R10); | 1351 __ movq(Address(RAX, Closure::type_arguments_offset()), R10); |
| 1339 | 1352 |
| 1340 // Done allocating and initializing the instance. | 1353 // Done allocating and initializing the instance. |
| 1341 // RAX: new object. | 1354 // RAX: new object. |
| 1342 __ addq(RAX, Immediate(kHeapObjectTag)); | 1355 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 1356 __ LeaveFrame(true); |
| 1343 __ ret(); | 1357 __ ret(); |
| 1344 | 1358 |
| 1345 __ Bind(&slow_case); | 1359 __ Bind(&slow_case); |
| 1346 } | 1360 } |
| 1347 if (has_type_arguments) { | 1361 if (has_type_arguments) { |
| 1348 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); | 1362 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); |
| 1349 } | 1363 } |
| 1350 if (is_implicit_instance_closure) { | 1364 if (is_implicit_instance_closure) { |
| 1351 __ movq(RAX, Address(RSP, kReceiverOffset)); | 1365 __ movq(RAX, Address(RSP, kReceiverOffset)); |
| 1352 } | 1366 } |
| 1353 // Create the stub frame. | 1367 |
| 1354 __ EnterStubFrame(); | |
| 1355 __ pushq(raw_null); // Setup space on stack for the return value. | 1368 __ pushq(raw_null); // Setup space on stack for the return value. |
| 1356 __ PushObject(func); | 1369 __ PushObject(func); |
| 1357 if (is_implicit_instance_closure) { | 1370 if (is_implicit_instance_closure) { |
| 1358 __ pushq(RAX); // Receiver. | 1371 __ pushq(RAX); // Receiver. |
| 1359 } | 1372 } |
| 1360 if (has_type_arguments) { | 1373 if (has_type_arguments) { |
| 1361 __ pushq(RCX); // Push type arguments of closure to be allocated. | 1374 __ pushq(RCX); // Push type arguments of closure to be allocated. |
| 1362 } else { | 1375 } else { |
| 1363 __ pushq(raw_null); // Push null type arguments. | 1376 __ pushq(raw_null); // Push null type arguments. |
| 1364 } | 1377 } |
| 1365 if (is_implicit_instance_closure) { | 1378 if (is_implicit_instance_closure) { |
| 1366 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry); | 1379 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry); |
| 1367 __ popq(RAX); // Pop type arguments. | 1380 __ popq(RAX); // Pop type arguments. |
| 1368 __ popq(RAX); // Pop receiver. | 1381 __ popq(RAX); // Pop receiver. |
| 1369 } else { | 1382 } else { |
| 1370 ASSERT(func.IsNonImplicitClosureFunction()); | 1383 ASSERT(func.IsNonImplicitClosureFunction()); |
| 1371 __ CallRuntime(kAllocateClosureRuntimeEntry); | 1384 __ CallRuntime(kAllocateClosureRuntimeEntry); |
| 1372 __ popq(RAX); // Pop type arguments. | 1385 __ popq(RAX); // Pop type arguments. |
| 1373 } | 1386 } |
| 1374 __ popq(RAX); // Pop the function object. | 1387 __ popq(RAX); // Pop the function object. |
| 1375 __ popq(RAX); // Pop the result. | 1388 __ popq(RAX); // Pop the result. |
| 1376 // RAX: New closure object. | 1389 // RAX: New closure object. |
| 1377 // Restore the calling frame. | 1390 // Restore the calling frame. |
| 1378 __ LeaveFrame(); | 1391 __ LeaveFrame(true); |
| 1379 __ ret(); | 1392 __ ret(); |
| 1380 } | 1393 } |
| 1381 | 1394 |
| 1382 | 1395 |
| 1383 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1396 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
| 1384 // from the entry code of a dart function after an error in passed argument | 1397 // from the entry code of a dart function after an error in passed argument |
| 1385 // name or number is detected. | 1398 // name or number is detected. |
| 1386 // Input parameters: | 1399 // Input parameters: |
| 1387 // RSP : points to return address. | 1400 // RSP : points to return address. |
| 1388 // RSP + 8 : address of last argument. | 1401 // RSP + 8 : address of last argument. |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1820 | 1833 |
| 1821 // TOS(0): return address (Dart code). | 1834 // TOS(0): return address (Dart code). |
| 1822 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { | 1835 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { |
| 1823 __ EnterStubFrame(); | 1836 __ EnterStubFrame(); |
| 1824 __ pushq(RAX); | 1837 __ pushq(RAX); |
| 1825 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry); | 1838 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry); |
| 1826 __ popq(RAX); | 1839 __ popq(RAX); |
| 1827 __ LeaveFrame(); | 1840 __ LeaveFrame(); |
| 1828 | 1841 |
| 1829 __ popq(R11); // discard return address of call to this stub. | 1842 __ popq(R11); // discard return address of call to this stub. |
| 1830 __ LeaveFrame(); | 1843 __ LeaveFrame(true); |
| 1831 __ ret(); | 1844 __ ret(); |
| 1832 } | 1845 } |
| 1833 | 1846 |
| 1834 | 1847 |
| 1835 // RBX: Inline cache data array. | 1848 // RBX: Inline cache data array. |
| 1836 // TOS(0): return address (Dart code). | 1849 // TOS(0): return address (Dart code). |
| 1837 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1850 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
| 1838 __ EnterStubFrame(); | 1851 __ EnterStubFrame(); |
| 1839 __ pushq(RBX); | 1852 __ pushq(RBX); |
| 1840 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1853 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2074 __ movq(RAX, Immediate(Smi::RawValue(kSmiCid))); | 2087 __ movq(RAX, Immediate(Smi::RawValue(kSmiCid))); |
| 2075 __ ret(); | 2088 __ ret(); |
| 2076 | 2089 |
| 2077 __ Bind(¬_smi); | 2090 __ Bind(¬_smi); |
| 2078 __ LoadClassId(RAX, RAX); | 2091 __ LoadClassId(RAX, RAX); |
| 2079 __ SmiTag(RAX); | 2092 __ SmiTag(RAX); |
| 2080 __ ret(); | 2093 __ ret(); |
| 2081 | 2094 |
| 2082 __ Bind(&update_ic_data); | 2095 __ Bind(&update_ic_data); |
| 2083 | 2096 |
| 2084 // RCX: ICData | 2097 // RBX: ICData |
| 2085 __ movq(RAX, Address(RSP, 1 * kWordSize)); | 2098 __ movq(RAX, Address(RSP, 1 * kWordSize)); |
| 2086 __ movq(R13, Address(RSP, 2 * kWordSize)); | 2099 __ movq(R13, Address(RSP, 2 * kWordSize)); |
| 2087 __ EnterStubFrame(); | 2100 __ EnterStubFrame(); |
| 2088 __ pushq(R13); // arg 0 | 2101 __ pushq(R13); // arg 0 |
| 2089 __ pushq(RAX); // arg 1 | 2102 __ pushq(RAX); // arg 1 |
| 2090 __ PushObject(Symbols::EqualOperator()); // Target's name. | 2103 __ PushObject(Symbols::EqualOperator()); // Target's name. |
| 2091 __ pushq(RBX); // ICData | 2104 __ pushq(RBX); // ICData |
| 2092 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry); | 2105 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry); |
| 2093 __ Drop(4); | 2106 __ Drop(4); |
| 2094 __ LeaveFrame(); | 2107 __ LeaveFrame(); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2228 __ movq(right, Address(RSP, 3 * kWordSize)); | 2241 __ movq(right, Address(RSP, 3 * kWordSize)); |
| 2229 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2242 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
| 2230 __ popq(right); | 2243 __ popq(right); |
| 2231 __ popq(left); | 2244 __ popq(left); |
| 2232 __ ret(); | 2245 __ ret(); |
| 2233 } | 2246 } |
| 2234 | 2247 |
| 2235 } // namespace dart | 2248 } // namespace dart |
| 2236 | 2249 |
| 2237 #endif // defined TARGET_ARCH_X64 | 2250 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |