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 |