| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 import '../closure.dart'; | 5 import '../closure.dart'; |
| 6 import '../common.dart'; | 6 import '../common.dart'; |
| 7 import '../compiler.dart' show Compiler; | 7 import '../compiler.dart' show Compiler; |
| 8 import '../constants/constant_system.dart'; | 8 import '../constants/constant_system.dart'; |
| 9 import '../constants/values.dart'; | 9 import '../constants/values.dart'; |
| 10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| 11 import '../elements/elements.dart'; | 11 import '../elements/elements.dart' |
| 12 show |
| 13 ClassLike, |
| 14 Entity, |
| 15 FieldLike, |
| 16 FunctionLike, |
| 17 JumpTarget, |
| 18 LabelDefinition, |
| 19 Local, |
| 20 MemberLike; |
| 12 import '../io/source_information.dart'; | 21 import '../io/source_information.dart'; |
| 13 import '../js/js.dart' as js; | 22 import '../js/js.dart' as js; |
| 14 import '../js_backend/backend_helpers.dart' show BackendHelpers; | 23 import '../js_backend/backend_helpers.dart' show BackendHelpers; |
| 15 import '../js_backend/js_backend.dart'; | 24 import '../js_backend/js_backend.dart'; |
| 16 import '../native/native.dart' as native; | 25 import '../native/native.dart' as native; |
| 17 import '../tree/dartstring.dart' as ast; | 26 import '../tree/dartstring.dart' as ast; |
| 18 import '../types/constants.dart' show computeTypeMask; | 27 import '../types/constants.dart' show computeTypeMask; |
| 19 import '../types/types.dart'; | 28 import '../types/types.dart'; |
| 20 import '../universe/selector.dart' show Selector; | 29 import '../universe/selector.dart' show Selector; |
| 21 import '../universe/side_effects.dart' show SideEffects; | 30 import '../universe/side_effects.dart' show SideEffects; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 assert(instruction != list.first); | 156 assert(instruction != list.first); |
| 148 } | 157 } |
| 149 } | 158 } |
| 150 | 159 |
| 151 currentBlock = node; | 160 currentBlock = node; |
| 152 visitInstructionList(node); | 161 visitInstructionList(node); |
| 153 } | 162 } |
| 154 } | 163 } |
| 155 | 164 |
| 156 class HGraph { | 165 class HGraph { |
| 157 Element element; // Used for debug printing. | 166 // TODO(johnniwinther): Maybe this should be [MemberLike]. |
| 167 Entity element; // Used for debug printing. |
| 158 HBasicBlock entry; | 168 HBasicBlock entry; |
| 159 HBasicBlock exit; | 169 HBasicBlock exit; |
| 160 HThis thisInstruction; | 170 HThis thisInstruction; |
| 161 | 171 |
| 162 /// Receiver parameter, set for methods using interceptor calling convention. | 172 /// Receiver parameter, set for methods using interceptor calling convention. |
| 163 HParameterValue explicitReceiverParameter; | 173 HParameterValue explicitReceiverParameter; |
| 164 bool isRecursiveMethod = false; | 174 bool isRecursiveMethod = false; |
| 165 bool calledInLoop = false; | 175 bool calledInLoop = false; |
| 166 final List<HBasicBlock> blocks = <HBasicBlock>[]; | 176 final List<HBasicBlock> blocks = <HBasicBlock>[]; |
| 167 | 177 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 ..sourceInformation = sourceInformation; | 227 ..sourceInformation = sourceInformation; |
| 218 entry.addAtExit(result); | 228 entry.addAtExit(result); |
| 219 constants[constant] = result; | 229 constants[constant] = result; |
| 220 } else if (result.block == null) { | 230 } else if (result.block == null) { |
| 221 // The constant was not used anymore. | 231 // The constant was not used anymore. |
| 222 entry.addAtExit(result); | 232 entry.addAtExit(result); |
| 223 } | 233 } |
| 224 return result; | 234 return result; |
| 225 } | 235 } |
| 226 | 236 |
| 227 HConstant addDeferredConstant(ConstantValue constant, PrefixElement prefix, | 237 HConstant addDeferredConstant(ConstantValue constant, Entity prefix, |
| 228 SourceInformation sourceInformation, Compiler compiler) { | 238 SourceInformation sourceInformation, Compiler compiler) { |
| 229 // TODO(sigurdm,johnniwinter): These deferred constants should be created | 239 // TODO(sigurdm,johnniwinther): These deferred constants should be created |
| 230 // by the constant evaluator. | 240 // by the constant evaluator. |
| 231 ConstantValue wrapper = new DeferredConstantValue(constant, prefix); | 241 ConstantValue wrapper = new DeferredConstantValue(constant, prefix); |
| 232 compiler.deferredLoadTask.registerConstantDeferredUse(wrapper, prefix); | 242 compiler.deferredLoadTask.registerConstantDeferredUse(wrapper, prefix); |
| 233 return addConstant(wrapper, compiler, sourceInformation: sourceInformation); | 243 return addConstant(wrapper, compiler, sourceInformation: sourceInformation); |
| 234 } | 244 } |
| 235 | 245 |
| 236 HConstant addConstantInt(int i, Compiler compiler) { | 246 HConstant addConstantInt(int i, Compiler compiler) { |
| 237 return addConstant(compiler.backend.constantSystem.createInt(i), compiler); | 247 return addConstant(compiler.backend.constantSystem.createInt(i), compiler); |
| 238 } | 248 } |
| 239 | 249 |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 921 bool isValue() => instructionType.isValue; | 931 bool isValue() => instructionType.isValue; |
| 922 | 932 |
| 923 bool canBeNull() => instructionType.isNullable; | 933 bool canBeNull() => instructionType.isNullable; |
| 924 | 934 |
| 925 bool isNull() => instructionType.isNull; | 935 bool isNull() => instructionType.isNull; |
| 926 | 936 |
| 927 bool isConflicting() => instructionType.isEmpty; | 937 bool isConflicting() => instructionType.isEmpty; |
| 928 | 938 |
| 929 /// Returns `true` if [typeMask] contains [cls]. | 939 /// Returns `true` if [typeMask] contains [cls]. |
| 930 static bool containsType( | 940 static bool containsType( |
| 931 TypeMask typeMask, ClassElement cls, ClosedWorld closedWorld) { | 941 TypeMask typeMask, ClassLike cls, ClosedWorld closedWorld) { |
| 932 return closedWorld.isInstantiated(cls) && | 942 return closedWorld.isInstantiated(cls) && |
| 933 typeMask.contains(cls, closedWorld); | 943 typeMask.contains(cls, closedWorld); |
| 934 } | 944 } |
| 935 | 945 |
| 936 /// Returns `true` if [typeMask] contains only [cls]. | 946 /// Returns `true` if [typeMask] contains only [cls]. |
| 937 static bool containsOnlyType( | 947 static bool containsOnlyType( |
| 938 TypeMask typeMask, ClassElement cls, ClosedWorld closedWorld) { | 948 TypeMask typeMask, ClassLike cls, ClosedWorld closedWorld) { |
| 939 return closedWorld.isInstantiated(cls) && typeMask.containsOnly(cls); | 949 return closedWorld.isInstantiated(cls) && typeMask.containsOnly(cls); |
| 940 } | 950 } |
| 941 | 951 |
| 942 /// Returns `true` if [typeMask] is an instance of [cls]. | 952 /// Returns `true` if [typeMask] is an instance of [cls]. |
| 943 static bool isInstanceOf( | 953 static bool isInstanceOf( |
| 944 TypeMask typeMask, ClassElement cls, ClosedWorld closedWorld) { | 954 TypeMask typeMask, ClassLike cls, ClosedWorld closedWorld) { |
| 945 return closedWorld.isImplemented(cls) && | 955 return closedWorld.isImplemented(cls) && |
| 946 typeMask.satisfies(cls, closedWorld); | 956 typeMask.satisfies(cls, closedWorld); |
| 947 } | 957 } |
| 948 | 958 |
| 949 bool canBePrimitive(Compiler compiler) { | 959 bool canBePrimitive(Compiler compiler) { |
| 950 return canBePrimitiveNumber(compiler) || | 960 return canBePrimitiveNumber(compiler) || |
| 951 canBePrimitiveArray(compiler) || | 961 canBePrimitiveArray(compiler) || |
| 952 canBePrimitiveBoolean(compiler) || | 962 canBePrimitiveBoolean(compiler) || |
| 953 canBePrimitiveString(compiler) || | 963 canBePrimitiveString(compiler) || |
| 954 isNull(); | 964 isNull(); |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 } | 1370 } |
| 1361 return false; | 1371 return false; |
| 1362 } | 1372 } |
| 1363 | 1373 |
| 1364 HInstruction convertType(Compiler compiler, DartType type, int kind) { | 1374 HInstruction convertType(Compiler compiler, DartType type, int kind) { |
| 1365 if (type == null) return this; | 1375 if (type == null) return this; |
| 1366 type = type.unaliased; | 1376 type = type.unaliased; |
| 1367 // Only the builder knows how to create [HTypeConversion] | 1377 // Only the builder knows how to create [HTypeConversion] |
| 1368 // instructions with generics. It has the generic type context | 1378 // instructions with generics. It has the generic type context |
| 1369 // available. | 1379 // available. |
| 1370 assert(type.kind != TypeKind.TYPE_VARIABLE); | 1380 assert(!type.isTypeVariable); |
| 1371 assert(type.treatAsRaw || type.isFunctionType); | 1381 assert(type.treatAsRaw || type.isFunctionType); |
| 1372 if (type.isDynamic) return this; | 1382 if (type.isDynamic) return this; |
| 1373 if (type.isObject) return this; | 1383 if (type.isObject) return this; |
| 1374 // The type element is either a class or the void element. | 1384 // The type element is either a class or the void element. |
| 1375 Element element = type.element; | |
| 1376 JavaScriptBackend backend = compiler.backend; | 1385 JavaScriptBackend backend = compiler.backend; |
| 1377 if (type.kind != TypeKind.INTERFACE) { | 1386 if (type.isVoid || type.isFunctionType) { |
| 1378 return new HTypeConversion(type, kind, backend.dynamicType, this); | 1387 return new HTypeConversion(type, kind, backend.dynamicType, this); |
| 1379 } else if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) { | 1388 } |
| 1389 assert(type.isInterfaceType); |
| 1390 if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) { |
| 1380 // Boolean conversion checks work on non-nullable booleans. | 1391 // Boolean conversion checks work on non-nullable booleans. |
| 1381 return new HTypeConversion(type, kind, backend.boolType, this); | 1392 return new HTypeConversion(type, kind, backend.boolType, this); |
| 1382 } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) { | 1393 } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) { |
| 1383 throw 'creating compound check to $type (this = ${this})'; | 1394 throw 'creating compound check to $type (this = ${this})'; |
| 1384 } else { | 1395 } else { |
| 1385 TypeMask subtype = | 1396 Entity cls = type.element; |
| 1386 new TypeMask.subtype(element.declaration, compiler.closedWorld); | 1397 TypeMask subtype = new TypeMask.subtype(cls, compiler.closedWorld); |
| 1387 return new HTypeConversion(type, kind, subtype, this); | 1398 return new HTypeConversion(type, kind, subtype, this); |
| 1388 } | 1399 } |
| 1389 } | 1400 } |
| 1390 | 1401 |
| 1391 /** | 1402 /** |
| 1392 * Return whether the instructions do not belong to a loop or | 1403 * Return whether the instructions do not belong to a loop or |
| 1393 * belong to the same loop. | 1404 * belong to the same loop. |
| 1394 */ | 1405 */ |
| 1395 bool hasSameLoopHeaderAs(HInstruction other) { | 1406 bool hasSameLoopHeaderAs(HInstruction other) { |
| 1396 return block.enclosingLoopHeader == other.block.enclosingLoopHeader; | 1407 return block.enclosingLoopHeader == other.block.enclosingLoopHeader; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1500 } | 1511 } |
| 1501 | 1512 |
| 1502 abstract class HControlFlow extends HInstruction { | 1513 abstract class HControlFlow extends HInstruction { |
| 1503 HControlFlow(inputs) : super(inputs, const TypeMask.nonNullEmpty()); | 1514 HControlFlow(inputs) : super(inputs, const TypeMask.nonNullEmpty()); |
| 1504 bool isControlFlow() => true; | 1515 bool isControlFlow() => true; |
| 1505 bool isJsStatement() => true; | 1516 bool isJsStatement() => true; |
| 1506 } | 1517 } |
| 1507 | 1518 |
| 1508 // Allocates and initializes an instance. | 1519 // Allocates and initializes an instance. |
| 1509 class HCreate extends HInstruction { | 1520 class HCreate extends HInstruction { |
| 1510 final ClassElement element; | 1521 final ClassLike element; |
| 1511 | 1522 |
| 1512 /// Does this instruction have reified type information as the last input? | 1523 /// Does this instruction have reified type information as the last input? |
| 1513 final bool hasRtiInput; | 1524 final bool hasRtiInput; |
| 1514 | 1525 |
| 1515 /// If this field is not `null`, this call is from an inlined constructor and | 1526 /// If this field is not `null`, this call is from an inlined constructor and |
| 1516 /// we have to register the instantiated type in the code generator. The | 1527 /// we have to register the instantiated type in the code generator. The |
| 1517 /// [instructionType] of this node is not enough, because we also need the | 1528 /// [instructionType] of this node is not enough, because we also need the |
| 1518 /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations]. | 1529 /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations]. |
| 1519 List<DartType> instantiatedTypes; | 1530 List<DartType> instantiatedTypes; |
| 1520 | 1531 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1555 // calling convention, which adds the actual receiver as a | 1566 // calling convention, which adds the actual receiver as a |
| 1556 // parameter to the call. | 1567 // parameter to the call. |
| 1557 return (selector != null) && (inputs.length - 2 == selector.argumentCount); | 1568 return (selector != null) && (inputs.length - 2 == selector.argumentCount); |
| 1558 } | 1569 } |
| 1559 } | 1570 } |
| 1560 | 1571 |
| 1561 abstract class HInvokeDynamic extends HInvoke { | 1572 abstract class HInvokeDynamic extends HInvoke { |
| 1562 final InvokeDynamicSpecializer specializer; | 1573 final InvokeDynamicSpecializer specializer; |
| 1563 Selector selector; | 1574 Selector selector; |
| 1564 TypeMask mask; | 1575 TypeMask mask; |
| 1565 Element element; | 1576 MemberLike element; |
| 1566 | 1577 |
| 1567 HInvokeDynamic(Selector selector, this.mask, this.element, | 1578 HInvokeDynamic(Selector selector, this.mask, this.element, |
| 1568 List<HInstruction> inputs, TypeMask type, | 1579 List<HInstruction> inputs, TypeMask type, |
| 1569 [bool isIntercepted = false]) | 1580 [bool isIntercepted = false]) |
| 1570 : super(inputs, type), | 1581 : super(inputs, type), |
| 1571 this.selector = selector, | 1582 this.selector = selector, |
| 1572 specializer = isIntercepted | 1583 specializer = isIntercepted |
| 1573 ? InvokeDynamicSpecializer.lookupSpecializer(selector) | 1584 ? InvokeDynamicSpecializer.lookupSpecializer(selector) |
| 1574 : const InvokeDynamicSpecializer(); | 1585 : const InvokeDynamicSpecializer(); |
| 1575 toString() => 'invoke dynamic: selector=$selector, mask=$mask'; | 1586 toString() => 'invoke dynamic: selector=$selector, mask=$mask'; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1608 HInvokeDynamicMethod(Selector selector, TypeMask mask, | 1619 HInvokeDynamicMethod(Selector selector, TypeMask mask, |
| 1609 List<HInstruction> inputs, TypeMask type, | 1620 List<HInstruction> inputs, TypeMask type, |
| 1610 [bool isIntercepted = false]) | 1621 [bool isIntercepted = false]) |
| 1611 : super(selector, mask, null, inputs, type, isIntercepted); | 1622 : super(selector, mask, null, inputs, type, isIntercepted); |
| 1612 | 1623 |
| 1613 String toString() => 'invoke dynamic method: selector=$selector, mask=$mask'; | 1624 String toString() => 'invoke dynamic method: selector=$selector, mask=$mask'; |
| 1614 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1625 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
| 1615 } | 1626 } |
| 1616 | 1627 |
| 1617 abstract class HInvokeDynamicField extends HInvokeDynamic { | 1628 abstract class HInvokeDynamicField extends HInvokeDynamic { |
| 1618 HInvokeDynamicField(Selector selector, TypeMask mask, Element element, | 1629 HInvokeDynamicField(Selector selector, TypeMask mask, MemberLike element, |
| 1619 List<HInstruction> inputs, TypeMask type) | 1630 List<HInstruction> inputs, TypeMask type) |
| 1620 : super(selector, mask, element, inputs, type); | 1631 : super(selector, mask, element, inputs, type); |
| 1621 toString() => 'invoke dynamic field: selector=$selector, mask=$mask'; | 1632 toString() => 'invoke dynamic field: selector=$selector, mask=$mask'; |
| 1622 } | 1633 } |
| 1623 | 1634 |
| 1624 class HInvokeDynamicGetter extends HInvokeDynamicField { | 1635 class HInvokeDynamicGetter extends HInvokeDynamicField { |
| 1625 HInvokeDynamicGetter(Selector selector, TypeMask mask, Element element, | 1636 HInvokeDynamicGetter(Selector selector, TypeMask mask, MemberLike element, |
| 1626 List<HInstruction> inputs, TypeMask type) | 1637 List<HInstruction> inputs, TypeMask type) |
| 1627 : super(selector, mask, element, inputs, type); | 1638 : super(selector, mask, element, inputs, type); |
| 1628 toString() => 'invoke dynamic getter: selector=$selector, mask=$mask'; | 1639 toString() => 'invoke dynamic getter: selector=$selector, mask=$mask'; |
| 1629 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); | 1640 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); |
| 1630 | 1641 |
| 1631 bool get isTearOff => element != null && element.isFunction; | 1642 bool get isTearOff => element != null && element.isFunction; |
| 1632 | 1643 |
| 1633 // There might be an interceptor input, so `inputs.last` is the dart receiver. | 1644 // There might be an interceptor input, so `inputs.last` is the dart receiver. |
| 1634 bool canThrow() => isTearOff ? inputs.last.canBeNull() : super.canThrow(); | 1645 bool canThrow() => isTearOff ? inputs.last.canBeNull() : super.canThrow(); |
| 1635 } | 1646 } |
| 1636 | 1647 |
| 1637 class HInvokeDynamicSetter extends HInvokeDynamicField { | 1648 class HInvokeDynamicSetter extends HInvokeDynamicField { |
| 1638 HInvokeDynamicSetter(Selector selector, TypeMask mask, Element element, | 1649 HInvokeDynamicSetter(Selector selector, TypeMask mask, MemberLike element, |
| 1639 List<HInstruction> inputs, TypeMask type) | 1650 List<HInstruction> inputs, TypeMask type) |
| 1640 : super(selector, mask, element, inputs, type); | 1651 : super(selector, mask, element, inputs, type); |
| 1641 toString() => 'invoke dynamic setter: selector=$selector, mask=$mask'; | 1652 toString() => 'invoke dynamic setter: selector=$selector, mask=$mask'; |
| 1642 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); | 1653 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); |
| 1643 } | 1654 } |
| 1644 | 1655 |
| 1645 class HInvokeStatic extends HInvoke { | 1656 class HInvokeStatic extends HInvoke { |
| 1646 final Element element; | 1657 final MemberLike element; |
| 1647 | 1658 |
| 1648 final bool targetCanThrow; | 1659 final bool targetCanThrow; |
| 1649 | 1660 |
| 1650 bool canThrow() => targetCanThrow; | 1661 bool canThrow() => targetCanThrow; |
| 1651 | 1662 |
| 1652 /// If this instruction is a call to a constructor, [instantiatedTypes] | 1663 /// If this instruction is a call to a constructor, [instantiatedTypes] |
| 1653 /// contains the type(s) used in the (Dart) `New` expression(s). The | 1664 /// contains the type(s) used in the (Dart) `New` expression(s). The |
| 1654 /// [instructionType] of this node is not enough, because we also need the | 1665 /// [instructionType] of this node is not enough, because we also need the |
| 1655 /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations]. | 1666 /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations]. |
| 1656 List<DartType> instantiatedTypes; | 1667 List<DartType> instantiatedTypes; |
| 1657 | 1668 |
| 1658 /** The first input must be the target. */ | 1669 /** The first input must be the target. */ |
| 1659 HInvokeStatic(this.element, inputs, TypeMask type, | 1670 HInvokeStatic(this.element, inputs, TypeMask type, |
| 1660 {this.targetCanThrow: true}) | 1671 {this.targetCanThrow: true}) |
| 1661 : super(inputs, type); | 1672 : super(inputs, type); |
| 1662 | 1673 |
| 1663 toString() => 'invoke static: $element'; | 1674 toString() => 'invoke static: $element'; |
| 1664 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); | 1675 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); |
| 1665 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE; | 1676 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE; |
| 1666 } | 1677 } |
| 1667 | 1678 |
| 1668 class HInvokeSuper extends HInvokeStatic { | 1679 class HInvokeSuper extends HInvokeStatic { |
| 1669 /** The class where the call to super is being done. */ | 1680 /** The class where the call to super is being done. */ |
| 1670 final ClassElement caller; | 1681 final ClassLike caller; |
| 1671 final bool isSetter; | 1682 final bool isSetter; |
| 1672 final Selector selector; | 1683 final Selector selector; |
| 1673 | 1684 |
| 1674 HInvokeSuper(Element element, this.caller, this.selector, inputs, type, | 1685 HInvokeSuper(MemberLike element, this.caller, this.selector, inputs, type, |
| 1675 SourceInformation sourceInformation, | 1686 SourceInformation sourceInformation, |
| 1676 {this.isSetter}) | 1687 {this.isSetter}) |
| 1677 : super(element, inputs, type) { | 1688 : super(element, inputs, type) { |
| 1678 this.sourceInformation = sourceInformation; | 1689 this.sourceInformation = sourceInformation; |
| 1679 } | 1690 } |
| 1680 | 1691 |
| 1681 HInstruction get receiver => inputs[0]; | 1692 HInstruction get receiver => inputs[0]; |
| 1682 HInstruction getDartReceiver(Compiler compiler) { | 1693 HInstruction getDartReceiver(Compiler compiler) { |
| 1683 return isCallOnInterceptor(compiler) ? inputs[1] : inputs[0]; | 1694 return isCallOnInterceptor(compiler) ? inputs[1] : inputs[0]; |
| 1684 } | 1695 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1704 // The 'inputs' are | 1715 // The 'inputs' are |
| 1705 // [receiver, arg1, ..., argN] or | 1716 // [receiver, arg1, ..., argN] or |
| 1706 // [interceptor, receiver, arg1, ... argN]. | 1717 // [interceptor, receiver, arg1, ... argN]. |
| 1707 HInvokeConstructorBody(element, inputs, type) : super(element, inputs, type); | 1718 HInvokeConstructorBody(element, inputs, type) : super(element, inputs, type); |
| 1708 | 1719 |
| 1709 String toString() => 'invoke constructor body: ${element.name}'; | 1720 String toString() => 'invoke constructor body: ${element.name}'; |
| 1710 accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this); | 1721 accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this); |
| 1711 } | 1722 } |
| 1712 | 1723 |
| 1713 abstract class HFieldAccess extends HInstruction { | 1724 abstract class HFieldAccess extends HInstruction { |
| 1714 final Element element; | 1725 // TODO(johnniwinther): This should be a [FieldLike] but JSIndexable.length is |
| 1726 // encoded using a [HFieldGet]. |
| 1727 final MemberLike element; |
| 1715 | 1728 |
| 1716 HFieldAccess(Element element, List<HInstruction> inputs, TypeMask type) | 1729 HFieldAccess(this.element, List<HInstruction> inputs, TypeMask type) |
| 1717 : this.element = element, | 1730 : super(inputs, type); |
| 1718 super(inputs, type); | |
| 1719 | 1731 |
| 1720 HInstruction get receiver => inputs[0]; | 1732 HInstruction get receiver => inputs[0]; |
| 1721 } | 1733 } |
| 1722 | 1734 |
| 1723 class HFieldGet extends HFieldAccess { | 1735 class HFieldGet extends HFieldAccess { |
| 1724 final bool isAssignable; | 1736 final bool isAssignable; |
| 1725 | 1737 |
| 1726 HFieldGet(Element element, HInstruction receiver, TypeMask type, | 1738 HFieldGet(MemberLike element, HInstruction receiver, TypeMask type, |
| 1727 {bool isAssignable}) | 1739 {bool isAssignable}) |
| 1728 : this.isAssignable = | 1740 : this.isAssignable = |
| 1729 (isAssignable != null) ? isAssignable : element.isAssignable, | 1741 (isAssignable != null) ? isAssignable : element.isAssignable, |
| 1730 super(element, <HInstruction>[receiver], type) { | 1742 super(element, <HInstruction>[receiver], type) { |
| 1731 sideEffects.clearAllSideEffects(); | 1743 sideEffects.clearAllSideEffects(); |
| 1732 sideEffects.clearAllDependencies(); | 1744 sideEffects.clearAllDependencies(); |
| 1733 setUseGvn(); | 1745 setUseGvn(); |
| 1734 if (this.isAssignable) { | 1746 if (this.isAssignable) { |
| 1735 sideEffects.setDependsOnInstancePropertyStore(); | 1747 sideEffects.setDependsOnInstancePropertyStore(); |
| 1736 } | 1748 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1757 | 1769 |
| 1758 accept(HVisitor visitor) => visitor.visitFieldGet(this); | 1770 accept(HVisitor visitor) => visitor.visitFieldGet(this); |
| 1759 | 1771 |
| 1760 int typeCode() => HInstruction.FIELD_GET_TYPECODE; | 1772 int typeCode() => HInstruction.FIELD_GET_TYPECODE; |
| 1761 bool typeEquals(other) => other is HFieldGet; | 1773 bool typeEquals(other) => other is HFieldGet; |
| 1762 bool dataEquals(HFieldGet other) => element == other.element; | 1774 bool dataEquals(HFieldGet other) => element == other.element; |
| 1763 String toString() => "FieldGet $element"; | 1775 String toString() => "FieldGet $element"; |
| 1764 } | 1776 } |
| 1765 | 1777 |
| 1766 class HFieldSet extends HFieldAccess { | 1778 class HFieldSet extends HFieldAccess { |
| 1767 HFieldSet(Element element, HInstruction receiver, HInstruction value) | 1779 HFieldSet(MemberLike element, HInstruction receiver, HInstruction value) |
| 1768 : super(element, <HInstruction>[receiver, value], | 1780 : super(element, <HInstruction>[receiver, value], |
| 1769 const TypeMask.nonNullEmpty()) { | 1781 const TypeMask.nonNullEmpty()) { |
| 1770 sideEffects.clearAllSideEffects(); | 1782 sideEffects.clearAllSideEffects(); |
| 1771 sideEffects.clearAllDependencies(); | 1783 sideEffects.clearAllDependencies(); |
| 1772 sideEffects.setChangesInstanceProperty(); | 1784 sideEffects.setChangesInstanceProperty(); |
| 1773 } | 1785 } |
| 1774 | 1786 |
| 1775 bool canThrow() => receiver.canBeNull(); | 1787 bool canThrow() => receiver.canBeNull(); |
| 1776 | 1788 |
| 1777 HInstruction getDartReceiver(Compiler compiler) => receiver; | 1789 HInstruction getDartReceiver(Compiler compiler) => receiver; |
| 1778 bool onlyThrowsNSM() => true; | 1790 bool onlyThrowsNSM() => true; |
| 1779 | 1791 |
| 1780 HInstruction get value => inputs[1]; | 1792 HInstruction get value => inputs[1]; |
| 1781 accept(HVisitor visitor) => visitor.visitFieldSet(this); | 1793 accept(HVisitor visitor) => visitor.visitFieldSet(this); |
| 1782 | 1794 |
| 1783 bool isJsStatement() => true; | 1795 bool isJsStatement() => true; |
| 1784 String toString() => "FieldSet $element"; | 1796 String toString() => "FieldSet $element"; |
| 1785 } | 1797 } |
| 1786 | 1798 |
| 1787 /** | 1799 /** |
| 1788 * HReadModifyWrite is a late stage instruction for a field (property) update | 1800 * HReadModifyWrite is a late stage instruction for a field (property) update |
| 1789 * via an assignment operation or pre- or post-increment. | 1801 * via an assignment operation or pre- or post-increment. |
| 1790 */ | 1802 */ |
| 1791 class HReadModifyWrite extends HLateInstruction { | 1803 class HReadModifyWrite extends HLateInstruction { |
| 1792 static const ASSIGN_OP = 0; | 1804 static const ASSIGN_OP = 0; |
| 1793 static const PRE_OP = 1; | 1805 static const PRE_OP = 1; |
| 1794 static const POST_OP = 2; | 1806 static const POST_OP = 2; |
| 1795 final Element element; | 1807 final FieldLike element; |
| 1796 final String jsOp; | 1808 final String jsOp; |
| 1797 final int opKind; | 1809 final int opKind; |
| 1798 | 1810 |
| 1799 HReadModifyWrite._(Element this.element, this.jsOp, this.opKind, | 1811 HReadModifyWrite._(this.element, this.jsOp, this.opKind, |
| 1800 List<HInstruction> inputs, TypeMask type) | 1812 List<HInstruction> inputs, TypeMask type) |
| 1801 : super(inputs, type) { | 1813 : super(inputs, type) { |
| 1802 sideEffects.clearAllSideEffects(); | 1814 sideEffects.clearAllSideEffects(); |
| 1803 sideEffects.clearAllDependencies(); | 1815 sideEffects.clearAllDependencies(); |
| 1804 sideEffects.setChangesInstanceProperty(); | 1816 sideEffects.setChangesInstanceProperty(); |
| 1805 sideEffects.setDependsOnInstancePropertyStore(); | 1817 sideEffects.setDependsOnInstancePropertyStore(); |
| 1806 } | 1818 } |
| 1807 | 1819 |
| 1808 HReadModifyWrite.assignOp(Element element, String jsOp, HInstruction receiver, | 1820 HReadModifyWrite.assignOp(FieldLike element, String jsOp, |
| 1809 HInstruction operand, TypeMask type) | 1821 HInstruction receiver, HInstruction operand, TypeMask type) |
| 1810 : this._( | 1822 : this._( |
| 1811 element, jsOp, ASSIGN_OP, <HInstruction>[receiver, operand], type); | 1823 element, jsOp, ASSIGN_OP, <HInstruction>[receiver, operand], type); |
| 1812 | 1824 |
| 1813 HReadModifyWrite.preOp( | 1825 HReadModifyWrite.preOp( |
| 1814 Element element, String jsOp, HInstruction receiver, TypeMask type) | 1826 FieldLike element, String jsOp, HInstruction receiver, TypeMask type) |
| 1815 : this._(element, jsOp, PRE_OP, <HInstruction>[receiver], type); | 1827 : this._(element, jsOp, PRE_OP, <HInstruction>[receiver], type); |
| 1816 | 1828 |
| 1817 HReadModifyWrite.postOp( | 1829 HReadModifyWrite.postOp( |
| 1818 Element element, String jsOp, HInstruction receiver, TypeMask type) | 1830 FieldLike element, String jsOp, HInstruction receiver, TypeMask type) |
| 1819 : this._(element, jsOp, POST_OP, <HInstruction>[receiver], type); | 1831 : this._(element, jsOp, POST_OP, <HInstruction>[receiver], type); |
| 1820 | 1832 |
| 1821 HInstruction get receiver => inputs[0]; | 1833 HInstruction get receiver => inputs[0]; |
| 1822 | 1834 |
| 1823 bool get isPreOp => opKind == PRE_OP; | 1835 bool get isPreOp => opKind == PRE_OP; |
| 1824 bool get isPostOp => opKind == POST_OP; | 1836 bool get isPostOp => opKind == POST_OP; |
| 1825 bool get isAssignOp => opKind == ASSIGN_OP; | 1837 bool get isAssignOp => opKind == ASSIGN_OP; |
| 1826 | 1838 |
| 1827 bool canThrow() => receiver.canBeNull(); | 1839 bool canThrow() => receiver.canBeNull(); |
| 1828 | 1840 |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2497 HThrow(HInstruction value, SourceInformation sourceInformation, | 2509 HThrow(HInstruction value, SourceInformation sourceInformation, |
| 2498 {this.isRethrow: false}) | 2510 {this.isRethrow: false}) |
| 2499 : super(<HInstruction>[value]) { | 2511 : super(<HInstruction>[value]) { |
| 2500 this.sourceInformation = sourceInformation; | 2512 this.sourceInformation = sourceInformation; |
| 2501 } | 2513 } |
| 2502 toString() => 'throw'; | 2514 toString() => 'throw'; |
| 2503 accept(HVisitor visitor) => visitor.visitThrow(this); | 2515 accept(HVisitor visitor) => visitor.visitThrow(this); |
| 2504 } | 2516 } |
| 2505 | 2517 |
| 2506 class HStatic extends HInstruction { | 2518 class HStatic extends HInstruction { |
| 2507 final Element element; | 2519 final MemberLike element; |
| 2508 HStatic(this.element, type) : super(<HInstruction>[], type) { | 2520 HStatic(this.element, type) : super(<HInstruction>[], type) { |
| 2509 assert(element != null); | 2521 assert(element != null); |
| 2510 assert(invariant(this, element.isDeclaration)); | |
| 2511 sideEffects.clearAllSideEffects(); | 2522 sideEffects.clearAllSideEffects(); |
| 2512 sideEffects.clearAllDependencies(); | 2523 sideEffects.clearAllDependencies(); |
| 2513 if (element.isAssignable) { | 2524 if (element.isAssignable) { |
| 2514 sideEffects.setDependsOnStaticPropertyStore(); | 2525 sideEffects.setDependsOnStaticPropertyStore(); |
| 2515 } | 2526 } |
| 2516 setUseGvn(); | 2527 setUseGvn(); |
| 2517 } | 2528 } |
| 2518 toString() => 'static ${element.name}'; | 2529 toString() => 'static ${element.name}'; |
| 2519 accept(HVisitor visitor) => visitor.visitStatic(this); | 2530 accept(HVisitor visitor) => visitor.visitStatic(this); |
| 2520 | 2531 |
| 2521 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode; | 2532 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode; |
| 2522 int typeCode() => HInstruction.STATIC_TYPECODE; | 2533 int typeCode() => HInstruction.STATIC_TYPECODE; |
| 2523 bool typeEquals(other) => other is HStatic; | 2534 bool typeEquals(other) => other is HStatic; |
| 2524 bool dataEquals(HStatic other) => element == other.element; | 2535 bool dataEquals(HStatic other) => element == other.element; |
| 2525 bool isCodeMotionInvariant() => !element.isAssignable; | 2536 bool isCodeMotionInvariant() => !element.isAssignable; |
| 2526 } | 2537 } |
| 2527 | 2538 |
| 2528 class HInterceptor extends HInstruction { | 2539 class HInterceptor extends HInstruction { |
| 2529 // This field should originally be null to allow GVN'ing all | 2540 // This field should originally be null to allow GVN'ing all |
| 2530 // [HInterceptor] on the same input. | 2541 // [HInterceptor] on the same input. |
| 2531 Set<ClassElement> interceptedClasses; | 2542 Set<ClassLike> interceptedClasses; |
| 2532 | 2543 |
| 2533 // inputs[0] is initially the only input, the receiver. | 2544 // inputs[0] is initially the only input, the receiver. |
| 2534 | 2545 |
| 2535 // inputs[1] is a constant interceptor when the interceptor is a constant | 2546 // inputs[1] is a constant interceptor when the interceptor is a constant |
| 2536 // except for a `null` receiver. This is used when the receiver can't be | 2547 // except for a `null` receiver. This is used when the receiver can't be |
| 2537 // falsy, except for `null`, allowing the generation of code like | 2548 // falsy, except for `null`, allowing the generation of code like |
| 2538 // | 2549 // |
| 2539 // (a && C.JSArray_methods).get$first(a) | 2550 // (a && C.JSArray_methods).get$first(a) |
| 2540 // | 2551 // |
| 2541 | 2552 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2572 /** | 2583 /** |
| 2573 * A "one-shot" interceptor is a call to a synthetized method that | 2584 * A "one-shot" interceptor is a call to a synthetized method that |
| 2574 * will fetch the interceptor of its first parameter, and make a call | 2585 * will fetch the interceptor of its first parameter, and make a call |
| 2575 * on a given selector with the remaining parameters. | 2586 * on a given selector with the remaining parameters. |
| 2576 * | 2587 * |
| 2577 * In order to share the same optimizations with regular interceptor | 2588 * In order to share the same optimizations with regular interceptor |
| 2578 * calls, this class extends [HInvokeDynamic] and also has the null | 2589 * calls, this class extends [HInvokeDynamic] and also has the null |
| 2579 * constant as the first input. | 2590 * constant as the first input. |
| 2580 */ | 2591 */ |
| 2581 class HOneShotInterceptor extends HInvokeDynamic { | 2592 class HOneShotInterceptor extends HInvokeDynamic { |
| 2582 Set<ClassElement> interceptedClasses; | 2593 Set<ClassLike> interceptedClasses; |
| 2583 HOneShotInterceptor(Selector selector, TypeMask mask, | 2594 HOneShotInterceptor(Selector selector, TypeMask mask, |
| 2584 List<HInstruction> inputs, TypeMask type, this.interceptedClasses) | 2595 List<HInstruction> inputs, TypeMask type, this.interceptedClasses) |
| 2585 : super(selector, mask, null, inputs, type, true) { | 2596 : super(selector, mask, null, inputs, type, true) { |
| 2586 assert(inputs[0] is HConstant); | 2597 assert(inputs[0] is HConstant); |
| 2587 assert(inputs[0].isNull()); | 2598 assert(inputs[0].isNull()); |
| 2588 } | 2599 } |
| 2589 bool isCallOnInterceptor(Compiler compiler) => true; | 2600 bool isCallOnInterceptor(Compiler compiler) => true; |
| 2590 | 2601 |
| 2591 String toString() => 'one shot interceptor: selector=$selector, mask=$mask'; | 2602 String toString() => 'one shot interceptor: selector=$selector, mask=$mask'; |
| 2592 accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this); | 2603 accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this); |
| 2593 } | 2604 } |
| 2594 | 2605 |
| 2595 /** An [HLazyStatic] is a static that is initialized lazily at first read. */ | 2606 /** An [HLazyStatic] is a static that is initialized lazily at first read. */ |
| 2596 class HLazyStatic extends HInstruction { | 2607 class HLazyStatic extends HInstruction { |
| 2597 final Element element; | 2608 final FieldLike element; |
| 2598 HLazyStatic(this.element, type) : super(<HInstruction>[], type) { | 2609 HLazyStatic(this.element, type) : super(<HInstruction>[], type) { |
| 2599 // TODO(4931): The first access has side-effects, but we afterwards we | 2610 // TODO(4931): The first access has side-effects, but we afterwards we |
| 2600 // should be able to GVN. | 2611 // should be able to GVN. |
| 2601 sideEffects.setAllSideEffects(); | 2612 sideEffects.setAllSideEffects(); |
| 2602 sideEffects.setDependsOnSomething(); | 2613 sideEffects.setDependsOnSomething(); |
| 2603 } | 2614 } |
| 2604 | 2615 |
| 2605 toString() => 'lazy static ${element.name}'; | 2616 toString() => 'lazy static ${element.name}'; |
| 2606 accept(HVisitor visitor) => visitor.visitLazyStatic(this); | 2617 accept(HVisitor visitor) => visitor.visitLazyStatic(this); |
| 2607 | 2618 |
| 2608 int typeCode() => 30; | 2619 int typeCode() => 30; |
| 2609 // TODO(4931): can we do better here? | 2620 // TODO(4931): can we do better here? |
| 2610 bool isCodeMotionInvariant() => false; | 2621 bool isCodeMotionInvariant() => false; |
| 2611 bool canThrow() => true; | 2622 bool canThrow() => true; |
| 2612 } | 2623 } |
| 2613 | 2624 |
| 2614 class HStaticStore extends HInstruction { | 2625 class HStaticStore extends HInstruction { |
| 2615 Element element; | 2626 MemberLike element; |
| 2616 HStaticStore(this.element, HInstruction value) | 2627 HStaticStore(this.element, HInstruction value) |
| 2617 : super(<HInstruction>[value], const TypeMask.nonNullEmpty()) { | 2628 : super(<HInstruction>[value], const TypeMask.nonNullEmpty()) { |
| 2618 sideEffects.clearAllSideEffects(); | 2629 sideEffects.clearAllSideEffects(); |
| 2619 sideEffects.clearAllDependencies(); | 2630 sideEffects.clearAllDependencies(); |
| 2620 sideEffects.setChangesStaticProperty(); | 2631 sideEffects.setChangesStaticProperty(); |
| 2621 } | 2632 } |
| 2622 toString() => 'static store ${element.name}'; | 2633 toString() => 'static store ${element.name}'; |
| 2623 accept(HVisitor visitor) => visitor.visitStaticStore(this); | 2634 accept(HVisitor visitor) => visitor.visitStaticStore(this); |
| 2624 | 2635 |
| 2625 int typeCode() => HInstruction.STATIC_STORE_TYPECODE; | 2636 int typeCode() => HInstruction.STATIC_STORE_TYPECODE; |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3471 class HDynamicType extends HRuntimeType { | 3482 class HDynamicType extends HRuntimeType { |
| 3472 HDynamicType(DynamicType dartType, TypeMask instructionType) | 3483 HDynamicType(DynamicType dartType, TypeMask instructionType) |
| 3473 : super(const <HInstruction>[], dartType, instructionType); | 3484 : super(const <HInstruction>[], dartType, instructionType); |
| 3474 | 3485 |
| 3475 accept(HVisitor visitor) => visitor.visitDynamicType(this); | 3486 accept(HVisitor visitor) => visitor.visitDynamicType(this); |
| 3476 | 3487 |
| 3477 int typeCode() => HInstruction.DYNAMIC_TYPE_TYPECODE; | 3488 int typeCode() => HInstruction.DYNAMIC_TYPE_TYPECODE; |
| 3478 | 3489 |
| 3479 bool typeEquals(HInstruction other) => other is HDynamicType; | 3490 bool typeEquals(HInstruction other) => other is HDynamicType; |
| 3480 } | 3491 } |
| OLD | NEW |