| 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..8fb49d605e77b41ab7449b2ba217c80f94e2450a 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 true 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,10 +1148,10 @@ 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
|
| -/// an integer.
|
| +/// [object] must be null or an indexable object, and [index] must be
|
| +/// an integer where `0 <= index < object.length`.
|
| class GetIndex extends Primitive {
|
| final Reference<Primitive> object;
|
| final Reference<Primitive> index;
|
| @@ -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();
|
|
|