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

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart

Issue 1668913002: dart2js cps: More aggressive operator specialization. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update test expectations Created 4 years, 10 months 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 side-by-side diff with in-line comments
Download patch
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 b0af0b99253e6a1fa3c2699e67f28acbc7820339..01c49a39607e2a60bb67f32b28378a237daf57cc 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -260,7 +260,7 @@ abstract class Primitive extends Variable<Primitive> {
// TODO(johnniwinther): Require source information for all primitives.
SourceInformation get sourceInformation => null;
- /// If this is a [Refinement], [BoundsCheck] or [NullCheck] node, returns the
+ /// If this is a [Refinement], [BoundsCheck] or [ReceiverCheck] node, returns the
/// value being refined, the indexable object being checked, or the value
/// that was checked to be non-null, respectively.
///
@@ -805,7 +805,7 @@ class Refinement extends Primitive {
class BoundsCheck extends Primitive {
final Reference<Primitive> object;
Reference<Primitive> index;
- Reference<Primitive> length; // FIXME write docs for length
+ Reference<Primitive> length;
int checks;
final SourceInformation sourceInformation;
@@ -879,53 +879,99 @@ class BoundsCheck extends Primitive {
Primitive get effectiveDefinition => object.definition.effectiveDefinition;
}
-/// Throw an exception if [value] is `null`.
+/// Throw a [NoSuchMethodError] if [value] cannot respond to [selector].
///
/// Returns [value] so this can be used to restrict code motion.
///
-/// In the simplest form this compiles to `value.toString;`.
+/// The check can take one of three forms:
///
-/// [selector] holds the selector that is the cause of the null check. This is
-/// usually a method that was inlined where [value] the receiver.
+/// value.toString;
+/// value.selectorName;
+/// value.selectorName(); (should only be used if check always fails)
///
-/// If [selector] is set and [useSelector] is true, `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.
+/// The first two forms are used when it is known that only null fails the
+/// check. Additionally, the check may be guarded by a [condition], allowing
+/// for three more forms:
///
-/// 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; (this form is valid but unused)
+/// if (condition) value.selectorName;
+/// if (condition) value.selectorName();
///
-/// if (condition) value.toString; (or .selector if non-null)
+/// The condition must be true if and only if the check should fail. It should
+/// ideally be of a form understood by JS engines, e.g. a `typeof` test.
///
-/// The latter form is useful when [condition] is a form understood by the JS
-/// runtime, such as a `typeof` test.
-class NullCheck extends Primitive {
+/// If [useSelector] is false, the first form instead becomes `value.toString;`.
+/// This form is faster when the value is non-null and the accessed property has
+/// been removed by tree shaking.
+///
+/// [selector] may not be one of the selectors implemented by the null object.
+class ReceiverCheck extends Primitive {
final Reference<Primitive> value;
final Selector selector;
- final bool useSelector;
- final Reference<Primitive> condition;
final SourceInformation sourceInformation;
+ final Reference<Primitive> condition;
+ final int _flags;
- NullCheck(Primitive value, this.sourceInformation,
- {Primitive condition,
- this.selector,
- this.useSelector: false})
- : this.value = new Reference<Primitive>(value),
- this.condition =
- condition == null ? null : new Reference<Primitive>(condition);
+ static const int _USE_SELECTOR = 1 << 0;
+ static const int _NULL_CHECK = 1 << 1;
- NullCheck.guarded(Primitive condition, Primitive value, this.selector,
- this.sourceInformation)
- : this.condition = new Reference<Primitive>(condition),
- this.value = new Reference<Primitive>(value),
- this.useSelector = true;
+ /// True if the selector name should be used in the check; otherwise
+ /// `toString` will be used.
+ bool get useSelector => _flags & _USE_SELECTOR != 0;
+
+ /// True if null is the only possible input that cannot respond to [selector].
+ bool get isNullCheck => _flags & _NULL_CHECK != 0;
+
+
+ /// Constructor for creating checks in arbitrary configurations.
+ ///
+ /// Consider using one of the named constructors instead.
+ ///
+ /// [useSelector] and [isNullCheck] are mandatory named arguments.
+ ReceiverCheck(Primitive value, this.selector, this.sourceInformation,
+ {Primitive condition, bool useSelector, bool isNullCheck})
+ : value = new Reference<Primitive>(value),
+ condition = _optionalReference(condition),
+ _flags = (useSelector ? _USE_SELECTOR : 0) |
+ (isNullCheck ? _NULL_CHECK : 0);
+
+ /// Simplified constructor for building null checks.
+ ///
+ /// Null must be the only possible input value that does not respond to
+ /// [selector].
+ ReceiverCheck.nullCheck(
+ Primitive value,
+ Selector selector,
+ SourceInformation sourceInformation,
+ {Primitive condition})
+ : this(value,
+ selector,
+ sourceInformation,
+ condition: condition,
+ useSelector: condition != null,
+ isNullCheck: true);
+
+ /// Simplified constructor for building the general check of form:
+ ///
+ /// if (condition) value.selectorName();
+ ///
+ ReceiverCheck.generalCheck(
+ Primitive value,
+ Selector selector,
+ SourceInformation sourceInformation,
+ Primitive condition)
+ : this(value,
+ selector,
+ sourceInformation,
+ condition: condition,
+ useSelector: true,
+ isNullCheck: false);
bool get isSafeForElimination => false;
bool get isSafeForReordering => false;
bool get hasValue => true;
- accept(Visitor visitor) => visitor.visitNullCheck(this);
+ accept(Visitor visitor) => visitor.visitReceiverCheck(this);
void setParentPointers() {
value.parent = this;
@@ -935,6 +981,10 @@ class NullCheck extends Primitive {
}
Primitive get effectiveDefinition => value.definition.effectiveDefinition;
+
+ String get nullCheckString => isNullCheck ? 'null-check' : 'general-check';
+ String get useSelectorString => useSelector ? 'use-selector' : 'no-selector';
+ String get flagString => '$nullCheckString $useSelectorString';
}
/// An "is" type test.
@@ -1930,6 +1980,16 @@ class Yield extends UnsafePrimitive {
}
}
+Reference<Primitive> _reference(Primitive definition) {
+ return new Reference<Primitive>(definition);
+}
+
+Reference<Primitive> _optionalReference(Primitive definition) {
+ return definition == null
+ ? null
+ : new Reference<Primitive>(definition);
+}
+
List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) {
return definitions.map((e) => new Reference<Primitive>(e)).toList();
}
@@ -2077,7 +2137,7 @@ abstract class Visitor<T> implements BlockVisitor<T> {
T visitSetIndex(SetIndex node);
T visitRefinement(Refinement node);
T visitBoundsCheck(BoundsCheck node);
- T visitNullCheck(NullCheck node);
+ T visitReceiverCheck(ReceiverCheck node);
T visitForeignCode(ForeignCode node);
}
@@ -2400,8 +2460,8 @@ class DeepRecursiveVisitor implements Visitor {
}
}
- processNullCheck(NullCheck node) {}
- visitNullCheck(NullCheck node) {
+ processNullCheck(ReceiverCheck node) {}
+ visitReceiverCheck(ReceiverCheck node) {
processNullCheck(node);
processReference(node.value);
if (node.condition != null) {
@@ -2761,11 +2821,13 @@ class DefinitionCopyingVisitor extends Visitor<Definition> {
}
}
- Definition visitNullCheck(NullCheck node) {
- return new NullCheck(getCopy(node.value), node.sourceInformation,
+ Definition visitReceiverCheck(ReceiverCheck node) {
+ return new ReceiverCheck(getCopy(node.value),
+ node.selector,
+ node.sourceInformation,
condition: node.condition == null ? null : getCopy(node.condition),
- selector: node.selector,
- useSelector: node.useSelector);
+ useSelector: node.useSelector,
+ isNullCheck: node.isNullCheck);
}
Definition visitForeignCode(ForeignCode node) {
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698