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

Unified Diff: sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart

Issue 312793002: dart2dart: Preserve variable names throughout the IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: SVN rebase Created 6 years, 6 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: sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
index c11b3ae8850a0a9e5da557f7d681ae688e532b0f..719f95647a3b18d3bafb950c6b18b928d5d25ffb 100644
--- a/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
@@ -9,9 +9,10 @@ library dart2js.ir_nodes;
import '../dart2jslib.dart' as dart2js show Constant;
import '../elements/elements.dart'
show FunctionElement, LibraryElement, ParameterElement, ClassElement,
- Element;
+ Element, VariableElement;
import '../universe/universe.dart' show Selector, SelectorKind;
import '../dart_types.dart' show DartType, GenericType;
+import '../helpers/helpers.dart';
abstract class Node {
static int hashCount = 0;
@@ -48,7 +49,26 @@ abstract class Definition extends Node {
}
}
+/// A pure expression that cannot throw or diverge.
+/// All primitives are named using the identity of the [Primitive] object.
abstract class Primitive extends Definition {
+ /// The [VariableElement] or [ParameterElement] from which the primitive
+ /// binding originated.
+ Element element;
+
+ /// Register in which the variable binding this primitive can be allocated.
+ /// Separate register spaces are used for primitives with different [element].
+ /// Assigned by [RegisterAllocator], is null before that phase.
+ int registerIndex;
+
+ /// Use the given element as a hint for naming this primitive.
+ ///
+ /// Has no effect if this primitive already has a non-null [element].
+ void useElementAsHint(Element hint) {
+ if (element == null) {
+ element = hint;
+ }
+ }
}
/// Operands to invocations and primitives are always variables. They point to
@@ -299,9 +319,9 @@ class LiteralMap extends Primitive {
}
class Parameter extends Primitive {
- final ParameterElement element;
-
- Parameter(this.element);
+ Parameter(Element element) {
+ super.element = element;
+ }
accept(Visitor visitor) => visitor.visitParameter(this);
}
@@ -502,3 +522,141 @@ class SExpressionStringifier extends Visitor<String> {
return '(IsTrue $value)';
}
}
+
+/// Keeps track of currently unused register indices.
+class RegisterArray {
+ int nextIndex = 0;
+ final List<int> freeStack = <int>[];
+
+ int makeIndex() {
+ if (freeStack.isEmpty) {
+ return nextIndex++;
+ } else {
+ return freeStack.removeLast();
+ }
+ }
+
+ void releaseIndex(int index) {
+ freeStack.add(index);
+ }
+}
+
+/// Assigns indices to each primitive in the IR such that primitives that are
+/// live simultaneously never get assigned the same index.
+/// This information is used by the dart tree builder to generate fewer
+/// redundant variables.
+/// Currently, the liveness analysis is very simple and is often inadequate
+/// for removing all of the redundant variables.
+class RegisterAllocator extends Visitor {
+ /// Separate register spaces for each source-level variable/parameter.
+ /// Note that null is used as key for primitives without elements.
+ final Map<Element, RegisterArray> elementRegisters =
+ <Element, RegisterArray>{};
+
+ RegisterArray getRegisterArray(Element element) {
+ RegisterArray registers = elementRegisters[element];
+ if (registers == null) {
+ registers = new RegisterArray();
+ elementRegisters[element] = registers;
+ }
+ return registers;
+ }
+
+ void allocate(Primitive primitive) {
+ if (primitive.registerIndex == null) {
+ primitive.registerIndex = getRegisterArray(primitive.element).makeIndex();
+ }
+ }
+
+ void release(Primitive primitive) {
+ // Do not share indices for temporaries as this may obstruct inlining.
+ if (primitive.element == null) return;
+ if (primitive.registerIndex != null) {
+ getRegisterArray(primitive.element).releaseIndex(primitive.registerIndex);
+ }
+ }
+
+ void visitReference(Reference reference) {
+ allocate(reference.definition);
+ }
+
+ void visitFunctionDefinition(FunctionDefinition node) {
+ visit(node.body);
+ node.parameters.forEach(allocate); // Assign indices to unused parameters.
+ elementRegisters.clear();
+ }
+
+ void visitLetPrim(LetPrim node) {
+ visit(node.body);
+ release(node.primitive);
+ visit(node.primitive);
+ }
+
+ void visitLetCont(LetCont node) {
+ visit(node.continuation);
+ visit(node.body);
+ }
+
+ void visitInvokeStatic(InvokeStatic node) {
+ node.arguments.forEach(visitReference);
+ }
+
+ void visitInvokeContinuation(InvokeContinuation node) {
+ node.arguments.forEach(visitReference);
+ }
+
+ void visitInvokeMethod(InvokeMethod node) {
+ visitReference(node.receiver);
+ node.arguments.forEach(visitReference);
+ }
+
+ void visitInvokeConstructor(InvokeConstructor node) {
+ node.arguments.forEach(visitReference);
+ }
+
+ void visitConcatenateStrings(ConcatenateStrings node) {
+ node.arguments.forEach(visitReference);
+ }
+
+ void visitBranch(Branch node) {
+ visit(node.condition);
+ }
+
+ void visitInvokeConstConstructor(InvokeConstConstructor node) {
+ node.arguments.forEach(visitReference);
+ }
+
+ void visitLiteralList(LiteralList node) {
+ node.values.forEach(visitReference);
+ }
+
+ void visitLiteralMap(LiteralMap node) {
+ for (int i = 0; i < node.keys.length; ++i) {
+ visitReference(node.keys[i]);
+ visitReference(node.values[i]);
+ }
+ }
+
+ void visitConstant(Constant node) {
+ }
+
+ void visitParameter(Parameter node) {
+ throw "Parameters should not be visited by RegisterAllocator";
+ }
+
+ void visitContinuation(Continuation node) {
+ visit(node.body);
+
+ // Arguments get allocated left-to-right, so we release parameters
+ // right-to-left. This increases the likelihood that arguments can be
+ // transferred without intermediate assignments.
+ for (int i = node.parameters.length - 1; i >= 0; --i) {
+ release(node.parameters[i]);
+ }
+ }
+
+ void visitIsTrue(IsTrue node) {
+ visitReference(node.value);
+ }
+
+}

Powered by Google App Engine
This is Rietveld 408576698