| 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/aot_optimizer.h" | 5 #include "vm/aot_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| 11 #include "vm/cpu.h" | 11 #include "vm/cpu.h" |
| 12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
| 13 #include "vm/exceptions.h" | 13 #include "vm/exceptions.h" |
| 14 #include "vm/flow_graph_builder.h" | 14 #include "vm/flow_graph_builder.h" |
| 15 #include "vm/flow_graph_compiler.h" | 15 #include "vm/flow_graph_compiler.h" |
| 16 #include "vm/flow_graph_inliner.h" | 16 #include "vm/flow_graph_inliner.h" |
| 17 #include "vm/flow_graph_range_analysis.h" | 17 #include "vm/flow_graph_range_analysis.h" |
| 18 #include "vm/hash_map.h" | 18 #include "vm/hash_map.h" |
| 19 #include "vm/il_printer.h" | 19 #include "vm/il_printer.h" |
| 20 #include "vm/intermediate_language.h" |
| 20 #include "vm/jit_optimizer.h" | 21 #include "vm/jit_optimizer.h" |
| 21 #include "vm/intermediate_language.h" | |
| 22 #include "vm/object.h" | 22 #include "vm/object.h" |
| 23 #include "vm/object_store.h" | 23 #include "vm/object_store.h" |
| 24 #include "vm/optimizer.h" |
| 24 #include "vm/parser.h" | 25 #include "vm/parser.h" |
| 25 #include "vm/precompiler.h" | 26 #include "vm/precompiler.h" |
| 26 #include "vm/resolver.h" | 27 #include "vm/resolver.h" |
| 27 #include "vm/scopes.h" | 28 #include "vm/scopes.h" |
| 28 #include "vm/stack_frame.h" | 29 #include "vm/stack_frame.h" |
| 29 #include "vm/symbols.h" | 30 #include "vm/symbols.h" |
| 30 | 31 |
| 31 namespace dart { | 32 namespace dart { |
| 32 | 33 |
| 33 DEFINE_FLAG(int, | 34 DEFINE_FLAG(int, |
| (...skipping 1307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1341 const TypeArguments& type_arguments = | 1342 const TypeArguments& type_arguments = |
| 1342 TypeArguments::Handle(type.arguments()); | 1343 TypeArguments::Handle(type.arguments()); |
| 1343 const bool is_raw_type = type_arguments.IsNull() || | 1344 const bool is_raw_type = type_arguments.IsNull() || |
| 1344 type_arguments.IsRaw(from_index, num_type_params); | 1345 type_arguments.IsRaw(from_index, num_type_params); |
| 1345 return is_raw_type; | 1346 return is_raw_type; |
| 1346 } | 1347 } |
| 1347 return true; | 1348 return true; |
| 1348 } | 1349 } |
| 1349 | 1350 |
| 1350 | 1351 |
| 1351 static bool CidTestResultsContains(const ZoneGrowableArray<intptr_t>& results, | |
| 1352 intptr_t test_cid) { | |
| 1353 for (intptr_t i = 0; i < results.length(); i += 2) { | |
| 1354 if (results[i] == test_cid) return true; | |
| 1355 } | |
| 1356 return false; | |
| 1357 } | |
| 1358 | |
| 1359 | |
| 1360 static void TryAddTest(ZoneGrowableArray<intptr_t>* results, | |
| 1361 intptr_t test_cid, | |
| 1362 bool result) { | |
| 1363 if (!CidTestResultsContains(*results, test_cid)) { | |
| 1364 results->Add(test_cid); | |
| 1365 results->Add(result); | |
| 1366 } | |
| 1367 } | |
| 1368 | |
| 1369 | |
| 1370 // Tries to add cid tests to 'results' so that no deoptimization is | |
| 1371 // necessary. | |
| 1372 // TODO(srdjan): Do also for other than 'int' type. | |
| 1373 static bool TryExpandTestCidsResult(ZoneGrowableArray<intptr_t>* results, | |
| 1374 const AbstractType& type) { | |
| 1375 ASSERT(results->length() >= 2); // At least on entry. | |
| 1376 const ClassTable& class_table = *Isolate::Current()->class_table(); | |
| 1377 if ((*results)[0] != kSmiCid) { | |
| 1378 const Class& cls = Class::Handle(class_table.At(kSmiCid)); | |
| 1379 const Class& type_class = Class::Handle(type.type_class()); | |
| 1380 const bool smi_is_subtype = | |
| 1381 cls.IsSubtypeOf(Object::null_type_arguments(), type_class, | |
| 1382 Object::null_type_arguments(), NULL, NULL, Heap::kOld); | |
| 1383 results->Add((*results)[results->length() - 2]); | |
| 1384 results->Add((*results)[results->length() - 2]); | |
| 1385 for (intptr_t i = results->length() - 3; i > 1; --i) { | |
| 1386 (*results)[i] = (*results)[i - 2]; | |
| 1387 } | |
| 1388 (*results)[0] = kSmiCid; | |
| 1389 (*results)[1] = smi_is_subtype; | |
| 1390 } | |
| 1391 | |
| 1392 ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded()); | |
| 1393 ASSERT(results->length() >= 2); | |
| 1394 if (type.IsSmiType()) { | |
| 1395 ASSERT((*results)[0] == kSmiCid); | |
| 1396 return false; | |
| 1397 } else if (type.IsIntType()) { | |
| 1398 ASSERT((*results)[0] == kSmiCid); | |
| 1399 TryAddTest(results, kMintCid, true); | |
| 1400 TryAddTest(results, kBigintCid, true); | |
| 1401 // Cannot deoptimize since all tests returning true have been added. | |
| 1402 return false; | |
| 1403 } else if (type.IsNumberType()) { | |
| 1404 ASSERT((*results)[0] == kSmiCid); | |
| 1405 TryAddTest(results, kMintCid, true); | |
| 1406 TryAddTest(results, kBigintCid, true); | |
| 1407 TryAddTest(results, kDoubleCid, true); | |
| 1408 return false; | |
| 1409 } else if (type.IsDoubleType()) { | |
| 1410 ASSERT((*results)[0] == kSmiCid); | |
| 1411 TryAddTest(results, kDoubleCid, true); | |
| 1412 return false; | |
| 1413 } | |
| 1414 return true; // May deoptimize since we have not identified all 'true' tests. | |
| 1415 } | |
| 1416 | |
| 1417 | |
| 1418 // TODO(srdjan): Use ICData to check if always true or false. | 1352 // TODO(srdjan): Use ICData to check if always true or false. |
| 1419 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 1353 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
| 1420 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 1354 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
| 1421 Definition* left = call->ArgumentAt(0); | 1355 Definition* left = call->ArgumentAt(0); |
| 1422 Definition* instantiator_type_args = NULL; | 1356 Definition* instantiator_type_args = NULL; |
| 1423 Definition* function_type_args = NULL; | 1357 Definition* function_type_args = NULL; |
| 1424 AbstractType& type = AbstractType::ZoneHandle(Z); | 1358 AbstractType& type = AbstractType::ZoneHandle(Z); |
| 1425 ASSERT(call->type_args_len() == 0); | 1359 ASSERT(call->type_args_len() == 0); |
| 1426 if (call->ArgumentCount() == 2) { | 1360 if (call->ArgumentCount() == 2) { |
| 1427 instantiator_type_args = flow_graph()->constant_null(); | 1361 instantiator_type_args = flow_graph()->constant_null(); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1504 } | 1438 } |
| 1505 | 1439 |
| 1506 const ICData& unary_checks = | 1440 const ICData& unary_checks = |
| 1507 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 1441 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 1508 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); | 1442 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
| 1509 if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) { | 1443 if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) { |
| 1510 ZoneGrowableArray<intptr_t>* results = | 1444 ZoneGrowableArray<intptr_t>* results = |
| 1511 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); | 1445 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); |
| 1512 InstanceOfAsBool(unary_checks, type, results); | 1446 InstanceOfAsBool(unary_checks, type, results); |
| 1513 if (results->length() == number_of_checks * 2) { | 1447 if (results->length() == number_of_checks * 2) { |
| 1514 const bool can_deopt = TryExpandTestCidsResult(results, type); | 1448 const bool can_deopt = |
| 1449 Optimizer::SpecializeTestCidsForNumericTypes(results, type); |
| 1515 if (can_deopt && !IsAllowedForInlining(call->deopt_id())) { | 1450 if (can_deopt && !IsAllowedForInlining(call->deopt_id())) { |
| 1516 // Guard against repeated speculative inlining. | 1451 // Guard against repeated speculative inlining. |
| 1517 return; | 1452 return; |
| 1518 } | 1453 } |
| 1519 TestCidsInstr* test_cids = new (Z) TestCidsInstr( | 1454 TestCidsInstr* test_cids = new (Z) TestCidsInstr( |
| 1520 call->token_pos(), Token::kIS, new (Z) Value(left), *results, | 1455 call->token_pos(), Token::kIS, new (Z) Value(left), *results, |
| 1521 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); | 1456 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); |
| 1522 // Remove type. | 1457 // Remove type. |
| 1523 ReplaceCall(call, test_cids); | 1458 ReplaceCall(call, test_cids); |
| 1524 return; | 1459 return; |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2198 FlowGraph::kEffect); | 2133 FlowGraph::kEffect); |
| 2199 current_iterator()->RemoveCurrentFromGraph(); | 2134 current_iterator()->RemoveCurrentFromGraph(); |
| 2200 } | 2135 } |
| 2201 } | 2136 } |
| 2202 } | 2137 } |
| 2203 } | 2138 } |
| 2204 | 2139 |
| 2205 #endif // DART_PRECOMPILER | 2140 #endif // DART_PRECOMPILER |
| 2206 | 2141 |
| 2207 } // namespace dart | 2142 } // namespace dart |
| OLD | NEW |