OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 library dart2js.ir_nodes; | 4 library dart2js.ir_nodes; |
5 | 5 |
6 import '../constants/expressions.dart'; | 6 import '../constants/expressions.dart'; |
7 import '../constants/values.dart' as values show ConstantValue; | 7 import '../constants/values.dart' as values show ConstantValue; |
8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
9 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; |
10 import '../io/source_information.dart' show SourceInformation; | 10 import '../io/source_information.dart' show SourceInformation; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 previous = current; | 57 previous = current; |
58 current = current.next; | 58 current = current.next; |
59 } while (current != null); | 59 } while (current != null); |
60 previous.next = firstRef; | 60 previous.next = firstRef; |
61 if (firstRef != null) firstRef.previous = previous; | 61 if (firstRef != null) firstRef.previous = previous; |
62 firstRef = other.firstRef; | 62 firstRef = other.firstRef; |
63 other.firstRef = null; | 63 other.firstRef = null; |
64 } | 64 } |
65 } | 65 } |
66 | 66 |
67 /// An expression that cannot throw or diverge and has no side-effects. | 67 /// A named value. |
68 /// All primitives are named using the identity of the [Primitive] object. | |
69 /// | 68 /// |
70 /// Primitives may allocate objects; this is not considered side-effect here. | 69 /// The identity of the [Primitive] object is the name of the value. |
71 /// | 70 /// The subclass describes how to compute the value. |
72 /// Although primitives may not mutate state, they may depend on state. | |
73 /// | 71 /// |
74 /// All primitives except [Parameter] must be bound by a [LetPrim]. | 72 /// All primitives except [Parameter] must be bound by a [LetPrim]. |
75 abstract class Primitive extends Definition<Primitive> { | 73 abstract class Primitive extends Definition<Primitive> { |
76 /// The [VariableElement] or [ParameterElement] from which the primitive | 74 /// The [VariableElement] or [ParameterElement] from which the primitive |
77 /// binding originated. | 75 /// binding originated. |
78 Entity hint; | 76 Entity hint; |
79 | 77 |
80 /// Use the given element as a hint for naming this primitive. | 78 /// Use the given element as a hint for naming this primitive. |
81 /// | 79 /// |
82 /// Has no effect if this primitive already has a non-null [element]. | 80 /// Has no effect if this primitive already has a non-null [element]. |
83 void useElementAsHint(Entity hint) { | 81 void useElementAsHint(Entity hint) { |
84 if (this.hint == null) { | 82 if (this.hint == null) { |
85 this.hint = hint; | 83 this.hint = hint; |
86 } | 84 } |
87 } | 85 } |
| 86 |
| 87 /// True if the primitive can be removed, assuming it has no uses |
| 88 /// (this getter does not check if there are any uses). |
| 89 /// |
| 90 /// False must be returned for primitives that may throw, diverge, or have |
| 91 /// observable side-effects. |
| 92 bool get isSafeForElimination => true; |
88 } | 93 } |
89 | 94 |
90 /// Operands to invocations and primitives are always variables. They point to | 95 /// Operands to invocations and primitives are always variables. They point to |
91 /// their definition and are doubly-linked into a list of occurrences. | 96 /// their definition and are doubly-linked into a list of occurrences. |
92 class Reference<T extends Definition<T>> { | 97 class Reference<T extends Definition<T>> { |
93 T definition; | 98 T definition; |
94 Reference<T> previous; | 99 Reference<T> previous; |
95 Reference<T> next; | 100 Reference<T> next; |
96 | 101 |
97 /// A pointer to the parent node. Is null until set by optimization passes. | 102 /// A pointer to the parent node. Is null until set by optimization passes. |
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 | 605 |
601 Expression plug(Expression expr) { | 606 Expression plug(Expression expr) { |
602 assert(body == null); | 607 assert(body == null); |
603 return body = expr; | 608 return body = expr; |
604 } | 609 } |
605 | 610 |
606 accept(Visitor visitor) => visitor.visitSetField(this); | 611 accept(Visitor visitor) => visitor.visitSetField(this); |
607 } | 612 } |
608 | 613 |
609 /// Directly reads from a field on a given object. | 614 /// Directly reads from a field on a given object. |
| 615 /// |
| 616 /// The [object] must either be `null` or an object that has [field]. |
610 class GetField extends Primitive { | 617 class GetField extends Primitive { |
611 final Reference<Primitive> object; | 618 final Reference<Primitive> object; |
612 FieldElement field; | 619 FieldElement field; |
613 | 620 |
| 621 /// True if the receiver is known not to be null. |
| 622 // TODO(asgerf): This is a placeholder until we agree on how to track |
| 623 // side effects. |
| 624 bool objectIsNotNull = false; |
| 625 |
614 GetField(Primitive object, this.field) | 626 GetField(Primitive object, this.field) |
615 : this.object = new Reference<Primitive>(object); | 627 : this.object = new Reference<Primitive>(object); |
616 | 628 |
617 accept(Visitor visitor) => visitor.visitGetField(this); | 629 accept(Visitor visitor) => visitor.visitGetField(this); |
| 630 |
| 631 @override |
| 632 bool get isSafeForElimination => objectIsNotNull; |
618 } | 633 } |
619 | 634 |
620 /// Reads the value of a static field or tears off a static method. | 635 /// Reads the value of a static field or tears off a static method. |
621 class GetStatic extends Primitive { | 636 class GetStatic extends Primitive { |
622 /// Can be [FieldElement] or [FunctionElement]. | 637 /// Can be [FieldElement] or [FunctionElement]. |
623 final Element element; | 638 final Element element; |
624 final SourceInformation sourceInformation; | 639 final SourceInformation sourceInformation; |
625 | 640 |
626 GetStatic(this.element, this.sourceInformation); | 641 GetStatic(this.element, this.sourceInformation); |
627 | 642 |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1256 const RemovalVisitor(); | 1271 const RemovalVisitor(); |
1257 | 1272 |
1258 processReference(Reference reference) { | 1273 processReference(Reference reference) { |
1259 reference.unlink(); | 1274 reference.unlink(); |
1260 } | 1275 } |
1261 | 1276 |
1262 static void remove(Node node) { | 1277 static void remove(Node node) { |
1263 (const RemovalVisitor()).visit(node); | 1278 (const RemovalVisitor()).visit(node); |
1264 } | 1279 } |
1265 } | 1280 } |
OLD | NEW |