Chromium Code Reviews| Index: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
| index 53a1a98b7f5c118b732ee793c3eb30e338ef2594..c7d68468cd7c802032b21139eb0eba2f54ea5243 100644 |
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
| @@ -234,7 +234,14 @@ abstract class Primitive extends Variable<Primitive> { |
| // TODO(johnniwinther): Require source information for all primitives. |
| SourceInformation get sourceInformation => null; |
| - /// If this is a [Refinement] node, returns the value being refined. |
| + /// If this is a [Refinement], [BoundsCheck] or [NullCheck] node, returns the |
| + /// value being refined, the indexable object being checked, or the value |
| + /// that was checked to be non-null, respectively. |
| + /// |
| + /// Those instructions all return the corresponding operand directly, and |
| + /// this getter can be used to get (closer to) where the value came from. |
| + // |
| + // TODO(asgerf): Also do this for [TypeCast]? |
| Primitive get effectiveDefinition => this; |
| /// True if the two primitives are (refinements of) the same value. |
| @@ -704,6 +711,54 @@ class Refinement extends Primitive { |
| } |
| } |
| +/// Throw an exception if [value] is `null`. |
| +/// |
| +/// Returns [value] so this can be used to restrict code motion. |
| +/// |
| +/// In the simplest form this compiles to `value.toString;`. |
| +/// |
| +/// If [selector] is set, `toString` is replaced with the (possibly minified) |
| +/// invocation name of the selector. This can be shorter and generate a more |
| +/// meaningful error message, but is expensive if [value] is non-null and does |
| +/// not have that property at runtime. |
| +/// |
| +/// If [condition] is set, it is assumed that [condition] is false if and only |
| +/// if [value] is null. The check then compiles to: |
| +/// |
| +/// if (condition) value.toString; (or .selector if non-null) |
| +/// |
| +/// The latter form is useful when [condition] is a form understood by the JS |
| +/// runtime, such as a `typeof` test. |
| +class NullCheck extends Primitive { |
| + final Reference<Primitive> value; |
| + Selector selector; |
| + Reference<Primitive> condition; |
| + final SourceInformation sourceInformation; |
| + |
| + NullCheck(Primitive value, this.sourceInformation) |
| + : this.value = new Reference<Primitive>(value); |
| + |
| + NullCheck.guarded(Primitive condition, Primitive value, this.selector, |
| + this.sourceInformation) |
| + : this.condition = new Reference<Primitive>(condition), |
| + this.value = new Reference<Primitive>(value); |
| + |
| + bool get isSafeForElimination => false; |
| + bool get isSafeForReordering => false; |
| + bool get hasValue => true; |
| + |
| + accept(Visitor visitor) => visitor.visitNullCheck(this); |
| + |
| + void setParentPointers() { |
| + value.parent = this; |
| + if (condition != null) { |
| + condition.parent = this; |
| + } |
| + } |
| + |
| + Primitive get effectiveDefinition => value.definition.effectiveDefinition; |
| +} |
| + |
| /// An "is" type test. |
| /// |
| /// Returns `true` if [value] is an instance of [type]. |
| @@ -1093,9 +1148,9 @@ class GetLength extends Primitive { |
| } |
| } |
| -/// Read an entry from a string or native list. |
| +/// Read an entry from an indexable object. |
| /// |
| -/// [object] must be null or a native list or a string, and [index] must be |
| +/// [object] must be null or an indexable object, and [index] must be |
| /// an integer. |
|
sra1
2015/12/11 03:34:06
Maybe say something about the index being valid
asgerf
2015/12/11 10:15:40
Done.
|
| class GetIndex extends Primitive { |
| final Reference<Primitive> object; |
| @@ -1732,6 +1787,7 @@ abstract class Visitor<T> { |
| T visitGetIndex(GetIndex node); |
| T visitSetIndex(SetIndex node); |
| T visitRefinement(Refinement node); |
| + T visitNullCheck(NullCheck node); |
| // Support for literal foreign code. |
| T visitForeignCode(ForeignCode node); |
| @@ -2050,6 +2106,15 @@ class DeepRecursiveVisitor implements Visitor { |
| processRefinement(node); |
| processReference(node.value); |
| } |
| + |
| + processNullCheck(NullCheck node) {} |
| + visitNullCheck(NullCheck node) { |
| + processNullCheck(node); |
| + processReference(node.value); |
| + if (node.condition != null) { |
| + processReference(node.condition); |
| + } |
| + } |
| } |
| typedef void StackAction(); |