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

Unified Diff: sdk/lib/_internal/compiler/implementation/compile_time_constants.dart

Issue 221873002: Compute frontend/backend specific constants. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 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/compile_time_constants.dart
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index 94523f092acdc2a38df11c8bef179891a973a8ec..3ee1cae15bde821f2aa9947e04c942a95cc04b11 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -4,14 +4,92 @@
part of dart2js;
+abstract class ConstantHandler {
floitsch 2014/04/02 16:50:02 The name "ConstantHandler" is now used with three
Johnni Winther 2014/04/07 11:42:27 Done.
+ Constant getConstantForVariable(VariableElement element);
+}
+
+abstract class ConstantCompiler extends ConstantHandler {
+ /**
+ * Returns a compile-time constant, or reports an error if the element is not
+ * a compile-time constant.
+ */
+ Constant compileConstant(VariableElement element);
+
+ Constant compileNode(Node node, TreeElements elements);
karlklose 2014/04/02 13:04:44 Please ad comments to these methods, too. And perh
Johnni Winther 2014/04/07 11:42:27 Done.
+
+ Constant compileMetadata(MetadataAnnotation metadata,
+ Node node, TreeElements elements);
+}
+
+abstract class BackendConstantHandler extends ConstantHandler {
+ /**
+ * Returns the a compile-time constant if the variable could be compiled
+ * eagerly. Otherwise returns `null`.
+ */
+ void compileVariable(VariableElement element);
+
+ Constant getConstantForNode(Node node, TreeElements elements);
+
+ Constant getConstantForMetadata(MetadataAnnotation metadata);
+}
+
+class DartConstantHandler extends CompilerTask
+ implements ConstantCompiler, BackendConstantHandler {
+ final DartConstantCompiler constantCompiler;
+
+ DartConstantHandler(Compiler compiler)
+ : this.constantCompiler = new DartConstantCompiler(compiler),
+ super(compiler);
+
+ String get name => 'ConstantHandler';
+
+ Constant getConstantForVariable(VariableElement element) {
+ return constantCompiler.getConstantForVariable(element);
+ }
+
+ Constant getConstantForNode(Node node, TreeElements elements) {
+ return constantCompiler.getConstantForNode(node, elements);
+ }
+
+ Constant getConstantForMetadata(MetadataAnnotation metadata) {
+ return metadata.value;
+ }
+
+ Constant compileConstant(VariableElement element) {
+ return measure(() {
+ return constantCompiler.compileConstant(element);
+ });
+ }
+
+ Constant compileVariable(VariableElement element) {
+ return measure(() {
+ return constantCompiler.compileVariable(element);
+ });
+ }
+
+ Constant compileNode(Node node, TreeElements elements) {
+ return measure(() {
+ return constantCompiler.compileNodeWithDefinitions(node, elements);
+ });
+ }
+
+ Constant compileMetadata(MetadataAnnotation metadata,
+ Node node,
+ TreeElements elements) {
+ return measure(() {
+ return constantCompiler.compileMetadata(metadata, node, elements);
+ });
+ }
+}
+
/**
- * The [ConstantHandler] keeps track of compile-time constants,
+ * The [ConstantCompilerBase] is used to keeps track of compile-time constants,
* initializations of global and static fields, and default values of
* optional parameters.
*/
-class ConstantHandler extends CompilerTask {
+abstract class ConstantCompilerBase implements ConstantCompiler {
+ final Compiler compiler;
final ConstantSystem constantSystem;
- final bool isMetadata;
/**
* Contains the initial value of fields. Must contain all static and global
@@ -20,66 +98,40 @@ class ConstantHandler extends CompilerTask {
*
* Invariant: The keys in this map are declarations.
*/
- final Map<VariableElement, Constant> initialVariableValues;
-
- /** Set of all registered compiled constants. */
- final Set<Constant> compiledConstants;
+ final Map<VariableElement, Constant> initialVariableValues =
+ new Map<VariableElement, Constant>();
/** The set of variable elements that are in the process of being computed. */
- final Set<VariableElement> pendingVariables;
-
- /** Caches the statics where the initial value cannot be eagerly compiled. */
- final Set<VariableElement> lazyStatics;
-
- ConstantHandler(Compiler compiler, this.constantSystem,
- { bool this.isMetadata: false })
- : initialVariableValues = new Map<VariableElement, dynamic>(),
- compiledConstants = new Set<Constant>(),
- pendingVariables = new Set<VariableElement>(),
- lazyStatics = new Set<VariableElement>(),
- super(compiler);
+ final Set<VariableElement> pendingVariables = new Set<VariableElement>();
- String get name => 'ConstantHandler';
-
- void addCompileTimeConstantForEmission(Constant constant) {
- compiledConstants.add(constant);
- }
+ ConstantCompilerBase(this.compiler, this.constantSystem);
Constant getConstantForVariable(VariableElement element) {
return initialVariableValues[element.declaration];
}
- /**
- * Returns a compile-time constant, or reports an error if the element is not
- * a compile-time constant.
- */
Constant compileConstant(VariableElement element) {
return compileVariable(element, isConst: true);
}
- /**
- * Returns the a compile-time constant if the variable could be compiled
- * eagerly. Otherwise returns `null`.
- */
Constant compileVariable(VariableElement element, {bool isConst: false}) {
- return measure(() {
- if (initialVariableValues.containsKey(element.declaration)) {
- Constant result = initialVariableValues[element.declaration];
- return result;
- }
- Element currentElement = element;
- if (element.isParameter()
- || element.isFieldParameter()
- || element.isVariable()) {
- currentElement = element.enclosingElement;
- }
- return compiler.withCurrentElement(currentElement, () {
- TreeElements definitions =
- compiler.analyzeElement(currentElement.declaration);
- Constant constant = compileVariableWithDefinitions(
- element, definitions, isConst: isConst);
- return constant;
- });
+
+ if (initialVariableValues.containsKey(element.declaration)) {
+ Constant result = initialVariableValues[element.declaration];
+ return result;
+ }
+ Element currentElement = element;
+ if (element.isParameter() ||
+ element.isFieldParameter() ||
+ element.isVariable()) {
+ currentElement = element.enclosingElement;
+ }
+ return compiler.withCurrentElement(currentElement, () {
+ TreeElements definitions =
+ compiler.analyzeElement(currentElement.declaration);
+ Constant constant = compileVariableWithDefinitions(
+ element, definitions, isConst: isConst);
+ return constant;
});
}
@@ -92,149 +144,114 @@ class ConstantHandler extends CompilerTask {
Constant compileVariableWithDefinitions(VariableElement element,
TreeElements definitions,
{bool isConst: false}) {
- return measure(() {
- if (!isConst && lazyStatics.contains(element)) return null;
-
- Node node = element.parseNode(compiler);
- if (pendingVariables.contains(element)) {
- if (isConst) {
- compiler.reportFatalError(
- node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
- } else {
- lazyStatics.add(element);
- return null;
- }
+ Node node = element.parseNode(compiler);
+ if (pendingVariables.contains(element)) {
+ if (isConst) {
+ compiler.reportFatalError(
+ node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
}
- pendingVariables.add(element);
+ return null;
+ }
+ pendingVariables.add(element);
- Expression initializer = element.initializer;
- Constant value;
- if (initializer == null) {
- // No initial value.
- value = new NullConstant();
- } else {
- value = compileNodeWithDefinitions(
- initializer, definitions, isConst: isConst);
- if (compiler.enableTypeAssertions &&
- value != null &&
- element.isField()) {
- DartType elementType = element.type;
- if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) {
+ Expression initializer = element.initializer;
+ Constant value;
+ if (initializer == null) {
+ // No initial value.
+ value = new NullConstant();
+ } else {
+ value = compileNodeWithDefinitions(
+ initializer, definitions, isConst: isConst);
+ if (compiler.enableTypeAssertions &&
+ value != null &&
+ element.isField()) {
+ DartType elementType = element.type;
+ if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) {
+ if (isConst) {
+ ErroneousElement element = elementType.element;
+ compiler.reportFatalError(
+ node, element.messageKind, element.messageArguments);
+ } else {
+ // We need to throw an exception at runtime.
+ value = null;
+ }
+ } else {
+ DartType constantType = value.computeType(compiler);
+ if (!constantSystem.isSubtype(compiler,
+ constantType, elementType)) {
if (isConst) {
- ErroneousElement element = elementType.element;
compiler.reportFatalError(
- node, element.messageKind, element.messageArguments);
+ node, MessageKind.NOT_ASSIGNABLE,
+ {'fromType': constantType, 'toType': elementType});
} else {
- // We need to throw an exception at runtime.
+ // If the field cannot be lazily initialized, we will throw
+ // the exception at runtime.
value = null;
}
- } else {
- DartType constantType = value.computeType(compiler);
- if (!constantSystem.isSubtype(compiler,
- constantType, elementType)) {
- if (isConst) {
- compiler.reportFatalError(
- node, MessageKind.NOT_ASSIGNABLE,
- {'fromType': constantType, 'toType': elementType});
- } else {
- // If the field cannot be lazily initialized, we will throw
- // the exception at runtime.
- value = null;
- }
- }
}
}
}
- if (value != null) {
- initialVariableValues[element.declaration] = value;
- } else {
- assert(!isConst);
- lazyStatics.add(element);
- }
- pendingVariables.remove(element);
- return value;
- });
+ }
+ if (value != null) {
+ initialVariableValues[element.declaration] = value;
+ } else {
+ assert(!isConst);
+ }
+ pendingVariables.remove(element);
+ return value;
}
Constant compileNodeWithDefinitions(Node node,
TreeElements definitions,
- {bool isConst: false}) {
- return measure(() {
- assert(node != null);
- Constant constant = definitions.getConstant(node);
- if (constant != null) {
- return constant;
- }
- CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
- this, definitions, compiler, isConst: isConst);
- constant = evaluator.evaluate(node);
- if (constant != null) {
- definitions.setConstant(node, constant);
- }
- return constant;
- });
+ {bool isConst: true}) {
+ assert(node != null);
+ CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
+ this, definitions, compiler, isConst: isConst);
+ return evaluator.evaluate(node);
}
- /**
- * Returns an [Iterable] of static non final fields that need to be
- * initialized. The fields list must be evaluated in order since they might
- * depend on each other.
- */
- Iterable<VariableElement> getStaticNonFinalFieldsForEmission() {
- return initialVariableValues.keys.where((element) {
- return element.kind == ElementKind.FIELD
- && !element.isInstanceMember()
- && !element.modifiers.isFinal()
- // The const fields are all either emitted elsewhere or inlined.
- && !element.modifiers.isConst();
- });
+ Constant compileNode(Node node, TreeElements elements) {
+ return compileNodeWithDefinitions(node, elements);
}
- List<VariableElement> getLazilyInitializedFieldsForEmission() {
- return new List<VariableElement>.from(lazyStatics);
+ Constant compileMetadata(MetadataAnnotation metadata,
+ Node node,
+ TreeElements elements) {
+ return compileNodeWithDefinitions(node, elements);
}
+}
- /**
- * Returns a list of constants topologically sorted so that dependencies
- * appear before the dependent constant. [preSortCompare] is a comparator
- * function that gives the constants a consistent order prior to the
- * topological sort which gives the constants an ordering that is less
- * sensitive to perturbations in the source code.
- */
- List<Constant> getConstantsForEmission([preSortCompare]) {
- // We must emit dependencies before their uses.
- Set<Constant> seenConstants = new Set<Constant>();
- List<Constant> result = new List<Constant>();
-
- void addConstant(Constant constant) {
- if (!seenConstants.contains(constant)) {
- constant.getDependencies().forEach(addConstant);
- assert(!seenConstants.contains(constant));
- result.add(constant);
- seenConstants.add(constant);
- }
- }
+class DartConstantCompiler extends ConstantCompilerBase {
+ DartConstantCompiler(Compiler compiler)
+ : super(compiler, const DartConstantSystem());
- List<Constant> sorted = compiledConstants.toList();
- if (preSortCompare != null) {
- sorted.sort(preSortCompare);
- }
- sorted.forEach(addConstant);
- return result;
+ Constant getConstantForNode(Node node, TreeElements definitions) {
+ return definitions.getConstant(node);
}
- Constant getInitialValueFor(VariableElement element) {
- Constant initialValue = initialVariableValues[element.declaration];
- if (initialValue == null) {
- compiler.internalError(element, "No initial value for given element.");
+ Constant getConstantForMetadata(MetadataAnnotation metadata) {
+ return metadata.value;
+ }
+
+ Constant compileNodeWithDefinitions(Node node,
+ TreeElements definitions,
+ {bool isConst: true}) {
+ Constant constant = definitions.getConstant(node);
+ if (constant != null) {
+ return constant;
+ }
+ constant =
+ super.compileNodeWithDefinitions(node, definitions, isConst: isConst);
+ if (constant != null) {
+ definitions.setConstant(node, constant);
}
- return initialValue;
+ return constant;
}
}
class CompileTimeConstantEvaluator extends Visitor {
bool isEvaluatingConstant;
- final ConstantHandler handler;
+ final ConstantCompilerBase handler;
final TreeElements elements;
final Compiler compiler;
@@ -440,6 +457,14 @@ class CompileTimeConstantEvaluator extends Visitor {
return false;
}
+ Constant visitIdentifier(Identifier node) {
+ Element element = elements[node];
+ if (Elements.isClass(element) || Elements.isTypedef(element)) {
+ return makeTypeConstant(element);
+ }
+ return signalNotCompileTimeConstant(node);
+ }
+
// TODO(floitsch): provide better error-messages.
Constant visitSend(Send send) {
Element element = elements[send];
@@ -477,11 +502,6 @@ class CompileTimeConstantEvaluator extends Visitor {
Constant right = evaluate(send.argumentsNode.nodes.tail.head);
Constant result = constantSystem.identity.fold(left, right);
if (result != null) return result;
- } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
- // The node itself is not a constant but we register the selector (the
- // identifier that refers to the class/typedef) as a constant.
- Constant typeConstant = makeTypeConstant(element);
- elements.setConstant(send.selector, typeConstant);
}
return signalNotCompileTimeConstant(send);
} else if (send.isPrefix) {
@@ -810,7 +830,7 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
* Invariant: [constructor] must be an implementation element.
*/
ConstructorEvaluator(FunctionElement constructor,
- ConstantHandler handler,
+ ConstantCompiler handler,
Compiler compiler)
: this.constructor = constructor,
this.definitions = new Map<Element, Constant>(),
@@ -843,6 +863,8 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
// TODO(ngeoffray): Handle type parameters.
if (elementType.element.isTypeVariable()) return;
if (!constantSystem.isSubtype(compiler, constantType, elementType)) {
+ // TODO(johnniwinther): Provide better [node] values that point to the
+ // origin of the constant and not (just) the assignment.
compiler.reportFatalError(
node, MessageKind.NOT_ASSIGNABLE,
{'fromType': elementType, 'toType': constantType});

Powered by Google App Engine
This is Rietveld 408576698