Index: pkg/compiler/lib/src/ssa/kernel_impact.dart |
diff --git a/pkg/compiler/lib/src/ssa/kernel_impact.dart b/pkg/compiler/lib/src/ssa/kernel_impact.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d4d161e8c5b79dc0857d1a416286c36131afbc13 |
--- /dev/null |
+++ b/pkg/compiler/lib/src/ssa/kernel_impact.dart |
@@ -0,0 +1,203 @@ |
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+import 'package:kernel/ast.dart' as ir; |
+ |
+import '../common.dart'; |
+import '../compiler.dart'; |
+import '../constants/expressions.dart'; |
+import '../dart_types.dart'; |
+import '../elements/elements.dart'; |
+import '../js_backend/backend.dart' show JavaScriptBackend; |
+import '../kernel/kernel.dart'; |
+import '../kernel/kernel_visitor.dart'; |
+import '../resolution/registry.dart' show ResolutionWorldImpactBuilder; |
+import '../universe/feature.dart'; |
+import '../universe/use.dart'; |
+ |
+import 'kernel_ast_adapter.dart'; |
+import '../common/resolution.dart'; |
+ |
+/// Computes the [ResolutionImpact] for [resolvedAst] through kernel. |
+ResolutionImpact build(Compiler compiler, ResolvedAst resolvedAst) { |
+ AstElement element = resolvedAst.element.implementation; |
+ Kernel kernel = new Kernel(compiler); |
+ KernelVisitor visitor = |
+ new KernelVisitor(element, resolvedAst.elements, kernel); |
+ IrFunction function; |
+ try { |
+ function = visitor.buildFunction(); |
+ } catch (e) { |
+ throw "Failed to convert to Kernel IR: $e"; |
+ } |
+ KernelImpactBuilder builder = new KernelImpactBuilder( |
+ function, element, resolvedAst, compiler, visitor, kernel); |
+ return builder.build(); |
+} |
+ |
+class KernelImpactBuilder extends ir.Visitor { |
+ final IrFunction function; |
+ final FunctionElement functionElement; |
+ final ResolvedAst resolvedAst; |
+ final Compiler compiler; |
+ |
+ JavaScriptBackend get backend => compiler.backend; |
+ |
+ ResolutionWorldImpactBuilder impactBuilder; |
+ KernelAstAdapter astAdapter; |
+ |
+ KernelImpactBuilder(this.function, this.functionElement, this.resolvedAst, |
+ this.compiler, KernelVisitor visitor, Kernel kernel) { |
+ this.impactBuilder = new ResolutionWorldImpactBuilder('$functionElement'); |
+ this.astAdapter = new KernelAstAdapter( |
+ compiler.backend, |
+ resolvedAst, |
+ visitor.nodeToAst, |
+ visitor.nodeToElement, |
+ kernel.functions, |
+ kernel.classes, |
+ kernel.libraries); |
+ } |
+ |
+ ResolutionImpact build() { |
+ if (function.kind == ir.ProcedureKind.Method || |
+ function.kind == ir.ProcedureKind.Operator) { |
+ buildMethod(function); |
+ } else { |
+ compiler.reporter.internalError( |
+ functionElement, |
+ "Unable to compute resolution impact for this kind of Kernel " |
+ "procedure: ${function.kind}"); |
+ } |
+ return impactBuilder; |
+ } |
+ |
+ /// Add a checked-mode type use of [type] if it is not `dynamic`. |
+ DartType checkType(DartType type) { |
+ if (!type.isDynamic) { |
+ impactBuilder.registerTypeUse(new TypeUse.checkedModeCheck(type)); |
+ } |
+ return type; |
+ } |
+ |
+ void buildMethod(IrFunction method) { |
+ method.node.body.accept(this); |
+ } |
+ |
+ void visitNodes(Iterable<ir.Node> nodes) { |
+ nodes.forEach((ir.Node node) => node.accept(this)); |
+ } |
+ |
+ @override |
+ void visitBlock(ir.Block block) => visitNodes(block.statements); |
+ |
+ @override |
+ void visitExpressionStatement(ir.ExpressionStatement exprStatement) { |
+ exprStatement.expression.accept(this); |
+ } |
+ |
+ @override |
+ void visitReturnStatement(ir.ReturnStatement returnStatement) { |
+ returnStatement.expression?.accept(this); |
+ } |
+ |
+ @override |
+ void visitIfStatement(ir.IfStatement ifStatement) { |
+ ifStatement.condition.accept(this); |
+ ifStatement.then.accept(this); |
+ ifStatement.otherwise?.accept(this); |
+ } |
+ |
+ @override |
+ void visitIntLiteral(ir.IntLiteral literal) { |
+ impactBuilder |
+ .registerConstantLiteral(new IntConstantExpression(literal.value)); |
+ } |
+ |
+ @override |
+ void visitDoubleLiteral(ir.DoubleLiteral literal) { |
+ impactBuilder |
+ .registerConstantLiteral(new DoubleConstantExpression(literal.value)); |
+ } |
+ |
+ @override |
+ void visitBoolLiteral(ir.BoolLiteral literal) { |
+ impactBuilder |
+ .registerConstantLiteral(new BoolConstantExpression(literal.value)); |
+ } |
+ |
+ @override |
+ void visitStringLiteral(ir.StringLiteral literal) { |
+ impactBuilder |
+ .registerConstantLiteral(new StringConstantExpression(literal.value)); |
+ } |
+ |
+ @override |
+ void visitSymbolLiteral(ir.SymbolLiteral literal) { |
+ impactBuilder.registerConstSymbolName(literal.value); |
+ } |
+ |
+ @override |
+ void visitNullLiteral(ir.NullLiteral literal) { |
+ impactBuilder.registerConstantLiteral(new NullConstantExpression()); |
+ } |
+ |
+ @override |
+ void visitListLiteral(ir.ListLiteral literal) { |
+ visitNodes(literal.expressions); |
+ DartType elementType = |
+ checkType(astAdapter.getDartType(literal.typeArgument)); |
+ |
+ impactBuilder.registerListLiteral(new ListLiteralUse( |
+ compiler.coreTypes.listType(elementType), |
+ isConstant: literal.isConst, |
+ isEmpty: literal.expressions.isEmpty)); |
+ } |
+ |
+ @override |
+ void visitMapLiteral(ir.MapLiteral literal) { |
+ visitNodes(literal.entries); |
+ DartType keyType = checkType(astAdapter.getDartType(literal.keyType)); |
+ DartType valueType = checkType(astAdapter.getDartType(literal.valueType)); |
+ impactBuilder.registerMapLiteral(new MapLiteralUse( |
+ compiler.coreTypes.mapType(keyType, valueType), |
+ isConstant: literal.isConst, |
+ isEmpty: literal.entries.isEmpty)); |
+ } |
+ |
+ void visitMapEntry(ir.MapEntry entry) { |
+ entry.key.accept(this); |
+ entry.value.accept(this); |
+ } |
+ |
+ void _visitArguments(ir.Arguments arguments) { |
+ for (ir.Expression argument in arguments.positional) { |
+ argument.accept(this); |
+ } |
+ for (ir.NamedExpression argument in arguments.named) { |
+ argument.value.accept(this); |
+ } |
+ } |
+ |
+ @override |
+ void visitStaticInvocation(ir.StaticInvocation invocation) { |
+ _visitArguments(invocation.arguments); |
+ Element target = astAdapter.getElement(invocation.target).declaration; |
+ impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
+ target, astAdapter.getCallStructure(invocation.arguments))); |
+ } |
+ |
+ @override |
+ void visitMethodInvocation(ir.MethodInvocation invocation) { |
+ invocation.receiver.accept(this); |
+ _visitArguments(invocation.arguments); |
+ impactBuilder.registerDynamicUse( |
+ new DynamicUse(astAdapter.getSelector(invocation), null)); |
+ } |
+ |
+ @override |
+ void visitNot(ir.Not not) { |
+ not.operand.accept(this); |
+ } |
+} |