| 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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 // Reset value types if guarded_cid was used. | 1401 // Reset value types if guarded_cid was used. |
| 1402 for (Value::Iterator it(load->input_use_list()); | 1402 for (Value::Iterator it(load->input_use_list()); |
| 1403 !it.Done(); | 1403 !it.Done(); |
| 1404 it.Advance()) { | 1404 it.Advance()) { |
| 1405 it.Current()->SetReachingType(NULL); | 1405 it.Current()->SetReachingType(NULL); |
| 1406 } | 1406 } |
| 1407 } | 1407 } |
| 1408 } | 1408 } |
| 1409 | 1409 |
| 1410 | 1410 |
| 1411 void FlowGraphOptimizer::InlineGrowableArrayCapacityGetter( | |
| 1412 InstanceCallInstr* call) { | |
| 1413 AddReceiverCheck(call); | |
| 1414 | |
| 1415 // TODO(srdjan): type of load should be GrowableObjectArrayType. | |
| 1416 LoadFieldInstr* data_load = new LoadFieldInstr( | |
| 1417 new Value(call->ArgumentAt(0)), | |
| 1418 Array::data_offset(), | |
| 1419 Type::ZoneHandle(Type::DynamicType())); | |
| 1420 data_load->set_result_cid(kArrayCid); | |
| 1421 InsertBefore(call, data_load, NULL, Definition::kValue); | |
| 1422 | |
| 1423 LoadFieldInstr* length_load = new LoadFieldInstr( | |
| 1424 new Value(data_load), | |
| 1425 Array::length_offset(), | |
| 1426 Type::ZoneHandle(Type::SmiType())); | |
| 1427 length_load->set_result_cid(kSmiCid); | |
| 1428 length_load->set_recognized_kind(MethodRecognizer::kObjectArrayLength); | |
| 1429 | |
| 1430 ReplaceCall(call, length_load); | |
| 1431 } | |
| 1432 | |
| 1433 | |
| 1434 static LoadFieldInstr* BuildLoadStringLength(Definition* str) { | 1411 static LoadFieldInstr* BuildLoadStringLength(Definition* str) { |
| 1435 // Treat length loads as mutable (i.e. affected by side effects) to avoid | 1412 // Treat length loads as mutable (i.e. affected by side effects) to avoid |
| 1436 // hoisting them since we can't hoist the preceding class-check. This | 1413 // hoisting them since we can't hoist the preceding class-check. This |
| 1437 // is because of externalization of strings that affects their class-id. | 1414 // is because of externalization of strings that affects their class-id. |
| 1438 const bool is_immutable = false; | 1415 const bool is_immutable = false; |
| 1439 LoadFieldInstr* load = new LoadFieldInstr( | 1416 LoadFieldInstr* load = new LoadFieldInstr( |
| 1440 new Value(str), | 1417 new Value(str), |
| 1441 String::length_offset(), | 1418 String::length_offset(), |
| 1442 Type::ZoneHandle(Type::SmiType()), | 1419 Type::ZoneHandle(Type::SmiType()), |
| 1443 is_immutable); | 1420 is_immutable); |
| 1444 load->set_result_cid(kSmiCid); | 1421 load->set_result_cid(kSmiCid); |
| 1445 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); | 1422 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); |
| 1446 return load; | 1423 return load; |
| 1447 } | 1424 } |
| 1448 | 1425 |
| 1449 | 1426 |
| 1450 void FlowGraphOptimizer::InlineStringIsEmptyGetter(InstanceCallInstr* call) { | |
| 1451 AddReceiverCheck(call); | |
| 1452 | |
| 1453 LoadFieldInstr* load = BuildLoadStringLength(call->ArgumentAt(0)); | |
| 1454 InsertBefore(call, load, NULL, Definition::kValue); | |
| 1455 | |
| 1456 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); | |
| 1457 StrictCompareInstr* compare = | |
| 1458 new StrictCompareInstr(call->token_pos(), | |
| 1459 Token::kEQ_STRICT, | |
| 1460 new Value(load), | |
| 1461 new Value(zero)); | |
| 1462 ReplaceCall(call, compare); | |
| 1463 } | |
| 1464 | |
| 1465 | |
| 1466 void FlowGraphOptimizer::InlineObjectCid(InstanceCallInstr* call) { | |
| 1467 LoadClassIdInstr* load = new LoadClassIdInstr(new Value(call->ArgumentAt(0))); | |
| 1468 ReplaceCall(call, load); | |
| 1469 } | |
| 1470 | |
| 1471 | |
| 1472 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | 1427 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
| 1473 MethodRecognizer::Kind getter) { | 1428 MethodRecognizer::Kind getter) { |
| 1474 if (!ShouldInlineSimd()) { | 1429 if (!ShouldInlineSimd()) { |
| 1475 return false; | 1430 return false; |
| 1476 } | 1431 } |
| 1477 AddCheckClass(call->ArgumentAt(0), | 1432 AddCheckClass(call->ArgumentAt(0), |
| 1478 ICData::ZoneHandle( | 1433 ICData::ZoneHandle( |
| 1479 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1434 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
| 1480 call->deopt_id(), | 1435 call->deopt_id(), |
| 1481 call->env(), | 1436 call->env(), |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1642 } else if (target.kind() == RawFunction::kNoSuchMethodDispatcher) { | 1597 } else if (target.kind() == RawFunction::kNoSuchMethodDispatcher) { |
| 1643 return false; | 1598 return false; |
| 1644 } | 1599 } |
| 1645 | 1600 |
| 1646 // Not an implicit getter. | 1601 // Not an implicit getter. |
| 1647 MethodRecognizer::Kind recognized_kind = | 1602 MethodRecognizer::Kind recognized_kind = |
| 1648 MethodRecognizer::RecognizeKind(target); | 1603 MethodRecognizer::RecognizeKind(target); |
| 1649 | 1604 |
| 1650 // VM objects length getter. | 1605 // VM objects length getter. |
| 1651 switch (recognized_kind) { | 1606 switch (recognized_kind) { |
| 1652 case MethodRecognizer::kObjectCid: { | |
| 1653 InlineObjectCid(call); | |
| 1654 return true; | |
| 1655 } | |
| 1656 case MethodRecognizer::kGrowableArrayCapacity: | |
| 1657 InlineGrowableArrayCapacityGetter(call); | |
| 1658 return true; | |
| 1659 case MethodRecognizer::kStringBaseIsEmpty: | |
| 1660 if (!ic_data.HasOneTarget()) { | |
| 1661 // Target is not only StringBase_get_isEmpty. | |
| 1662 return false; | |
| 1663 } | |
| 1664 InlineStringIsEmptyGetter(call); | |
| 1665 return true; | |
| 1666 case MethodRecognizer::kFloat32x4ShuffleX: | 1607 case MethodRecognizer::kFloat32x4ShuffleX: |
| 1667 case MethodRecognizer::kFloat32x4ShuffleY: | 1608 case MethodRecognizer::kFloat32x4ShuffleY: |
| 1668 case MethodRecognizer::kFloat32x4ShuffleZ: | 1609 case MethodRecognizer::kFloat32x4ShuffleZ: |
| 1669 case MethodRecognizer::kFloat32x4ShuffleW: | 1610 case MethodRecognizer::kFloat32x4ShuffleW: |
| 1670 case MethodRecognizer::kFloat32x4GetSignMask: | 1611 case MethodRecognizer::kFloat32x4GetSignMask: |
| 1671 if (!ic_data.HasReceiverClassId(kFloat32x4Cid) || | 1612 if (!ic_data.HasReceiverClassId(kFloat32x4Cid) || |
| 1672 !ic_data.HasOneTarget()) { | 1613 !ic_data.HasOneTarget()) { |
| 1673 return false; | 1614 return false; |
| 1674 } | 1615 } |
| 1675 return InlineFloat32x4Getter(call, recognized_kind); | 1616 return InlineFloat32x4Getter(call, recognized_kind); |
| (...skipping 5858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7534 } | 7475 } |
| 7535 | 7476 |
| 7536 // Insert materializations at environment uses. | 7477 // Insert materializations at environment uses. |
| 7537 for (intptr_t i = 0; i < exits.length(); i++) { | 7478 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7538 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7479 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7539 } | 7480 } |
| 7540 } | 7481 } |
| 7541 | 7482 |
| 7542 | 7483 |
| 7543 } // namespace dart | 7484 } // namespace dart |
| OLD | NEW |