OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 import 'package:kernel/ast.dart' as ir; |
| 6 |
| 7 import '../common.dart'; |
| 8 import '../compiler.dart'; |
| 9 import '../constants/expressions.dart'; |
| 10 import '../dart_types.dart'; |
| 11 import '../elements/elements.dart'; |
| 12 import '../js_backend/backend.dart' show JavaScriptBackend; |
| 13 import '../kernel/kernel.dart'; |
| 14 import '../kernel/kernel_visitor.dart'; |
| 15 import '../resolution/registry.dart' show ResolutionWorldImpactBuilder; |
| 16 import '../universe/feature.dart'; |
| 17 import '../universe/use.dart'; |
| 18 |
| 19 import 'kernel_ast_adapter.dart'; |
| 20 import '../common/resolution.dart'; |
| 21 |
| 22 /// Computes the [ResolutionImpact] for [resolvedAst] through kernel. |
| 23 ResolutionImpact build(Compiler compiler, ResolvedAst resolvedAst) { |
| 24 AstElement element = resolvedAst.element.implementation; |
| 25 Kernel kernel = new Kernel(compiler); |
| 26 KernelVisitor visitor = |
| 27 new KernelVisitor(element, resolvedAst.elements, kernel); |
| 28 IrFunction function; |
| 29 try { |
| 30 function = visitor.buildFunction(); |
| 31 } catch (e) { |
| 32 throw "Failed to convert to Kernel IR: $e"; |
| 33 } |
| 34 KernelImpactBuilder builder = new KernelImpactBuilder( |
| 35 function, element, resolvedAst, compiler, visitor, kernel); |
| 36 return builder.build(); |
| 37 } |
| 38 |
| 39 class KernelImpactBuilder extends ir.Visitor { |
| 40 final IrFunction function; |
| 41 final FunctionElement functionElement; |
| 42 final ResolvedAst resolvedAst; |
| 43 final Compiler compiler; |
| 44 |
| 45 JavaScriptBackend get backend => compiler.backend; |
| 46 |
| 47 ResolutionWorldImpactBuilder worldImpact; |
| 48 KernelAstAdapter astAdapter; |
| 49 |
| 50 KernelImpactBuilder(this.function, this.functionElement, this.resolvedAst, |
| 51 this.compiler, KernelVisitor visitor, Kernel kernel) { |
| 52 this.worldImpact = new ResolutionWorldImpactBuilder('$functionElement'); |
| 53 this.astAdapter = new KernelAstAdapter( |
| 54 compiler.backend, |
| 55 resolvedAst, |
| 56 visitor.nodeToAst, |
| 57 visitor.nodeToElement, |
| 58 kernel.functions, |
| 59 kernel.classes, |
| 60 kernel.libraries); |
| 61 } |
| 62 |
| 63 ResolutionImpact build() { |
| 64 if (function.kind == ir.ProcedureKind.Method || |
| 65 function.kind == ir.ProcedureKind.Operator) { |
| 66 buildMethod(function); |
| 67 } else { |
| 68 compiler.reporter.internalError( |
| 69 functionElement, |
| 70 "Unable to compute resolution impact for this kind of Kernel " |
| 71 "procedure: ${function.kind}"); |
| 72 } |
| 73 return worldImpact; |
| 74 } |
| 75 |
| 76 /// Add a checked-mode type use of [type] if it is not `dynamic`. |
| 77 DartType checkType(DartType type) { |
| 78 if (!type.isDynamic) { |
| 79 worldImpact.registerTypeUse(new TypeUse.checkedModeCheck(type)); |
| 80 } |
| 81 return type; |
| 82 } |
| 83 |
| 84 void buildMethod(IrFunction method) { |
| 85 method.node.body.accept(this); |
| 86 } |
| 87 |
| 88 void visitNodes(Iterable<ir.Node> nodes) { |
| 89 nodes.forEach((ir.Node node) => node.accept(this)); |
| 90 } |
| 91 |
| 92 @override |
| 93 void visitBlock(ir.Block block) => visitNodes(block.statements); |
| 94 |
| 95 @override |
| 96 void visitExpressionStatement(ir.ExpressionStatement exprStatement) { |
| 97 exprStatement.expression.accept(this); |
| 98 } |
| 99 |
| 100 @override |
| 101 void visitReturnStatement(ir.ReturnStatement returnStatement) { |
| 102 returnStatement.expression?.accept(this); |
| 103 } |
| 104 |
| 105 @override |
| 106 void visitIfStatement(ir.IfStatement ifStatement) { |
| 107 ifStatement.condition.accept(this); |
| 108 ifStatement.then.accept(this); |
| 109 ifStatement.otherwise?.accept(this); |
| 110 } |
| 111 |
| 112 @override |
| 113 void visitIntLiteral(ir.IntLiteral literal) { |
| 114 worldImpact |
| 115 .registerConstantLiteral(new IntConstantExpression(literal.value)); |
| 116 } |
| 117 |
| 118 @override |
| 119 void visitDoubleLiteral(ir.DoubleLiteral literal) { |
| 120 worldImpact |
| 121 .registerConstantLiteral(new DoubleConstantExpression(literal.value)); |
| 122 } |
| 123 |
| 124 @override |
| 125 void visitBoolLiteral(ir.BoolLiteral literal) { |
| 126 worldImpact |
| 127 .registerConstantLiteral(new BoolConstantExpression(literal.value)); |
| 128 } |
| 129 |
| 130 @override |
| 131 void visitStringLiteral(ir.StringLiteral literal) { |
| 132 worldImpact |
| 133 .registerConstantLiteral(new StringConstantExpression(literal.value)); |
| 134 } |
| 135 |
| 136 @override |
| 137 void visitSymbolLiteral(ir.SymbolLiteral literal) { |
| 138 worldImpact.registerConstSymbolName(literal.value); |
| 139 } |
| 140 |
| 141 @override |
| 142 void visitNullLiteral(ir.NullLiteral literal) { |
| 143 worldImpact.registerConstantLiteral(new NullConstantExpression()); |
| 144 } |
| 145 |
| 146 @override |
| 147 void visitListLiteral(ir.ListLiteral literal) { |
| 148 visitNodes(literal.expressions); |
| 149 DartType elementType = |
| 150 checkType(astAdapter.getDartType(literal.typeArgument)); |
| 151 |
| 152 worldImpact.registerListLiteral(new ListLiteralUse( |
| 153 compiler.coreTypes.listType(elementType), |
| 154 isConstant: literal.isConst, |
| 155 isEmpty: literal.expressions.isEmpty)); |
| 156 } |
| 157 |
| 158 @override |
| 159 void visitMapLiteral(ir.MapLiteral literal) { |
| 160 visitNodes(literal.entries); |
| 161 DartType keyType = checkType(astAdapter.getDartType(literal.keyType)); |
| 162 DartType valueType = checkType(astAdapter.getDartType(literal.valueType)); |
| 163 worldImpact.registerMapLiteral(new MapLiteralUse( |
| 164 compiler.coreTypes.mapType(keyType, valueType), |
| 165 isConstant: literal.isConst, |
| 166 isEmpty: literal.entries.isEmpty)); |
| 167 } |
| 168 |
| 169 void visitMapEntry(ir.MapEntry entry) { |
| 170 entry.key.accept(this); |
| 171 entry.value.accept(this); |
| 172 } |
| 173 |
| 174 void _visitArguments(ir.Arguments arguments) { |
| 175 for (ir.Expression argument in arguments.positional) { |
| 176 argument.accept(this); |
| 177 } |
| 178 for (ir.NamedExpression argument in arguments.named) { |
| 179 argument.value.accept(this); |
| 180 } |
| 181 } |
| 182 |
| 183 @override |
| 184 void visitStaticInvocation(ir.StaticInvocation invocation) { |
| 185 _visitArguments(invocation.arguments); |
| 186 Element target = astAdapter.getElement(invocation.target).declaration; |
| 187 worldImpact.registerStaticUse(new StaticUse.staticInvoke( |
| 188 target, astAdapter.getCallStructure(invocation.arguments))); |
| 189 } |
| 190 |
| 191 @override |
| 192 void visitMethodInvocation(ir.MethodInvocation invocation) { |
| 193 invocation.receiver.accept(this); |
| 194 _visitArguments(invocation.arguments); |
| 195 worldImpact.registerDynamicUse( |
| 196 new DynamicUse(astAdapter.getSelector(invocation), null)); |
| 197 } |
| 198 |
| 199 @override |
| 200 void visitNot(ir.Not not) { |
| 201 not.operand.accept(this); |
| 202 } |
| 203 } |
OLD | NEW |