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 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 __ ret(); | 269 __ ret(); |
270 } | 270 } |
271 | 271 |
272 | 272 |
273 // Input parameters: | 273 // Input parameters: |
274 // R10: arguments descriptor array. | 274 // R10: arguments descriptor array. |
275 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 275 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
276 __ EnterStubFrame(); | 276 __ EnterStubFrame(); |
277 __ pushq(R10); // Preserve arguments descriptor array. | 277 __ pushq(R10); // Preserve arguments descriptor array. |
278 // Setup space on stack for return value. | 278 // Setup space on stack for return value. |
279 __ PushObject(Object::null_object(), PP); | 279 __ PushObject(Object::null_object()); |
280 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); | 280 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); |
281 __ popq(RAX); // Get Code object result. | 281 __ popq(RAX); // Get Code object result. |
282 __ popq(R10); // Restore arguments descriptor array. | 282 __ popq(R10); // Restore arguments descriptor array. |
283 // Remove the stub frame as we are about to jump to the dart function. | 283 // Remove the stub frame as we are about to jump to the dart function. |
284 __ LeaveStubFrame(); | 284 __ LeaveStubFrame(); |
285 | 285 |
286 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); | 286 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
287 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 287 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
288 __ jmp(RBX); | 288 __ jmp(RBX); |
289 } | 289 } |
290 | 290 |
291 | 291 |
292 // Called from a static call only when an invalid code has been entered | 292 // Called from a static call only when an invalid code has been entered |
293 // (invalid because its function was optimized or deoptimized). | 293 // (invalid because its function was optimized or deoptimized). |
294 // R10: arguments descriptor array. | 294 // R10: arguments descriptor array. |
295 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 295 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
296 __ EnterStubFrame(); | 296 __ EnterStubFrame(); |
297 __ pushq(R10); // Preserve arguments descriptor array. | 297 __ pushq(R10); // Preserve arguments descriptor array. |
298 // Setup space on stack for return value. | 298 // Setup space on stack for return value. |
299 __ PushObject(Object::null_object(), PP); | 299 __ PushObject(Object::null_object()); |
300 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); | 300 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); |
301 __ popq(RAX); // Get Code object. | 301 __ popq(RAX); // Get Code object. |
302 __ popq(R10); // Restore arguments descriptor array. | 302 __ popq(R10); // Restore arguments descriptor array. |
303 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 303 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
304 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 304 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
305 __ LeaveStubFrame(); | 305 __ LeaveStubFrame(); |
306 __ jmp(RAX); | 306 __ jmp(RAX); |
307 __ int3(); | 307 __ int3(); |
308 } | 308 } |
309 | 309 |
310 | 310 |
311 // Called from object allocate instruction when the allocation stub has been | 311 // Called from object allocate instruction when the allocation stub has been |
312 // disabled. | 312 // disabled. |
313 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { | 313 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { |
314 __ EnterStubFrame(); | 314 __ EnterStubFrame(); |
315 // Setup space on stack for return value. | 315 // Setup space on stack for return value. |
316 __ PushObject(Object::null_object(), PP); | 316 __ PushObject(Object::null_object()); |
317 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); | 317 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); |
318 __ popq(RAX); // Get Code object. | 318 __ popq(RAX); // Get Code object. |
319 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 319 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
320 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 320 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
321 __ LeaveStubFrame(); | 321 __ LeaveStubFrame(); |
322 __ jmp(RAX); | 322 __ jmp(RAX); |
323 __ int3(); | 323 __ int3(); |
324 } | 324 } |
325 | 325 |
326 | 326 |
327 // Input parameters: | 327 // Input parameters: |
328 // R10: smi-tagged argument count, may be zero. | 328 // R10: smi-tagged argument count, may be zero. |
329 // RBP[kParamEndSlotFromFp + 1]: last argument. | 329 // RBP[kParamEndSlotFromFp + 1]: last argument. |
330 static void PushArgumentsArray(Assembler* assembler) { | 330 static void PushArgumentsArray(Assembler* assembler) { |
331 __ LoadObject(R12, Object::null_object(), PP); | 331 __ LoadObject(R12, Object::null_object()); |
332 // Allocate array to store arguments of caller. | 332 // Allocate array to store arguments of caller. |
333 __ movq(RBX, R12); // Null element type for raw Array. | 333 __ movq(RBX, R12); // Null element type for raw Array. |
334 const ExternalLabel array_label(StubCode::AllocateArrayEntryPoint()); | 334 const ExternalLabel array_label(StubCode::AllocateArrayEntryPoint()); |
335 __ call(&array_label); | 335 __ call(&array_label); |
336 __ SmiUntag(R10); | 336 __ SmiUntag(R10); |
337 // RAX: newly allocated array. | 337 // RAX: newly allocated array. |
338 // R10: length of the array (was preserved by the stub). | 338 // R10: length of the array (was preserved by the stub). |
339 __ pushq(RAX); // Array is in RAX and on top of stack. | 339 __ pushq(RAX); // Array is in RAX and on top of stack. |
340 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); | 340 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); |
341 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | 341 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 540 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
541 // Three words (saved pp, saved fp, stub's pc marker) | 541 // Three words (saved pp, saved fp, stub's pc marker) |
542 // in the stack above the return address. | 542 // in the stack above the return address. |
543 __ movq(RAX, Address(RSP, RAX, TIMES_4, | 543 __ movq(RAX, Address(RSP, RAX, TIMES_4, |
544 kSavedAboveReturnAddress * kWordSize)); | 544 kSavedAboveReturnAddress * kWordSize)); |
545 // Preserve IC data and arguments descriptor. | 545 // Preserve IC data and arguments descriptor. |
546 __ pushq(RBX); | 546 __ pushq(RBX); |
547 __ pushq(R10); | 547 __ pushq(R10); |
548 | 548 |
549 // Space for the result of the runtime call. | 549 // Space for the result of the runtime call. |
550 __ PushObject(Object::null_object(), PP); | 550 __ PushObject(Object::null_object()); |
551 __ pushq(RAX); // Receiver. | 551 __ pushq(RAX); // Receiver. |
552 __ pushq(RBX); // IC data. | 552 __ pushq(RBX); // IC data. |
553 __ pushq(R10); // Arguments descriptor. | 553 __ pushq(R10); // Arguments descriptor. |
554 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); | 554 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); |
555 // Discard arguments. | 555 // Discard arguments. |
556 __ popq(RAX); | 556 __ popq(RAX); |
557 __ popq(RAX); | 557 __ popq(RAX); |
558 __ popq(RAX); | 558 __ popq(RAX); |
559 __ popq(RAX); // Return value from the runtime call (function). | 559 __ popq(RAX); // Return value from the runtime call (function). |
560 __ popq(R10); // Restore arguments descriptor. | 560 __ popq(R10); // Restore arguments descriptor. |
(...skipping 12 matching lines...) Expand all Loading... |
573 } | 573 } |
574 | 574 |
575 | 575 |
576 // Called for inline allocation of arrays. | 576 // Called for inline allocation of arrays. |
577 // Input parameters: | 577 // Input parameters: |
578 // R10 : Array length as Smi. | 578 // R10 : Array length as Smi. |
579 // RBX : array element type (either NULL or an instantiated type). | 579 // RBX : array element type (either NULL or an instantiated type). |
580 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. | 580 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. |
581 // The newly allocated object is returned in RAX. | 581 // The newly allocated object is returned in RAX. |
582 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 582 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
583 // Must load pool pointer before being able to patch. | |
584 Register new_pp = R13; | |
585 __ LoadPoolPointer(new_pp); | |
586 Label slow_case; | 583 Label slow_case; |
587 // Compute the size to be allocated, it is based on the array length | 584 // Compute the size to be allocated, it is based on the array length |
588 // and is computed as: | 585 // and is computed as: |
589 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 586 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
590 __ movq(RDI, R10); // Array Length. | 587 __ movq(RDI, R10); // Array Length. |
591 // Check that length is a positive Smi. | 588 // Check that length is a positive Smi. |
592 __ testq(RDI, Immediate(kSmiTagMask)); | 589 __ testq(RDI, Immediate(kSmiTagMask)); |
593 if (FLAG_use_slow_path) { | 590 if (FLAG_use_slow_path) { |
594 __ jmp(&slow_case); | 591 __ jmp(&slow_case); |
595 } else { | 592 } else { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 // Set the length field. | 664 // Set the length field. |
668 __ InitializeFieldNoBarrier(RAX, | 665 __ InitializeFieldNoBarrier(RAX, |
669 FieldAddress(RAX, Array::length_offset()), | 666 FieldAddress(RAX, Array::length_offset()), |
670 R10); | 667 R10); |
671 | 668 |
672 // Initialize all array elements to raw_null. | 669 // Initialize all array elements to raw_null. |
673 // RAX: new object start as a tagged pointer. | 670 // RAX: new object start as a tagged pointer. |
674 // RCX: new object end address. | 671 // RCX: new object end address. |
675 // RDI: iterator which initially points to the start of the variable | 672 // RDI: iterator which initially points to the start of the variable |
676 // data area to be initialized. | 673 // data area to be initialized. |
677 __ LoadObject(R12, Object::null_object(), PP); | 674 __ LoadObject(R12, Object::null_object()); |
678 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); | 675 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); |
679 Label done; | 676 Label done; |
680 Label init_loop; | 677 Label init_loop; |
681 __ Bind(&init_loop); | 678 __ Bind(&init_loop); |
682 __ cmpq(RDI, RCX); | 679 __ cmpq(RDI, RCX); |
683 #if defined(DEBUG) | 680 #if defined(DEBUG) |
684 static const bool kJumpLength = Assembler::kFarJump; | 681 static const bool kJumpLength = Assembler::kFarJump; |
685 #else | 682 #else |
686 static const bool kJumpLength = Assembler::kNearJump; | 683 static const bool kJumpLength = Assembler::kNearJump; |
687 #endif // DEBUG | 684 #endif // DEBUG |
688 __ j(ABOVE_EQUAL, &done, kJumpLength); | 685 __ j(ABOVE_EQUAL, &done, kJumpLength); |
689 // No generational barrier needed, since we are storing null. | 686 // No generational barrier needed, since we are storing null. |
690 __ InitializeFieldNoBarrier(RAX, Address(RDI, 0), R12); | 687 __ InitializeFieldNoBarrier(RAX, Address(RDI, 0), R12); |
691 __ addq(RDI, Immediate(kWordSize)); | 688 __ addq(RDI, Immediate(kWordSize)); |
692 __ jmp(&init_loop, kJumpLength); | 689 __ jmp(&init_loop, kJumpLength); |
693 __ Bind(&done); | 690 __ Bind(&done); |
694 __ ret(); // returns the newly allocated object in RAX. | 691 __ ret(); // returns the newly allocated object in RAX. |
695 | 692 |
696 // Unable to allocate the array using the fast inline code, just call | 693 // Unable to allocate the array using the fast inline code, just call |
697 // into the runtime. | 694 // into the runtime. |
698 __ Bind(&slow_case); | 695 __ Bind(&slow_case); |
699 // Create a stub frame as we are pushing some objects on the stack before | 696 // Create a stub frame as we are pushing some objects on the stack before |
700 // calling into the runtime. | 697 // calling into the runtime. |
701 __ EnterStubFrame(); | 698 __ EnterStubFrame(); |
702 // Setup space on stack for return value. | 699 // Setup space on stack for return value. |
703 __ PushObject(Object::null_object(), PP); | 700 __ PushObject(Object::null_object()); |
704 __ pushq(R10); // Array length as Smi. | 701 __ pushq(R10); // Array length as Smi. |
705 __ pushq(RBX); // Element type. | 702 __ pushq(RBX); // Element type. |
706 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); | 703 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); |
707 __ popq(RAX); // Pop element type argument. | 704 __ popq(RAX); // Pop element type argument. |
708 __ popq(R10); // Pop array length argument. | 705 __ popq(R10); // Pop array length argument. |
709 __ popq(RAX); // Pop return value from return slot. | 706 __ popq(RAX); // Pop return value from return slot. |
710 __ LeaveStubFrame(); | 707 __ LeaveStubFrame(); |
711 __ ret(); | 708 __ ret(); |
712 } | 709 } |
713 | 710 |
(...skipping 23 matching lines...) Expand all Loading... |
737 const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize; | 734 const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize; |
738 __ pushq(kArgDescReg); | 735 __ pushq(kArgDescReg); |
739 | 736 |
740 // Save C++ ABI callee-saved registers. | 737 // Save C++ ABI callee-saved registers. |
741 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters, | 738 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters, |
742 CallingConventions::kCalleeSaveXmmRegisters); | 739 CallingConventions::kCalleeSaveXmmRegisters); |
743 | 740 |
744 // We now load the pool pointer(PP) as we are about to invoke dart code and we | 741 // We now load the pool pointer(PP) as we are about to invoke dart code and we |
745 // could potentially invoke some intrinsic functions which need the PP to be | 742 // could potentially invoke some intrinsic functions which need the PP to be |
746 // set up. | 743 // set up. |
747 __ LoadPoolPointer(PP); | 744 __ LoadPoolPointer(); |
748 | 745 |
749 // If any additional (or fewer) values are pushed, the offsets in | 746 // If any additional (or fewer) values are pushed, the offsets in |
750 // kExitLinkSlotFromEntryFp will need to be changed. | 747 // kExitLinkSlotFromEntryFp will need to be changed. |
751 | 748 |
752 // Set up THR, which caches the current thread in Dart code. | 749 // Set up THR, which caches the current thread in Dart code. |
753 if (THR != kThreadReg) { | 750 if (THR != kThreadReg) { |
754 __ movq(THR, kThreadReg); | 751 __ movq(THR, kThreadReg); |
755 } | 752 } |
756 // Load Isolate pointer into kIsolateReg. | 753 // Load Isolate pointer into kIsolateReg. |
757 const Register kIsolateReg = RBX; | 754 const Register kIsolateReg = RBX; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 __ LoadIsolate(kIsolateReg); | 828 __ LoadIsolate(kIsolateReg); |
832 __ popq(Address(THR, Thread::top_exit_frame_info_offset())); | 829 __ popq(Address(THR, Thread::top_exit_frame_info_offset())); |
833 __ popq(Address(THR, Thread::top_resource_offset())); | 830 __ popq(Address(THR, Thread::top_resource_offset())); |
834 | 831 |
835 // Restore the current VMTag from the stack. | 832 // Restore the current VMTag from the stack. |
836 __ popq(Address(kIsolateReg, Isolate::vm_tag_offset())); | 833 __ popq(Address(kIsolateReg, Isolate::vm_tag_offset())); |
837 | 834 |
838 // Restore C++ ABI callee-saved registers. | 835 // Restore C++ ABI callee-saved registers. |
839 __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters, | 836 __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters, |
840 CallingConventions::kCalleeSaveXmmRegisters); | 837 CallingConventions::kCalleeSaveXmmRegisters); |
| 838 __ set_constant_pool_allowed(false); |
841 | 839 |
842 // Restore the frame pointer. | 840 // Restore the frame pointer. |
843 __ LeaveFrame(); | 841 __ LeaveFrame(); |
844 | 842 |
845 __ ret(); | 843 __ ret(); |
846 } | 844 } |
847 | 845 |
848 | 846 |
849 // Called for inline allocation of contexts. | 847 // Called for inline allocation of contexts. |
850 // Input: | 848 // Input: |
851 // R10: number of context variables. | 849 // R10: number of context variables. |
852 // Output: | 850 // Output: |
853 // RAX: new allocated RawContext object. | 851 // RAX: new allocated RawContext object. |
854 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 852 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
855 __ LoadObject(R12, Object::null_object(), PP); | 853 __ LoadObject(R12, Object::null_object()); |
856 if (FLAG_inline_alloc) { | 854 if (FLAG_inline_alloc) { |
857 Label slow_case; | 855 Label slow_case; |
858 // First compute the rounded instance size. | 856 // First compute the rounded instance size. |
859 // R10: number of context variables. | 857 // R10: number of context variables. |
860 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); | 858 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
861 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); | 859 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
862 __ andq(R13, Immediate(-kObjectAlignment)); | 860 __ andq(R13, Immediate(-kObjectAlignment)); |
863 | 861 |
864 // Now allocate the object. | 862 // Now allocate the object. |
865 // R10: number of context variables. | 863 // R10: number of context variables. |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1058 // The generated code is different if the class is parameterized. | 1056 // The generated code is different if the class is parameterized. |
1059 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; | 1057 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; |
1060 ASSERT(!is_cls_parameterized || | 1058 ASSERT(!is_cls_parameterized || |
1061 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); | 1059 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); |
1062 // kInlineInstanceSize is a constant used as a threshold for determining | 1060 // kInlineInstanceSize is a constant used as a threshold for determining |
1063 // when the object initialization should be done as a loop or as | 1061 // when the object initialization should be done as a loop or as |
1064 // straight line code. | 1062 // straight line code. |
1065 const int kInlineInstanceSize = 12; // In words. | 1063 const int kInlineInstanceSize = 12; // In words. |
1066 const intptr_t instance_size = cls.instance_size(); | 1064 const intptr_t instance_size = cls.instance_size(); |
1067 ASSERT(instance_size > 0); | 1065 ASSERT(instance_size > 0); |
1068 __ LoadObject(R12, Object::null_object(), PP); | 1066 __ LoadObject(R12, Object::null_object()); |
1069 if (is_cls_parameterized) { | 1067 if (is_cls_parameterized) { |
1070 __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset)); | 1068 __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset)); |
1071 // RDX: instantiated type arguments. | 1069 // RDX: instantiated type arguments. |
1072 } | 1070 } |
1073 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size) && | 1071 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size) && |
1074 !cls.trace_allocation()) { | 1072 !cls.trace_allocation()) { |
1075 Label slow_case; | 1073 Label slow_case; |
1076 // Allocate the object and update top to point to | 1074 // Allocate the object and update top to point to |
1077 // next object start and initialize the allocated object. | 1075 // next object start and initialize the allocated object. |
1078 // RDX: instantiated type arguments (if is_cls_parameterized). | 1076 // RDX: instantiated type arguments (if is_cls_parameterized). |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 // RAX: new object (tagged). | 1152 // RAX: new object (tagged). |
1155 __ ret(); | 1153 __ ret(); |
1156 | 1154 |
1157 __ Bind(&slow_case); | 1155 __ Bind(&slow_case); |
1158 } | 1156 } |
1159 // If is_cls_parameterized: | 1157 // If is_cls_parameterized: |
1160 // RDX: new object type arguments. | 1158 // RDX: new object type arguments. |
1161 // Create a stub frame. | 1159 // Create a stub frame. |
1162 __ EnterStubFrame(); // Uses PP to access class object. | 1160 __ EnterStubFrame(); // Uses PP to access class object. |
1163 __ pushq(R12); // Setup space on stack for return value. | 1161 __ pushq(R12); // Setup space on stack for return value. |
1164 __ PushObject(cls, PP); // Push class of object to be allocated. | 1162 __ PushObject(cls); // Push class of object to be allocated. |
1165 if (is_cls_parameterized) { | 1163 if (is_cls_parameterized) { |
1166 __ pushq(RDX); // Push type arguments of object to be allocated. | 1164 __ pushq(RDX); // Push type arguments of object to be allocated. |
1167 } else { | 1165 } else { |
1168 __ pushq(R12); // Push null type arguments. | 1166 __ pushq(R12); // Push null type arguments. |
1169 } | 1167 } |
1170 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. | 1168 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. |
1171 __ popq(RAX); // Pop argument (type arguments of object). | 1169 __ popq(RAX); // Pop argument (type arguments of object). |
1172 __ popq(RAX); // Pop argument (class of object). | 1170 __ popq(RAX); // Pop argument (class of object). |
1173 __ popq(RAX); // Pop result (newly allocated object). | 1171 __ popq(RAX); // Pop result (newly allocated object). |
1174 // RAX: new object | 1172 // RAX: new object |
(...skipping 12 matching lines...) Expand all Loading... |
1187 // RSP : points to return address. | 1185 // RSP : points to return address. |
1188 // RSP + 8 : address of last argument. | 1186 // RSP + 8 : address of last argument. |
1189 // R10 : arguments descriptor array. | 1187 // R10 : arguments descriptor array. |
1190 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { | 1188 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { |
1191 __ EnterStubFrame(); | 1189 __ EnterStubFrame(); |
1192 | 1190 |
1193 // Load the receiver. | 1191 // Load the receiver. |
1194 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1192 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
1195 __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize)); | 1193 __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize)); |
1196 | 1194 |
1197 __ LoadObject(R12, Object::null_object(), PP); | 1195 __ LoadObject(R12, Object::null_object()); |
1198 __ pushq(R12); // Setup space on stack for result from noSuchMethod. | 1196 __ pushq(R12); // Setup space on stack for result from noSuchMethod. |
1199 __ pushq(RAX); // Receiver. | 1197 __ pushq(RAX); // Receiver. |
1200 __ pushq(R10); // Arguments descriptor array. | 1198 __ pushq(R10); // Arguments descriptor array. |
1201 | 1199 |
1202 __ movq(R10, R13); // Smi-tagged arguments array length. | 1200 __ movq(R10, R13); // Smi-tagged arguments array length. |
1203 PushArgumentsArray(assembler); | 1201 PushArgumentsArray(assembler); |
1204 | 1202 |
1205 const intptr_t kNumArgs = 3; | 1203 const intptr_t kNumArgs = 3; |
1206 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); | 1204 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); |
1207 // noSuchMethod on closures always throws an error, so it will never return. | 1205 // noSuchMethod on closures always throws an error, so it will never return. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1274 } | 1272 } |
1275 case Token::kSUB: { | 1273 case Token::kSUB: { |
1276 __ subq(RAX, RCX); | 1274 __ subq(RAX, RCX); |
1277 __ j(OVERFLOW, not_smi_or_overflow); | 1275 __ j(OVERFLOW, not_smi_or_overflow); |
1278 break; | 1276 break; |
1279 } | 1277 } |
1280 case Token::kEQ: { | 1278 case Token::kEQ: { |
1281 Label done, is_true; | 1279 Label done, is_true; |
1282 __ cmpq(RAX, RCX); | 1280 __ cmpq(RAX, RCX); |
1283 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1281 __ j(EQUAL, &is_true, Assembler::kNearJump); |
1284 __ LoadObject(RAX, Bool::False(), PP); | 1282 __ LoadObject(RAX, Bool::False()); |
1285 __ jmp(&done, Assembler::kNearJump); | 1283 __ jmp(&done, Assembler::kNearJump); |
1286 __ Bind(&is_true); | 1284 __ Bind(&is_true); |
1287 __ LoadObject(RAX, Bool::True(), PP); | 1285 __ LoadObject(RAX, Bool::True()); |
1288 __ Bind(&done); | 1286 __ Bind(&done); |
1289 break; | 1287 break; |
1290 } | 1288 } |
1291 default: UNIMPLEMENTED(); | 1289 default: UNIMPLEMENTED(); |
1292 } | 1290 } |
1293 | 1291 |
1294 | 1292 |
1295 if (should_update_result_range) { | 1293 if (should_update_result_range) { |
1296 Label done; | 1294 Label done; |
1297 __ movq(RSI, RAX); | 1295 __ movq(RSI, RAX); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1445 | 1443 |
1446 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1444 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
1447 __ addq(R12, Immediate(entry_size)); // Next entry. | 1445 __ addq(R12, Immediate(entry_size)); // Next entry. |
1448 __ movq(R13, Address(R12, 0)); // Next class ID. | 1446 __ movq(R13, Address(R12, 0)); // Next class ID. |
1449 | 1447 |
1450 __ Bind(&test); | 1448 __ Bind(&test); |
1451 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1449 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
1452 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1450 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
1453 | 1451 |
1454 __ Comment("IC miss"); | 1452 __ Comment("IC miss"); |
1455 __ LoadObject(R12, Object::null_object(), PP); | 1453 __ LoadObject(R12, Object::null_object()); |
1456 // Compute address of arguments (first read number of arguments from | 1454 // Compute address of arguments (first read number of arguments from |
1457 // arguments descriptor array and then compute address on the stack). | 1455 // arguments descriptor array and then compute address on the stack). |
1458 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1456 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
1459 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. | 1457 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. |
1460 __ EnterStubFrame(); | 1458 __ EnterStubFrame(); |
1461 __ pushq(R10); // Preserve arguments descriptor array. | 1459 __ pushq(R10); // Preserve arguments descriptor array. |
1462 __ pushq(RBX); // Preserve IC data object. | 1460 __ pushq(RBX); // Preserve IC data object. |
1463 __ pushq(R12); // Setup space on stack for result (target code object). | 1461 __ pushq(R12); // Setup space on stack for result (target code object). |
1464 // Push call arguments. | 1462 // Push call arguments. |
1465 for (intptr_t i = 0; i < num_args; i++) { | 1463 for (intptr_t i = 0; i < num_args; i++) { |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1763 | 1761 |
1764 | 1762 |
1765 // RBX: Contains an ICData. | 1763 // RBX: Contains an ICData. |
1766 // TOS(0): return address (Dart code). | 1764 // TOS(0): return address (Dart code). |
1767 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { | 1765 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { |
1768 __ EnterStubFrame(); | 1766 __ EnterStubFrame(); |
1769 // Preserve IC data. | 1767 // Preserve IC data. |
1770 __ pushq(RBX); | 1768 __ pushq(RBX); |
1771 // Room for result. Debugger stub returns address of the | 1769 // Room for result. Debugger stub returns address of the |
1772 // unpatched runtime stub. | 1770 // unpatched runtime stub. |
1773 __ LoadObject(R12, Object::null_object(), PP); | 1771 __ LoadObject(R12, Object::null_object()); |
1774 __ pushq(R12); // Room for result. | 1772 __ pushq(R12); // Room for result. |
1775 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1773 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1776 __ popq(RAX); // Address of original. | 1774 __ popq(RAX); // Address of original. |
1777 __ popq(RBX); // Restore IC data. | 1775 __ popq(RBX); // Restore IC data. |
1778 __ LeaveStubFrame(); | 1776 __ LeaveStubFrame(); |
1779 __ jmp(RAX); // Jump to original stub. | 1777 __ jmp(RAX); // Jump to original stub. |
1780 } | 1778 } |
1781 | 1779 |
1782 | 1780 |
1783 // TOS(0): return address (Dart code). | 1781 // TOS(0): return address (Dart code). |
1784 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { | 1782 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { |
1785 __ EnterStubFrame(); | 1783 __ EnterStubFrame(); |
1786 // Room for result. Debugger stub returns address of the | 1784 // Room for result. Debugger stub returns address of the |
1787 // unpatched runtime stub. | 1785 // unpatched runtime stub. |
1788 __ LoadObject(R12, Object::null_object(), PP); | 1786 __ LoadObject(R12, Object::null_object()); |
1789 __ pushq(R12); // Room for result. | 1787 __ pushq(R12); // Room for result. |
1790 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1788 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1791 __ popq(RAX); // Address of original. | 1789 __ popq(RAX); // Address of original. |
1792 __ LeaveStubFrame(); | 1790 __ LeaveStubFrame(); |
1793 __ jmp(RAX); // Jump to original stub. | 1791 __ jmp(RAX); // Jump to original stub. |
1794 } | 1792 } |
1795 | 1793 |
1796 | 1794 |
1797 // Called only from unoptimized code. | 1795 // Called only from unoptimized code. |
1798 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1796 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
(...skipping 19 matching lines...) Expand all Loading... |
1818 // TOS + 1: instantiator type arguments (can be NULL). | 1816 // TOS + 1: instantiator type arguments (can be NULL). |
1819 // TOS + 2: instance. | 1817 // TOS + 2: instance. |
1820 // TOS + 3: SubtypeTestCache. | 1818 // TOS + 3: SubtypeTestCache. |
1821 // Result in RCX: null -> not found, otherwise result (true or false). | 1819 // Result in RCX: null -> not found, otherwise result (true or false). |
1822 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1820 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
1823 ASSERT((1 <= n) && (n <= 3)); | 1821 ASSERT((1 <= n) && (n <= 3)); |
1824 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1822 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
1825 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1823 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
1826 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1824 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
1827 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); | 1825 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); |
1828 __ LoadObject(R12, Object::null_object(), PP); | 1826 __ LoadObject(R12, Object::null_object()); |
1829 if (n > 1) { | 1827 if (n > 1) { |
1830 __ LoadClass(R10, RAX, kNoRegister); | 1828 __ LoadClass(R10, RAX); |
1831 // Compute instance type arguments into R13. | 1829 // Compute instance type arguments into R13. |
1832 Label has_no_type_arguments; | 1830 Label has_no_type_arguments; |
1833 __ movq(R13, R12); | 1831 __ movq(R13, R12); |
1834 __ movl(RDI, FieldAddress(R10, | 1832 __ movl(RDI, FieldAddress(R10, |
1835 Class::type_arguments_field_offset_in_words_offset())); | 1833 Class::type_arguments_field_offset_in_words_offset())); |
1836 __ cmpl(RDI, Immediate(Class::kNoTypeArguments)); | 1834 __ cmpl(RDI, Immediate(Class::kNoTypeArguments)); |
1837 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); | 1835 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); |
1838 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0)); | 1836 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0)); |
1839 __ Bind(&has_no_type_arguments); | 1837 __ Bind(&has_no_type_arguments); |
1840 } | 1838 } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1969 Immediate(0)); | 1967 Immediate(0)); |
1970 __ jmp(CallingConventions::kArg1Reg); // Jump to the exception handler code. | 1968 __ jmp(CallingConventions::kArg1Reg); // Jump to the exception handler code. |
1971 } | 1969 } |
1972 | 1970 |
1973 | 1971 |
1974 // Calls to the runtime to optimize the given function. | 1972 // Calls to the runtime to optimize the given function. |
1975 // RDI: function to be reoptimized. | 1973 // RDI: function to be reoptimized. |
1976 // R10: argument descriptor (preserved). | 1974 // R10: argument descriptor (preserved). |
1977 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 1975 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
1978 __ EnterStubFrame(); | 1976 __ EnterStubFrame(); |
1979 __ LoadObject(R12, Object::null_object(), PP); | 1977 __ LoadObject(R12, Object::null_object()); |
1980 __ pushq(R10); | 1978 __ pushq(R10); |
1981 __ pushq(R12); // Setup space on stack for return value. | 1979 __ pushq(R12); // Setup space on stack for return value. |
1982 __ pushq(RDI); | 1980 __ pushq(RDI); |
1983 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); | 1981 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
1984 __ popq(RAX); // Disard argument. | 1982 __ popq(RAX); // Disard argument. |
1985 __ popq(RAX); // Get Code object. | 1983 __ popq(RAX); // Get Code object. |
1986 __ popq(R10); // Restore argument descriptor. | 1984 __ popq(R10); // Restore argument descriptor. |
1987 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 1985 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
1988 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1986 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
1989 __ LeaveStubFrame(); | 1987 __ LeaveStubFrame(); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2115 __ movq(RDI, FieldAddress(cache, MegamorphicCache::buckets_offset())); | 2113 __ movq(RDI, FieldAddress(cache, MegamorphicCache::buckets_offset())); |
2116 __ movq(RBX, FieldAddress(cache, MegamorphicCache::mask_offset())); | 2114 __ movq(RBX, FieldAddress(cache, MegamorphicCache::mask_offset())); |
2117 // RDI: cache buckets array. | 2115 // RDI: cache buckets array. |
2118 // RBX: mask. | 2116 // RBX: mask. |
2119 __ movq(RCX, RAX); | 2117 __ movq(RCX, RAX); |
2120 | 2118 |
2121 Label loop, update, call_target_function; | 2119 Label loop, update, call_target_function; |
2122 __ jmp(&loop); | 2120 __ jmp(&loop); |
2123 | 2121 |
2124 __ Bind(&update); | 2122 __ Bind(&update); |
2125 __ AddImmediate(RCX, Immediate(Smi::RawValue(1)), PP); | 2123 __ AddImmediate(RCX, Immediate(Smi::RawValue(1))); |
2126 __ Bind(&loop); | 2124 __ Bind(&loop); |
2127 __ andq(RCX, RBX); | 2125 __ andq(RCX, RBX); |
2128 const intptr_t base = Array::data_offset(); | 2126 const intptr_t base = Array::data_offset(); |
2129 // RCX is smi tagged, but table entries are two words, so TIMES_8. | 2127 // RCX is smi tagged, but table entries are two words, so TIMES_8. |
2130 __ movq(RDX, FieldAddress(RDI, RCX, TIMES_8, base)); | 2128 __ movq(RDX, FieldAddress(RDI, RCX, TIMES_8, base)); |
2131 | 2129 |
2132 ASSERT(kIllegalCid == 0); | 2130 ASSERT(kIllegalCid == 0); |
2133 __ testq(RDX, RDX); | 2131 __ testq(RDX, RDX); |
2134 __ j(ZERO, &call_target_function, Assembler::kNearJump); | 2132 __ j(ZERO, &call_target_function, Assembler::kNearJump); |
2135 __ cmpq(RDX, RAX); | 2133 __ cmpq(RDX, RAX); |
2136 __ j(NOT_EQUAL, &update, Assembler::kNearJump); | 2134 __ j(NOT_EQUAL, &update, Assembler::kNearJump); |
2137 | 2135 |
2138 __ Bind(&call_target_function); | 2136 __ Bind(&call_target_function); |
2139 // Call the target found in the cache. For a class id match, this is a | 2137 // Call the target found in the cache. For a class id match, this is a |
2140 // proper target for the given name and arguments descriptor. If the | 2138 // proper target for the given name and arguments descriptor. If the |
2141 // illegal class id was found, the target is a cache miss handler that can | 2139 // illegal class id was found, the target is a cache miss handler that can |
2142 // be invoked as a normal Dart function. | 2140 // be invoked as a normal Dart function. |
2143 __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize)); | 2141 __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize)); |
2144 __ movq(target, FieldAddress(RAX, Function::instructions_offset())); | 2142 __ movq(target, FieldAddress(RAX, Function::instructions_offset())); |
2145 // TODO(srdjan): Evaluate performance impact of moving the instruction below | 2143 // TODO(srdjan): Evaluate performance impact of moving the instruction below |
2146 // to the call site, instead of having it here. | 2144 // to the call site, instead of having it here. |
2147 __ AddImmediate( | 2145 __ AddImmediate( |
2148 target, Immediate(Instructions::HeaderSize() - kHeapObjectTag), PP); | 2146 target, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
2149 } | 2147 } |
2150 | 2148 |
2151 | 2149 |
2152 // Called from megamorphic calls. | 2150 // Called from megamorphic calls. |
2153 // RDI: receiver. | 2151 // RDI: receiver. |
2154 // RBX: lookup cache. | 2152 // RBX: lookup cache. |
2155 // Result: | 2153 // Result: |
2156 // RCX: entry point. | 2154 // RCX: entry point. |
2157 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2155 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2158 EmitMegamorphicLookup(assembler, RDI, RBX, RCX); | 2156 EmitMegamorphicLookup(assembler, RDI, RBX, RCX); |
2159 __ ret(); | 2157 __ ret(); |
2160 } | 2158 } |
2161 | 2159 |
2162 } // namespace dart | 2160 } // namespace dart |
2163 | 2161 |
2164 #endif // defined TARGET_ARCH_X64 | 2162 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |