Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: runtime/vm/stub_code_mips.cc

Issue 154393003: Implement eager instantiation and canonicalization of type arguments at run (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698