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

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

Issue 2338093002: Build entire program with kernel for conversion to ssa. (Closed)
Patch Set: some tweaks Created 4 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/kernel/kernel_visitor.dart ('k') | pkg/compiler/lib/src/ssa/kernel_ast_adapter.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_kernel.dart
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 88cfe1809e999e1aa68ab945d61165da7babd9a7..3eb696af225dc25b6d65c3249b15e748d6f9dd35 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -8,14 +8,14 @@ import '../common.dart';
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
import '../common/tasks.dart' show CompilerTask;
import '../compiler.dart';
+import '../dart_types.dart';
import '../elements/elements.dart';
import '../io/source_information.dart';
import '../js_backend/backend.dart' show JavaScriptBackend;
import '../kernel/kernel.dart';
-import '../kernel/kernel_visitor.dart';
-import '../resolution/tree_elements.dart';
import '../tree/dartstring.dart';
import '../types/masks.dart';
+import '../universe/selector.dart';
import 'graph_builder.dart';
import 'kernel_ast_adapter.dart';
@@ -37,23 +37,16 @@ class SsaKernelBuilderTask extends CompilerTask {
return measure(() {
AstElement element = work.element.implementation;
Kernel kernel = backend.kernelTask.kernel;
- ir.Procedure function = kernel.functions[element];
- KernelSsaBuilder builder = new KernelSsaBuilder(
- function,
- element,
- work.resolvedAst,
- backend.compiler,
- work.registry,
- sourceInformationFactory,
- kernel);
+ KernelSsaBuilder builder = new KernelSsaBuilder(element, work.resolvedAst,
+ backend.compiler, work.registry, sourceInformationFactory, kernel);
return builder.build();
});
}
}
class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
- final ir.Procedure function;
- final FunctionElement functionElement;
+ ir.Node target;
+ final AstElement targetElement;
final ResolvedAst resolvedAst;
final Compiler compiler;
final CodegenRegistry registry;
@@ -64,45 +57,79 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
KernelAstAdapter astAdapter;
KernelSsaBuilder(
- this.function,
- this.functionElement,
+ this.targetElement,
this.resolvedAst,
this.compiler,
this.registry,
SourceInformationStrategy sourceInformationFactory,
Kernel kernel) {
- graph.element = functionElement;
+ graph.element = targetElement;
// TODO(het): Should sourceInformationBuilder be in GraphBuilder?
this.sourceInformationBuilder =
sourceInformationFactory.createBuilderForContext(resolvedAst);
graph.sourceInformation =
sourceInformationBuilder.buildVariableDeclaration();
- this.localsHandler =
- new LocalsHandler(this, functionElement, null, compiler);
+ this.localsHandler = new LocalsHandler(this, targetElement, null, compiler);
this.astAdapter = new KernelAstAdapter(
compiler.backend,
resolvedAst,
kernel.nodeToAst,
kernel.nodeToElement,
+ kernel.fields,
kernel.functions,
kernel.classes,
kernel.libraries);
+ Element originTarget = targetElement;
+ if (originTarget.isPatch) {
+ originTarget = originTarget.origin;
+ }
+ if (originTarget is FunctionElement) {
+ target = kernel.functions[originTarget];
+ } else if (originTarget is FieldElement) {
+ target = kernel.fields[originTarget];
+ }
}
HGraph build() {
// TODO(het): no reason to do this here...
HInstruction.idCounter = 0;
- if (function.kind == ir.ProcedureKind.Method ||
- function.kind == ir.ProcedureKind.Operator) {
- buildMethod(function, functionElement);
+ if (target is ir.Procedure) {
+ buildProcedure(target);
+ } else if (target is ir.Field) {
+ buildField(target);
+ } else if (target is ir.Constructor) {
+ // TODO(het): Actually handle this correctly
+ HBasicBlock block = graph.addNewBlock();
+ open(graph.entry);
+ close(new HGoto()).addSuccessor(block);
+ open(block);
+ closeAndGotoExit(new HGoto());
+ graph.finalize();
+ }
+ assert(graph.isValid());
+ return graph;
+ }
+
+ void buildProcedure(ir.Procedure procedure) {
+ if (procedure.kind == ir.ProcedureKind.Method ||
+ procedure.kind == ir.ProcedureKind.Operator ||
+ procedure.kind == ir.ProcedureKind.Getter ||
+ procedure.kind == ir.ProcedureKind.Factory) {
+ buildMethod(procedure);
} else {
compiler.reporter.internalError(
- functionElement,
+ targetElement,
"Unable to convert this kind of Kernel "
- "procedure to SSA: ${function.kind}");
+ "procedure to SSA: ${procedure.kind}");
}
- assert(graph.isValid());
- return graph;
+ }
+
+ void buildField(ir.Field field) {
+ openFunction();
+ field.initializer.accept(this);
+ HInstruction value = pop();
+ closeAndGotoExit(new HReturn(value, null));
+ closeFunction();
}
@override
@@ -123,17 +150,16 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
}
/// Builds a SSA graph for [method].
- void buildMethod(ir.Procedure method, FunctionElement functionElement) {
- openFunction(functionElement);
+ void buildMethod(ir.Procedure method) {
+ openFunction();
method.function.body.accept(this);
closeFunction();
}
- // TODO(het): get function element from astAdapter?
- void openFunction(FunctionElement functionElement) {
+ void openFunction() {
HBasicBlock block = graph.addNewBlock();
open(graph.entry);
- localsHandler.startFunction(functionElement, resolvedAst.node);
+ localsHandler.startFunction(targetElement, resolvedAst.node);
close(new HGoto()).addSuccessor(block);
open(block);
@@ -145,6 +171,12 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
}
@override
+ void defaultExpression(ir.Expression expression) {
+ // TODO(het): This is only to get tests working
+ stack.add(graph.addConstantNull(compiler));
+ }
+
+ @override
void visitBlock(ir.Block block) {
assert(!isAborted());
for (ir.Statement statement in block.statements) {
@@ -166,7 +198,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
}
@override
- visitExpressionStatement(ir.ExpressionStatement exprStatement) {
+ void visitExpressionStatement(ir.ExpressionStatement exprStatement) {
exprStatement.expression.accept(this);
pop();
}
@@ -189,52 +221,150 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
@override
void visitIfStatement(ir.IfStatement ifStatement) {
- SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, compiler);
- branchBuilder.handleIf(
+ SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler);
+ brancher.handleIf(
() => ifStatement.condition.accept(this),
() => ifStatement.then.accept(this),
() => ifStatement.otherwise?.accept(this));
}
@override
+ void visitConditionalExpression(ir.ConditionalExpression conditional) {
+ SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler);
+ brancher.handleConditional(
+ () => conditional.condition.accept(this),
+ () => conditional.then.accept(this),
+ () => conditional.otherwise.accept(this));
+ }
+
+ @override
+ void visitLogicalExpression(ir.LogicalExpression logicalExpression) {
+ SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler);
+ brancher.handleLogicalBinary(() => logicalExpression.left.accept(this),
+ () => logicalExpression.right.accept(this),
+ isAnd: logicalExpression.operator == '&&');
+ }
+
+ @override
void visitIntLiteral(ir.IntLiteral intLiteral) {
stack.add(graph.addConstantInt(intLiteral.value, compiler));
}
@override
- visitDoubleLiteral(ir.DoubleLiteral doubleLiteral) {
+ void visitDoubleLiteral(ir.DoubleLiteral doubleLiteral) {
stack.add(graph.addConstantDouble(doubleLiteral.value, compiler));
}
@override
- visitBoolLiteral(ir.BoolLiteral boolLiteral) {
+ void visitBoolLiteral(ir.BoolLiteral boolLiteral) {
stack.add(graph.addConstantBool(boolLiteral.value, compiler));
}
@override
- visitStringLiteral(ir.StringLiteral stringLiteral) {
+ void visitStringLiteral(ir.StringLiteral stringLiteral) {
stack.add(graph.addConstantString(
new DartString.literal(stringLiteral.value), compiler));
}
@override
- visitSymbolLiteral(ir.SymbolLiteral symbolLiteral) {
+ void visitSymbolLiteral(ir.SymbolLiteral symbolLiteral) {
stack.add(graph.addConstant(
astAdapter.getConstantForSymbol(symbolLiteral), compiler));
registry?.registerConstSymbol(symbolLiteral.value);
}
@override
- visitNullLiteral(ir.NullLiteral nullLiteral) {
+ void visitNullLiteral(ir.NullLiteral nullLiteral) {
stack.add(graph.addConstantNull(compiler));
}
@override
- visitVariableGet(ir.VariableGet variableGet) {
+ void visitStaticGet(ir.StaticGet staticGet) {
+ var staticTarget = staticGet.target;
+ Element element = astAdapter.getElement(staticTarget).declaration;
+ if (staticTarget is ir.Procedure &&
+ staticTarget.kind == ir.ProcedureKind.Getter) {
+ // Invoke the getter
+ _pushStaticInvocation(
+ target, const <HInstruction>[], astAdapter.returnTypeOf(target));
+ } else {
+ push(new HStatic(element, astAdapter.inferredTypeOf(staticTarget)));
+ }
+ }
+
+ @override
+ void visitStaticSet(ir.StaticSet staticSet) {
+ VariableElement field = astAdapter.getElement(staticSet.target);
+ staticSet.value.accept(this);
+ HInstruction value = pop();
+ add(new HStaticStore(field, value));
+ stack.add(value);
+ }
+
+ @override
+ void visitPropertyGet(ir.PropertyGet propertyGet) {
+ propertyGet.receiver.accept(this);
+ HInstruction receiver = pop();
+
+ List<HInstruction> inputs = <HInstruction>[];
+ bool isIntercepted = astAdapter.isIntercepted(propertyGet);
+ if (isIntercepted) {
+ HInterceptor interceptor = _interceptorFor(receiver);
+ inputs.add(interceptor);
+ }
+ inputs.add(receiver);
+
+ TypeMask type = astAdapter.selectorGetterTypeOf(propertyGet);
+
+ push(new HInvokeDynamicGetter(astAdapter.getGetterSelector(propertyGet),
+ astAdapter.typeOfGet(propertyGet), null, inputs, type));
+ }
+
+ @override
+ void visitVariableGet(ir.VariableGet variableGet) {
LocalElement local = astAdapter.getElement(variableGet.variable);
stack.add(localsHandler.readLocal(local));
}
+ @override
+ void visitVariableSet(ir.VariableSet variableSet) {
+ variableSet.value.accept(this);
+ HInstruction value = pop();
+ _visitLocalSetter(variableSet.variable, value);
+ }
+
+ @override
+ void visitVariableDeclaration(ir.VariableDeclaration declaration) {
+ LocalElement local = astAdapter.getElement(declaration);
+ if (declaration.initializer == null) {
+ HInstruction initialValue = graph.addConstantNull(compiler);
+ localsHandler.updateLocal(local, initialValue);
+ } else {
+ // TODO(het): handle case where the variable is top-level or static
+ declaration.initializer.accept(this);
+ HInstruction initialValue = pop();
+
+ _visitLocalSetter(declaration, initialValue);
+
+ // Ignore value
+ pop();
+ }
+ }
+
+ void _visitLocalSetter(ir.VariableDeclaration variable, HInstruction value) {
+ // TODO(het): handle case where the variable is top-level or static
+ LocalElement local = astAdapter.getElement(variable);
+
+ // Give the value a name if it doesn't have one already.
+ if (value.sourceElement == null) {
+ value.sourceElement = local;
+ }
+
+ stack.add(value);
+ // TODO(het): check or trust type
+ localsHandler.updateLocal(local, value);
+ }
+
// TODO(het): Also extract type arguments
/// Extracts the list of instructions for the expressions in the arguments.
List<HInstruction> _visitArguments(ir.Arguments arguments) {
@@ -253,12 +383,18 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
}
@override
- visitStaticInvocation(ir.StaticInvocation invocation) {
+ void visitStaticInvocation(ir.StaticInvocation invocation) {
ir.Procedure target = invocation.target;
- bool targetCanThrow = astAdapter.getCanThrow(target);
TypeMask typeMask = astAdapter.returnTypeOf(target);
- var arguments = _visitArguments(invocation.arguments);
+ List<HInstruction> arguments = _visitArguments(invocation.arguments);
+
+ _pushStaticInvocation(target, arguments, typeMask);
+ }
+
+ void _pushStaticInvocation(
+ ir.Node target, List<HInstruction> arguments, TypeMask typeMask) {
+ bool targetCanThrow = astAdapter.getCanThrow(target);
HInstruction instruction = new HInvokeStatic(
astAdapter.getElement(target).declaration, arguments, typeMask,
@@ -270,7 +406,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
// TODO(het): Decide when to inline
@override
- visitMethodInvocation(ir.MethodInvocation invocation) {
+ void visitMethodInvocation(ir.MethodInvocation invocation) {
invocation.receiver.accept(this);
HInstruction receiver = pop();
@@ -281,9 +417,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
bool isIntercepted = astAdapter.isIntercepted(invocation);
if (isIntercepted) {
- HInterceptor interceptor =
- new HInterceptor(receiver, backend.nonNullType);
- add(interceptor);
+ HInterceptor interceptor = _interceptorFor(receiver);
inputs.add(interceptor);
}
inputs.addAll(arguments);
@@ -294,13 +428,92 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
astAdapter.typeOfInvocation(invocation), inputs, type, isIntercepted));
}
+ HInterceptor _interceptorFor(HInstruction intercepted) {
+ HInterceptor interceptor =
+ new HInterceptor(intercepted, backend.nonNullType);
+ add(interceptor);
+ return interceptor;
+ }
+
+ static ir.Class _containingClass(ir.TreeNode node) {
+ while (node != null) {
+ if (node is ir.Class) return node;
+ node = node.parent;
+ }
+ return null;
+ }
+
+ @override
+ void visitSuperMethodInvocation(ir.SuperMethodInvocation invocation) {
+ List<HInstruction> arguments = _visitArguments(invocation.arguments);
+ HInstruction receiver = localsHandler.readThis();
+ Selector selector = astAdapter.getSelector(invocation);
+ ir.Class surroundingClass = _containingClass(invocation);
+
+ List<HInstruction> inputs = <HInstruction>[];
+ if (astAdapter.isIntercepted(invocation)) {
+ inputs.add(_interceptorFor(receiver));
+ }
+ inputs.add(receiver);
+ inputs.addAll(arguments);
+
+ HInstruction instruction = new HInvokeSuper(
+ astAdapter.getElement(invocation.interfaceTarget),
+ astAdapter.getElement(surroundingClass),
+ selector,
+ inputs,
+ astAdapter.returnTypeOf(invocation.interfaceTarget),
+ null,
+ isSetter: selector.isSetter || selector.isIndexSet);
+ instruction.sideEffects =
+ compiler.world.getSideEffectsOfSelector(selector, null);
+ push(instruction);
+ }
+
+ @override
+ void visitConstructorInvocation(ir.ConstructorInvocation invocation) {
+ ir.Constructor target = invocation.target;
+ List<HInstruction> arguments = _visitArguments(invocation.arguments);
+ TypeMask typeMask = new TypeMask.nonNullExact(
+ astAdapter.getElement(target.enclosingClass), compiler.world);
+ _pushStaticInvocation(target, arguments, typeMask);
+ }
+
+ @override
+ void visitIsExpression(ir.IsExpression isExpression) {
+ isExpression.operand.accept(this);
+ HInstruction expression = pop();
+
+ DartType type = astAdapter.getDartType(isExpression.type);
+
+ if (backend.hasDirectCheckFor(type)) {
+ push(new HIs.direct(type, expression, backend.boolType));
+ return;
+ }
+
+ // The interceptor is not always needed. It is removed by optimization
+ // when the receiver type or tested type permit.
+ HInterceptor interceptor = _interceptorFor(expression);
+ push(new HIs.raw(type, expression, interceptor, backend.boolType));
+ }
+
+ @override
+ void visitThrow(ir.Throw throwNode) {
+ throwNode.expression.accept(this);
+ HInstruction expression = pop();
+ if (isReachable) {
+ push(new HThrowExpression(expression, null));
+ isReachable = false;
+ }
+ }
+
@override
- visitThisExpression(ir.ThisExpression thisExpression) {
+ void visitThisExpression(ir.ThisExpression thisExpression) {
stack.add(localsHandler.readThis());
}
@override
- visitNot(ir.Not not) {
+ void visitNot(ir.Not not) {
not.operand.accept(this);
push(new HNot(popBoolified(), backend.boolType));
}
« no previous file with comments | « pkg/compiler/lib/src/kernel/kernel_visitor.dart ('k') | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698