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

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

Issue 226953003: Revert "Compute frontend/backend specific constants." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 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 cc0eac63aafbc4f065a6449c07f68e46dd66af0f..94523f092acdc2a38df11c8bef179891a973a8ec 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -4,77 +4,14 @@
part of dart2js;
-/// A [ConstantEnvironment] provides access for constants compiled for variable
-/// initializers.
-abstract class ConstantEnvironment {
- /// Returns the constant for the initializer of [element].
- Constant getConstantForVariable(VariableElement element);
-}
-
-/// A class that can compile and provide constants for variables, nodes and
-/// metadata.
-abstract class ConstantCompiler extends ConstantEnvironment {
- /// Compiles the compile-time constant for the initializer of [element], or
- /// reports an error if the initializer is not a compile-time constant.
- ///
- /// Depending on implementation, the constant compiler might also compute
- /// the compile-time constant for the backend interpretation of constants.
- ///
- /// The returned constant is always of the frontend interpretation.
- Constant compileConstant(VariableElement element);
-
- /// Computes the compile-time constant for the variable initializer,
- /// if possible.
- void compileVariable(VariableElement element);
-
- /// Compiles the compile-time constant for [node], or reports an error if
- /// [node] is not a compile-time constant.
- ///
- /// Depending on implementation, the constant compiler might also compute
- /// the compile-time constant for the backend interpretation of constants.
- ///
- /// The returned constant is always of the frontend interpretation.
- Constant compileNode(Node node, TreeElements elements);
-
- /// Compiles the compile-time constant for the value [metadata], or reports an
- /// error if the value is not a compile-time constant.
- ///
- /// Depending on implementation, the constant compiler might also compute
- /// the compile-time constant for the backend interpretation of constants.
- ///
- /// The returned constant is always of the frontend interpretation.
- Constant compileMetadata(MetadataAnnotation metadata,
- Node node, TreeElements elements);
-}
-
-/// A [BackendConstantEnvironment] provides access to constants needed for
-/// backend implementation.
-abstract class BackendConstantEnvironment extends ConstantEnvironment {
- /// Returns the compile-time constant associated with [node].
- ///
- /// Depending on implementation, the constant might be stored in [elements].
- Constant getConstantForNode(Node node, TreeElements elements);
-
- /// Returns the compile-time constant value of [metadata].
- Constant getConstantForMetadata(MetadataAnnotation metadata);
-}
-
-/// Interface for the task that compiles the constant environments for the
-/// frontend and backend interpretation of compile-time constants.
-abstract class ConstantCompilerTask extends CompilerTask
- implements ConstantCompiler {
- ConstantCompilerTask(Compiler compiler) : super(compiler);
-}
-
/**
- * The [ConstantCompilerBase] is provides base implementation for compilation of
- * compile-time constants for both the Dart and JavaScript interpretation of
- * constants. It keeps track of compile-time constants for initializations of
- * global and static fields, and default values of optional parameters.
+ * The [ConstantHandler] keeps track of compile-time constants,
+ * initializations of global and static fields, and default values of
+ * optional parameters.
*/
-abstract class ConstantCompilerBase implements ConstantCompiler {
- final Compiler compiler;
+class ConstantHandler extends CompilerTask {
final ConstantSystem constantSystem;
+ final bool isMetadata;
/**
* Contains the initial value of fields. Must contain all static and global
@@ -83,40 +20,66 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
*
* Invariant: The keys in this map are declarations.
*/
- final Map<VariableElement, Constant> initialVariableValues =
- new Map<VariableElement, Constant>();
+ final Map<VariableElement, Constant> initialVariableValues;
+
+ /** Set of all registered compiled constants. */
+ final Set<Constant> compiledConstants;
/** The set of variable elements that are in the process of being computed. */
- final Set<VariableElement> pendingVariables = new Set<VariableElement>();
+ final Set<VariableElement> pendingVariables;
+
+ /** Caches the statics where the initial value cannot be eagerly compiled. */
+ final Set<VariableElement> lazyStatics;
- ConstantCompilerBase(this.compiler, this.constantSystem);
+ 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);
+
+ String get name => 'ConstantHandler';
+
+ void addCompileTimeConstantForEmission(Constant constant) {
+ compiledConstants.add(constant);
+ }
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}) {
-
- 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;
+ 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;
+ });
});
}
@@ -129,116 +92,149 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
Constant compileVariableWithDefinitions(VariableElement element,
TreeElements definitions,
{bool isConst: false}) {
- Node node = element.parseNode(compiler);
- if (pendingVariables.contains(element)) {
- if (isConst) {
- compiler.reportFatalError(
- node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
+ 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;
+ }
}
- return null;
- }
- pendingVariables.add(element);
+ 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) {
- 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)) {
+ 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, MessageKind.NOT_ASSIGNABLE,
- {'fromType': constantType, 'toType': elementType});
+ node, element.messageKind, element.messageArguments);
} else {
- // If the field cannot be lazily initialized, we will throw
- // the exception at runtime.
+ // We need to throw an 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);
- }
- pendingVariables.remove(element);
- return value;
+ if (value != null) {
+ initialVariableValues[element.declaration] = value;
+ } else {
+ assert(!isConst);
+ lazyStatics.add(element);
+ }
+ pendingVariables.remove(element);
+ return value;
+ });
}
Constant compileNodeWithDefinitions(Node node,
TreeElements definitions,
- {bool isConst: true}) {
- assert(node != null);
- CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
- this, definitions, compiler, isConst: isConst);
- return evaluator.evaluate(node);
+ {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;
+ });
}
- Constant compileNode(Node node, TreeElements elements) {
- return compileNodeWithDefinitions(node, elements);
+ /**
+ * 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 compileMetadata(MetadataAnnotation metadata,
- Node node,
- TreeElements elements) {
- return compileNodeWithDefinitions(node, elements);
+ List<VariableElement> getLazilyInitializedFieldsForEmission() {
+ return new List<VariableElement>.from(lazyStatics);
}
-}
-/// [ConstantCompiler] that uses the Dart semantics for the compile-time
-/// constant evaluation.
-class DartConstantCompiler extends ConstantCompilerBase {
- DartConstantCompiler(Compiler compiler)
- : super(compiler, const DartConstantSystem());
-
- Constant getConstantForNode(Node node, TreeElements definitions) {
- return definitions.getConstant(node);
- }
+ /**
+ * 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);
+ }
+ }
- Constant getConstantForMetadata(MetadataAnnotation metadata) {
- return metadata.value;
+ List<Constant> sorted = compiledConstants.toList();
+ if (preSortCompare != null) {
+ sorted.sort(preSortCompare);
+ }
+ sorted.forEach(addConstant);
+ return result;
}
- Constant compileNodeWithDefinitions(Node node,
- TreeElements definitions,
- {bool isConst: true}) {
- Constant constant = definitions.getConstant(node);
- if (constant != null) {
- return constant;
+ Constant getInitialValueFor(VariableElement element) {
+ Constant initialValue = initialVariableValues[element.declaration];
+ if (initialValue == null) {
+ compiler.internalError(element, "No initial value for given element.");
}
- constant =
- super.compileNodeWithDefinitions(node, definitions, isConst: isConst);
- if (constant != null) {
- definitions.setConstant(node, constant);
- }
- return constant;
+ return initialValue;
}
}
class CompileTimeConstantEvaluator extends Visitor {
bool isEvaluatingConstant;
- final ConstantCompilerBase handler;
+ final ConstantHandler handler;
final TreeElements elements;
final Compiler compiler;
@@ -444,14 +440,6 @@ 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];
@@ -489,6 +477,11 @@ 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) {
@@ -817,7 +810,7 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
* Invariant: [constructor] must be an implementation element.
*/
ConstructorEvaluator(FunctionElement constructor,
- ConstantCompiler handler,
+ ConstantHandler handler,
Compiler compiler)
: this.constructor = constructor,
this.definitions = new Map<Element, Constant>(),
@@ -850,8 +843,6 @@ 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});
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/common.dart ('k') | sdk/lib/_internal/compiler/implementation/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698