Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: pkg/compiler/lib/src/ssa/nodes.dart

Issue 2464103002: Introduce ClassLike, MemberLike, FieldLike and FunctionLike (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698