Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 9 import '../common/names.dart'; | 9 import '../common/names.dart'; |
| 10 import '../common/tasks.dart' show CompilerTask; | 10 import '../common/tasks.dart' show CompilerTask; |
| 11 import '../compiler.dart'; | 11 import '../compiler.dart'; |
| 12 import '../dart_types.dart'; | 12 import '../dart_types.dart'; |
| 13 import '../elements/elements.dart'; | 13 import '../elements/elements.dart'; |
| 14 import '../io/source_information.dart'; | 14 import '../io/source_information.dart'; |
| 15 import '../js_backend/backend.dart' show JavaScriptBackend; | 15 import '../js_backend/backend.dart' show JavaScriptBackend; |
| 16 import '../kernel/kernel.dart'; | 16 import '../kernel/kernel.dart'; |
| 17 import '../resolution/tree_elements.dart'; | 17 import '../resolution/tree_elements.dart'; |
| 18 import '../tree/dartstring.dart'; | 18 import '../tree/dartstring.dart'; |
| 19 import '../types/masks.dart'; | 19 import '../types/masks.dart'; |
| 20 import '../universe/call_structure.dart' show CallStructure; | |
| 20 import '../universe/selector.dart'; | 21 import '../universe/selector.dart'; |
| 22 import '../universe/use.dart' show TypeUse; | |
| 21 import 'graph_builder.dart'; | 23 import 'graph_builder.dart'; |
| 22 import 'kernel_ast_adapter.dart'; | 24 import 'kernel_ast_adapter.dart'; |
| 23 import 'kernel_string_builder.dart'; | 25 import 'kernel_string_builder.dart'; |
| 24 import 'locals_handler.dart'; | 26 import 'locals_handler.dart'; |
| 25 import 'loop_handler.dart'; | 27 import 'loop_handler.dart'; |
| 26 import 'nodes.dart'; | 28 import 'nodes.dart'; |
| 27 import 'ssa_branch_builder.dart'; | 29 import 'ssa_branch_builder.dart'; |
| 30 import 'type_builder.dart'; | |
| 28 | 31 |
| 29 class SsaKernelBuilderTask extends CompilerTask { | 32 class SsaKernelBuilderTask extends CompilerTask { |
| 30 final JavaScriptBackend backend; | 33 final JavaScriptBackend backend; |
| 31 final SourceInformationStrategy sourceInformationFactory; | 34 final SourceInformationStrategy sourceInformationFactory; |
| 32 | 35 |
| 33 String get name => 'SSA kernel builder'; | 36 String get name => 'SSA kernel builder'; |
| 34 | 37 |
| 35 SsaKernelBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) | 38 SsaKernelBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) |
| 36 : backend = backend, | 39 : backend = backend, |
| 37 super(backend.compiler.measurer); | 40 super(backend.compiler.measurer); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 55 | 58 |
| 56 @override | 59 @override |
| 57 JavaScriptBackend get backend => compiler.backend; | 60 JavaScriptBackend get backend => compiler.backend; |
| 58 | 61 |
| 59 @override | 62 @override |
| 60 TreeElements get elements => resolvedAst.elements; | 63 TreeElements get elements => resolvedAst.elements; |
| 61 | 64 |
| 62 SourceInformationBuilder sourceInformationBuilder; | 65 SourceInformationBuilder sourceInformationBuilder; |
| 63 KernelAstAdapter astAdapter; | 66 KernelAstAdapter astAdapter; |
| 64 LoopHandler<ir.Node> loopHandler; | 67 LoopHandler<ir.Node> loopHandler; |
| 68 TypeBuilder typeBuilder; | |
| 65 | 69 |
| 66 KernelSsaBuilder( | 70 KernelSsaBuilder( |
| 67 this.targetElement, | 71 this.targetElement, |
| 68 this.resolvedAst, | 72 this.resolvedAst, |
| 69 Compiler compiler, | 73 Compiler compiler, |
| 70 this.registry, | 74 this.registry, |
| 71 SourceInformationStrategy sourceInformationFactory, | 75 SourceInformationStrategy sourceInformationFactory, |
| 72 Kernel kernel) { | 76 Kernel kernel) { |
| 73 this.compiler = compiler; | 77 this.compiler = compiler; |
| 74 this.loopHandler = new KernelLoopHandler(this); | 78 this.loopHandler = new KernelLoopHandler(this); |
| 79 typeBuilder = new TypeBuilder(this); | |
| 75 graph.element = targetElement; | 80 graph.element = targetElement; |
| 76 // TODO(het): Should sourceInformationBuilder be in GraphBuilder? | 81 // TODO(het): Should sourceInformationBuilder be in GraphBuilder? |
| 77 this.sourceInformationBuilder = | 82 this.sourceInformationBuilder = |
| 78 sourceInformationFactory.createBuilderForContext(resolvedAst); | 83 sourceInformationFactory.createBuilderForContext(resolvedAst); |
| 79 graph.sourceInformation = | 84 graph.sourceInformation = |
| 80 sourceInformationBuilder.buildVariableDeclaration(); | 85 sourceInformationBuilder.buildVariableDeclaration(); |
| 81 this.localsHandler = new LocalsHandler(this, targetElement, null, compiler); | 86 this.localsHandler = new LocalsHandler(this, targetElement, null, compiler); |
| 82 this.astAdapter = new KernelAstAdapter(kernel, compiler.backend, | 87 this.astAdapter = new KernelAstAdapter(kernel, compiler.backend, |
| 83 resolvedAst, kernel.nodeToAst, kernel.nodeToElement); | 88 resolvedAst, kernel.nodeToAst, kernel.nodeToElement); |
| 84 Element originTarget = targetElement; | 89 Element originTarget = targetElement; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 111 if (field.initializer != null) { | 116 if (field.initializer != null) { |
| 112 field.initializer.accept(this); | 117 field.initializer.accept(this); |
| 113 } else { | 118 } else { |
| 114 stack.add(graph.addConstantNull(compiler)); | 119 stack.add(graph.addConstantNull(compiler)); |
| 115 } | 120 } |
| 116 HInstruction value = pop(); | 121 HInstruction value = pop(); |
| 117 closeAndGotoExit(new HReturn(value, null)); | 122 closeAndGotoExit(new HReturn(value, null)); |
| 118 closeFunction(); | 123 closeFunction(); |
| 119 } | 124 } |
| 120 | 125 |
| 126 /// Pops the most recent instruction from the stack and 'boolifies' it. | |
| 127 /// | |
| 128 /// Boolification is checking if the value is '=== true'. | |
| 121 @override | 129 @override |
| 122 HInstruction popBoolified() { | 130 HInstruction popBoolified() { |
| 123 HInstruction value = pop(); | 131 HInstruction value = pop(); |
| 124 // TODO(het): add boolean conversion type check | 132 if (typeBuilder.checkOrTrustTypes) { |
| 133 return typeBuilder.potentiallyCheckOrTrustType( | |
| 134 value, compiler.coreTypes.boolType, | |
| 135 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); | |
| 136 } | |
| 125 HInstruction result = new HBoolify(value, backend.boolType); | 137 HInstruction result = new HBoolify(value, backend.boolType); |
| 126 add(result); | 138 add(result); |
| 127 return result; | 139 return result; |
| 128 } | 140 } |
| 129 | 141 |
| 130 void buildConstructor(ir.Constructor constructor) { | 142 void buildConstructor(ir.Constructor constructor) { |
| 131 // TODO(het): Actually handle this correctly | 143 // TODO(het): Actually handle this correctly |
| 132 HBasicBlock block = graph.addNewBlock(); | 144 HBasicBlock block = graph.addNewBlock(); |
| 133 open(graph.entry); | 145 open(graph.entry); |
| 134 close(new HGoto()).addSuccessor(block); | 146 close(new HGoto()).addSuccessor(block); |
| 135 open(block); | 147 open(block); |
| 136 closeAndGotoExit(new HGoto()); | 148 closeAndGotoExit(new HGoto()); |
| 137 graph.finalize(); | 149 graph.finalize(); |
| 138 } | 150 } |
| 139 | 151 |
| 152 HTypeConversion buildFunctionTypeConversion( | |
| 153 HInstruction original, DartType type, int kind) { | |
| 154 String name = | |
| 155 kind == HTypeConversion.CAST_TYPE_CHECK ? '_asCheck' : '_assertCheck'; | |
| 156 | |
| 157 List<HInstruction> arguments = <HInstruction>[ | |
| 158 buildFunctionType(type), | |
| 159 original | |
| 160 ]; | |
| 161 _pushDynamicInvocation(null, null, arguments, | |
| 162 selector: new Selector.call( | |
| 163 new Name(name, astAdapter.jsHelperLibrary), CallStructure.ONE_ARG)); | |
| 164 | |
| 165 return new HTypeConversion(type, kind, original.instructionType, pop()); | |
| 166 } | |
| 167 | |
| 140 /// Builds a SSA graph for [procedure]. | 168 /// Builds a SSA graph for [procedure]. |
| 141 void buildProcedure(ir.Procedure procedure) { | 169 void buildProcedure(ir.Procedure procedure) { |
| 142 openFunction(); | 170 openFunction(); |
| 143 procedure.function.body.accept(this); | 171 procedure.function.body.accept(this); |
| 144 closeFunction(); | 172 closeFunction(); |
| 145 } | 173 } |
| 146 | 174 |
| 147 void openFunction() { | 175 void openFunction() { |
| 148 HBasicBlock block = graph.addNewBlock(); | 176 HBasicBlock block = graph.addNewBlock(); |
| 149 open(graph.entry); | 177 open(graph.entry); |
| 150 localsHandler.startFunction(targetElement, resolvedAst.node); | 178 localsHandler.startFunction(targetElement, resolvedAst.node); |
| 151 close(new HGoto()).addSuccessor(block); | 179 close(new HGoto()).addSuccessor(block); |
| 152 | 180 |
| 153 open(block); | 181 open(block); |
| 154 } | 182 } |
| 155 | 183 |
| 156 void closeFunction() { | 184 void closeFunction() { |
| 157 if (!isAborted()) closeAndGotoExit(new HGoto()); | 185 if (!isAborted()) closeAndGotoExit(new HGoto()); |
| 158 graph.finalize(); | 186 graph.finalize(); |
| 159 } | 187 } |
| 160 | 188 |
| 189 /// Pushes a boolean checking [expression] against null. | |
| 190 pushCheckNull(HInstruction expression) { | |
| 191 push(new HIdentity( | |
| 192 expression, graph.addConstantNull(compiler), null, backend.boolType)); | |
| 193 } | |
| 194 | |
| 161 @override | 195 @override |
| 162 void defaultExpression(ir.Expression expression) { | 196 void defaultExpression(ir.Expression expression) { |
| 163 // TODO(het): This is only to get tests working | 197 // TODO(het): This is only to get tests working |
| 164 stack.add(graph.addConstantNull(compiler)); | 198 stack.add(graph.addConstantNull(compiler)); |
| 165 } | 199 } |
| 166 | 200 |
| 201 /// Returns the current source element. | |
| 202 /// | |
| 203 /// The returned element is a declaration element. | |
| 204 @override | |
| 205 Element get sourceElement => astAdapter.getElement(target); | |
|
Siggi Cherem (dart-lang)
2016/11/14 18:30:21
let's add a small TODO here that we need to update
Emily Fortuna
2016/11/14 19:03:39
Done.
| |
| 206 | |
| 167 @override | 207 @override |
| 168 void visitBlock(ir.Block block) { | 208 void visitBlock(ir.Block block) { |
| 169 assert(!isAborted()); | 209 assert(!isAborted()); |
| 170 for (ir.Statement statement in block.statements) { | 210 for (ir.Statement statement in block.statements) { |
| 171 statement.accept(this); | 211 statement.accept(this); |
| 172 if (!isReachable) { | 212 if (!isReachable) { |
| 173 // The block has been aborted by a return or a throw. | 213 // The block has been aborted by a return or a throw. |
| 174 if (stack.isNotEmpty) { | 214 if (stack.isNotEmpty) { |
| 175 compiler.reporter.internalError( | 215 compiler.reporter.internalError( |
| 176 NO_LOCATION_SPANNABLE, 'Non-empty instruction stack.'); | 216 NO_LOCATION_SPANNABLE, 'Non-empty instruction stack.'); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 190 exprStatement.expression.accept(this); | 230 exprStatement.expression.accept(this); |
| 191 pop(); | 231 pop(); |
| 192 } | 232 } |
| 193 | 233 |
| 194 @override | 234 @override |
| 195 void visitReturnStatement(ir.ReturnStatement returnStatement) { | 235 void visitReturnStatement(ir.ReturnStatement returnStatement) { |
| 196 HInstruction value; | 236 HInstruction value; |
| 197 if (returnStatement.expression == null) { | 237 if (returnStatement.expression == null) { |
| 198 value = graph.addConstantNull(compiler); | 238 value = graph.addConstantNull(compiler); |
| 199 } else { | 239 } else { |
| 240 assert(target is ir.Procedure); | |
| 200 returnStatement.expression.accept(this); | 241 returnStatement.expression.accept(this); |
| 201 value = pop(); | 242 value = typeBuilder.potentiallyCheckOrTrustType(pop(), |
| 202 // TODO(het): Check or trust the type of value | 243 astAdapter.getFunctionReturnType((target as ir.Procedure).function)); |
| 203 } | 244 } |
| 204 // TODO(het): Add source information | 245 // TODO(het): Add source information |
| 205 // TODO(het): Set a return value instead of closing the function when we | 246 // TODO(het): Set a return value instead of closing the function when we |
| 206 // support inlining. | 247 // support inlining. |
| 207 closeAndGotoExit(new HReturn(value, null)); | 248 closeAndGotoExit(new HReturn(value, null)); |
| 208 } | 249 } |
| 209 | 250 |
| 210 @override | 251 @override |
| 211 void visitForStatement(ir.ForStatement forStatement) { | 252 void visitForStatement(ir.ForStatement forStatement) { |
| 212 assert(isReachable); | 253 assert(isReachable); |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 584 staticSet.value.accept(this); | 625 staticSet.value.accept(this); |
| 585 HInstruction value = pop(); | 626 HInstruction value = pop(); |
| 586 | 627 |
| 587 var staticTarget = staticSet.target; | 628 var staticTarget = staticSet.target; |
| 588 if (staticTarget is ir.Procedure) { | 629 if (staticTarget is ir.Procedure) { |
| 589 // Invoke the setter | 630 // Invoke the setter |
| 590 _pushStaticInvocation(staticTarget, <HInstruction>[value], | 631 _pushStaticInvocation(staticTarget, <HInstruction>[value], |
| 591 astAdapter.returnTypeOf(staticTarget)); | 632 astAdapter.returnTypeOf(staticTarget)); |
| 592 pop(); | 633 pop(); |
| 593 } else { | 634 } else { |
| 594 // TODO(het): check or trust type | 635 add(new HStaticStore( |
| 595 add(new HStaticStore(astAdapter.getMember(staticTarget), value)); | 636 astAdapter.getMember(staticTarget), |
| 637 typeBuilder.potentiallyCheckOrTrustType( | |
| 638 value, astAdapter.getDartType(staticTarget.setterType)))); | |
| 596 } | 639 } |
| 597 stack.add(value); | 640 stack.add(value); |
| 598 } | 641 } |
| 599 | 642 |
| 600 @override | 643 @override |
| 601 void visitPropertyGet(ir.PropertyGet propertyGet) { | 644 void visitPropertyGet(ir.PropertyGet propertyGet) { |
| 602 propertyGet.receiver.accept(this); | 645 propertyGet.receiver.accept(this); |
| 603 HInstruction receiver = pop(); | 646 HInstruction receiver = pop(); |
| 604 | 647 |
| 605 _pushDynamicInvocation(propertyGet, astAdapter.typeOfGet(propertyGet), | 648 _pushDynamicInvocation(propertyGet, astAdapter.typeOfGet(propertyGet), |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 640 void _visitLocalSetter(ir.VariableDeclaration variable, HInstruction value) { | 683 void _visitLocalSetter(ir.VariableDeclaration variable, HInstruction value) { |
| 641 // TODO(het): handle case where the variable is top-level or static | 684 // TODO(het): handle case where the variable is top-level or static |
| 642 LocalElement local = astAdapter.getElement(variable); | 685 LocalElement local = astAdapter.getElement(variable); |
| 643 | 686 |
| 644 // Give the value a name if it doesn't have one already. | 687 // Give the value a name if it doesn't have one already. |
| 645 if (value.sourceElement == null) { | 688 if (value.sourceElement == null) { |
| 646 value.sourceElement = local; | 689 value.sourceElement = local; |
| 647 } | 690 } |
| 648 | 691 |
| 649 stack.add(value); | 692 stack.add(value); |
| 650 // TODO(het): check or trust type | 693 localsHandler.updateLocal( |
| 651 localsHandler.updateLocal(local, value); | 694 local, |
| 695 typeBuilder.potentiallyCheckOrTrustType( | |
| 696 value, astAdapter.getDartType(variable.type))); | |
| 652 } | 697 } |
| 653 | 698 |
| 654 // TODO(het): Also extract type arguments | 699 // TODO(het): Also extract type arguments |
| 655 /// Extracts the list of instructions for the expressions in the arguments. | 700 /// Extracts the list of instructions for the expressions in the arguments. |
| 656 List<HInstruction> _visitArguments(ir.Arguments arguments) { | 701 List<HInstruction> _visitArguments(ir.Arguments arguments) { |
| 657 List<HInstruction> result = <HInstruction>[]; | 702 List<HInstruction> result = <HInstruction>[]; |
| 658 | 703 |
| 659 for (ir.Expression argument in arguments.positional) { | 704 for (ir.Expression argument in arguments.positional) { |
| 660 argument.accept(this); | 705 argument.accept(this); |
| 661 result.add(pop()); | 706 result.add(pop()); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 817 push(new HNot(popBoolified(), backend.boolType)); | 862 push(new HNot(popBoolified(), backend.boolType)); |
| 818 } | 863 } |
| 819 | 864 |
| 820 @override | 865 @override |
| 821 void visitStringConcatenation(ir.StringConcatenation stringConcat) { | 866 void visitStringConcatenation(ir.StringConcatenation stringConcat) { |
| 822 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); | 867 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); |
| 823 stringConcat.accept(stringBuilder); | 868 stringConcat.accept(stringBuilder); |
| 824 stack.add(stringBuilder.result); | 869 stack.add(stringBuilder.result); |
| 825 } | 870 } |
| 826 } | 871 } |
| OLD | NEW |