OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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" |
(...skipping 658 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)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after 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 (false) { |
864 // TODO(regis): Implement fast inline allocation of contexts. | 957 // TODO(regis): Implement fast inline allocation of contexts. |
865 __ Unimplemented("AllocateContext stub - inline allocation"); | 958 __ Unimplemented("AllocateContext stub - inline allocation"); |
866 } | 959 } |
867 // Create the stub frame. | 960 // Create the stub frame. |
868 __ EnterFrame(0); | 961 __ EnterFrame(0); |
869 __ pushq(raw_null); // Setup space on stack for the return value. | 962 __ pushq(raw_null); // Setup space on stack for the return value. |
870 __ SmiTag(RDX); | 963 __ SmiTag(R10); |
871 __ pushq(RDX); // Push number of context variables. | 964 __ pushq(R10); // Push number of context variables. |
872 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. | 965 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. |
873 __ popq(RAX); // Pop number of context variables argument. | 966 __ popq(RAX); // Pop number of context variables argument. |
874 __ popq(RAX); // Pop the new context object. | 967 __ popq(RAX); // Pop the new context object. |
875 // RAX: new object | 968 // RAX: new object |
876 // Restore the frame pointer. | 969 // Restore the frame pointer. |
877 __ LeaveFrame(); | 970 __ LeaveFrame(); |
878 __ ret(); | 971 __ ret(); |
879 } | 972 } |
880 | 973 |
881 | 974 |
882 | |
883 | |
884 // Called for inline allocation of objects. | 975 // Called for inline allocation of objects. |
885 // Input parameters: | 976 // Input parameters: |
886 // RSP + 16 : type arguments object (only if class is parameterized). | 977 // RSP + 16 : type arguments object (only if class is parameterized). |
887 // RSP + 8 : type arguments of instantiator (only if class is parameterized). | 978 // RSP + 8 : type arguments of instantiator (only if class is parameterized). |
888 // RSP : points to return address. | 979 // RSP : points to return address. |
889 // Uses RAX, RBX, RCX, RDX, RDI as temporary registers. | 980 // Uses RAX, RBX, RCX, RDX, RDI as temporary registers. |
890 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 981 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
891 const Class& cls) { | 982 const Class& cls) { |
892 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; | 983 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; |
893 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; | 984 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1134 } | 1225 } |
1135 __ popq(RAX); // Pop the function object. | 1226 __ popq(RAX); // Pop the function object. |
1136 __ popq(RAX); // Pop the result. | 1227 __ popq(RAX); // Pop the result. |
1137 // RAX: New closure object. | 1228 // RAX: New closure object. |
1138 // Restore the calling frame. | 1229 // Restore the calling frame. |
1139 __ LeaveFrame(); | 1230 __ LeaveFrame(); |
1140 __ ret(); | 1231 __ ret(); |
1141 } | 1232 } |
1142 | 1233 |
1143 | 1234 |
| 1235 // Called for invoking noSuchMethod function from the entry code of a dart |
| 1236 // function after an error in passed named arguments is detected. |
| 1237 // Input parameters: |
| 1238 // RBP : points to previous frame pointer. |
| 1239 // RBP + 8 : points to return address. |
| 1240 // RBP + 16 : address of last argument (arg n-1). |
| 1241 // RBP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 1242 // RBX : ic-data array. |
| 1243 // R10 : arguments descriptor array. |
1144 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1244 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
1145 __ Unimplemented("CallNoSuchMethodFunction stub"); | 1245 // The target function was not found, so invoke method |
| 1246 // "void noSuchMethod(function_name, Array arguments)". |
| 1247 // TODO(regis): For now, we simply pass the actual arguments, both positional |
| 1248 // and named, as the argument array. This is not correct if out-of-order |
| 1249 // named arguments were passed. |
| 1250 // The signature of the "noSuchMethod" method has to change from |
| 1251 // noSuchMethod(String name, Array arguments) to something like |
| 1252 // noSuchMethod(InvocationMirror call). |
| 1253 // Also, the class NoSuchMethodException has to be modified accordingly. |
| 1254 // Total number of args is the first Smi in args descriptor array (R10). |
| 1255 const Immediate raw_null = |
| 1256 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1257 __ movq(R13, FieldAddress(R10, Array::data_offset())); // R13 is Smi. |
| 1258 __ movq(RAX, Address(RBP, R13, TIMES_4, kWordSize)); // Get receiver. |
| 1259 |
| 1260 __ EnterFrame(0); |
| 1261 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. |
| 1262 __ pushq(RAX); // Receiver. |
| 1263 __ pushq(RBX); // IC data array. |
| 1264 __ pushq(R10); // Arguments descriptor array. |
| 1265 __ SmiUntag(R13); |
| 1266 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. |
| 1267 // See stack layout below explaining "wordSize * 8" offset. |
| 1268 PushArgumentsArray(assembler, (kWordSize * 8)); |
| 1269 |
| 1270 // Stack: |
| 1271 // TOS + 0: Argument array. |
| 1272 // TOS + 1: Arguments descriptor array. |
| 1273 // TOS + 2: Ic-data array. |
| 1274 // TOS + 3: Receiver. |
| 1275 // TOS + 4: Place for result from noSuchMethod. |
| 1276 // TOS + 5: Saved RBP of previous frame. <== RBP |
| 1277 // TOS + 6: Dart callee (or stub) code return address |
| 1278 // TOS + 7: Saved RBP of dart caller frame. |
| 1279 // TOS + 8: Dart caller code return address |
| 1280 // TOS + 9: Last argument of caller. |
| 1281 // .... |
| 1282 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 1283 // Remove arguments. |
| 1284 __ popq(RAX); |
| 1285 __ popq(RAX); |
| 1286 __ popq(RAX); |
| 1287 __ popq(RAX); |
| 1288 __ popq(RAX); // Get result into RAX. |
| 1289 |
| 1290 // Remove the stub frame as we are about to return. |
| 1291 __ LeaveFrame(); |
| 1292 __ ret(); |
1146 } | 1293 } |
1147 | 1294 |
1148 | 1295 |
| 1296 |
1149 // Generate inline cache check for 'num_args'. | 1297 // Generate inline cache check for 'num_args'. |
1150 // RBX: Inline cache data array. | 1298 // RBX: Inline cache data array. |
1151 // R10: Arguments array. | 1299 // R10: Arguments array. |
1152 // TOS(0): return address | 1300 // TOS(0): return address |
1153 // Control flow: | 1301 // Control flow: |
1154 // - If receiver is null -> jump to IC miss. | 1302 // - If receiver is null -> jump to IC miss. |
1155 // - If receiver is Smi -> load Smi class. | 1303 // - If receiver is Smi -> load Smi class. |
1156 // - If receiver is not-Smi -> load receiver's class. | 1304 // - If receiver is not-Smi -> load receiver's class. |
1157 // - Check if 'num_args' (including receiver) match any IC data group. | 1305 // - Check if 'num_args' (including receiver) match any IC data group. |
1158 // - Match found -> jump to target. | 1306 // - Match found -> jump to target. |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 } | 1460 } |
1313 | 1461 |
1314 | 1462 |
1315 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1463 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
1316 __ Unimplemented("BreakpointDynamic stub"); | 1464 __ Unimplemented("BreakpointDynamic stub"); |
1317 } | 1465 } |
1318 | 1466 |
1319 } // namespace dart | 1467 } // namespace dart |
1320 | 1468 |
1321 #endif // defined TARGET_ARCH_X64 | 1469 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |