OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/code_generator.h" | 8 #include "vm/code_generator.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/ic_data.h" | 10 #include "vm/ic_data.h" |
11 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 } | 159 } |
160 | 160 |
161 | 161 |
162 // Input parameters: | 162 // Input parameters: |
163 // RSP : points to return address. | 163 // RSP : points to return address. |
164 // RSP + 8 : address of return value. | 164 // RSP + 8 : address of return value. |
165 // RAX : address of first argument in argument array. | 165 // RAX : address of first argument in argument array. |
166 // RAX - 8*R10 + 8 : address of last argument in argument array. | 166 // RAX - 8*R10 + 8 : address of last argument in argument array. |
167 // RBX : address of the native function to call. | 167 // RBX : address of the native function to call. |
168 // R10 : number of arguments to the call. | 168 // R10 : number of arguments to the call. |
169 // Uses R8. | |
170 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { | 169 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { |
171 const intptr_t native_args_struct_offset = 0; | 170 const intptr_t native_args_struct_offset = 0; |
172 const intptr_t isolate_offset = | 171 const intptr_t isolate_offset = |
173 NativeArguments::isolate_offset() + native_args_struct_offset; | 172 NativeArguments::isolate_offset() + native_args_struct_offset; |
174 const intptr_t argc_offset = | 173 const intptr_t argc_offset = |
175 NativeArguments::argc_offset() + native_args_struct_offset; | 174 NativeArguments::argc_offset() + native_args_struct_offset; |
176 const intptr_t argv_offset = | 175 const intptr_t argv_offset = |
177 NativeArguments::argv_offset() + native_args_struct_offset; | 176 NativeArguments::argv_offset() + native_args_struct_offset; |
178 const intptr_t retval_offset = | 177 const intptr_t retval_offset = |
179 NativeArguments::retval_offset() + native_args_struct_offset; | 178 NativeArguments::retval_offset() + native_args_struct_offset; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 // Remove the stub frame as we are about to jump to the dart function. | 267 // Remove the stub frame as we are about to jump to the dart function. |
269 __ LeaveFrame(); | 268 __ LeaveFrame(); |
270 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); | 269 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); |
271 | 270 |
272 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); | 271 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
273 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 272 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
274 __ jmp(RBX); | 273 __ jmp(RBX); |
275 } | 274 } |
276 | 275 |
277 | 276 |
| 277 // Called when number of invocations exceeds |
| 278 // --optimization_invocation_threshold. |
| 279 // RAX: target function. |
| 280 // R10: arguments descriptor array (num_args is first Smi element). |
278 void StubCode::GenerateOptimizeInvokedFunctionStub(Assembler* assembler) { | 281 void StubCode::GenerateOptimizeInvokedFunctionStub(Assembler* assembler) { |
279 __ Unimplemented("OptimizeInvokedFunction stub"); | 282 __ Untested("OptimizeInvokedFunction stub"); |
| 283 __ EnterFrame(0); |
| 284 __ pushq(R10); // Preserve arguments descriptor array. |
| 285 __ pushq(RAX); // Preserve target function. |
| 286 __ pushq(RAX); // Target function. |
| 287 __ CallRuntimeFromStub(kOptimizeInvokedFunctionRuntimeEntry); |
| 288 __ popq(RAX); // discard argument. |
| 289 __ popq(RAX); // Restore function. |
| 290 __ popq(R10); // Restore arguments descriptor array. |
| 291 __ movq(RAX, FieldAddress(RAX, Function::code_offset())); |
| 292 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
| 293 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 294 __ LeaveFrame(); |
| 295 __ jmp(RAX); |
| 296 __ int3(); |
280 } | 297 } |
281 | 298 |
282 | 299 |
| 300 // Called from a static call only when an invalid code has been entered |
| 301 // (invalid because its function was optimized or deoptimized). |
| 302 // RBX: function object. |
| 303 // R10: arguments descriptor array (num_args is first Smi element). |
283 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 304 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
284 __ Unimplemented("FixCallersTarget stub"); | 305 __ Untested("FixCallersTarget stub"); |
| 306 __ EnterFrame(0); |
| 307 __ pushq(R10); // Preserve arguments descriptor array. |
| 308 __ pushq(RBX); // Preserve target function. |
| 309 __ pushq(RBX); // Target function. |
| 310 __ CallRuntimeFromStub(kFixCallersTargetRuntimeEntry); |
| 311 __ popq(RAX); // discard argument. |
| 312 __ popq(RAX); // Restore function. |
| 313 __ popq(R10); // Restore arguments descriptor array. |
| 314 __ movq(RAX, FieldAddress(RAX, Function::code_offset())); |
| 315 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
| 316 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 317 __ LeaveFrame(); |
| 318 __ jmp(RAX); |
| 319 __ int3(); |
285 } | 320 } |
286 | 321 |
287 | 322 |
288 // Lookup for [function-name, arg count] in 'functions_map_'. | 323 // Lookup for [function-name, arg count] in 'functions_map_'. |
289 // Input parameters (to be treated as read only, unless calling to target!): | 324 // Input parameters (to be treated as read only, unless calling to target!): |
290 // RBX: ic-data array. | 325 // RBX: ic-data array. |
291 // R10: arguments descriptor array (num_args is first Smi element). | 326 // R10: arguments descriptor array (num_args is first Smi element). |
292 // Stack: return address, arguments. | 327 // Stack: return address, arguments. |
293 // If the lookup succeeds we jump to the target method from here, otherwise | 328 // If the lookup succeeds we jump to the target method from here, otherwise |
294 // we continue in code generated by the caller of 'MegamorphicLookup'. | 329 // we continue in code generated by the caller of 'MegamorphicLookup'. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 __ Bind(&next_iteration); | 398 __ Bind(&next_iteration); |
364 __ AddImmediate(R12, Immediate(FunctionsCache::kNumEntries * kWordSize)); | 399 __ AddImmediate(R12, Immediate(FunctionsCache::kNumEntries * kWordSize)); |
365 __ jmp(&loop, Assembler::kNearJump); | 400 __ jmp(&loop, Assembler::kNearJump); |
366 | 401 |
367 __ Bind(¬_found); | 402 __ Bind(¬_found); |
368 } | 403 } |
369 | 404 |
370 | 405 |
371 // Input parameters: | 406 // Input parameters: |
372 // R13: argument count, may be zero. | 407 // R13: argument count, may be zero. |
373 // Uses RAX, RBX, R10, R12. | |
374 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { | 408 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { |
375 const Immediate raw_null = | 409 const Immediate raw_null = |
376 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 410 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
377 | 411 |
378 // Allocate array to store arguments of caller. | 412 // Allocate array to store arguments of caller. |
379 __ movq(R10, R13); // Arguments array length. | 413 __ movq(R10, R13); // Arguments array length. |
380 __ SmiTag(R10); // Convert to Smi. | 414 __ SmiTag(R10); // Convert to Smi. |
381 __ movq(RBX, raw_null); // Null element type for raw Array. | 415 __ movq(RBX, raw_null); // Null element type for raw Array. |
382 __ call(&StubCode::AllocateArrayLabel()); | 416 __ call(&StubCode::AllocateArrayLabel()); |
383 __ SmiUntag(R10); | 417 __ SmiUntag(R10); |
(...skipping 14 matching lines...) Expand all Loading... |
398 __ j(POSITIVE, &loop, Assembler::kNearJump); | 432 __ j(POSITIVE, &loop, Assembler::kNearJump); |
399 } | 433 } |
400 | 434 |
401 | 435 |
402 // Input parameters: | 436 // Input parameters: |
403 // RBX: ic-data array. | 437 // RBX: ic-data array. |
404 // R10: arguments descriptor array (num_args is first Smi element). | 438 // R10: arguments descriptor array (num_args is first Smi element). |
405 // Note: The receiver object is the first argument to the function being | 439 // Note: The receiver object is the first argument to the function being |
406 // called, the stub accesses the receiver from this location directly | 440 // called, the stub accesses the receiver from this location directly |
407 // when trying to resolve the call. | 441 // when trying to resolve the call. |
408 // Uses R13. | |
409 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 442 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
410 const Immediate raw_null = | 443 const Immediate raw_null = |
411 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 444 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
412 | 445 |
413 MegamorphicLookup(assembler); | 446 MegamorphicLookup(assembler); |
414 // Lookup in function_table_ failed, resolve, compile and enter function | 447 // Lookup in function_table_ failed, resolve, compile and enter function |
415 // into function_table_. | 448 // into function_table_. |
416 | 449 |
417 // Create a stub frame as we are pushing some objects on the stack before | 450 // Create a stub frame as we are pushing some objects on the stack before |
418 // calling into the runtime. | 451 // calling into the runtime. |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 __ popq(RAX); | 619 __ popq(RAX); |
587 __ popq(RAX); // Get result into RAX. | 620 __ popq(RAX); // Get result into RAX. |
588 | 621 |
589 // Remove the stub frame as we are about to return. | 622 // Remove the stub frame as we are about to return. |
590 __ LeaveFrame(); | 623 __ LeaveFrame(); |
591 __ ret(); | 624 __ ret(); |
592 } | 625 } |
593 | 626 |
594 | 627 |
595 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 628 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
596 __ Unimplemented("Deoptimize stub"); | 629 __ Untested("Deoptimize stub"); |
| 630 __ EnterFrame(0); |
| 631 // RAX: deoptimization reason id. |
| 632 // Stack at this point: |
| 633 // TOS + 0: Saved EBP of function frame that will be deoptimized. <== EBP |
| 634 // TOS + 1: Deoptimization point (return address), will be patched. |
| 635 // TOS + 2: top-of-stack at deoptimization point (all arguments on stack). |
| 636 __ pushq(RAX); |
| 637 __ CallRuntimeFromStub(kDeoptimizeRuntimeEntry); |
| 638 __ popq(RAX); |
| 639 __ LeaveFrame(); |
| 640 __ ret(); |
597 } | 641 } |
598 | 642 |
599 | 643 |
600 // Called for inline allocation of arrays. | 644 // Called for inline allocation of arrays. |
601 // Input parameters: | 645 // Input parameters: |
602 // R10 : Array length as Smi. | 646 // R10 : Array length as Smi. |
603 // RBX : array element type (either NULL or an instantiated type). | 647 // RBX : array element type (either NULL or an instantiated type). |
604 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. | 648 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. |
605 // The newly allocated object is returned in RAX. | 649 // The newly allocated object is returned in RAX. |
606 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 650 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset())); | 713 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset())); |
670 __ movq(RBX, Address(RBX, Isolate::object_store_offset())); | 714 __ movq(RBX, Address(RBX, Isolate::object_store_offset())); |
671 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset())); | 715 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset())); |
672 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX); | 716 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX); |
673 // Calculate the size tag. | 717 // Calculate the size tag. |
674 // RAX: new object start as a tagged pointer. | 718 // RAX: new object start as a tagged pointer. |
675 // R12: new object end address. | 719 // R12: new object end address. |
676 // R10: Array length as Smi. | 720 // R10: Array length as Smi. |
677 { | 721 { |
678 Label size_tag_overflow, done; | 722 Label size_tag_overflow, done; |
679 __ leaq(RBX, Address(R10, TIMES_2, fixed_size)); // R10 is Smi. | 723 __ leaq(RBX, Address(R10, TIMES_4, fixed_size)); // R10 is Smi. |
680 ASSERT(kSmiTagShift == 1); | 724 ASSERT(kSmiTagShift == 1); |
681 __ andq(RBX, Immediate(-kObjectAlignment)); | 725 __ andq(RBX, Immediate(-kObjectAlignment)); |
682 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 726 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
683 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 727 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
684 __ shlq(RBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); | 728 __ shlq(RBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); |
685 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); | 729 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); |
686 __ jmp(&done); | 730 __ jmp(&done); |
687 | 731 |
688 __ Bind(&size_tag_overflow); | 732 __ Bind(&size_tag_overflow); |
689 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0)); | 733 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0)); |
690 __ Bind(&done); | 734 __ Bind(&done); |
691 } | 735 } |
692 | 736 |
693 // Initialize all array elements to raw_null. | 737 // Initialize all array elements to raw_null. |
694 // RAX: new object start as a tagged pointer. | 738 // RAX: new object start as a tagged pointer. |
695 // R12: new object end address. | 739 // R12: new object end address. |
| 740 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
696 // RBX: iterator which initially points to the start of the variable | 741 // RBX: iterator which initially points to the start of the variable |
697 // data area to be initialized. | 742 // data area to be initialized. |
698 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | |
699 Label done; | 743 Label done; |
700 Label init_loop; | 744 Label init_loop; |
701 __ Bind(&init_loop); | 745 __ Bind(&init_loop); |
702 __ cmpq(RBX, R12); | 746 __ cmpq(RBX, R12); |
703 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 747 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
704 __ movq(Address(RBX, 0), raw_null); | 748 __ movq(Address(RBX, 0), raw_null); |
705 __ addq(RBX, Immediate(kWordSize)); | 749 __ addq(RBX, Immediate(kWordSize)); |
706 __ jmp(&init_loop, Assembler::kNearJump); | 750 __ jmp(&init_loop, Assembler::kNearJump); |
707 __ Bind(&done); | 751 __ Bind(&done); |
708 | 752 |
(...skipping 14 matching lines...) Expand all Loading... |
723 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); | 767 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); |
724 __ popq(RAX); // Pop instantiator. | 768 __ popq(RAX); // Pop instantiator. |
725 __ popq(RAX); // Pop element type argument. | 769 __ popq(RAX); // Pop element type argument. |
726 __ popq(R10); // Pop array length argument. | 770 __ popq(R10); // Pop array length argument. |
727 __ popq(RAX); // Pop return value from return slot. | 771 __ popq(RAX); // Pop return value from return slot. |
728 __ LeaveFrame(); | 772 __ LeaveFrame(); |
729 __ ret(); | 773 __ ret(); |
730 } | 774 } |
731 | 775 |
732 | 776 |
| 777 // Input parameters: |
| 778 // R10: Arguments descriptor array (num_args is first Smi element, closure |
| 779 // object is not included in num_args). |
| 780 // Note: The closure object is pushed before the first argument to the function |
| 781 // being called, the stub accesses the closure from this location directly |
| 782 // when setting up the context and resolving the entry point. |
733 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 783 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
734 __ Unimplemented("CallClosureFunction stub"); | 784 const Immediate raw_null = |
| 785 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 786 |
| 787 // Total number of args is the first Smi in args descriptor array (R10). |
| 788 __ movq(RAX, FieldAddress(R10, Array::data_offset())); // Load num_args. |
| 789 // Load closure object in R13. |
| 790 __ movq(R13, Address(RSP, RAX, TIMES_4, kWordSize)); // RAX is a Smi. |
| 791 |
| 792 // Verify that R13 is a closure by checking its class. |
| 793 Label not_closure; |
| 794 __ cmpq(R13, raw_null); |
| 795 // Not a closure, but null object. |
| 796 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 797 __ testq(R13, Immediate(kSmiTagMask)); |
| 798 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. |
| 799 // Verify that the class of the object is a closure class by checking that |
| 800 // class.signature_function() is not null. |
| 801 __ movq(RAX, FieldAddress(R13, Object::class_offset())); |
| 802 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset())); |
| 803 __ cmpq(RAX, raw_null); |
| 804 // Actual class is not a closure class. |
| 805 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 806 |
| 807 // RAX is just the signature function. Load the actual closure function. |
| 808 __ movq(RBX, FieldAddress(R13, Closure::function_offset())); |
| 809 |
| 810 // Load closure context in CTX; note that CTX has already been preserved. |
| 811 __ movq(CTX, FieldAddress(R13, Closure::context_offset())); |
| 812 |
| 813 // Load closure function code in RAX. |
| 814 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); |
| 815 __ cmpq(RAX, raw_null); |
| 816 Label function_compiled; |
| 817 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); |
| 818 |
| 819 // Create a stub frame as we are pushing some objects on the stack before |
| 820 // calling into the runtime. |
| 821 __ EnterFrame(0); |
| 822 |
| 823 __ pushq(R10); // Preserve arguments descriptor array. |
| 824 __ pushq(RBX); // Preserve read-only function object argument. |
| 825 __ CallRuntimeFromStub(kCompileFunctionRuntimeEntry); |
| 826 __ popq(RBX); // Restore read-only function object argument in RBX. |
| 827 __ popq(R10); // Restore arguments descriptor array. |
| 828 // Restore RAX. |
| 829 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); |
| 830 |
| 831 // Remove the stub frame as we are about to jump to the closure function. |
| 832 __ LeaveFrame(); |
| 833 |
| 834 __ Bind(&function_compiled); |
| 835 // RAX: Code. |
| 836 // RBX: Function. |
| 837 // R10: Arguments descriptor array (num_args is first Smi element). |
| 838 |
| 839 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
| 840 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 841 __ jmp(RBX); |
| 842 |
| 843 __ Bind(¬_closure); |
| 844 // Call runtime to report that a closure call was attempted on a non-closure |
| 845 // object, passing the non-closure object and its arguments array. |
| 846 // R13: non-closure object. |
| 847 // R10: arguments descriptor array (num_args is first Smi element, closure |
| 848 // object is not included in num_args). |
| 849 |
| 850 // Create a stub frame as we are pushing some objects on the stack before |
| 851 // calling into the runtime. |
| 852 __ EnterFrame(0); |
| 853 |
| 854 __ pushq(raw_null); // Setup space on stack for result from error reporting. |
| 855 __ pushq(R13); // Non-closure object. |
| 856 // Total number of args is the first Smi in args descriptor array (R10). |
| 857 __ movq(R13, FieldAddress(R10, Array::data_offset())); // Load num_args. |
| 858 __ SmiUntag(R13); |
| 859 // See stack layout below explaining "wordSize * 4" offset. |
| 860 PushArgumentsArray(assembler, (kWordSize * 4)); |
| 861 |
| 862 // Stack: |
| 863 // TOS + 0: Argument array. |
| 864 // TOS + 1: Non-closure object. |
| 865 // TOS + 2: Place for result from reporting the error. |
| 866 // TOS + 3: Saved RBP of previous frame. <== RBP |
| 867 // TOS + 4: Dart code return address |
| 868 // TOS + 5: Last argument of caller. |
| 869 // .... |
| 870 __ CallRuntimeFromStub(kReportObjectNotClosureRuntimeEntry); |
| 871 __ Stop("runtime call throws an exception"); |
735 } | 872 } |
736 | 873 |
737 | 874 |
738 // Called when invoking Dart code from C++ (VM code). | 875 // Called when invoking Dart code from C++ (VM code). |
739 // Input parameters: | 876 // Input parameters: |
740 // RSP : points to return address. | 877 // RSP : points to return address. |
741 // RDI : entrypoint of the Dart function to call. | 878 // RDI : entrypoint of the Dart function to call. |
742 // RSI : arguments descriptor array. | 879 // RSI : arguments descriptor array. |
743 // RDX : pointer to the argument array. | 880 // RDX : pointer to the argument array. |
744 // RCX : new context containing the current isolate pointer. | 881 // RCX : new context containing the current isolate pointer. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
846 | 983 |
847 // Restore the frame pointer. | 984 // Restore the frame pointer. |
848 __ LeaveFrame(); | 985 __ LeaveFrame(); |
849 | 986 |
850 __ ret(); | 987 __ ret(); |
851 } | 988 } |
852 | 989 |
853 | 990 |
854 // Called for inline allocation of contexts. | 991 // Called for inline allocation of contexts. |
855 // Input: | 992 // Input: |
856 // RDX: number of context variables. | 993 // R10: number of context variables. |
857 // Output: | 994 // Output: |
858 // RAX: new allocated RawContext object. | 995 // RAX: new allocated RawContext object. |
859 // RBX and RDX are destroyed. | |
860 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 996 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
861 const Immediate raw_null = | 997 const Immediate raw_null = |
862 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 998 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
863 if (false) { | 999 if (FLAG_inline_alloc) { |
864 // TODO(regis): Implement fast inline allocation of contexts. | 1000 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
865 __ Unimplemented("AllocateContext stub - inline allocation"); | 1001 Label slow_case; |
| 1002 Heap* heap = Isolate::Current()->heap(); |
| 1003 // First compute the rounded instance size. |
| 1004 // R10: number of context variables. |
| 1005 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
| 1006 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
| 1007 __ andq(R13, Immediate(-kObjectAlignment)); |
| 1008 |
| 1009 // Now allocate the object. |
| 1010 // R10: number of context variables. |
| 1011 __ movq(RAX, Immediate(heap->TopAddress())); |
| 1012 __ movq(RAX, Address(RAX, 0)); |
| 1013 __ addq(R13, RAX); |
| 1014 // Check if the allocation fits into the remaining space. |
| 1015 // RAX: potential new object. |
| 1016 // R13: potential next object start. |
| 1017 // R10: number of context variables. |
| 1018 __ movq(RDI, Immediate(heap->EndAddress())); |
| 1019 __ cmpq(R13, Address(RDI, 0)); |
| 1020 if (FLAG_use_slow_path) { |
| 1021 __ jmp(&slow_case); |
| 1022 } else { |
| 1023 __ j(ABOVE_EQUAL, &slow_case); |
| 1024 } |
| 1025 |
| 1026 // Successfully allocated the object, now update top to point to |
| 1027 // next object start and initialize the object. |
| 1028 // RAX: new object. |
| 1029 // R13: next object start. |
| 1030 // R10: number of context variables. |
| 1031 __ movq(RDI, Immediate(heap->TopAddress())); |
| 1032 __ movq(Address(RDI, 0), R13); |
| 1033 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 1034 |
| 1035 // Initialize the class field in the context object. |
| 1036 // RAX: new object. |
| 1037 // R10: number of context variables. |
| 1038 __ LoadObject(R13, context_class); // Load up class field of context. |
| 1039 __ StoreIntoObject(RAX, |
| 1040 FieldAddress(RAX, Context::class_offset()), |
| 1041 R13); |
| 1042 // Calculate the size tag. |
| 1043 // RAX: new object. |
| 1044 // R10: number of context variables. |
| 1045 { |
| 1046 Label size_tag_overflow, done; |
| 1047 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
| 1048 __ andq(R13, Immediate(-kObjectAlignment)); |
| 1049 __ cmpq(R13, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| 1050 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
| 1051 __ shlq(R13, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); |
| 1052 __ movq(FieldAddress(RAX, Context::tags_offset()), R13); // Tags. |
| 1053 __ jmp(&done); |
| 1054 |
| 1055 __ Bind(&size_tag_overflow); |
| 1056 // Set overflow size tag value. |
| 1057 __ movq(FieldAddress(RAX, Context::tags_offset()), Immediate(0)); |
| 1058 __ Bind(&done); |
| 1059 } |
| 1060 |
| 1061 // Setup up number of context variables field. |
| 1062 // RAX: new object. |
| 1063 // R10: number of context variables as integer value (not object). |
| 1064 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); |
| 1065 |
| 1066 // Setup isolate field. |
| 1067 // Load Isolate pointer from Context structure into R13. |
| 1068 // RAX: new object. |
| 1069 // R10: number of context variables. |
| 1070 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); |
| 1071 // R13: Isolate, not an object. |
| 1072 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); |
| 1073 |
| 1074 const Immediate raw_null = |
| 1075 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1076 // Setup the parent field. |
| 1077 // RAX: new object. |
| 1078 // R10: number of context variables. |
| 1079 __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null); |
| 1080 |
| 1081 // Initialize the context variables. |
| 1082 // RAX: new object. |
| 1083 // R10: number of context variables. |
| 1084 { |
| 1085 Label loop, entry; |
| 1086 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); |
| 1087 |
| 1088 __ jmp(&entry, Assembler::kNearJump); |
| 1089 __ Bind(&loop); |
| 1090 __ decq(R10); |
| 1091 __ movq(Address(R13, R10, TIMES_8, 0), raw_null); |
| 1092 __ Bind(&entry); |
| 1093 __ cmpq(R10, Immediate(0)); |
| 1094 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1095 } |
| 1096 |
| 1097 // Done allocating and initializing the context. |
| 1098 // RAX: new object. |
| 1099 __ ret(); |
| 1100 |
| 1101 __ Bind(&slow_case); |
866 } | 1102 } |
867 // Create the stub frame. | 1103 // Create a stub frame. |
868 __ EnterFrame(0); | 1104 __ EnterFrame(0); |
869 __ pushq(raw_null); // Setup space on stack for the return value. | 1105 __ pushq(raw_null); // Setup space on stack for the return value. |
870 __ SmiTag(RDX); | 1106 __ SmiTag(R10); |
871 __ pushq(RDX); // Push number of context variables. | 1107 __ pushq(R10); // Push number of context variables. |
872 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. | 1108 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. |
873 __ popq(RAX); // Pop number of context variables argument. | 1109 __ popq(RAX); // Pop number of context variables argument. |
874 __ popq(RAX); // Pop the new context object. | 1110 __ popq(RAX); // Pop the new context object. |
875 // RAX: new object | 1111 // RAX: new object |
876 // Restore the frame pointer. | 1112 // Restore the frame pointer. |
877 __ LeaveFrame(); | 1113 __ LeaveFrame(); |
878 __ ret(); | 1114 __ ret(); |
879 } | 1115 } |
880 | 1116 |
881 | 1117 |
882 | |
883 | |
884 // Called for inline allocation of objects. | 1118 // Called for inline allocation of objects. |
885 // Input parameters: | 1119 // Input parameters: |
886 // RSP + 16 : type arguments object (only if class is parameterized). | 1120 // RSP + 16 : type arguments object (only if class is parameterized). |
887 // RSP + 8 : type arguments of instantiator (only if class is parameterized). | 1121 // RSP + 8 : type arguments of instantiator (only if class is parameterized). |
888 // RSP : points to return address. | 1122 // RSP : points to return address. |
889 // Uses RAX, RBX, RCX, RDX, RDI as temporary registers. | |
890 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1123 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
891 const Class& cls) { | 1124 const Class& cls) { |
892 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; | 1125 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; |
893 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; | 1126 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; |
894 const Immediate raw_null = | 1127 const Immediate raw_null = |
895 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1128 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
896 // The generated code is different if the class is parameterized. | 1129 // The generated code is different if the class is parameterized. |
897 const bool is_cls_parameterized = | 1130 const bool is_cls_parameterized = |
898 cls.type_arguments_instance_field_offset() != Class::kNoTypeArguments; | 1131 cls.type_arguments_instance_field_offset() != Class::kNoTypeArguments; |
899 // kInlineInstanceSize is a constant used as a threshold for determining | 1132 // kInlineInstanceSize is a constant used as a threshold for determining |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 } | 1309 } |
1077 | 1310 |
1078 | 1311 |
1079 // Called for inline allocation of closures. | 1312 // Called for inline allocation of closures. |
1080 // Input parameters: | 1313 // Input parameters: |
1081 // If the signature class is not parameterized, the receiver, if any, will be | 1314 // If the signature class is not parameterized, the receiver, if any, will be |
1082 // at RSP + 8 instead of RSP + 16, since no type arguments are passed. | 1315 // at RSP + 8 instead of RSP + 16, since no type arguments are passed. |
1083 // RSP + 16 (or RSP + 8): receiver (only if implicit instance closure). | 1316 // RSP + 16 (or RSP + 8): receiver (only if implicit instance closure). |
1084 // RSP + 8 : type arguments object (only if signature class is parameterized). | 1317 // RSP + 8 : type arguments object (only if signature class is parameterized). |
1085 // RSP : points to return address. | 1318 // RSP : points to return address. |
1086 // Uses RAX, RCX as temporary registers. | |
1087 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 1319 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
1088 const Function& func) { | 1320 const Function& func) { |
1089 const Immediate raw_null = | 1321 const Immediate raw_null = |
1090 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1322 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1091 ASSERT(func.IsClosureFunction()); | 1323 ASSERT(func.IsClosureFunction()); |
1092 const bool is_implicit_static_closure = | 1324 const bool is_implicit_static_closure = |
1093 func.IsImplicitStaticClosureFunction(); | 1325 func.IsImplicitStaticClosureFunction(); |
1094 const bool is_implicit_instance_closure = | 1326 const bool is_implicit_instance_closure = |
1095 func.IsImplicitInstanceClosureFunction(); | 1327 func.IsImplicitInstanceClosureFunction(); |
1096 const Class& cls = Class::ZoneHandle(func.signature_class()); | 1328 const Class& cls = Class::ZoneHandle(func.signature_class()); |
1097 const bool has_type_arguments = cls.HasTypeArguments(); | 1329 const bool has_type_arguments = cls.HasTypeArguments(); |
1098 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; | 1330 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; |
1099 const intptr_t kReceiverOffset = (has_type_arguments ? 2 : 1) * kWordSize; | 1331 const intptr_t kReceiverOffset = (has_type_arguments ? 2 : 1) * kWordSize; |
1100 if (false) { | 1332 const intptr_t closure_size = Closure::InstanceSize(); |
1101 // TODO(regis): Implement inline context allocation. | 1333 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. |
1102 __ Unimplemented("AllocateClosure stub - inline allocation"); | 1334 if (FLAG_inline_alloc && |
| 1335 PageSpace::IsPageAllocatableSize(closure_size + context_size)) { |
| 1336 Label slow_case; |
| 1337 Heap* heap = Isolate::Current()->heap(); |
| 1338 __ movq(RAX, Immediate(heap->TopAddress())); |
| 1339 __ movq(RAX, Address(RAX, 0)); |
| 1340 __ leaq(R13, Address(RAX, closure_size)); |
| 1341 if (is_implicit_instance_closure) { |
| 1342 __ movq(RBX, R13); // RBX: new context address. |
| 1343 __ addq(R13, Immediate(context_size)); |
| 1344 } |
| 1345 // Check if the allocation fits into the remaining space. |
| 1346 // RAX: potential new closure object. |
| 1347 // RBX: potential new context object (only if is_implicit_closure). |
| 1348 // R13: potential next object start. |
| 1349 __ movq(RDI, Immediate(heap->EndAddress())); |
| 1350 __ cmpq(R13, Address(RDI, 0)); |
| 1351 if (FLAG_use_slow_path) { |
| 1352 __ jmp(&slow_case); |
| 1353 } else { |
| 1354 __ j(ABOVE_EQUAL, &slow_case); |
| 1355 } |
| 1356 |
| 1357 // Successfully allocated the object, now update top to point to |
| 1358 // next object start and initialize the object. |
| 1359 __ movq(RDI, Immediate(heap->TopAddress())); |
| 1360 __ movq(Address(RDI, 0), R13); |
| 1361 |
| 1362 // Initialize the class field in the object. |
| 1363 // RAX: new closure object. |
| 1364 // RBX: new context object (only if is_implicit_closure). |
| 1365 __ LoadObject(R10, cls); // Load signature class of closure. |
| 1366 __ movq(Address(RAX, Closure::class_offset()), R10); |
| 1367 // Set the tags. |
| 1368 __ movq(Address(RAX, Closure::tags_offset()), |
| 1369 Immediate(RawObject::SizeTag::encode(closure_size))); |
| 1370 |
| 1371 // Initialize the function field in the object. |
| 1372 // RAX: new closure object. |
| 1373 // RBX: new context object (only if is_implicit_closure). |
| 1374 // R13: next object start. |
| 1375 __ LoadObject(R10, func); // Load function of closure to be allocated. |
| 1376 __ movq(Address(RAX, Closure::function_offset()), R10); |
| 1377 |
| 1378 // Setup the context for this closure. |
| 1379 if (is_implicit_static_closure) { |
| 1380 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 1381 ASSERT(object_store != NULL); |
| 1382 const Context& empty_context = |
| 1383 Context::ZoneHandle(object_store->empty_context()); |
| 1384 __ LoadObject(R10, empty_context); |
| 1385 __ movq(Address(RAX, Closure::context_offset()), R10); |
| 1386 } else if (is_implicit_instance_closure) { |
| 1387 // Initialize the new context capturing the receiver. |
| 1388 |
| 1389 // Set the class field to the Context class. |
| 1390 __ LoadObject(R13, Class::ZoneHandle(Object::context_class())); |
| 1391 __ movq(Address(RBX, Context::class_offset()), R13); |
| 1392 // Set the tags. |
| 1393 __ movq(Address(RBX, Context::tags_offset()), |
| 1394 Immediate(RawObject::SizeTag::encode(context_size))); |
| 1395 |
| 1396 // Set number of variables field to 1 (for captured receiver). |
| 1397 __ movq(Address(RBX, Context::num_variables_offset()), Immediate(1)); |
| 1398 |
| 1399 // Set isolate field to isolate of current context. |
| 1400 __ movq(R10, FieldAddress(CTX, Context::isolate_offset())); |
| 1401 __ movq(Address(RBX, Context::isolate_offset()), R10); |
| 1402 |
| 1403 // Set the parent field to null. |
| 1404 __ movq(Address(RBX, Context::parent_offset()), raw_null); |
| 1405 |
| 1406 // Initialize the context variable to the receiver. |
| 1407 __ movq(R10, Address(RSP, kReceiverOffset)); |
| 1408 __ movq(Address(RBX, Context::variable_offset(0)), R10); |
| 1409 |
| 1410 // Set the newly allocated context in the newly allocated closure. |
| 1411 __ addq(RBX, Immediate(kHeapObjectTag)); |
| 1412 __ movq(Address(RAX, Closure::context_offset()), RBX); |
| 1413 } else { |
| 1414 __ movq(Address(RAX, Closure::context_offset()), CTX); |
| 1415 } |
| 1416 |
| 1417 // Set the type arguments field in the newly allocated closure. |
| 1418 if (has_type_arguments) { |
| 1419 ASSERT(!is_implicit_static_closure); |
| 1420 // Use the passed-in type arguments. |
| 1421 __ movq(R10, Address(RSP, kTypeArgumentsOffset)); |
| 1422 __ movq(Address(RAX, Closure::type_arguments_offset()), R10); |
| 1423 } else { |
| 1424 // Set to null. |
| 1425 __ movq(Address(RAX, Closure::type_arguments_offset()), raw_null); |
| 1426 } |
| 1427 |
| 1428 __ movq(Address(RAX, Closure::smrck_offset()), raw_null); |
| 1429 |
| 1430 // Done allocating and initializing the instance. |
| 1431 // RAX: new object. |
| 1432 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 1433 __ ret(); |
| 1434 |
| 1435 __ Bind(&slow_case); |
1103 } | 1436 } |
1104 if (has_type_arguments) { | 1437 if (has_type_arguments) { |
1105 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); | 1438 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); |
1106 } | 1439 } |
1107 if (is_implicit_instance_closure) { | 1440 if (is_implicit_instance_closure) { |
1108 __ movq(RAX, Address(RSP, kReceiverOffset)); | 1441 __ movq(RAX, Address(RSP, kReceiverOffset)); |
1109 } | 1442 } |
1110 // Create the stub frame. | 1443 // Create the stub frame. |
1111 __ EnterFrame(0); | 1444 __ EnterFrame(0); |
1112 __ pushq(raw_null); // Setup space on stack for the return value. | 1445 __ pushq(raw_null); // Setup space on stack for the return value. |
(...skipping 21 matching lines...) Expand all Loading... |
1134 } | 1467 } |
1135 __ popq(RAX); // Pop the function object. | 1468 __ popq(RAX); // Pop the function object. |
1136 __ popq(RAX); // Pop the result. | 1469 __ popq(RAX); // Pop the result. |
1137 // RAX: New closure object. | 1470 // RAX: New closure object. |
1138 // Restore the calling frame. | 1471 // Restore the calling frame. |
1139 __ LeaveFrame(); | 1472 __ LeaveFrame(); |
1140 __ ret(); | 1473 __ ret(); |
1141 } | 1474 } |
1142 | 1475 |
1143 | 1476 |
| 1477 // Called for invoking noSuchMethod function from the entry code of a dart |
| 1478 // function after an error in passed named arguments is detected. |
| 1479 // Input parameters: |
| 1480 // RBP : points to previous frame pointer. |
| 1481 // RBP + 8 : points to return address. |
| 1482 // RBP + 16 : address of last argument (arg n-1). |
| 1483 // RBP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 1484 // RBX : ic-data array. |
| 1485 // R10 : arguments descriptor array. |
1144 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1486 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
1145 __ Unimplemented("CallNoSuchMethodFunction stub"); | 1487 // The target function was not found, so invoke method |
| 1488 // "void noSuchMethod(function_name, Array arguments)". |
| 1489 // TODO(regis): For now, we simply pass the actual arguments, both positional |
| 1490 // and named, as the argument array. This is not correct if out-of-order |
| 1491 // named arguments were passed. |
| 1492 // The signature of the "noSuchMethod" method has to change from |
| 1493 // noSuchMethod(String name, Array arguments) to something like |
| 1494 // noSuchMethod(InvocationMirror call). |
| 1495 // Also, the class NoSuchMethodException has to be modified accordingly. |
| 1496 // Total number of args is the first Smi in args descriptor array (R10). |
| 1497 const Immediate raw_null = |
| 1498 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1499 __ movq(R13, FieldAddress(R10, Array::data_offset())); |
| 1500 __ SmiUntag(R13); |
| 1501 __ movq(RAX, Address(RBP, R13, TIMES_8, kWordSize)); // Get receiver. |
| 1502 |
| 1503 __ EnterFrame(0); |
| 1504 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. |
| 1505 __ pushq(RAX); // Receiver. |
| 1506 __ pushq(RBX); // IC data array. |
| 1507 __ pushq(R10); // Arguments descriptor array. |
| 1508 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. |
| 1509 // See stack layout below explaining "wordSize * 8" offset. |
| 1510 PushArgumentsArray(assembler, (kWordSize * 8)); |
| 1511 |
| 1512 // Stack: |
| 1513 // TOS + 0: Argument array. |
| 1514 // TOS + 1: Arguments descriptor array. |
| 1515 // TOS + 2: Ic-data array. |
| 1516 // TOS + 3: Receiver. |
| 1517 // TOS + 4: Place for result from noSuchMethod. |
| 1518 // TOS + 5: Saved RBP of previous frame. <== RBP |
| 1519 // TOS + 6: Dart callee (or stub) code return address |
| 1520 // TOS + 7: Saved RBP of dart caller frame. |
| 1521 // TOS + 8: Dart caller code return address |
| 1522 // TOS + 9: Last argument of caller. |
| 1523 // .... |
| 1524 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 1525 // Remove arguments. |
| 1526 __ popq(RAX); |
| 1527 __ popq(RAX); |
| 1528 __ popq(RAX); |
| 1529 __ popq(RAX); |
| 1530 __ popq(RAX); // Get result into RAX. |
| 1531 |
| 1532 // Remove the stub frame as we are about to return. |
| 1533 __ LeaveFrame(); |
| 1534 __ ret(); |
1146 } | 1535 } |
1147 | 1536 |
1148 | 1537 |
| 1538 |
1149 // Generate inline cache check for 'num_args'. | 1539 // Generate inline cache check for 'num_args'. |
1150 // RBX: Inline cache data array. | 1540 // RBX: Inline cache data array. |
1151 // R10: Arguments array. | 1541 // R10: Arguments array. |
1152 // TOS(0): return address | 1542 // TOS(0): return address |
1153 // Control flow: | 1543 // Control flow: |
1154 // - If receiver is null -> jump to IC miss. | 1544 // - If receiver is null -> jump to IC miss. |
1155 // - If receiver is Smi -> load Smi class. | 1545 // - If receiver is Smi -> load Smi class. |
1156 // - If receiver is not-Smi -> load receiver's class. | 1546 // - If receiver is not-Smi -> load receiver's class. |
1157 // - Check if 'num_args' (including receiver) match any IC data group. | 1547 // - Check if 'num_args' (including receiver) match any IC data group. |
1158 // - Match found -> jump to target. | 1548 // - Match found -> jump to target. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1690 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1301 return GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1691 return GenerateNArgsCheckInlineCacheStub(assembler, 1); |
1302 } | 1692 } |
1303 | 1693 |
1304 | 1694 |
1305 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1695 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
1306 return GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1696 return GenerateNArgsCheckInlineCacheStub(assembler, 2); |
1307 } | 1697 } |
1308 | 1698 |
1309 | 1699 |
| 1700 // RBX: Function object. |
| 1701 // R10: Arguments array. |
| 1702 // TOS(0): return address (Dart code). |
1310 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1703 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
1311 __ Unimplemented("BreakpointStatic stub"); | 1704 __ Untested("BreakpointStatic stub"); |
| 1705 __ EnterFrame(0); |
| 1706 __ pushq(R10); |
| 1707 __ pushq(RBX); |
| 1708 __ CallRuntimeFromStub(kBreakpointStaticHandlerRuntimeEntry); |
| 1709 __ popq(RBX); |
| 1710 __ popq(R10); |
| 1711 __ LeaveFrame(); |
| 1712 |
| 1713 // Now call the static function. The breakpoint handler function |
| 1714 // ensures that the call target is compiled. |
| 1715 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); |
| 1716 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
| 1717 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1718 __ jmp(RBX); |
1312 } | 1719 } |
1313 | 1720 |
1314 | 1721 |
| 1722 // RBX: Inline cache data array. |
| 1723 // R10: Arguments array. |
| 1724 // TOS(0): return address (Dart code). |
1315 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1725 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
1316 __ Unimplemented("BreakpointDynamic stub"); | 1726 __ Untested("BreakpointDynamic stub"); |
| 1727 __ EnterFrame(0); |
| 1728 __ pushq(RBX); |
| 1729 __ pushq(R10); |
| 1730 __ CallRuntimeFromStub(kBreakpointDynamicHandlerRuntimeEntry); |
| 1731 __ popq(R10); |
| 1732 __ popq(RBX); |
| 1733 __ LeaveFrame(); |
| 1734 // Now call the dynamic function. |
| 1735 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); |
1317 } | 1736 } |
1318 | 1737 |
1319 } // namespace dart | 1738 } // namespace dart |
1320 | 1739 |
1321 #endif // defined TARGET_ARCH_X64 | 1740 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |