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

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

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

Powered by Google App Engine
This is Rietveld 408576698