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 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset())); | 669 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset())); |
670 __ movq(RBX, Address(RBX, Isolate::object_store_offset())); | 670 __ movq(RBX, Address(RBX, Isolate::object_store_offset())); |
671 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset())); | 671 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset())); |
672 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX); | 672 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX); |
673 // Calculate the size tag. | 673 // Calculate the size tag. |
674 // RAX: new object start as a tagged pointer. | 674 // RAX: new object start as a tagged pointer. |
675 // R12: new object end address. | 675 // R12: new object end address. |
676 // R10: Array length as Smi. | 676 // R10: Array length as Smi. |
677 { | 677 { |
678 Label size_tag_overflow, done; | 678 Label size_tag_overflow, done; |
679 __ leaq(RBX, Address(R10, TIMES_2, fixed_size)); // R10 is Smi. | 679 __ leaq(RBX, Address(R10, TIMES_4, fixed_size)); // R10 is Smi. |
680 ASSERT(kSmiTagShift == 1); | 680 ASSERT(kSmiTagShift == 1); |
681 __ andq(RBX, Immediate(-kObjectAlignment)); | 681 __ andq(RBX, Immediate(-kObjectAlignment)); |
682 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 682 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
683 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 683 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
684 __ shlq(RBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); | 684 __ shlq(RBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); |
685 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); | 685 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); |
686 __ jmp(&done); | 686 __ jmp(&done); |
687 | 687 |
688 __ Bind(&size_tag_overflow); | 688 __ Bind(&size_tag_overflow); |
689 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0)); | 689 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0)); |
690 __ Bind(&done); | 690 __ Bind(&done); |
691 } | 691 } |
692 | 692 |
693 // Initialize all array elements to raw_null. | 693 // Initialize all array elements to raw_null. |
694 // RAX: new object start as a tagged pointer. | 694 // RAX: new object start as a tagged pointer. |
695 // R12: new object end address. | 695 // R12: new object end address. |
| 696 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
696 // RBX: iterator which initially points to the start of the variable | 697 // RBX: iterator which initially points to the start of the variable |
697 // data area to be initialized. | 698 // data area to be initialized. |
698 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | |
699 Label done; | 699 Label done; |
700 Label init_loop; | 700 Label init_loop; |
701 __ Bind(&init_loop); | 701 __ Bind(&init_loop); |
702 __ cmpq(RBX, R12); | 702 __ cmpq(RBX, R12); |
703 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 703 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
704 __ movq(Address(RBX, 0), raw_null); | 704 __ movq(Address(RBX, 0), raw_null); |
705 __ addq(RBX, Immediate(kWordSize)); | 705 __ addq(RBX, Immediate(kWordSize)); |
706 __ jmp(&init_loop, Assembler::kNearJump); | 706 __ jmp(&init_loop, Assembler::kNearJump); |
707 __ Bind(&done); | 707 __ Bind(&done); |
708 | 708 |
(...skipping 14 matching lines...) Expand all Loading... |
723 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); | 723 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); |
724 __ popq(RAX); // Pop instantiator. | 724 __ popq(RAX); // Pop instantiator. |
725 __ popq(RAX); // Pop element type argument. | 725 __ popq(RAX); // Pop element type argument. |
726 __ popq(R10); // Pop array length argument. | 726 __ popq(R10); // Pop array length argument. |
727 __ popq(RAX); // Pop return value from return slot. | 727 __ popq(RAX); // Pop return value from return slot. |
728 __ LeaveFrame(); | 728 __ LeaveFrame(); |
729 __ ret(); | 729 __ ret(); |
730 } | 730 } |
731 | 731 |
732 | 732 |
| 733 // Input parameters: |
| 734 // R10: Arguments descriptor array (num_args is first Smi element, closure |
| 735 // object is not included in num_args). |
| 736 // Note: The closure object is pushed before the first argument to the function |
| 737 // being called, the stub accesses the closure from this location directly |
| 738 // when setting up the context and resolving the entry point. |
| 739 // Uses R13. |
733 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 740 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
734 __ Unimplemented("CallClosureFunction stub"); | 741 const Immediate raw_null = |
| 742 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 743 |
| 744 // Total number of args is the first Smi in args descriptor array (R10). |
| 745 __ movq(RAX, FieldAddress(R10, Array::data_offset())); // Load num_args. |
| 746 // Load closure object in R13. |
| 747 __ movq(R13, Address(RSP, RAX, TIMES_4, kWordSize)); // RAX is a Smi. |
| 748 |
| 749 // Verify that R13 is a closure by checking its class. |
| 750 Label not_closure; |
| 751 __ cmpq(R13, raw_null); |
| 752 // Not a closure, but null object. |
| 753 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 754 __ testq(R13, Immediate(kSmiTagMask)); |
| 755 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. |
| 756 // Verify that the class of the object is a closure class by checking that |
| 757 // class.signature_function() is not null. |
| 758 __ movq(RAX, FieldAddress(R13, Object::class_offset())); |
| 759 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset())); |
| 760 __ cmpq(RAX, raw_null); |
| 761 // Actual class is not a closure class. |
| 762 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 763 |
| 764 // RAX is just the signature function. Load the actual closure function. |
| 765 __ movq(RBX, FieldAddress(R13, Closure::function_offset())); |
| 766 |
| 767 // Load closure context in CTX; note that CTX has already been preserved. |
| 768 __ movq(CTX, FieldAddress(R13, Closure::context_offset())); |
| 769 |
| 770 // Load closure function code in RAX. |
| 771 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); |
| 772 __ cmpq(RAX, raw_null); |
| 773 Label function_compiled; |
| 774 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); |
| 775 |
| 776 // Create a stub frame as we are pushing some objects on the stack before |
| 777 // calling into the runtime. |
| 778 __ EnterFrame(0); |
| 779 |
| 780 __ pushq(R10); // Preserve arguments descriptor array. |
| 781 __ pushq(RBX); |
| 782 __ CallRuntimeFromStub(kCompileFunctionRuntimeEntry); |
| 783 __ popq(RBX); // Restore read-only function object argument in RBX. |
| 784 __ popq(R10); // Restore arguments descriptor array. |
| 785 // Restore RAX. |
| 786 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); |
| 787 |
| 788 // Remove the stub frame as we are about to jump to the closure function. |
| 789 __ LeaveFrame(); |
| 790 |
| 791 __ Bind(&function_compiled); |
| 792 // RAX: Code. |
| 793 // RBX: Function. |
| 794 // R10: Arguments descriptor array (num_args is first Smi element). |
| 795 |
| 796 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
| 797 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 798 __ jmp(RBX); |
| 799 |
| 800 __ Bind(¬_closure); |
| 801 // Call runtime to report that a closure call was attempted on a non-closure |
| 802 // object, passing the non-closure object and its arguments array. |
| 803 // R13: non-closure object. |
| 804 // R10: arguments descriptor array (num_args is first Smi element, closure |
| 805 // object is not included in num_args). |
| 806 |
| 807 // Create a stub frame as we are pushing some objects on the stack before |
| 808 // calling into the runtime. |
| 809 __ EnterFrame(0); |
| 810 |
| 811 __ pushq(raw_null); // Setup space on stack for result from error reporting. |
| 812 __ pushq(R13); // Non-closure object. |
| 813 // Total number of args is the first Smi in args descriptor array (R10). |
| 814 __ movq(R13, FieldAddress(R10, Array::data_offset())); // Load num_args. |
| 815 __ SmiUntag(R13); |
| 816 // See stack layout below explaining "wordSize * 4" offset. |
| 817 PushArgumentsArray(assembler, (kWordSize * 4)); |
| 818 |
| 819 // Stack: |
| 820 // TOS + 0: Argument array. |
| 821 // TOS + 1: Non-closure object. |
| 822 // TOS + 2: Place for result from reporting the error. |
| 823 // TOS + 3: Saved RBP of previous frame. <== RBP |
| 824 // TOS + 4: Dart code return address |
| 825 // TOS + 5: Last argument of caller. |
| 826 // .... |
| 827 __ CallRuntimeFromStub(kReportObjectNotClosureRuntimeEntry); |
| 828 __ Stop("runtime call throws an exception"); |
735 } | 829 } |
736 | 830 |
737 | 831 |
738 // Called when invoking Dart code from C++ (VM code). | 832 // Called when invoking Dart code from C++ (VM code). |
739 // Input parameters: | 833 // Input parameters: |
740 // RSP : points to return address. | 834 // RSP : points to return address. |
741 // RDI : entrypoint of the Dart function to call. | 835 // RDI : entrypoint of the Dart function to call. |
742 // RSI : arguments descriptor array. | 836 // RSI : arguments descriptor array. |
743 // RDX : pointer to the argument array. | 837 // RDX : pointer to the argument array. |
744 // RCX : new context containing the current isolate pointer. | 838 // RCX : new context containing the current isolate pointer. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
846 | 940 |
847 // Restore the frame pointer. | 941 // Restore the frame pointer. |
848 __ LeaveFrame(); | 942 __ LeaveFrame(); |
849 | 943 |
850 __ ret(); | 944 __ ret(); |
851 } | 945 } |
852 | 946 |
853 | 947 |
854 // Called for inline allocation of contexts. | 948 // Called for inline allocation of contexts. |
855 // Input: | 949 // Input: |
856 // RDX: number of context variables. | 950 // R10: number of context variables. |
857 // Output: | 951 // Output: |
858 // RAX: new allocated RawContext object. | 952 // RAX: new allocated RawContext object. |
859 // RBX and RDX are destroyed. | |
860 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 953 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
861 const Immediate raw_null = | 954 const Immediate raw_null = |
862 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 955 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
863 if (false) { | 956 if (FLAG_inline_alloc) { |
864 // TODO(regis): Implement fast inline allocation of contexts. | 957 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
865 __ Unimplemented("AllocateContext stub - inline allocation"); | 958 Label slow_case; |
| 959 Heap* heap = Isolate::Current()->heap(); |
| 960 // First compute the rounded instance size. |
| 961 // R10: number of context variables. |
| 962 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
| 963 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
| 964 __ andq(R13, Immediate(-kObjectAlignment)); |
| 965 |
| 966 // Now allocate the object. |
| 967 // R10: number of context variables. |
| 968 __ movq(RAX, Immediate(heap->TopAddress())); |
| 969 __ movq(RAX, Address(RAX, 0)); |
| 970 __ addq(R13, RAX); |
| 971 // Check if the allocation fits into the remaining space. |
| 972 // RAX: potential new object. |
| 973 // R13: potential next object start. |
| 974 // R10: number of context variables. |
| 975 __ movq(RDI, Immediate(heap->EndAddress())); |
| 976 __ cmpq(R13, Address(RDI, 0)); |
| 977 if (FLAG_use_slow_path) { |
| 978 __ jmp(&slow_case); |
| 979 } else { |
| 980 __ j(ABOVE_EQUAL, &slow_case); |
| 981 } |
| 982 |
| 983 // Successfully allocated the object, now update top to point to |
| 984 // next object start and initialize the object. |
| 985 // RAX: new object. |
| 986 // R13: next object start. |
| 987 // R10: number of context variables. |
| 988 __ movq(RDI, Immediate(heap->TopAddress())); |
| 989 __ movq(Address(RDI, 0), R13); |
| 990 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 991 |
| 992 // Initialize the class field in the context object. |
| 993 // RAX: new object. |
| 994 // R10: number of context variables. |
| 995 __ LoadObject(R13, context_class); // Load up class field of context. |
| 996 __ StoreIntoObject(RAX, |
| 997 FieldAddress(RAX, Context::class_offset()), |
| 998 R13); |
| 999 // Calculate the size tag. |
| 1000 // RAX: new object. |
| 1001 // R10: number of context variables. |
| 1002 { |
| 1003 Label size_tag_overflow, done; |
| 1004 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
| 1005 __ andq(R13, Immediate(-kObjectAlignment)); |
| 1006 __ cmpq(R13, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| 1007 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
| 1008 __ shlq(R13, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); |
| 1009 __ movq(FieldAddress(RAX, Context::tags_offset()), R13); // Tags. |
| 1010 __ jmp(&done); |
| 1011 |
| 1012 __ Bind(&size_tag_overflow); |
| 1013 // Set overflow size tag value. |
| 1014 __ movq(FieldAddress(RAX, Context::tags_offset()), Immediate(0)); |
| 1015 __ Bind(&done); |
| 1016 } |
| 1017 |
| 1018 // Setup up number of context variables field. |
| 1019 // RAX: new object. |
| 1020 // R10: number of context variables as integer value (not object). |
| 1021 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); |
| 1022 |
| 1023 // Setup isolate field. |
| 1024 // Load Isolate pointer from Context structure into R13. |
| 1025 // RAX: new object. |
| 1026 // R10: number of context variables. |
| 1027 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); |
| 1028 // R13: Isolate, not an object. |
| 1029 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); |
| 1030 |
| 1031 const Immediate raw_null = |
| 1032 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1033 // Setup the parent field. |
| 1034 // RAX: new object. |
| 1035 // R10: number of context variables. |
| 1036 __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null); |
| 1037 |
| 1038 // Initialize the context variables. |
| 1039 // RAX: new object. |
| 1040 // R10: number of context variables. |
| 1041 { |
| 1042 Label loop, entry; |
| 1043 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); |
| 1044 |
| 1045 __ jmp(&entry, Assembler::kNearJump); |
| 1046 __ Bind(&loop); |
| 1047 __ decq(R10); |
| 1048 __ movq(Address(R13, R10, TIMES_8, 0), raw_null); |
| 1049 __ Bind(&entry); |
| 1050 __ cmpq(R10, Immediate(0)); |
| 1051 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1052 } |
| 1053 |
| 1054 // Done allocating and initializing the context. |
| 1055 // RAX: new object. |
| 1056 __ ret(); |
| 1057 |
| 1058 __ Bind(&slow_case); |
866 } | 1059 } |
867 // Create the stub frame. | 1060 // Create a stub frame. |
868 __ EnterFrame(0); | 1061 __ EnterFrame(0); |
869 __ pushq(raw_null); // Setup space on stack for the return value. | 1062 __ pushq(raw_null); // Setup space on stack for the return value. |
870 __ SmiTag(RDX); | 1063 __ SmiTag(R10); |
871 __ pushq(RDX); // Push number of context variables. | 1064 __ pushq(R10); // Push number of context variables. |
872 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. | 1065 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. |
873 __ popq(RAX); // Pop number of context variables argument. | 1066 __ popq(RAX); // Pop number of context variables argument. |
874 __ popq(RAX); // Pop the new context object. | 1067 __ popq(RAX); // Pop the new context object. |
875 // RAX: new object | 1068 // RAX: new object |
876 // Restore the frame pointer. | 1069 // Restore the frame pointer. |
877 __ LeaveFrame(); | 1070 __ LeaveFrame(); |
878 __ ret(); | 1071 __ ret(); |
879 } | 1072 } |
880 | 1073 |
881 | 1074 |
882 | |
883 | |
884 // Called for inline allocation of objects. | 1075 // Called for inline allocation of objects. |
885 // Input parameters: | 1076 // Input parameters: |
886 // RSP + 16 : type arguments object (only if class is parameterized). | 1077 // RSP + 16 : type arguments object (only if class is parameterized). |
887 // RSP + 8 : type arguments of instantiator (only if class is parameterized). | 1078 // RSP + 8 : type arguments of instantiator (only if class is parameterized). |
888 // RSP : points to return address. | 1079 // RSP : points to return address. |
889 // Uses RAX, RBX, RCX, RDX, RDI as temporary registers. | 1080 // Uses RAX, RBX, RCX, RDX, RDI as temporary registers. |
890 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1081 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
891 const Class& cls) { | 1082 const Class& cls) { |
892 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; | 1083 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; |
893 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; | 1084 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1090 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1281 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1091 ASSERT(func.IsClosureFunction()); | 1282 ASSERT(func.IsClosureFunction()); |
1092 const bool is_implicit_static_closure = | 1283 const bool is_implicit_static_closure = |
1093 func.IsImplicitStaticClosureFunction(); | 1284 func.IsImplicitStaticClosureFunction(); |
1094 const bool is_implicit_instance_closure = | 1285 const bool is_implicit_instance_closure = |
1095 func.IsImplicitInstanceClosureFunction(); | 1286 func.IsImplicitInstanceClosureFunction(); |
1096 const Class& cls = Class::ZoneHandle(func.signature_class()); | 1287 const Class& cls = Class::ZoneHandle(func.signature_class()); |
1097 const bool has_type_arguments = cls.HasTypeArguments(); | 1288 const bool has_type_arguments = cls.HasTypeArguments(); |
1098 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; | 1289 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; |
1099 const intptr_t kReceiverOffset = (has_type_arguments ? 2 : 1) * kWordSize; | 1290 const intptr_t kReceiverOffset = (has_type_arguments ? 2 : 1) * kWordSize; |
1100 if (false) { | 1291 const intptr_t closure_size = Closure::InstanceSize(); |
1101 // TODO(regis): Implement inline context allocation. | 1292 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. |
1102 __ Unimplemented("AllocateClosure stub - inline allocation"); | 1293 if (FLAG_inline_alloc && |
| 1294 PageSpace::IsPageAllocatableSize(closure_size + context_size)) { |
| 1295 Label slow_case; |
| 1296 Heap* heap = Isolate::Current()->heap(); |
| 1297 __ movq(RAX, Immediate(heap->TopAddress())); |
| 1298 __ movq(RAX, Address(RAX, 0)); |
| 1299 __ leaq(R13, Address(RAX, closure_size)); |
| 1300 if (is_implicit_instance_closure) { |
| 1301 __ movq(RBX, R13); // RBX: new context address. |
| 1302 __ addq(R13, Immediate(context_size)); |
| 1303 } |
| 1304 // Check if the allocation fits into the remaining space. |
| 1305 // RAX: potential new closure object. |
| 1306 // RBX: potential new context object (only if is_implicit_closure). |
| 1307 // R13: potential next object start. |
| 1308 __ movq(RDI, Immediate(heap->EndAddress())); |
| 1309 __ cmpq(R13, Address(RDI, 0)); |
| 1310 if (FLAG_use_slow_path) { |
| 1311 __ jmp(&slow_case); |
| 1312 } else { |
| 1313 __ j(ABOVE_EQUAL, &slow_case); |
| 1314 } |
| 1315 |
| 1316 // Successfully allocated the object, now update top to point to |
| 1317 // next object start and initialize the object. |
| 1318 __ movq(RDI, Immediate(heap->TopAddress())); |
| 1319 __ movq(Address(RDI, 0), R13); |
| 1320 |
| 1321 // Initialize the class field in the object. |
| 1322 // RAX: new closure object. |
| 1323 // RBX: new context object (only if is_implicit_closure). |
| 1324 __ LoadObject(R10, cls); // Load signature class of closure. |
| 1325 __ movq(Address(RAX, Closure::class_offset()), R10); |
| 1326 // Set the tags. |
| 1327 __ movq(Address(RAX, Closure::tags_offset()), |
| 1328 Immediate(RawObject::SizeTag::encode(closure_size))); |
| 1329 |
| 1330 // Initialize the function field in the object. |
| 1331 // RAX: new closure object. |
| 1332 // RBX: new context object (only if is_implicit_closure). |
| 1333 // R13: next object start. |
| 1334 __ LoadObject(R10, func); // Load function of closure to be allocated. |
| 1335 __ movq(Address(RAX, Closure::function_offset()), R10); |
| 1336 |
| 1337 // Setup the context for this closure. |
| 1338 if (is_implicit_static_closure) { |
| 1339 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 1340 ASSERT(object_store != NULL); |
| 1341 const Context& empty_context = |
| 1342 Context::ZoneHandle(object_store->empty_context()); |
| 1343 __ LoadObject(R10, empty_context); |
| 1344 __ movq(Address(RAX, Closure::context_offset()), R10); |
| 1345 } else if (is_implicit_instance_closure) { |
| 1346 // Initialize the new context capturing the receiver. |
| 1347 |
| 1348 // Set the class field to the Context class. |
| 1349 __ LoadObject(R13, Class::ZoneHandle(Object::context_class())); |
| 1350 __ movq(Address(RBX, Context::class_offset()), R13); |
| 1351 // Set the tags. |
| 1352 __ movq(Address(RBX, Context::tags_offset()), |
| 1353 Immediate(RawObject::SizeTag::encode(context_size))); |
| 1354 |
| 1355 // Set number of variables field to 1 (for captured receiver). |
| 1356 __ movq(Address(RBX, Context::num_variables_offset()), Immediate(1)); |
| 1357 |
| 1358 // Set isolate field to isolate of current context. |
| 1359 __ movq(R10, FieldAddress(CTX, Context::isolate_offset())); |
| 1360 __ movq(Address(RBX, Context::isolate_offset()), R10); |
| 1361 |
| 1362 // Set the parent field to null. |
| 1363 __ movq(Address(RBX, Context::parent_offset()), raw_null); |
| 1364 |
| 1365 // Initialize the context variable to the receiver. |
| 1366 __ movq(R10, Address(RSP, kReceiverOffset)); |
| 1367 __ movq(Address(RBX, Context::variable_offset(0)), R10); |
| 1368 |
| 1369 // Set the newly allocated context in the newly allocated closure. |
| 1370 __ addq(RBX, Immediate(kHeapObjectTag)); |
| 1371 __ movq(Address(RAX, Closure::context_offset()), RBX); |
| 1372 } else { |
| 1373 __ movq(Address(RAX, Closure::context_offset()), CTX); |
| 1374 } |
| 1375 |
| 1376 // Set the type arguments field in the newly allocated closure. |
| 1377 if (has_type_arguments) { |
| 1378 ASSERT(!is_implicit_static_closure); |
| 1379 // Use the passed-in type arguments. |
| 1380 __ movq(R10, Address(RSP, kTypeArgumentsOffset)); |
| 1381 __ movq(Address(RAX, Closure::type_arguments_offset()), R10); |
| 1382 } else { |
| 1383 // Set to null. |
| 1384 __ movq(Address(RAX, Closure::type_arguments_offset()), raw_null); |
| 1385 } |
| 1386 |
| 1387 __ movq(Address(RAX, Closure::smrck_offset()), raw_null); |
| 1388 |
| 1389 // Done allocating and initializing the instance. |
| 1390 // RAX: new object. |
| 1391 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 1392 __ ret(); |
| 1393 |
| 1394 __ Bind(&slow_case); |
1103 } | 1395 } |
1104 if (has_type_arguments) { | 1396 if (has_type_arguments) { |
1105 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); | 1397 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); |
1106 } | 1398 } |
1107 if (is_implicit_instance_closure) { | 1399 if (is_implicit_instance_closure) { |
1108 __ movq(RAX, Address(RSP, kReceiverOffset)); | 1400 __ movq(RAX, Address(RSP, kReceiverOffset)); |
1109 } | 1401 } |
1110 // Create the stub frame. | 1402 // Create the stub frame. |
1111 __ EnterFrame(0); | 1403 __ EnterFrame(0); |
1112 __ pushq(raw_null); // Setup space on stack for the return value. | 1404 __ pushq(raw_null); // Setup space on stack for the return value. |
(...skipping 21 matching lines...) Expand all Loading... |
1134 } | 1426 } |
1135 __ popq(RAX); // Pop the function object. | 1427 __ popq(RAX); // Pop the function object. |
1136 __ popq(RAX); // Pop the result. | 1428 __ popq(RAX); // Pop the result. |
1137 // RAX: New closure object. | 1429 // RAX: New closure object. |
1138 // Restore the calling frame. | 1430 // Restore the calling frame. |
1139 __ LeaveFrame(); | 1431 __ LeaveFrame(); |
1140 __ ret(); | 1432 __ ret(); |
1141 } | 1433 } |
1142 | 1434 |
1143 | 1435 |
| 1436 // Called for invoking noSuchMethod function from the entry code of a dart |
| 1437 // function after an error in passed named arguments is detected. |
| 1438 // Input parameters: |
| 1439 // RBP : points to previous frame pointer. |
| 1440 // RBP + 8 : points to return address. |
| 1441 // RBP + 16 : address of last argument (arg n-1). |
| 1442 // RBP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 1443 // RBX : ic-data array. |
| 1444 // R10 : arguments descriptor array. |
1144 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1445 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
1145 __ Unimplemented("CallNoSuchMethodFunction stub"); | 1446 // The target function was not found, so invoke method |
| 1447 // "void noSuchMethod(function_name, Array arguments)". |
| 1448 // TODO(regis): For now, we simply pass the actual arguments, both positional |
| 1449 // and named, as the argument array. This is not correct if out-of-order |
| 1450 // named arguments were passed. |
| 1451 // The signature of the "noSuchMethod" method has to change from |
| 1452 // noSuchMethod(String name, Array arguments) to something like |
| 1453 // noSuchMethod(InvocationMirror call). |
| 1454 // Also, the class NoSuchMethodException has to be modified accordingly. |
| 1455 // Total number of args is the first Smi in args descriptor array (R10). |
| 1456 const Immediate raw_null = |
| 1457 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1458 __ movq(R13, FieldAddress(R10, Array::data_offset())); |
| 1459 __ SmiUntag(R13); |
| 1460 __ movq(RAX, Address(RBP, R13, TIMES_8, kWordSize)); // Get receiver. |
| 1461 |
| 1462 __ EnterFrame(0); |
| 1463 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. |
| 1464 __ pushq(RAX); // Receiver. |
| 1465 __ pushq(RBX); // IC data array. |
| 1466 __ pushq(R10); // Arguments descriptor array. |
| 1467 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. |
| 1468 // See stack layout below explaining "wordSize * 8" offset. |
| 1469 PushArgumentsArray(assembler, (kWordSize * 8)); |
| 1470 |
| 1471 // Stack: |
| 1472 // TOS + 0: Argument array. |
| 1473 // TOS + 1: Arguments descriptor array. |
| 1474 // TOS + 2: Ic-data array. |
| 1475 // TOS + 3: Receiver. |
| 1476 // TOS + 4: Place for result from noSuchMethod. |
| 1477 // TOS + 5: Saved RBP of previous frame. <== RBP |
| 1478 // TOS + 6: Dart callee (or stub) code return address |
| 1479 // TOS + 7: Saved RBP of dart caller frame. |
| 1480 // TOS + 8: Dart caller code return address |
| 1481 // TOS + 9: Last argument of caller. |
| 1482 // .... |
| 1483 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 1484 // Remove arguments. |
| 1485 __ popq(RAX); |
| 1486 __ popq(RAX); |
| 1487 __ popq(RAX); |
| 1488 __ popq(RAX); |
| 1489 __ popq(RAX); // Get result into RAX. |
| 1490 |
| 1491 // Remove the stub frame as we are about to return. |
| 1492 __ LeaveFrame(); |
| 1493 __ ret(); |
1146 } | 1494 } |
1147 | 1495 |
1148 | 1496 |
| 1497 |
1149 // Generate inline cache check for 'num_args'. | 1498 // Generate inline cache check for 'num_args'. |
1150 // RBX: Inline cache data array. | 1499 // RBX: Inline cache data array. |
1151 // R10: Arguments array. | 1500 // R10: Arguments array. |
1152 // TOS(0): return address | 1501 // TOS(0): return address |
1153 // Control flow: | 1502 // Control flow: |
1154 // - If receiver is null -> jump to IC miss. | 1503 // - If receiver is null -> jump to IC miss. |
1155 // - If receiver is Smi -> load Smi class. | 1504 // - If receiver is Smi -> load Smi class. |
1156 // - If receiver is not-Smi -> load receiver's class. | 1505 // - If receiver is not-Smi -> load receiver's class. |
1157 // - Check if 'num_args' (including receiver) match any IC data group. | 1506 // - Check if 'num_args' (including receiver) match any IC data group. |
1158 // - Match found -> jump to target. | 1507 // - Match found -> jump to target. |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 } | 1661 } |
1313 | 1662 |
1314 | 1663 |
1315 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1664 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
1316 __ Unimplemented("BreakpointDynamic stub"); | 1665 __ Unimplemented("BreakpointDynamic stub"); |
1317 } | 1666 } |
1318 | 1667 |
1319 } // namespace dart | 1668 } // namespace dart |
1320 | 1669 |
1321 #endif // defined TARGET_ARCH_X64 | 1670 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |