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

Unified Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 1112563002: Refactor SsaBuilder.visitStaticSend and visitGetterSend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 5 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
« no previous file with comments | « pkg/compiler/lib/src/resolved_visitor.dart ('k') | tests/compiler/dart2js/compiler_helper.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/ssa/builder.dart
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 93de3b9d117507622aecfa3857dde2f0f6db1ada..38a47424bde247df22b3fb40e1c96183d0c9e892 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -1518,12 +1518,6 @@ class SsaBuilder extends NewResolvedVisitor {
return graph.addConstant(getConstantForNode(node), compiler);
}
- bool isLazilyInitialized(VariableElement element) {
- ConstantExpression initialValue =
- backend.constants.getConstantForVariable(element);
- return initialValue == null;
- }
-
TypeMask cachedTypeOfThis;
TypeMask getTypeOfThis() {
@@ -3245,95 +3239,122 @@ class SsaBuilder extends NewResolvedVisitor {
}
}
- void generateGetter(ast.Send send, Element element) {
- if (element != null && element.isForeign(backend)) {
- visitForeignGetter(send);
- } else if (Elements.isStaticOrTopLevelField(element)) {
- ConstantExpression constant;
- if (element.isField && !element.isAssignable) {
+ /// Generate read access of an unresolved static or top level entity.
+ void generateStaticUnresolvedGet(ast.Send node, Element element) {
+ if (element is ErroneousElement) {
+ // An erroneous element indicates an unresolved static getter.
+ generateThrowNoSuchMethod(
+ node,
+ noSuchMethodTargetSymbolString(element, 'get'),
+ argumentNodes: const Link<ast.Node>());
+ } else {
+ // This happens when [element] has parse errors.
+ assert(invariant(node, element.isErroneous));
+ // TODO(ahe): Do something like the above, that is, emit a runtime
+ // error.
+ stack.add(graph.addConstantNull(compiler));
+ }
+ }
+
+ /// Read a static or top level [field] of constant value.
+ void generateStaticConstGet(
+ ast.Send node,
+ FieldElement field,
+ ConstantExpression constant) {
+ ConstantValue value = constant.value;
+ HConstant instruction;
+ // Constants that are referred via a deferred prefix should be referred
+ // by reference.
+ PrefixElement prefix = compiler.deferredLoadTask
+ .deferredPrefixElement(node, elements);
+ if (prefix != null) {
+ instruction = graph.addDeferredConstant(value, prefix, compiler);
+ } else {
+ instruction = graph.addConstant(value, compiler);
+ }
+ stack.add(instruction);
+ // The inferrer may have found a better type than the constant
+ // handler in the case of lists, because the constant handler
+ // does not look at elements in the list.
+ TypeMask type =
+ TypeMaskFactory.inferredTypeForElement(field, compiler);
+ if (!type.containsAll(compiler.world) &&
+ !instruction.isConstantNull()) {
+ // TODO(13429): The inferrer should know that an element
+ // cannot be null.
+ instruction.instructionType = type.nonNullable();
+ }
+ }
+
+ /// Read a static or top level [field].
+ void generateStaticFieldGet(ast.Send node, FieldElement field) {
+ generateIsDeferredLoadedCheckIfNeeded(node);
+
+ ConstantExpression constant =
+ backend.constants.getConstantForVariable(field);
+ if (constant != null) {
+ if (!field.isAssignable) {
// A static final or const. Get its constant value and inline it if
// the value can be compiled eagerly.
- constant = backend.constants.getConstantForVariable(element);
- }
- if (constant != null) {
- ConstantValue value = constant.value;
- HConstant instruction;
- // Constants that are referred via a deferred prefix should be referred
- // by reference.
- PrefixElement prefix = compiler.deferredLoadTask
- .deferredPrefixElement(send, elements);
- if (prefix != null) {
- instruction = graph.addDeferredConstant(value, prefix, compiler);
- } else {
- instruction = graph.addConstant(value, compiler);
- }
- stack.add(instruction);
- // The inferrer may have found a better type than the constant
- // handler in the case of lists, because the constant handler
- // does not look at elements in the list.
- TypeMask type =
- TypeMaskFactory.inferredTypeForElement(element, compiler);
- if (!type.containsAll(compiler.world) &&
- !instruction.isConstantNull()) {
- // TODO(13429): The inferrer should know that an element
- // cannot be null.
- instruction.instructionType = type.nonNullable();
- }
- } else if (element.isField && isLazilyInitialized(element)) {
- HInstruction instruction = new HLazyStatic(
- element,
- TypeMaskFactory.inferredTypeForElement(element, compiler));
- push(instruction);
+ generateStaticConstGet(node, field, constant);
} else {
- if (element.isGetter) {
- pushInvokeStatic(send, element, <HInstruction>[]);
- } else {
- // TODO(5346): Try to avoid the need for calling [declaration] before
- // creating an [HStatic].
- HInstruction instruction = new HStatic(
- element.declaration,
- TypeMaskFactory.inferredTypeForElement(element, compiler));
- push(instruction);
- }
- }
- } else if (Elements.isInstanceSend(send, elements)) {
- HInstruction receiver = generateInstanceSendReceiver(send);
- generateInstanceGetterWithCompiledReceiver(
- send, elements.getSelector(send), receiver);
- } else if (Elements.isStaticOrTopLevelFunction(element)) {
- // TODO(5346): Try to avoid the need for calling [declaration] before
- // creating an [HStatic].
- push(new HStatic(element.declaration, backend.nonNullType));
- // TODO(ahe): This should be registered in codegen.
- registry.registerGetOfStaticFunction(element.declaration);
- } else if (Elements.isErroneous(element)) {
- if (element is ErroneousElement) {
- // An erroneous element indicates an unresolved static getter.
- generateThrowNoSuchMethod(
- send,
- noSuchMethodTargetSymbolString(element, 'get'),
- argumentNodes: const Link<ast.Node>());
- } else {
- // TODO(ahe): Do something like the above, that is, emit a runtime
- // error.
- stack.add(graph.addConstantNull(compiler));
+ // TODO(5346): Try to avoid the need for calling [declaration] before
+ // creating an [HStatic].
+ HInstruction instruction = new HStatic(
+ field.declaration,
+ TypeMaskFactory.inferredTypeForElement(field, compiler));
+ push(instruction);
}
} else {
- if (send.asSendSet() == null) {
- internalError(send, "Unhandled local: $element");
- }
- // TODO(johnniwinther): Remove this when [generateGetter] is no longer
- // called from [visitSendSet] (for compound assignments).
- handleLocalGet(element);
+ HInstruction instruction = new HLazyStatic(
+ field,
+ TypeMaskFactory.inferredTypeForElement(field, compiler));
+ push(instruction);
+ }
+ }
+
+ /// Generate a getter invocation of the static or top level [getter].
+ void generateStaticGetterGet(ast.Send node, MethodElement getter) {
+ if (getter.isDeferredLoaderGetter) {
+ generateDeferredLoaderGet(node, getter);
+ } else {
+ generateIsDeferredLoadedCheckIfNeeded(node);
+ pushInvokeStatic(node, getter, <HInstruction>[]);
}
}
+ /// Generate a dynamic getter invocation.
+ void generateDynamicGet(ast.Send node) {
+ HInstruction receiver = generateInstanceSendReceiver(node);
+ generateInstanceGetterWithCompiledReceiver(
+ node, elements.getSelector(node), receiver);
+ }
+
+ /// Generate a closurization of the static or top level [function].
+ void generateStaticFunctionGet(ast.Send node, MethodElement function) {
+ generateIsDeferredLoadedCheckIfNeeded(node);
+ // TODO(5346): Try to avoid the need for calling [declaration] before
+ // creating an [HStatic].
+ push(new HStatic(function.declaration, backend.nonNullType));
+ // TODO(ahe): This should be registered in codegen.
+ registry.registerGetOfStaticFunction(function.declaration);
+ }
+
/// Read a local variable, function or parameter.
void handleLocalGet(LocalElement local) {
stack.add(localsHandler.readLocal(local));
}
@override
+ void visitDynamicPropertyGet(
+ ast.Send node,
+ ast.Node receiver,
+ Selector selector,
+ _) {
+ generateDynamicGet(node);
+ }
+
+ @override
void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) {
handleLocalGet(variable);
}
@@ -3348,6 +3369,62 @@ class SsaBuilder extends NewResolvedVisitor {
handleLocalGet(function);
}
+ @override
+ void visitStaticFieldGet(
+ ast.Send node,
+ FieldElement field,
+ _) {
+ generateStaticFieldGet(node, field);
+ }
+
+ @override
+ void visitStaticFunctionGet(
+ ast.Send node,
+ MethodElement function,
+ _) {
+ generateStaticFunctionGet(node, function);
+ }
+
+ @override
+ void visitStaticGetterGet(
+ ast.Send node,
+ FunctionElement getter,
+ _) {
+ generateStaticGetterGet(node, getter);
+ }
+
+ @override
+ void visitThisPropertyGet(
+ ast.Send node,
+ Selector selector,
+ _) {
+ generateDynamicGet(node);
+ }
+
+ @override
+ void visitTopLevelFieldGet(
+ ast.Send node,
+ FieldElement field,
+ _) {
+ generateStaticFieldGet(node, field);
+ }
+
+ @override
+ void visitTopLevelFunctionGet(
+ ast.Send node,
+ MethodElement function,
+ _) {
+ generateStaticFunctionGet(node, function);
+ }
+
+ @override
+ void visitTopLevelGetterGet(
+ ast.Send node,
+ FunctionElement getter,
+ _) {
+ generateStaticGetterGet(node, getter);
+ }
+
void generateInstanceSetterWithCompiledReceiver(ast.Send send,
HInstruction receiver,
HInstruction value,
@@ -4014,9 +4091,8 @@ class SsaBuilder extends NewResolvedVisitor {
<HInstruction>[]));
}
- visitForeignSend(ast.Send node) {
- Selector selector = elements.getSelector(node);
- String name = selector.name;
+ void handleForeignSend(ast.Send node, FunctionElement element) {
+ String name = element.name;
if (name == 'JS') {
handleForeignJs(node);
} else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') {
@@ -4091,15 +4167,13 @@ class SsaBuilder extends NewResolvedVisitor {
} else if (name == 'JS_STRING_CONCAT') {
handleJsStringConcat(node);
} else {
- throw "Unknown foreign: ${selector}";
+ throw "Unknown foreign: ${element}";
}
}
- visitForeignGetter(ast.Send node) {
- Element element = elements[node];
+ generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader) {
// Until now we only handle these as getters.
- invariant(node, element.isDeferredLoaderGetter);
- FunctionElement deferredLoader = element;
+ invariant(node, deferredLoader.isDeferredLoaderGetter);
Element loadFunction = compiler.loadLibraryFunction;
PrefixElement prefixElement = deferredLoader.enclosingElement;
String loadId = compiler.deferredLoadTask
@@ -4798,72 +4872,156 @@ class SsaBuilder extends NewResolvedVisitor {
}
assert(invariant(node, node.arguments.tail.isEmpty,
message: "Invalid assertion: $node"));
- buildStaticFunctionInvoke(
+ generateStaticFunctionInvoke(
node, backend.assertMethod, CallStructure.ONE_ARG);
}
visitStaticSend(ast.Send node) {
- CallStructure callStructure = elements.getSelector(node).callStructure;
- Element element = elements[node];
- if (elements.isAssert(node)) {
- element = backend.assertMethod;
- }
- if (element.isForeign(backend) && element.isFunction) {
- visitForeignSend(node);
- return;
- }
- if (element.isErroneous) {
- if (element is ErroneousElement) {
- // An erroneous element indicates that the funciton could not be
- // resolved (a warning has been issued).
- generateThrowNoSuchMethod(node,
- noSuchMethodTargetSymbolString(element),
- argumentNodes: node.arguments);
- } else {
- // TODO(ahe): Do something like [generateWrongArgumentCountError].
- stack.add(graph.addConstantNull(compiler));
- }
- return;
- }
- invariant(element, !element.isGenerativeConstructor);
- generateIsDeferredLoadedCheckIfNeeded(node);
- if (element.isFunction) {
- // TODO(5347): Try to avoid the need for calling [implementation] before
- // calling [makeStaticArgumentList].
- if (!callStructure.signatureApplies(element.implementation)) {
- generateWrongArgumentCountError(node, element, node.arguments);
- return;
- }
- buildStaticFunctionInvoke(node, element, callStructure);
- } else {
- generateGetter(node, element);
- List<HInstruction> inputs = <HInstruction>[pop()];
- addDynamicSendArgumentsToList(node, inputs);
- Selector closureSelector = callStructure.callSelector;
- pushWithPosition(
- new HInvokeClosure(closureSelector, inputs, backend.dynamicType),
- node);
- }
+ internalError(node, "Unexpected visitStaticSend");
}
- void buildStaticFunctionInvoke(
+ /// Generate an invocation to the static or top level [function].
+ void generateStaticFunctionInvoke(
ast.Send node,
- FunctionElement element,
+ FunctionElement function,
CallStructure callStructure) {
List<HInstruction> inputs = makeStaticArgumentList(
callStructure,
node.arguments,
- element.implementation);
+ function.implementation);
- if (element == compiler.identicalFunction) {
+ if (function == compiler.identicalFunction) {
pushWithPosition(
new HIdentity(inputs[0], inputs[1], null, backend.boolType), node);
return;
} else {
- pushInvokeStatic(node, element, inputs);
+ pushInvokeStatic(node, function, inputs);
+ }
+ }
+
+ /// Generate an invocation to a static or top level function with the wrong
+ /// number of arguments.
+ void generateStaticFunctionIncompatibleInvoke(ast.Send node,
+ Element element) {
+ generateWrongArgumentCountError(node, element, node.arguments);
+ }
+
+ @override
+ void visitStaticFieldInvoke(
+ ast.Send node,
+ FieldElement field,
+ ast.NodeList arguments,
+ CallStructure callStructure,
+ _) {
+ generateStaticFieldGet(node, field);
+ generateCallInvoke(node, pop());
+ }
+
+ @override
+ void visitStaticFunctionInvoke(
+ ast.Send node,
+ MethodElement function,
+ ast.NodeList arguments,
+ CallStructure callStructure,
+ _) {
+ generateStaticFunctionInvoke(node, function, callStructure);
+ }
+
+ @override
+ void visitStaticFunctionIncompatibleInvoke(
+ ast.Send node,
+ MethodElement function,
+ ast.NodeList arguments,
+ CallStructure callStructure,
+ _) {
+ generateStaticFunctionIncompatibleInvoke(node, function);
+ }
+
+ @override
+ void visitStaticGetterInvoke(
+ ast.Send node,
+ FunctionElement getter,
+ ast.NodeList arguments,
+ CallStructure callStructure,
+ _) {
+ generateStaticGetterGet(node, getter);
+ generateCallInvoke(node, pop());
+ }
+
+ @override
+ void visitTopLevelFieldInvoke(
+ ast.Send node,
+ FieldElement field,
+ ast.NodeList arguments,
+ CallStructure callStructure,
+ _) {
+ generateStaticFieldGet(node, field);
+ generateCallInvoke(node, pop());
+ }
+
+ @override
+ void visitTopLevelFunctionInvoke(
+ ast.Send node,
+ MethodElement function,
+ ast.NodeList arguments,
+ CallStructure callStructure,
+ _) {
+ if (function.isForeign(backend)) {
+ handleForeignSend(node, function);
+ } else {
+ generateStaticFunctionInvoke(node, function, callStructure);
}
}
+ @override
+ void visitTopLevelFunctionIncompatibleInvoke(
+ ast.Send node,
+ MethodElement function,
+ ast.NodeList arguments,
+ CallStructure callStructure,
+ _) {
+ generateStaticFunctionIncompatibleInvoke(node, function);
+ }
+
+ @override
+ void visitTopLevelGetterInvoke(
+ ast.Send node,
+ FunctionElement getter,
+ ast.NodeList arguments,
+ CallStructure callStructure,
+ _) {
+ generateStaticGetterGet(node, getter);
+ generateCallInvoke(node, pop());
+ }
+
+ @override
+ void visitUnresolvedGet(
+ ast.Send node,
+ Element element,
+ _) {
+ generateStaticUnresolvedGet(node, element);
+ }
+
+ @override
+ void visitUnresolvedInvoke(
+ ast.Send node,
+ Element element,
+ ast.NodeList arguments,
+ Selector selector,
+ _) {
+ if (element is ErroneousElement) {
+ // An erroneous element indicates that the funciton could not be
+ // resolved (a warning has been issued).
+ generateThrowNoSuchMethod(node,
+ noSuchMethodTargetSymbolString(element),
+ argumentNodes: node.arguments);
+ } else {
+ // TODO(ahe): Do something like [generateWrongArgumentCountError].
+ stack.add(graph.addConstantNull(compiler));
+ }
+ return;
+ }
+
HConstant addConstantString(String string) {
ast.DartString dartString = new ast.DartString.literal(string);
ConstantValue constant = constantSystem.createString(dartString);
@@ -4985,8 +5143,7 @@ class SsaBuilder extends NewResolvedVisitor {
}
visitGetterSend(ast.Send node) {
- generateIsDeferredLoadedCheckIfNeeded(node);
- generateGetter(node, elements[node]);
+ internalError(node, "Unexpected visitGetterSend");
}
// TODO(antonm): migrate rest of SsaFromAstMixin to internalError.
@@ -5390,8 +5547,18 @@ class SsaBuilder extends NewResolvedVisitor {
receiver = generateInstanceSendReceiver(node);
generateInstanceGetterWithCompiledReceiver(
node, elements.getGetterSelectorInComplexSendSet(node), receiver);
+ } else if (getter.isErroneous) {
+ generateStaticUnresolvedGet(node, getter);
+ } else if (getter.isField) {
+ generateStaticFieldGet(node, getter);
+ } else if (getter.isGetter) {
+ generateStaticGetterGet(node, getter);
+ } else if (getter.isFunction) {
+ generateStaticFunctionGet(node, getter);
+ } else if (getter.isLocal) {
+ handleLocalGet(getter);
} else {
- generateGetter(node, getter);
+ internalError(node, "Unexpected getter: $getter");
}
HInstruction getterInstruction = pop();
handleComplexOperatorSend(node, getterInstruction, node.arguments);
« no previous file with comments | « pkg/compiler/lib/src/resolved_visitor.dart ('k') | tests/compiler/dart2js/compiler_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698