| 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 1326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 // Reset value types if guarded_cid was used. | 1337 // Reset value types if guarded_cid was used. |
| 1338 for (Value::Iterator it(load->input_use_list()); | 1338 for (Value::Iterator it(load->input_use_list()); |
| 1339 !it.Done(); | 1339 !it.Done(); |
| 1340 it.Advance()) { | 1340 it.Advance()) { |
| 1341 it.Current()->SetReachingType(NULL); | 1341 it.Current()->SetReachingType(NULL); |
| 1342 } | 1342 } |
| 1343 } | 1343 } |
| 1344 } | 1344 } |
| 1345 | 1345 |
| 1346 | 1346 |
| 1347 void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call, | |
| 1348 intptr_t length_offset, | |
| 1349 bool is_immutable, | |
| 1350 MethodRecognizer::Kind kind) { | |
| 1351 AddReceiverCheck(call); | |
| 1352 | |
| 1353 LoadFieldInstr* load = new LoadFieldInstr( | |
| 1354 new Value(call->ArgumentAt(0)), | |
| 1355 length_offset, | |
| 1356 Type::ZoneHandle(Type::SmiType()), | |
| 1357 is_immutable); | |
| 1358 load->set_result_cid(kSmiCid); | |
| 1359 load->set_recognized_kind(kind); | |
| 1360 ReplaceCall(call, load); | |
| 1361 } | |
| 1362 | |
| 1363 | |
| 1364 void FlowGraphOptimizer::InlineGrowableArrayCapacityGetter( | 1347 void FlowGraphOptimizer::InlineGrowableArrayCapacityGetter( |
| 1365 InstanceCallInstr* call) { | 1348 InstanceCallInstr* call) { |
| 1366 AddReceiverCheck(call); | 1349 AddReceiverCheck(call); |
| 1367 | 1350 |
| 1368 // TODO(srdjan): type of load should be GrowableObjectArrayType. | 1351 // TODO(srdjan): type of load should be GrowableObjectArrayType. |
| 1369 LoadFieldInstr* data_load = new LoadFieldInstr( | 1352 LoadFieldInstr* data_load = new LoadFieldInstr( |
| 1370 new Value(call->ArgumentAt(0)), | 1353 new Value(call->ArgumentAt(0)), |
| 1371 Array::data_offset(), | 1354 Array::data_offset(), |
| 1372 Type::ZoneHandle(Type::DynamicType())); | 1355 Type::ZoneHandle(Type::DynamicType())); |
| 1373 data_load->set_result_cid(kArrayCid); | 1356 data_load->set_result_cid(kArrayCid); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1393 new Value(str), | 1376 new Value(str), |
| 1394 String::length_offset(), | 1377 String::length_offset(), |
| 1395 Type::ZoneHandle(Type::SmiType()), | 1378 Type::ZoneHandle(Type::SmiType()), |
| 1396 is_immutable); | 1379 is_immutable); |
| 1397 load->set_result_cid(kSmiCid); | 1380 load->set_result_cid(kSmiCid); |
| 1398 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); | 1381 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); |
| 1399 return load; | 1382 return load; |
| 1400 } | 1383 } |
| 1401 | 1384 |
| 1402 | 1385 |
| 1403 void FlowGraphOptimizer::InlineStringLengthGetter(InstanceCallInstr* call) { | |
| 1404 AddReceiverCheck(call); | |
| 1405 LoadFieldInstr* load = BuildLoadStringLength(call->ArgumentAt(0)); | |
| 1406 ReplaceCall(call, load); | |
| 1407 } | |
| 1408 | |
| 1409 | |
| 1410 void FlowGraphOptimizer::InlineStringIsEmptyGetter(InstanceCallInstr* call) { | 1386 void FlowGraphOptimizer::InlineStringIsEmptyGetter(InstanceCallInstr* call) { |
| 1411 AddReceiverCheck(call); | 1387 AddReceiverCheck(call); |
| 1412 | 1388 |
| 1413 LoadFieldInstr* load = BuildLoadStringLength(call->ArgumentAt(0)); | 1389 LoadFieldInstr* load = BuildLoadStringLength(call->ArgumentAt(0)); |
| 1414 InsertBefore(call, load, NULL, Definition::kValue); | 1390 InsertBefore(call, load, NULL, Definition::kValue); |
| 1415 | 1391 |
| 1416 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); | 1392 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); |
| 1417 StrictCompareInstr* compare = | 1393 StrictCompareInstr* compare = |
| 1418 new StrictCompareInstr(call->token_pos(), | 1394 new StrictCompareInstr(call->token_pos(), |
| 1419 Token::kEQ_STRICT, | 1395 Token::kEQ_STRICT, |
| 1420 new Value(load), | 1396 new Value(load), |
| 1421 new Value(zero)); | 1397 new Value(zero)); |
| 1422 ReplaceCall(call, compare); | 1398 ReplaceCall(call, compare); |
| 1423 } | 1399 } |
| 1424 | 1400 |
| 1425 | 1401 |
| 1426 void FlowGraphOptimizer::InlineObjectCid(InstanceCallInstr* call) { | 1402 void FlowGraphOptimizer::InlineObjectCid(InstanceCallInstr* call) { |
| 1427 LoadClassIdInstr* load = new LoadClassIdInstr(new Value(call->ArgumentAt(0))); | 1403 LoadClassIdInstr* load = new LoadClassIdInstr(new Value(call->ArgumentAt(0))); |
| 1428 ReplaceCall(call, load); | 1404 ReplaceCall(call, load); |
| 1429 } | 1405 } |
| 1430 | 1406 |
| 1431 | 1407 |
| 1432 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) { | |
| 1433 switch (kind) { | |
| 1434 case MethodRecognizer::kObjectArrayLength: | |
| 1435 case MethodRecognizer::kImmutableArrayLength: | |
| 1436 return Array::length_offset(); | |
| 1437 case MethodRecognizer::kTypedDataLength: | |
| 1438 // .length is defined in _TypedList which is the base class for internal | |
| 1439 // and external typed data. | |
| 1440 ASSERT(TypedData::length_offset() == ExternalTypedData::length_offset()); | |
| 1441 return TypedData::length_offset(); | |
| 1442 case MethodRecognizer::kGrowableArrayLength: | |
| 1443 return GrowableObjectArray::length_offset(); | |
| 1444 default: | |
| 1445 UNREACHABLE(); | |
| 1446 return 0; | |
| 1447 } | |
| 1448 } | |
| 1449 | |
| 1450 | |
| 1451 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | 1408 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
| 1452 MethodRecognizer::Kind getter) { | 1409 MethodRecognizer::Kind getter) { |
| 1453 if (!ShouldInlineSimd()) { | 1410 if (!ShouldInlineSimd()) { |
| 1454 return false; | 1411 return false; |
| 1455 } | 1412 } |
| 1456 AddCheckClass(call->ArgumentAt(0), | 1413 AddCheckClass(call->ArgumentAt(0), |
| 1457 ICData::ZoneHandle( | 1414 ICData::ZoneHandle( |
| 1458 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1415 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
| 1459 call->deopt_id(), | 1416 call->deopt_id(), |
| 1460 call->env(), | 1417 call->env(), |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 // Not an implicit getter. | 1547 // Not an implicit getter. |
| 1591 MethodRecognizer::Kind recognized_kind = | 1548 MethodRecognizer::Kind recognized_kind = |
| 1592 MethodRecognizer::RecognizeKind(target); | 1549 MethodRecognizer::RecognizeKind(target); |
| 1593 | 1550 |
| 1594 // VM objects length getter. | 1551 // VM objects length getter. |
| 1595 switch (recognized_kind) { | 1552 switch (recognized_kind) { |
| 1596 case MethodRecognizer::kObjectCid: { | 1553 case MethodRecognizer::kObjectCid: { |
| 1597 InlineObjectCid(call); | 1554 InlineObjectCid(call); |
| 1598 return true; | 1555 return true; |
| 1599 } | 1556 } |
| 1600 case MethodRecognizer::kObjectArrayLength: | |
| 1601 case MethodRecognizer::kImmutableArrayLength: | |
| 1602 case MethodRecognizer::kTypedDataLength: | |
| 1603 case MethodRecognizer::kGrowableArrayLength: { | |
| 1604 if (!ic_data.HasOneTarget()) { | |
| 1605 // TODO(srdjan): Implement for mutiple targets. | |
| 1606 return false; | |
| 1607 } | |
| 1608 const bool is_immutable = | |
| 1609 (recognized_kind == MethodRecognizer::kObjectArrayLength) || | |
| 1610 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || | |
| 1611 (recognized_kind == MethodRecognizer::kTypedDataLength); | |
| 1612 InlineArrayLengthGetter(call, | |
| 1613 OffsetForLengthGetter(recognized_kind), | |
| 1614 is_immutable, | |
| 1615 recognized_kind); | |
| 1616 return true; | |
| 1617 } | |
| 1618 case MethodRecognizer::kGrowableArrayCapacity: | 1557 case MethodRecognizer::kGrowableArrayCapacity: |
| 1619 InlineGrowableArrayCapacityGetter(call); | 1558 InlineGrowableArrayCapacityGetter(call); |
| 1620 return true; | 1559 return true; |
| 1621 case MethodRecognizer::kStringBaseLength: | |
| 1622 if (!ic_data.HasOneTarget()) { | |
| 1623 // Target is not only StringBase_get_length. | |
| 1624 return false; | |
| 1625 } | |
| 1626 InlineStringLengthGetter(call); | |
| 1627 return true; | |
| 1628 case MethodRecognizer::kStringBaseIsEmpty: | 1560 case MethodRecognizer::kStringBaseIsEmpty: |
| 1629 if (!ic_data.HasOneTarget()) { | 1561 if (!ic_data.HasOneTarget()) { |
| 1630 // Target is not only StringBase_get_isEmpty. | 1562 // Target is not only StringBase_get_isEmpty. |
| 1631 return false; | 1563 return false; |
| 1632 } | 1564 } |
| 1633 InlineStringIsEmptyGetter(call); | 1565 InlineStringIsEmptyGetter(call); |
| 1634 return true; | 1566 return true; |
| 1635 case MethodRecognizer::kFloat32x4ShuffleX: | 1567 case MethodRecognizer::kFloat32x4ShuffleX: |
| 1636 case MethodRecognizer::kFloat32x4ShuffleY: | 1568 case MethodRecognizer::kFloat32x4ShuffleY: |
| 1637 case MethodRecognizer::kFloat32x4ShuffleZ: | 1569 case MethodRecognizer::kFloat32x4ShuffleZ: |
| 1638 case MethodRecognizer::kFloat32x4ShuffleW: | 1570 case MethodRecognizer::kFloat32x4ShuffleW: |
| 1639 if (!ic_data.HasReceiverClassId(kFloat32x4Cid) || | 1571 if (!ic_data.HasReceiverClassId(kFloat32x4Cid) || |
| 1640 !ic_data.HasOneTarget()) { | 1572 !ic_data.HasOneTarget()) { |
| 1641 return false; | 1573 return false; |
| 1642 } | 1574 } |
| 1643 return InlineFloat32x4Getter(call, recognized_kind); | 1575 return InlineFloat32x4Getter(call, recognized_kind); |
| 1644 case MethodRecognizer::kUint32x4GetFlagX: | 1576 case MethodRecognizer::kUint32x4GetFlagX: |
| 1645 case MethodRecognizer::kUint32x4GetFlagY: | 1577 case MethodRecognizer::kUint32x4GetFlagY: |
| 1646 case MethodRecognizer::kUint32x4GetFlagZ: | 1578 case MethodRecognizer::kUint32x4GetFlagZ: |
| 1647 case MethodRecognizer::kUint32x4GetFlagW: { | 1579 case MethodRecognizer::kUint32x4GetFlagW: { |
| 1648 if (!ic_data.HasReceiverClassId(kUint32x4Cid) || | 1580 if (!ic_data.HasReceiverClassId(kUint32x4Cid) || |
| 1649 !ic_data.HasOneTarget()) { | 1581 !ic_data.HasOneTarget()) { |
| 1650 return false; | 1582 return false; |
| 1651 } | 1583 } |
| 1652 return InlineUint32x4Getter(call, recognized_kind); | 1584 return InlineUint32x4Getter(call, recognized_kind); |
| 1653 } | 1585 } |
| 1654 default: | 1586 default: |
| 1655 ASSERT(recognized_kind == MethodRecognizer::kUnknown); | 1587 break; |
| 1656 } | 1588 } |
| 1657 return false; | 1589 return false; |
| 1658 } | 1590 } |
| 1659 | 1591 |
| 1660 | 1592 |
| 1661 LoadIndexedInstr* FlowGraphOptimizer::BuildStringCodeUnitAt( | 1593 LoadIndexedInstr* FlowGraphOptimizer::BuildStringCodeUnitAt( |
| 1662 InstanceCallInstr* call, | 1594 InstanceCallInstr* call, |
| 1663 intptr_t cid) { | 1595 intptr_t cid) { |
| 1664 Definition* str = call->ArgumentAt(0); | 1596 Definition* str = call->ArgumentAt(0); |
| 1665 Definition* index = call->ArgumentAt(1); | 1597 Definition* index = call->ArgumentAt(1); |
| (...skipping 5743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7409 } | 7341 } |
| 7410 | 7342 |
| 7411 // Insert materializations at environment uses. | 7343 // Insert materializations at environment uses. |
| 7412 for (intptr_t i = 0; i < exits.length(); i++) { | 7344 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7413 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7345 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7414 } | 7346 } |
| 7415 } | 7347 } |
| 7416 | 7348 |
| 7417 | 7349 |
| 7418 } // namespace dart | 7350 } // namespace dart |
| OLD | NEW |