| 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" |
| (...skipping 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1436 TryAddTest(results, kDoubleCid, true); | 1436 TryAddTest(results, kDoubleCid, true); |
| 1437 return false; | 1437 return false; |
| 1438 } else if (type.IsDoubleType()) { | 1438 } else if (type.IsDoubleType()) { |
| 1439 ASSERT((*results)[0] == kSmiCid); | 1439 ASSERT((*results)[0] == kSmiCid); |
| 1440 TryAddTest(results, kDoubleCid, true); | 1440 TryAddTest(results, kDoubleCid, true); |
| 1441 return false; | 1441 return false; |
| 1442 } | 1442 } |
| 1443 return true; // May deoptimize since we have not identified all 'true' tests. | 1443 return true; // May deoptimize since we have not identified all 'true' tests. |
| 1444 } | 1444 } |
| 1445 | 1445 |
| 1446 // Tells whether the function of the call matches the core private name. |
| 1447 static bool matches_core(InstanceCallInstr* call, const String& name) { |
| 1448 return call->function_name().raw() == Library::PrivateCoreLibName(name).raw(); |
| 1449 } |
| 1446 | 1450 |
| 1447 // TODO(srdjan): Use ICData to check if always true or false. | 1451 // TODO(srdjan): Use ICData to check if always true or false. |
| 1448 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 1452 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
| 1449 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 1453 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
| 1450 Definition* left = call->ArgumentAt(0); | 1454 Definition* left = call->ArgumentAt(0); |
| 1451 Definition* type_args = NULL; | 1455 Definition* type_args = NULL; |
| 1452 AbstractType& type = AbstractType::ZoneHandle(Z); | 1456 AbstractType& type = AbstractType::ZoneHandle(Z); |
| 1457 bool negate = false; |
| 1453 if (call->ArgumentCount() == 2) { | 1458 if (call->ArgumentCount() == 2) { |
| 1454 type_args = flow_graph()->constant_null(); | 1459 type_args = flow_graph()->constant_null(); |
| 1455 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf())); | 1460 if (matches_core(call, Symbols::_simpleInstanceOf())) { |
| 1456 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw(); | 1461 type = |
| 1462 AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw(); |
| 1463 negate = false; // Just to be sure. |
| 1464 } else { |
| 1465 if (matches_core(call, Symbols::_instanceOfNum())) { |
| 1466 type = Type::Number(); |
| 1467 } else if (matches_core(call, Symbols::_instanceOfInt())) { |
| 1468 type = Type::IntType(); |
| 1469 } else if (matches_core(call, Symbols::_instanceOfSmi())) { |
| 1470 type = Type::SmiType(); |
| 1471 } else if (matches_core(call, Symbols::_instanceOfDouble())) { |
| 1472 type = Type::Double(); |
| 1473 } else if (matches_core(call, Symbols::_instanceOfString())) { |
| 1474 type = Type::StringType(); |
| 1475 } else { |
| 1476 UNIMPLEMENTED(); |
| 1477 } |
| 1478 negate = |
| 1479 Bool::Cast( |
| 1480 call->ArgumentAt(1)->OriginalDefinition()->AsConstant()->value()) |
| 1481 .value(); |
| 1482 } |
| 1457 } else { | 1483 } else { |
| 1458 type_args = call->ArgumentAt(1); | 1484 type_args = call->ArgumentAt(1); |
| 1459 type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw(); | 1485 type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw(); |
| 1486 negate = |
| 1487 Bool::Cast( |
| 1488 call->ArgumentAt(3)->OriginalDefinition()->AsConstant()->value()) |
| 1489 .value(); |
| 1460 } | 1490 } |
| 1461 | 1491 |
| 1462 if (TypeCheckAsClassEquality(type)) { | 1492 if (TypeCheckAsClassEquality(type)) { |
| 1463 LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left)); | 1493 LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left)); |
| 1464 InsertBefore(call, left_cid, NULL, FlowGraph::kValue); | 1494 InsertBefore(call, left_cid, NULL, FlowGraph::kValue); |
| 1465 const intptr_t type_cid = Class::Handle(Z, type.type_class()).id(); | 1495 const intptr_t type_cid = Class::Handle(Z, type.type_class()).id(); |
| 1466 ConstantInstr* cid = | 1496 ConstantInstr* cid = |
| 1467 flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(type_cid))); | 1497 flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(type_cid))); |
| 1468 | 1498 |
| 1469 StrictCompareInstr* check_cid = | 1499 StrictCompareInstr* check_cid = new (Z) StrictCompareInstr( |
| 1470 new (Z) StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT, | 1500 call->token_pos(), negate ? Token::kNE_STRICT : Token::kEQ_STRICT, |
| 1471 new (Z) Value(left_cid), new (Z) Value(cid), | 1501 new (Z) Value(left_cid), new (Z) Value(cid), |
| 1472 false); // No number check. | 1502 false); // No number check. |
| 1473 ReplaceCall(call, check_cid); | 1503 ReplaceCall(call, check_cid); |
| 1474 return; | 1504 return; |
| 1475 } | 1505 } |
| 1476 | 1506 |
| 1477 if (precompiler_ != NULL) { | 1507 if (precompiler_ != NULL) { |
| 1478 TypeRangeCache* cache = precompiler_->type_range_cache(); | 1508 TypeRangeCache* cache = precompiler_->type_range_cache(); |
| 1479 intptr_t lower_limit, upper_limit; | 1509 intptr_t lower_limit, upper_limit; |
| 1480 if (cache != NULL && | 1510 if (cache != NULL && |
| 1481 cache->InstanceOfHasClassRange(type, &lower_limit, &upper_limit)) { | 1511 cache->InstanceOfHasClassRange(type, &lower_limit, &upper_limit)) { |
| 1482 // left.instanceof(type) => | 1512 // left.instanceof(type) => |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1498 args->Add(arg); | 1528 args->Add(arg); |
| 1499 arg = new (Z) PushArgumentInstr(new (Z) Value(lower_cid)); | 1529 arg = new (Z) PushArgumentInstr(new (Z) Value(lower_cid)); |
| 1500 InsertBefore(call, arg, NULL, FlowGraph::kEffect); | 1530 InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
| 1501 args->Add(arg); | 1531 args->Add(arg); |
| 1502 arg = new (Z) PushArgumentInstr(new (Z) Value(upper_cid)); | 1532 arg = new (Z) PushArgumentInstr(new (Z) Value(upper_cid)); |
| 1503 InsertBefore(call, arg, NULL, FlowGraph::kEffect); | 1533 InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
| 1504 args->Add(arg); | 1534 args->Add(arg); |
| 1505 | 1535 |
| 1506 const Library& dart_internal = | 1536 const Library& dart_internal = |
| 1507 Library::Handle(Z, Library::InternalLibrary()); | 1537 Library::Handle(Z, Library::InternalLibrary()); |
| 1508 const String& target_name = Symbols::_classRangeCheck(); | 1538 const String& target_name = negate ? Symbols::_classRangeCheckNegative() |
| 1539 : Symbols::_classRangeCheck(); |
| 1509 const Function& target = Function::ZoneHandle( | 1540 const Function& target = Function::ZoneHandle( |
| 1510 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); | 1541 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); |
| 1511 ASSERT(!target.IsNull()); | 1542 ASSERT(!target.IsNull()); |
| 1512 ASSERT(target.IsRecognized() && target.always_inline()); | 1543 ASSERT(target.IsRecognized() && target.always_inline()); |
| 1513 | 1544 |
| 1514 StaticCallInstr* new_call = | 1545 StaticCallInstr* new_call = |
| 1515 new (Z) StaticCallInstr(call->token_pos(), target, | 1546 new (Z) StaticCallInstr(call->token_pos(), target, |
| 1516 Object::null_array(), // argument_names | 1547 Object::null_array(), // argument_names |
| 1517 args, call->deopt_id()); | 1548 args, call->deopt_id()); |
| 1518 Environment* copy = call->env()->DeepCopy( | 1549 Environment* copy = call->env()->DeepCopy( |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1533 if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) { | 1564 if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) { |
| 1534 ZoneGrowableArray<intptr_t>* results = | 1565 ZoneGrowableArray<intptr_t>* results = |
| 1535 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); | 1566 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); |
| 1536 InstanceOfAsBool(unary_checks, type, results); | 1567 InstanceOfAsBool(unary_checks, type, results); |
| 1537 if (results->length() == number_of_checks * 2) { | 1568 if (results->length() == number_of_checks * 2) { |
| 1538 const bool can_deopt = TryExpandTestCidsResult(results, type); | 1569 const bool can_deopt = TryExpandTestCidsResult(results, type); |
| 1539 if (can_deopt && !IsAllowedForInlining(call->deopt_id())) { | 1570 if (can_deopt && !IsAllowedForInlining(call->deopt_id())) { |
| 1540 // Guard against repeated speculative inlining. | 1571 // Guard against repeated speculative inlining. |
| 1541 return; | 1572 return; |
| 1542 } | 1573 } |
| 1543 TestCidsInstr* test_cids = new (Z) TestCidsInstr( | 1574 TestCidsInstr* test_cids = new (Z) |
| 1544 call->token_pos(), Token::kIS, new (Z) Value(left), *results, | 1575 TestCidsInstr(call->token_pos(), negate ? Token::kISNOT : Token::kIS, |
| 1545 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); | 1576 new (Z) Value(left), *results, |
| 1577 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); |
| 1546 // Remove type. | 1578 // Remove type. |
| 1547 ReplaceCall(call, test_cids); | 1579 ReplaceCall(call, test_cids); |
| 1548 return; | 1580 return; |
| 1549 } | 1581 } |
| 1550 } | 1582 } |
| 1551 | 1583 |
| 1552 InstanceOfInstr* instance_of = | 1584 InstanceOfInstr* instance_of = new (Z) |
| 1553 new (Z) InstanceOfInstr(call->token_pos(), new (Z) Value(left), | 1585 InstanceOfInstr(call->token_pos(), new (Z) Value(left), |
| 1554 new (Z) Value(type_args), type, call->deopt_id()); | 1586 new (Z) Value(type_args), type, negate, call->deopt_id()); |
| 1555 ReplaceCall(call, instance_of); | 1587 ReplaceCall(call, instance_of); |
| 1556 } | 1588 } |
| 1557 | 1589 |
| 1558 | 1590 |
| 1559 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). | 1591 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). |
| 1560 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 1592 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
| 1561 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 1593 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
| 1562 Definition* left = call->ArgumentAt(0); | 1594 Definition* left = call->ArgumentAt(0); |
| 1563 Definition* type_args = call->ArgumentAt(1); | 1595 Definition* type_args = call->ArgumentAt(1); |
| 1564 const AbstractType& type = | 1596 const AbstractType& type = |
| (...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2130 FlowGraph::kEffect); | 2162 FlowGraph::kEffect); |
| 2131 current_iterator()->RemoveCurrentFromGraph(); | 2163 current_iterator()->RemoveCurrentFromGraph(); |
| 2132 } | 2164 } |
| 2133 } | 2165 } |
| 2134 } | 2166 } |
| 2135 } | 2167 } |
| 2136 | 2168 |
| 2137 #endif // DART_PRECOMPILER | 2169 #endif // DART_PRECOMPILER |
| 2138 | 2170 |
| 2139 } // namespace dart | 2171 } // namespace dart |
| OLD | NEW |