OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library dart2js.cps_ir.type_propagation; | 4 library dart2js.cps_ir.type_propagation; |
5 | 5 |
6 import 'optimizers.dart'; | 6 import 'optimizers.dart'; |
7 | 7 |
8 import '../closure.dart' show | 8 import '../closure.dart' show |
9 ClosureClassElement; | 9 ClosureClassElement; |
10 import '../common.dart'; | 10 import '../common.dart'; |
(...skipping 1427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 } | 1438 } |
1439 | 1439 |
1440 bool isInterceptedSelector(Selector selector) { | 1440 bool isInterceptedSelector(Selector selector) { |
1441 return backend.isInterceptedSelector(selector); | 1441 return backend.isInterceptedSelector(selector); |
1442 } | 1442 } |
1443 | 1443 |
1444 /// If [node] is a getter or setter invocation, tries to replace the | 1444 /// If [node] is a getter or setter invocation, tries to replace the |
1445 /// invocation with a direct access to a field. | 1445 /// invocation with a direct access to a field. |
1446 /// | 1446 /// |
1447 /// Returns `true` if the node was replaced. | 1447 /// Returns `true` if the node was replaced. |
1448 Primitive specializeFieldAccess(InvokeMethod node) { | 1448 specializeFieldAccess(InvokeMethod node) { |
1449 if (!node.selector.isGetter && !node.selector.isSetter) return null; | |
1450 AbstractConstantValue receiver = getValue(node.receiver); | 1449 AbstractConstantValue receiver = getValue(node.receiver); |
1451 Element target = | 1450 Element target = |
1452 typeSystem.locateSingleElement(receiver.type, node.selector); | 1451 typeSystem.locateSingleElement(receiver.type, node.selector); |
1453 if (target is! FieldElement) return null; | 1452 if (target is! FieldElement) return null; |
1454 // TODO(asgerf): Inlining native fields will make some tests pass for the | 1453 // TODO(asgerf): Inlining native fields will make some tests pass for the |
1455 // wrong reason, so for testing reasons avoid inlining them. | 1454 // wrong reason, so for testing reasons avoid inlining them. |
1456 if (backend.isNative(target) || backend.isJsInterop(target)) { | 1455 if (backend.isNative(target) || backend.isJsInterop(target)) { |
1457 return null; | 1456 return null; |
1458 } | 1457 } |
1459 if (node.selector.isGetter) { | 1458 if (node.selector.isGetter) { |
1460 return new GetField(node.receiver, target); | 1459 return new GetField(node.receiver, target); |
1461 } else { | 1460 } else if (node.selector.isSetter) { |
1462 if (target.isFinal) return null; | 1461 if (target.isFinal) return null; |
1463 assert(node.hasNoUses); | 1462 assert(node.hasNoUses); |
1464 return new SetField(node.receiver, | 1463 return new SetField(node.receiver, |
1465 target, | 1464 target, |
1466 node.argument(0)); | 1465 node.argument(0)); |
| 1466 } else if (node.selector.isCall) { |
| 1467 CpsFragment cps = new CpsFragment(node.sourceInformation); |
| 1468 Primitive fieldValue = cps.letPrim(new GetField(node.receiver, target)); |
| 1469 Primitive result = cps.invokeMethod( |
| 1470 fieldValue, |
| 1471 new Selector.callClosureFrom(node.selector), |
| 1472 typeSystem.getFieldType(target), |
| 1473 node.arguments.toList()); |
| 1474 node.replaceUsesWith(result); |
| 1475 return cps; |
| 1476 } else { |
| 1477 return null; |
1467 } | 1478 } |
1468 } | 1479 } |
1469 | 1480 |
1470 /// Create a check that throws if [index] is not a valid index on [list]. | 1481 /// Create a check that throws if [index] is not a valid index on [list]. |
1471 /// | 1482 /// |
1472 /// This function assumes that [index] is an integer. | 1483 /// This function assumes that [index] is an integer. |
1473 /// | 1484 /// |
1474 /// Returns a CPS fragment whose context is the branch where no error | 1485 /// Returns a CPS fragment whose context is the branch where no error |
1475 /// was thrown. | 1486 /// was thrown. |
1476 Primitive makeBoundsCheck(CpsFragment cps, | 1487 Primitive makeBoundsCheck(CpsFragment cps, |
(...skipping 2070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3547 } | 3558 } |
3548 | 3559 |
3549 Primitive makeCheck(CpsFragment cps, Primitive value) { | 3560 Primitive makeCheck(CpsFragment cps, Primitive value) { |
3550 return cps.applyBuiltin(negatedOperator, [value]); | 3561 return cps.applyBuiltin(negatedOperator, [value]); |
3551 } | 3562 } |
3552 | 3563 |
3553 Primitive makeRefinement(CpsFragment cps, Primitive value, World world) { | 3564 Primitive makeRefinement(CpsFragment cps, Primitive value, World world) { |
3554 return cps.refine(value, new TypeMask.nonNullSubclass(classElement, world)); | 3565 return cps.refine(value, new TypeMask.nonNullSubclass(classElement, world)); |
3555 } | 3566 } |
3556 } | 3567 } |
OLD | NEW |