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_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
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" |
11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
13 #include "vm/heap.h" | 13 #include "vm/heap.h" |
14 #include "vm/instructions.h" | 14 #include "vm/instructions.h" |
15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
16 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
18 | 18 |
19 #define __ assembler-> | 19 #define __ assembler-> |
20 | 20 |
21 namespace dart { | 21 namespace dart { |
22 | 22 |
23 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); | 23 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); |
24 DEFINE_FLAG(bool, use_slow_path, false, | 24 DEFINE_FLAG(bool, use_slow_path, false, |
25 "Set to true for debugging & verifying the slow paths."); | 25 "Set to true for debugging & verifying the slow paths."); |
| 26 DECLARE_FLAG(bool, trace_optimized_ic_calls); |
26 DECLARE_FLAG(int, optimization_counter_threshold); | 27 DECLARE_FLAG(int, optimization_counter_threshold); |
27 DECLARE_FLAG(bool, trace_optimized_ic_calls); | |
28 | 28 |
29 | 29 |
30 // Input parameters: | 30 // Input parameters: |
31 // RA : return address. | 31 // RA : return address. |
32 // SP : address of last argument in argument array. | 32 // SP : address of last argument in argument array. |
33 // SP + 4*S4 - 4 : address of first argument in argument array. | 33 // SP + 4*S4 - 4 : address of first argument in argument array. |
34 // SP + 4*S4 : address of return value. | 34 // SP + 4*S4 : address of return value. |
35 // S5 : address of the runtime function to call. | 35 // S5 : address of the runtime function to call. |
36 // S4 : number of arguments to the call. | 36 // S4 : number of arguments to the call. |
37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
(...skipping 1257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1295 // The generated code is different if the class is parameterized. | 1295 // The generated code is different if the class is parameterized. |
1296 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; | 1296 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; |
1297 ASSERT(!is_cls_parameterized || | 1297 ASSERT(!is_cls_parameterized || |
1298 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); | 1298 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); |
1299 // kInlineInstanceSize is a constant used as a threshold for determining | 1299 // kInlineInstanceSize is a constant used as a threshold for determining |
1300 // when the object initialization should be done as a loop or as | 1300 // when the object initialization should be done as a loop or as |
1301 // straight line code. | 1301 // straight line code. |
1302 const int kInlineInstanceSize = 12; | 1302 const int kInlineInstanceSize = 12; |
1303 const intptr_t instance_size = cls.instance_size(); | 1303 const intptr_t instance_size = cls.instance_size(); |
1304 ASSERT(instance_size > 0); | 1304 ASSERT(instance_size > 0); |
1305 const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize(); | 1305 Label slow_case_with_type_arguments; |
1306 if (FLAG_inline_alloc && | 1306 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) { |
1307 Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) { | 1307 Label slow_case_reload_type_arguments; |
1308 Label slow_case; | 1308 if (is_cls_parameterized) { |
| 1309 // Instantiation of the type arguments vector is only required if an |
| 1310 // instantiator is provided (not kNoInstantiator, but may be null). |
| 1311 __ lw(T1, Address(SP, 1 * kWordSize)); |
| 1312 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 1313 // R1: type arguments, instantiated or not. |
| 1314 // R0: instantiator type arguments or kNoInstantiator. |
| 1315 Label type_arguments_ready; |
| 1316 __ BranchEqual(T0, Smi::RawValue(StubCode::kNoInstantiator), |
| 1317 &type_arguments_ready); |
| 1318 // Lookup instantiator EDI in instantiations array of type arguments EDX |
| 1319 // and, if found, use cached instantiated type arguments. |
| 1320 __ lw(T2, FieldAddress(T1, TypeArguments::instantiations_offset())); |
| 1321 __ lw(T3, FieldAddress(T2, Array::length_offset())); |
| 1322 __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag); |
| 1323 __ sll(TMP, T3, 1); // T3 is Smi. |
| 1324 __ addu(T3, T2, TMP); |
| 1325 Label loop, found; |
| 1326 __ Bind(&loop); |
| 1327 __ BranchUnsignedGreaterEqual(T2, T3, &slow_case_reload_type_arguments); |
| 1328 __ lw(T1, Address(T2, 0 * kWordSize)); // Cached instantiator. |
| 1329 __ beq(T1, T0, &found); |
| 1330 __ BranchEqual(T1, Smi::RawValue(StubCode::kNoInstantiator), |
| 1331 &slow_case_reload_type_arguments); |
| 1332 __ b(&loop); |
| 1333 __ delay_slot()->addiu(T2, T2, Immediate(2 * kWordSize)); |
| 1334 __ Bind(&found); |
| 1335 __ lw(T1, Address(T2, 1 * kWordSize)); // Cached instantiated args. |
| 1336 __ LoadImmediate(T0, Smi::RawValue(StubCode::kNoInstantiator)); |
| 1337 __ Bind(&type_arguments_ready); |
| 1338 // T0: instantiated type arguments. |
| 1339 // T1: kNoInstantiator. |
| 1340 } |
| 1341 // Allocate the object and update top to point to |
| 1342 // next object start and initialize the allocated object. |
| 1343 // T0: instantiated type arguments (if is_cls_parameterized). |
| 1344 // T1: kNoInstantiator (if is_cls_parameterized). |
1309 Heap* heap = Isolate::Current()->heap(); | 1345 Heap* heap = Isolate::Current()->heap(); |
1310 __ LoadImmediate(T5, heap->TopAddress()); | 1346 __ LoadImmediate(T5, heap->TopAddress()); |
1311 __ lw(T2, Address(T5)); | 1347 __ lw(T2, Address(T5)); |
1312 __ LoadImmediate(T4, instance_size); | 1348 __ LoadImmediate(T4, instance_size); |
1313 __ addu(T3, T2, T4); | 1349 __ addu(T3, T2, T4); |
1314 if (is_cls_parameterized) { | |
1315 Label no_instantiator; | |
1316 __ lw(T1, Address(SP, 1 * kWordSize)); | |
1317 __ lw(T0, Address(SP, 0 * kWordSize)); | |
1318 // A new InstantiatedTypeArguments object only needs to be allocated if | |
1319 // the instantiator is provided (not kNoInstantiator, but may be null). | |
1320 __ BranchEqual(T0, Smi::RawValue(StubCode::kNoInstantiator), | |
1321 &no_instantiator); | |
1322 __ delay_slot()->mov(T4, T3); | |
1323 __ AddImmediate(T3, type_args_size); | |
1324 __ Bind(&no_instantiator); | |
1325 // T4: potential new object end and, if T4 != T3, potential new | |
1326 // InstantiatedTypeArguments object start. | |
1327 } | |
1328 // Check if the allocation fits into the remaining space. | 1350 // Check if the allocation fits into the remaining space. |
1329 // T2: potential new object start. | 1351 // T2: potential new object start. |
1330 // T3: potential next object start. | 1352 // T3: potential next object start. |
1331 __ LoadImmediate(TMP, heap->EndAddress()); | 1353 __ LoadImmediate(TMP, heap->EndAddress()); |
1332 __ lw(CMPRES1, Address(TMP)); | 1354 __ lw(CMPRES1, Address(TMP)); |
1333 if (FLAG_use_slow_path) { | 1355 if (FLAG_use_slow_path) { |
1334 __ b(&slow_case); | 1356 __ b(&slow_case_with_type_arguments); |
1335 } else { | 1357 } else { |
1336 __ BranchUnsignedGreaterEqual(T3, CMPRES1, &slow_case); | 1358 __ BranchUnsignedGreaterEqual(T3, CMPRES1, |
| 1359 &slow_case_with_type_arguments); |
1337 } | 1360 } |
1338 | |
1339 // Successfully allocated the object(s), now update top to point to | 1361 // Successfully allocated the object(s), now update top to point to |
1340 // next object start and initialize the object. | 1362 // next object start and initialize the object. |
1341 __ sw(T3, Address(T5)); | 1363 __ sw(T3, Address(T5)); |
1342 | 1364 __ UpdateAllocationStats(cls.id(), T5); |
1343 if (is_cls_parameterized) { | |
1344 // Initialize the type arguments field in the object. | |
1345 // T2: new object start. | |
1346 // T4: potential new object end and, if T4 != T3, potential new | |
1347 // InstantiatedTypeArguments object start. | |
1348 // T3: next object start. | |
1349 Label type_arguments_ready; | |
1350 __ beq(T4, T3, &type_arguments_ready); | |
1351 // Initialize InstantiatedTypeArguments object at T4. | |
1352 __ sw(T1, Address(T4, | |
1353 InstantiatedTypeArguments::uninstantiated_type_arguments_offset())); | |
1354 __ sw(T0, Address(T4, | |
1355 InstantiatedTypeArguments::instantiator_type_arguments_offset())); | |
1356 const Class& ita_cls = | |
1357 Class::ZoneHandle(Object::instantiated_type_arguments_class()); | |
1358 // Set the tags. | |
1359 uword tags = 0; | |
1360 tags = RawObject::SizeTag::update(type_args_size, tags); | |
1361 tags = RawObject::ClassIdTag::update(ita_cls.id(), tags); | |
1362 __ LoadImmediate(T0, tags); | |
1363 __ sw(T0, Address(T4, Instance::tags_offset())); | |
1364 // Set the new InstantiatedTypeArguments object (T4) as the type | |
1365 // arguments (T1) of the new object (T2). | |
1366 __ addiu(T1, T4, Immediate(kHeapObjectTag)); | |
1367 // Set T3 to new object end. | |
1368 __ mov(T3, T4); | |
1369 __ Bind(&type_arguments_ready); | |
1370 // T2: new object. | |
1371 // T1: new object type arguments. | |
1372 } | |
1373 | 1365 |
1374 // T2: new object start. | 1366 // T2: new object start. |
1375 // T3: next object start. | 1367 // T3: next object start. |
1376 // T1: new object type arguments (if is_cls_parameterized). | 1368 // T1: new object type arguments (if is_cls_parameterized). |
1377 // Set the tags. | 1369 // Set the tags. |
1378 uword tags = 0; | 1370 uword tags = 0; |
1379 tags = RawObject::SizeTag::update(instance_size, tags); | 1371 tags = RawObject::SizeTag::update(instance_size, tags); |
1380 ASSERT(cls.id() != kIllegalCid); | 1372 ASSERT(cls.id() != kIllegalCid); |
1381 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1373 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
1382 __ LoadImmediate(T0, tags); | 1374 __ LoadImmediate(T0, tags); |
(...skipping 27 matching lines...) Expand all Loading... |
1410 __ addiu(T4, T4, Immediate(kWordSize)); | 1402 __ addiu(T4, T4, Immediate(kWordSize)); |
1411 __ bne(T4, T3, &loop); | 1403 __ bne(T4, T3, &loop); |
1412 __ delay_slot()->sw(T7, Address(T4, -kWordSize)); | 1404 __ delay_slot()->sw(T7, Address(T4, -kWordSize)); |
1413 __ Bind(&loop_exit); | 1405 __ Bind(&loop_exit); |
1414 } | 1406 } |
1415 if (is_cls_parameterized) { | 1407 if (is_cls_parameterized) { |
1416 // R1: new object type arguments. | 1408 // R1: new object type arguments. |
1417 // Set the type arguments in the new object. | 1409 // Set the type arguments in the new object. |
1418 __ sw(T1, Address(T2, cls.type_arguments_field_offset())); | 1410 __ sw(T1, Address(T2, cls.type_arguments_field_offset())); |
1419 } | 1411 } |
1420 __ UpdateAllocationStats(cls.id(), T5); | |
1421 // Done allocating and initializing the instance. | 1412 // Done allocating and initializing the instance. |
1422 // T2: new object still missing its heap tag. | 1413 // T2: new object still missing its heap tag. |
1423 __ Ret(); | 1414 __ Ret(); |
1424 __ delay_slot()->addiu(V0, T2, Immediate(kHeapObjectTag)); | 1415 __ delay_slot()->addiu(V0, T2, Immediate(kHeapObjectTag)); |
1425 | 1416 |
1426 __ Bind(&slow_case); | 1417 __ Bind(&slow_case_reload_type_arguments); |
1427 } | 1418 } |
1428 if (is_cls_parameterized) { | 1419 if (is_cls_parameterized) { |
1429 __ lw(T1, Address(SP, 1 * kWordSize)); | 1420 __ lw(T1, Address(SP, 1 * kWordSize)); |
1430 __ lw(T0, Address(SP, 0 * kWordSize)); | 1421 __ lw(T0, Address(SP, 0 * kWordSize)); |
1431 } | 1422 } |
| 1423 __ Bind(&slow_case_with_type_arguments); |
| 1424 // If is_cls_parameterized: |
| 1425 // T1: new object type arguments (instantiated or not). |
| 1426 // T0: instantiator type arguments or kNoInstantiator. |
1432 // Create a stub frame as we are pushing some objects on the stack before | 1427 // Create a stub frame as we are pushing some objects on the stack before |
1433 // calling into the runtime. | 1428 // calling into the runtime. |
1434 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. | 1429 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. |
1435 __ LoadObject(TMP, cls); | 1430 __ LoadObject(TMP, cls); |
1436 | 1431 |
1437 __ addiu(SP, SP, Immediate(-4 * kWordSize)); | 1432 __ addiu(SP, SP, Immediate(-4 * kWordSize)); |
1438 // Space on stack for return value. | 1433 // Space on stack for return value. |
1439 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null())); | 1434 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null())); |
1440 __ sw(T7, Address(SP, 3 * kWordSize)); | 1435 __ sw(T7, Address(SP, 3 * kWordSize)); |
1441 __ sw(TMP, Address(SP, 2 * kWordSize)); // Class of object to be allocated. | 1436 __ sw(TMP, Address(SP, 2 * kWordSize)); // Class of object to be allocated. |
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2138 // A0: instance (must be preserved). | 2133 // A0: instance (must be preserved). |
2139 // A1: instantiator type arguments or NULL. | 2134 // A1: instantiator type arguments or NULL. |
2140 // A2: cache array. | 2135 // A2: cache array. |
2141 // Result in V0: null -> not found, otherwise result (true or false). | 2136 // Result in V0: null -> not found, otherwise result (true or false). |
2142 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 2137 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
2143 __ TraceSimMsg("SubtypeNTestCacheStub"); | 2138 __ TraceSimMsg("SubtypeNTestCacheStub"); |
2144 ASSERT((1 <= n) && (n <= 3)); | 2139 ASSERT((1 <= n) && (n <= 3)); |
2145 if (n > 1) { | 2140 if (n > 1) { |
2146 // Get instance type arguments. | 2141 // Get instance type arguments. |
2147 __ LoadClass(T0, A0); | 2142 __ LoadClass(T0, A0); |
2148 // Compute instance type arguments into R4. | 2143 // Compute instance type arguments into T1. |
2149 Label has_no_type_arguments; | 2144 Label has_no_type_arguments; |
| 2145 __ LoadImmediate(T1, reinterpret_cast<intptr_t>(Object::null())); |
2150 __ lw(T2, FieldAddress(T0, | 2146 __ lw(T2, FieldAddress(T0, |
2151 Class::type_arguments_field_offset_in_words_offset())); | 2147 Class::type_arguments_field_offset_in_words_offset())); |
2152 __ BranchEqual(T2, Class::kNoTypeArguments, &has_no_type_arguments); | 2148 __ BranchEqual(T2, Class::kNoTypeArguments, &has_no_type_arguments); |
2153 __ sll(T2, T2, 2); | 2149 __ sll(T2, T2, 2); |
2154 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4 | 2150 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4 |
2155 __ lw(T1, FieldAddress(T2, 0)); | 2151 __ lw(T1, FieldAddress(T2, 0)); |
2156 __ Bind(&has_no_type_arguments); | 2152 __ Bind(&has_no_type_arguments); |
2157 } | 2153 } |
2158 __ LoadClassId(T0, A0); | 2154 __ LoadClassId(T0, A0); |
2159 // A0: instance. | 2155 // A0: instance. |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2428 const Register right = T0; | 2424 const Register right = T0; |
2429 __ lw(left, Address(SP, 1 * kWordSize)); | 2425 __ lw(left, Address(SP, 1 * kWordSize)); |
2430 __ lw(right, Address(SP, 0 * kWordSize)); | 2426 __ lw(right, Address(SP, 0 * kWordSize)); |
2431 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2427 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
2432 __ Ret(); | 2428 __ Ret(); |
2433 } | 2429 } |
2434 | 2430 |
2435 } // namespace dart | 2431 } // namespace dart |
2436 | 2432 |
2437 #endif // defined TARGET_ARCH_MIPS | 2433 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |