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

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

Issue 1330503003: dart2js cps: Add path-sensitive types by inserting refinement IR nodes. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Comments Created 5 years, 3 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
« no previous file with comments | « pkg/compiler/lib/src/common/names.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 b685c4582b9235c20c78583dc47cdbf5db06ba25..c0c4942f3e0c7cfde46c29356ae4acc5c907df8e 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
library dart2js.ir_nodes;
+import 'dart:collection';
import '../constants/values.dart' as values show ConstantValue;
import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
import '../elements/elements.dart';
@@ -119,6 +120,41 @@ abstract class Definition<T extends Definition<T>> extends Node {
}
}
+class EffectiveUseIterator extends Iterator<Reference<Primitive>> {
+ Reference<Primitive> current;
+ Reference<Primitive> next;
+ final List<Refinement> stack = <Refinement>[];
+
+ EffectiveUseIterator(Primitive prim) : next = prim.firstRef;
+
+ bool moveNext() {
+ Reference<Primitive> ref = next;
+ while (true) {
+ if (ref == null) {
+ if (stack.isNotEmpty) {
+ ref = stack.removeLast().firstRef;
+ } else {
+ current = null;
+ return false;
+ }
+ } else if (ref.parent is Refinement) {
+ stack.add(ref.parent);
+ ref = ref.next;
+ } else {
+ current = ref;
+ next = current.next;
+ return true;
+ }
+ }
+ }
+}
+
+class EffectiveUseIterable extends IterableBase<Reference<Primitive>> {
+ Primitive primitive;
+ EffectiveUseIterable(this.primitive);
+ EffectiveUseIterator get iterator => new EffectiveUseIterator(primitive);
+}
+
/// A named value.
///
/// The identity of the [Primitive] object is the name of the value.
@@ -153,6 +189,34 @@ abstract class Primitive extends Definition<Primitive> {
/// The source information associated with this primitive.
// TODO(johnniwinther): Require source information for all primitives.
SourceInformation get sourceInformation => null;
+
+ /// If this is a [Refinement] node, returns the value being refined.
+ Primitive get effectiveDefinition => this;
+
+ /// True if the two primitives are (refinements of) the same value.
+ bool sameValue(Primitive other) {
+ return effectiveDefinition == other.effectiveDefinition;
+ }
+
+ /// Iterates all non-refinement uses of the primitive and all uses of
+ /// a [Refinement] of this primitive (transitively).
+ ///
+ /// Notes regarding concurrent modification:
+ /// - The current reference may safely be unlinked.
+ /// - Yet unvisited references may not be unlinked.
+ /// - References to this primitive created during iteration will not be seen.
+ /// - References to a refinement of this primitive may not be created during
+ /// iteration.
+ EffectiveUseIterable get effectiveUses => new EffectiveUseIterable(this);
+
+ bool get hasMultipleEffectiveUses {
+ Iterator it = effectiveUses.iterator;
+ return it.moveNext() && it.moveNext();
+ }
+
+ bool get hasNoEffectiveUses {
+ return effectiveUses.isEmpty;
+ }
}
/// Operands to invocations and primitives are always variables. They point to
@@ -439,6 +503,28 @@ class InvokeConstructor extends CallExpression {
accept(Visitor visitor) => visitor.visitInvokeConstructor(this);
}
+/// An alias for [value] in a context where the value is known to satisfy
+/// [type].
+///
+/// Refinement nodes are inserted before the type propagator pass and removed
+/// afterwards, so as not to complicate passes that don't reason about types,
+/// but need to reason about value references being identical (i.e. referring
+/// to the same primitive).
+class Refinement extends Primitive {
+ Reference<Primitive> value;
+ final TypeMask type;
+
+ Refinement(Primitive value, this.type)
+ : value = new Reference<Primitive>(value);
+
+ bool get isSafeForElimination => true;
+ bool get isSafeForReordering => false;
+
+ accept(Visitor visitor) => visitor.visitRefinement(this);
+
+ Primitive get effectiveDefinition => value.definition.effectiveDefinition;
+}
+
/// An "is" type test.
///
/// Returns `true` if [value] is an instance of [type].
@@ -1201,6 +1287,7 @@ abstract class Visitor<T> {
T visitGetLength(GetLength node);
T visitGetIndex(GetIndex node);
T visitSetIndex(SetIndex node);
+ T visitRefinement(Refinement node);
// Support for literal foreign code.
T visitForeignCode(ForeignCode node);
@@ -1504,6 +1591,12 @@ class LeafVisitor implements Visitor {
processReference(node.index);
processReference(node.value);
}
+
+ processRefinement(Refinement node) {}
+ visitRefinement(Refinement node) {
+ processRefinement(node);
+ processReference(node.value);
+ }
}
typedef void StackAction();
« no previous file with comments | « pkg/compiler/lib/src/common/names.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