OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 // SP : address of last argument in argument array. | 32 // SP : address of last argument in argument array. |
33 // SP + 4*R4 - 4 : address of first argument in argument array. | 33 // SP + 4*R4 - 4 : address of first argument in argument array. |
34 // SP + 4*R4 : address of return value. | 34 // SP + 4*R4 : address of return value. |
35 // R5 : address of the runtime function to call. | 35 // R5 : address of the runtime function to call. |
36 // R4 : number of arguments to the call. | 36 // R4 : number of arguments to the call. |
37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
38 const intptr_t isolate_offset = NativeArguments::isolate_offset(); | 38 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
39 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); | 39 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); |
40 const intptr_t argv_offset = NativeArguments::argv_offset(); | 40 const intptr_t argv_offset = NativeArguments::argv_offset(); |
41 const intptr_t retval_offset = NativeArguments::retval_offset(); | 41 const intptr_t retval_offset = NativeArguments::retval_offset(); |
| 42 const intptr_t exitframe_last_param_slot_from_fp = 1; |
42 | 43 |
43 __ EnterStubFrame(); | 44 __ EnterFrame((1 << FP) | (1 << LR), 0); |
44 | 45 |
45 // Load current Isolate pointer from Context structure into R0. | 46 // Load current Isolate pointer from Context structure into R0. |
46 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); | 47 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); |
47 | 48 |
48 // Save exit frame information to enable stack walking as we are about | 49 // Save exit frame information to enable stack walking as we are about |
49 // to transition to Dart VM C++ code. | 50 // to transition to Dart VM C++ code. |
50 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset()); | 51 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset()); |
51 | 52 |
52 // Save current Context pointer into Isolate structure. | 53 // Save current Context pointer into Isolate structure. |
53 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset()); | 54 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset()); |
(...skipping 13 matching lines...) Expand all Loading... |
67 // Set isolate in NativeArgs: R0 already contains CTX. | 68 // Set isolate in NativeArgs: R0 already contains CTX. |
68 | 69 |
69 // There are no runtime calls to closures, so we do not need to set the tag | 70 // There are no runtime calls to closures, so we do not need to set the tag |
70 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. | 71 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. |
71 ASSERT(argc_tag_offset == 1 * kWordSize); | 72 ASSERT(argc_tag_offset == 1 * kWordSize); |
72 __ mov(R1, ShifterOperand(R4)); // Set argc in NativeArguments. | 73 __ mov(R1, ShifterOperand(R4)); // Set argc in NativeArguments. |
73 | 74 |
74 ASSERT(argv_offset == 2 * kWordSize); | 75 ASSERT(argv_offset == 2 * kWordSize); |
75 __ add(R2, FP, ShifterOperand(R4, LSL, 2)); // Compute argv. | 76 __ add(R2, FP, ShifterOperand(R4, LSL, 2)); // Compute argv. |
76 // Set argv in NativeArguments. | 77 // Set argv in NativeArguments. |
77 __ AddImmediate(R2, kParamEndSlotFromFp * kWordSize); | 78 __ AddImmediate(R2, exitframe_last_param_slot_from_fp * kWordSize); |
78 | 79 |
79 ASSERT(retval_offset == 3 * kWordSize); | 80 ASSERT(retval_offset == 3 * kWordSize); |
80 __ add(R3, R2, ShifterOperand(kWordSize)); // Retval is next to 1st argument. | 81 __ add(R3, R2, ShifterOperand(kWordSize)); // Retval is next to 1st argument. |
81 | 82 |
82 // Call runtime or redirection via simulator. | 83 // Call runtime or redirection via simulator. |
83 __ blx(R5); | 84 __ blx(R5); |
84 | 85 |
85 // Reset exit frame information in Isolate structure. | 86 // Reset exit frame information in Isolate structure. |
86 __ LoadImmediate(R2, 0); | 87 __ LoadImmediate(R2, 0); |
87 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset()); | 88 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset()); |
88 | 89 |
89 // Load Context pointer from Isolate structure into R2. | 90 // Load Context pointer from Isolate structure into R2. |
90 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset()); | 91 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset()); |
91 | 92 |
92 // Reset Context pointer in Isolate structure. | 93 // Reset Context pointer in Isolate structure. |
93 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); | 94 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); |
94 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset()); | 95 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset()); |
95 | 96 |
96 // Cache Context pointer into CTX while executing Dart code. | 97 // Cache Context pointer into CTX while executing Dart code. |
97 __ mov(CTX, ShifterOperand(R2)); | 98 __ mov(CTX, ShifterOperand(R2)); |
98 | 99 |
99 __ LeaveStubFrame(); | 100 __ LeaveFrame((1 << FP) | (1 << LR)); |
100 __ Ret(); | 101 __ Ret(); |
101 } | 102 } |
102 | 103 |
103 | 104 |
104 // Print the stop message. | 105 // Print the stop message. |
105 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { | 106 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { |
106 OS::Print("Stop message: %s\n", message); | 107 OS::Print("Stop message: %s\n", message); |
107 } | 108 } |
108 END_LEAF_RUNTIME_ENTRY | 109 END_LEAF_RUNTIME_ENTRY |
109 | 110 |
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 | 774 |
774 // Called when invoking Dart code from C++ (VM code). | 775 // Called when invoking Dart code from C++ (VM code). |
775 // Input parameters: | 776 // Input parameters: |
776 // LR : points to return address. | 777 // LR : points to return address. |
777 // R0 : entrypoint of the Dart function to call. | 778 // R0 : entrypoint of the Dart function to call. |
778 // R1 : arguments descriptor array. | 779 // R1 : arguments descriptor array. |
779 // R2 : arguments array. | 780 // R2 : arguments array. |
780 // R3 : new context containing the current isolate pointer. | 781 // R3 : new context containing the current isolate pointer. |
781 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | 782 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
782 // Save frame pointer coming in. | 783 // Save frame pointer coming in. |
783 __ EnterStubFrame(); | 784 __ EnterFrame((1 << FP) | (1 << LR), 0); |
784 | 785 |
785 // Save new context and C++ ABI callee-saved registers. | 786 // Save new context and C++ ABI callee-saved registers. |
786 const intptr_t kNewContextOffsetFromFp = | 787 const intptr_t kNewContextOffsetFromFp = |
787 -(1 + kAbiPreservedCpuRegCount) * kWordSize; | 788 -(1 + kAbiPreservedCpuRegCount) * kWordSize; |
788 __ PushList((1 << R3) | kAbiPreservedCpuRegs); | 789 __ PushList((1 << R3) | kAbiPreservedCpuRegs); |
789 | 790 |
790 const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg); | 791 const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg); |
791 ASSERT(2 * kAbiPreservedFpuRegCount < 16); | 792 ASSERT(2 * kAbiPreservedFpuRegCount < 16); |
792 // Save FPU registers. 2 D registers per Q register. | 793 // Save FPU registers. 2 D registers per Q register. |
793 __ vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount); | 794 __ vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount); |
794 | 795 |
| 796 // We now load the pool pointer(PP) as we are about to invoke dart code and we |
| 797 // could potentially invoke some intrinsic functions which need the PP to be |
| 798 // set up. |
| 799 __ LoadPoolPointer(); |
| 800 |
795 // The new Context structure contains a pointer to the current Isolate | 801 // The new Context structure contains a pointer to the current Isolate |
796 // structure. Cache the Context pointer in the CTX register so that it is | 802 // structure. Cache the Context pointer in the CTX register so that it is |
797 // available in generated code and calls to Isolate::Current() need not be | 803 // available in generated code and calls to Isolate::Current() need not be |
798 // done. The assumption is that this register will never be clobbered by | 804 // done. The assumption is that this register will never be clobbered by |
799 // compiled or runtime stub code. | 805 // compiled or runtime stub code. |
800 | 806 |
801 // Cache the new Context pointer into CTX while executing Dart code. | 807 // Cache the new Context pointer into CTX while executing Dart code. |
802 __ ldr(CTX, Address(R3, VMHandles::kOffsetOfRawPtrInHandle)); | 808 __ ldr(CTX, Address(R3, VMHandles::kOffsetOfRawPtrInHandle)); |
803 | 809 |
804 // Load Isolate pointer from Context structure into temporary register R8. | 810 // Load Isolate pointer from Context structure into temporary register R8. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 __ StoreToOffset(kWord, R4, CTX, Isolate::top_context_offset()); | 876 __ StoreToOffset(kWord, R4, CTX, Isolate::top_context_offset()); |
871 __ StoreToOffset(kWord, R5, CTX, Isolate::top_exit_frame_info_offset()); | 877 __ StoreToOffset(kWord, R5, CTX, Isolate::top_exit_frame_info_offset()); |
872 | 878 |
873 // Restore C++ ABI callee-saved registers. | 879 // Restore C++ ABI callee-saved registers. |
874 // Restore FPU registers. 2 D registers per Q register. | 880 // Restore FPU registers. 2 D registers per Q register. |
875 __ vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount); | 881 __ vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount); |
876 // Restore CPU registers. | 882 // Restore CPU registers. |
877 __ PopList((1 << R3) | kAbiPreservedCpuRegs); // Ignore restored R3. | 883 __ PopList((1 << R3) | kAbiPreservedCpuRegs); // Ignore restored R3. |
878 | 884 |
879 // Restore the frame pointer and return. | 885 // Restore the frame pointer and return. |
880 __ LeaveStubFrame(); | 886 __ LeaveFrame((1 << FP) | (1 << LR)); |
881 __ Ret(); | 887 __ Ret(); |
882 } | 888 } |
883 | 889 |
884 | 890 |
885 // Called for inline allocation of contexts. | 891 // Called for inline allocation of contexts. |
886 // Input: | 892 // Input: |
887 // R1: number of context variables. | 893 // R1: number of context variables. |
888 // Output: | 894 // Output: |
889 // R0: new allocated RawContext object. | 895 // R0: new allocated RawContext object. |
890 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 896 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1216 } else { | 1222 } else { |
1217 // Push null type arguments and kNoInstantiator. | 1223 // Push null type arguments and kNoInstantiator. |
1218 __ LoadImmediate(R1, Smi::RawValue(StubCode::kNoInstantiator)); | 1224 __ LoadImmediate(R1, Smi::RawValue(StubCode::kNoInstantiator)); |
1219 __ PushList((1 << R1) | (1 << R2)); | 1225 __ PushList((1 << R1) | (1 << R2)); |
1220 } | 1226 } |
1221 __ CallRuntime(kAllocateObjectRuntimeEntry, 3); // Allocate object. | 1227 __ CallRuntime(kAllocateObjectRuntimeEntry, 3); // Allocate object. |
1222 __ Drop(3); // Pop arguments. | 1228 __ Drop(3); // Pop arguments. |
1223 __ Pop(R0); // Pop result (newly allocated object). | 1229 __ Pop(R0); // Pop result (newly allocated object). |
1224 // R0: new object | 1230 // R0: new object |
1225 // Restore the frame pointer. | 1231 // Restore the frame pointer. |
1226 __ LeaveStubFrame(true); | 1232 __ LeaveStubFrame(); |
1227 __ Ret(); | 1233 __ Ret(); |
1228 } | 1234 } |
1229 | 1235 |
1230 | 1236 |
1231 // Called for inline allocation of closures. | 1237 // Called for inline allocation of closures. |
1232 // Input parameters: | 1238 // Input parameters: |
1233 // LR : return address. | 1239 // LR : return address. |
1234 // SP + 4 : receiver (null if not an implicit instance closure). | 1240 // SP + 4 : receiver (null if not an implicit instance closure). |
1235 // SP + 0 : type arguments object (null if class is no parameterized). | 1241 // SP + 0 : type arguments object (null if class is no parameterized). |
1236 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 1242 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1325 } | 1331 } |
1326 | 1332 |
1327 // Set the type arguments field in the newly allocated closure. | 1333 // Set the type arguments field in the newly allocated closure. |
1328 __ ldr(R0, Address(FP, kTypeArgumentsFPOffset)); | 1334 __ ldr(R0, Address(FP, kTypeArgumentsFPOffset)); |
1329 __ str(R0, Address(R2, Closure::type_arguments_offset())); | 1335 __ str(R0, Address(R2, Closure::type_arguments_offset())); |
1330 | 1336 |
1331 // Done allocating and initializing the instance. | 1337 // Done allocating and initializing the instance. |
1332 // R2: new object still missing its heap tag. | 1338 // R2: new object still missing its heap tag. |
1333 __ add(R0, R2, ShifterOperand(kHeapObjectTag)); | 1339 __ add(R0, R2, ShifterOperand(kHeapObjectTag)); |
1334 // R0: new object. | 1340 // R0: new object. |
1335 __ LeaveStubFrame(true); | 1341 __ LeaveStubFrame(); |
1336 __ Ret(); | 1342 __ Ret(); |
1337 | 1343 |
1338 __ Bind(&slow_case); | 1344 __ Bind(&slow_case); |
1339 } | 1345 } |
1340 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1346 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
1341 __ Push(R0); // Setup space on stack for return value. | 1347 __ Push(R0); // Setup space on stack for return value. |
1342 __ PushObject(func); | 1348 __ PushObject(func); |
1343 if (is_implicit_instance_closure) { | 1349 if (is_implicit_instance_closure) { |
1344 __ ldr(R1, Address(FP, kReceiverFPOffset)); | 1350 __ ldr(R1, Address(FP, kReceiverFPOffset)); |
1345 __ Push(R1); // Receiver. | 1351 __ Push(R1); // Receiver. |
1346 } | 1352 } |
1347 // R0: raw null. | 1353 // R0: raw null. |
1348 if (has_type_arguments) { | 1354 if (has_type_arguments) { |
1349 __ ldr(R0, Address(FP, kTypeArgumentsFPOffset)); | 1355 __ ldr(R0, Address(FP, kTypeArgumentsFPOffset)); |
1350 } | 1356 } |
1351 __ Push(R0); // Push type arguments of closure to be allocated or null. | 1357 __ Push(R0); // Push type arguments of closure to be allocated or null. |
1352 | 1358 |
1353 if (is_implicit_instance_closure) { | 1359 if (is_implicit_instance_closure) { |
1354 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry, 3); | 1360 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry, 3); |
1355 __ Drop(2); // Pop arguments (type arguments of object and receiver). | 1361 __ Drop(2); // Pop arguments (type arguments of object and receiver). |
1356 } else { | 1362 } else { |
1357 ASSERT(func.IsNonImplicitClosureFunction()); | 1363 ASSERT(func.IsNonImplicitClosureFunction()); |
1358 __ CallRuntime(kAllocateClosureRuntimeEntry, 2); | 1364 __ CallRuntime(kAllocateClosureRuntimeEntry, 2); |
1359 __ Drop(1); // Pop argument (type arguments of object). | 1365 __ Drop(1); // Pop argument (type arguments of object). |
1360 } | 1366 } |
1361 __ Drop(1); // Pop function object. | 1367 __ Drop(1); // Pop function object. |
1362 __ Pop(R0); | 1368 __ Pop(R0); |
1363 // R0: new object | 1369 // R0: new object |
1364 // Restore the frame pointer. | 1370 // Restore the frame pointer. |
1365 __ LeaveStubFrame(true); | 1371 __ LeaveStubFrame(); |
1366 __ Ret(); | 1372 __ Ret(); |
1367 } | 1373 } |
1368 | 1374 |
1369 | 1375 |
1370 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1376 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
1371 // from the entry code of a dart function after an error in passed argument | 1377 // from the entry code of a dart function after an error in passed argument |
1372 // name or number is detected. | 1378 // name or number is detected. |
1373 // Input parameters: | 1379 // Input parameters: |
1374 // LR : return address. | 1380 // LR : return address. |
1375 // SP : address of last argument. | 1381 // SP : address of last argument. |
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2074 __ ldr(temp, FieldAddress(left, Mint::value_offset() + 1 * kWordSize)); | 2080 __ ldr(temp, FieldAddress(left, Mint::value_offset() + 1 * kWordSize)); |
2075 __ ldr(IP, FieldAddress(right, Mint::value_offset() + 1 * kWordSize)); | 2081 __ ldr(IP, FieldAddress(right, Mint::value_offset() + 1 * kWordSize)); |
2076 __ cmp(temp, ShifterOperand(IP)); | 2082 __ cmp(temp, ShifterOperand(IP)); |
2077 __ b(&done); | 2083 __ b(&done); |
2078 | 2084 |
2079 __ Bind(&check_bigint); | 2085 __ Bind(&check_bigint); |
2080 __ CompareClassId(left, kBigintCid, temp); | 2086 __ CompareClassId(left, kBigintCid, temp); |
2081 __ b(&reference_compare, NE); | 2087 __ b(&reference_compare, NE); |
2082 __ CompareClassId(right, kBigintCid, temp); | 2088 __ CompareClassId(right, kBigintCid, temp); |
2083 __ b(&done, NE); | 2089 __ b(&done, NE); |
2084 __ EnterStubFrame(0); | 2090 __ EnterStubFrame(); |
2085 __ ReserveAlignedFrameSpace(2 * kWordSize); | 2091 __ ReserveAlignedFrameSpace(2 * kWordSize); |
2086 __ stm(IA, SP, (1 << R0) | (1 << R1)); | 2092 __ stm(IA, SP, (1 << R0) | (1 << R1)); |
2087 __ CallRuntime(kBigintCompareRuntimeEntry, 2); | 2093 __ CallRuntime(kBigintCompareRuntimeEntry, 2); |
2088 // Result in R0, 0 means equal. | 2094 // Result in R0, 0 means equal. |
2089 __ LeaveStubFrame(); | 2095 __ LeaveStubFrame(); |
2090 __ cmp(R0, ShifterOperand(0)); | 2096 __ cmp(R0, ShifterOperand(0)); |
2091 __ b(&done); | 2097 __ b(&done); |
2092 | 2098 |
2093 __ Bind(&reference_compare); | 2099 __ Bind(&reference_compare); |
2094 __ cmp(left, ShifterOperand(right)); | 2100 __ cmp(left, ShifterOperand(right)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2136 const Register right = R0; | 2142 const Register right = R0; |
2137 __ ldr(left, Address(SP, 1 * kWordSize)); | 2143 __ ldr(left, Address(SP, 1 * kWordSize)); |
2138 __ ldr(right, Address(SP, 0 * kWordSize)); | 2144 __ ldr(right, Address(SP, 0 * kWordSize)); |
2139 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2145 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
2140 __ Ret(); | 2146 __ Ret(); |
2141 } | 2147 } |
2142 | 2148 |
2143 } // namespace dart | 2149 } // namespace dart |
2144 | 2150 |
2145 #endif // defined TARGET_ARCH_ARM | 2151 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |