| 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 '../closure.dart'; |
| 7 import '../common.dart'; | 8 import '../common.dart'; |
| 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 9 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 9 import '../common/names.dart'; | 10 import '../common/names.dart'; |
| 10 import '../common/tasks.dart' show CompilerTask; | 11 import '../common/tasks.dart' show CompilerTask; |
| 11 import '../compiler.dart'; | 12 import '../compiler.dart'; |
| 12 import '../constants/values.dart' | 13 import '../constants/values.dart' |
| 13 show | 14 show |
| 14 ConstantValue, | 15 ConstantValue, |
| 15 InterceptorConstantValue, | 16 InterceptorConstantValue, |
| 16 StringConstantValue, | 17 StringConstantValue, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 sourceInformationBuilder.buildVariableDeclaration(); | 108 sourceInformationBuilder.buildVariableDeclaration(); |
| 108 this.localsHandler = new LocalsHandler(this, targetElement, null, compiler); | 109 this.localsHandler = new LocalsHandler(this, targetElement, null, compiler); |
| 109 this.astAdapter = new KernelAstAdapter(kernel, compiler.backend, | 110 this.astAdapter = new KernelAstAdapter(kernel, compiler.backend, |
| 110 resolvedAst, kernel.nodeToAst, kernel.nodeToElement); | 111 resolvedAst, kernel.nodeToAst, kernel.nodeToElement); |
| 111 Element originTarget = targetElement; | 112 Element originTarget = targetElement; |
| 112 if (originTarget.isPatch) { | 113 if (originTarget.isPatch) { |
| 113 originTarget = originTarget.origin; | 114 originTarget = originTarget.origin; |
| 114 } | 115 } |
| 115 if (originTarget is FunctionElement) { | 116 if (originTarget is FunctionElement) { |
| 116 target = kernel.functions[originTarget]; | 117 target = kernel.functions[originTarget]; |
| 118 // Closures require a lookup one level deeper in the closure class mapper. |
| 119 if (target == null) { |
| 120 ClosureClassMap classMap = compiler.closureToClassMapper |
| 121 .getClosureToClassMapping(originTarget.resolvedAst); |
| 122 if (classMap.closureElement != null) { |
| 123 target = kernel.localFunctions[classMap.closureElement]; |
| 124 } |
| 125 } |
| 117 } else if (originTarget is FieldElement) { | 126 } else if (originTarget is FieldElement) { |
| 118 target = kernel.fields[originTarget]; | 127 target = kernel.fields[originTarget]; |
| 119 } | 128 } |
| 120 } | 129 } |
| 121 | 130 |
| 122 HGraph build() { | 131 HGraph build() { |
| 123 // TODO(het): no reason to do this here... | 132 // TODO(het): no reason to do this here... |
| 124 HInstruction.idCounter = 0; | 133 HInstruction.idCounter = 0; |
| 125 if (target is ir.Procedure) { | 134 if (target is ir.Procedure) { |
| 126 buildProcedure(target); | 135 target = (target as ir.Procedure).function; |
| 136 buildFunctionNode(target); |
| 127 } else if (target is ir.Field) { | 137 } else if (target is ir.Field) { |
| 128 buildField(target); | 138 buildField(target); |
| 129 } else if (target is ir.Constructor) { | 139 } else if (target is ir.Constructor) { |
| 130 buildConstructor(target); | 140 buildConstructor(target); |
| 141 } else if (target is ir.FunctionExpression) { |
| 142 target = (target as ir.FunctionExpression).function; |
| 143 buildFunctionNode(target); |
| 144 } else { |
| 145 throw 'No case implemented to handle $target'; |
| 131 } | 146 } |
| 132 assert(graph.isValid()); | 147 assert(graph.isValid()); |
| 133 return graph; | 148 return graph; |
| 134 } | 149 } |
| 135 | 150 |
| 136 void buildField(ir.Field field) { | 151 void buildField(ir.Field field) { |
| 137 openFunction(); | 152 openFunction(); |
| 138 if (field.initializer != null) { | 153 if (field.initializer != null) { |
| 139 field.initializer.accept(this); | 154 field.initializer.accept(this); |
| 140 } else { | 155 } else { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 _buildInitializers(constructor, fieldValues); | 342 _buildInitializers(constructor, fieldValues); |
| 328 } | 343 } |
| 329 | 344 |
| 330 HTypeConversion buildFunctionTypeConversion( | 345 HTypeConversion buildFunctionTypeConversion( |
| 331 HInstruction original, DartType type, int kind) { | 346 HInstruction original, DartType type, int kind) { |
| 332 HInstruction reifiedType = buildFunctionType(type); | 347 HInstruction reifiedType = buildFunctionType(type); |
| 333 return new HTypeConversion.viaMethodOnType( | 348 return new HTypeConversion.viaMethodOnType( |
| 334 type, kind, original.instructionType, reifiedType, original); | 349 type, kind, original.instructionType, reifiedType, original); |
| 335 } | 350 } |
| 336 | 351 |
| 337 /// Builds a SSA graph for [procedure]. | 352 /// Builds a SSA graph for FunctionNodes, found in FunctionExpressions and |
| 338 void buildProcedure(ir.Procedure procedure) { | 353 /// Procedures. |
| 354 void buildFunctionNode(ir.FunctionNode functionNode) { |
| 339 openFunction(); | 355 openFunction(); |
| 340 procedure.function.body.accept(this); | 356 functionNode.body.accept(this); |
| 341 closeFunction(); | 357 closeFunction(); |
| 342 } | 358 } |
| 343 | 359 |
| 344 void addImplicitInstantiation(DartType type) { | 360 void addImplicitInstantiation(DartType type) { |
| 345 if (type != null) { | 361 if (type != null) { |
| 346 currentImplicitInstantiations.add(type); | 362 currentImplicitInstantiations.add(type); |
| 347 } | 363 } |
| 348 } | 364 } |
| 349 | 365 |
| 350 void removeImplicitInstantiation(DartType type) { | 366 void removeImplicitInstantiation(DartType type) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 exprStatement.expression.accept(this); | 442 exprStatement.expression.accept(this); |
| 427 pop(); | 443 pop(); |
| 428 } | 444 } |
| 429 | 445 |
| 430 @override | 446 @override |
| 431 void visitReturnStatement(ir.ReturnStatement returnStatement) { | 447 void visitReturnStatement(ir.ReturnStatement returnStatement) { |
| 432 HInstruction value; | 448 HInstruction value; |
| 433 if (returnStatement.expression == null) { | 449 if (returnStatement.expression == null) { |
| 434 value = graph.addConstantNull(compiler); | 450 value = graph.addConstantNull(compiler); |
| 435 } else { | 451 } else { |
| 436 assert(target is ir.Procedure); | 452 assert(target is ir.FunctionNode); |
| 437 returnStatement.expression.accept(this); | 453 returnStatement.expression.accept(this); |
| 438 value = typeBuilder.potentiallyCheckOrTrustType(pop(), | 454 value = typeBuilder.potentiallyCheckOrTrustType(pop(), |
| 439 astAdapter.getFunctionReturnType((target as ir.Procedure).function)); | 455 astAdapter.getFunctionReturnType(target)); |
| 440 } | 456 } |
| 441 // TODO(het): Add source information | 457 // TODO(het): Add source information |
| 442 // TODO(het): Set a return value instead of closing the function when we | 458 // TODO(het): Set a return value instead of closing the function when we |
| 443 // support inlining. | 459 // support inlining. |
| 444 closeAndGotoExit(new HReturn(value, null)); | 460 closeAndGotoExit(new HReturn(value, null)); |
| 445 } | 461 } |
| 446 | 462 |
| 447 @override | 463 @override |
| 448 void visitForStatement(ir.ForStatement forStatement) { | 464 void visitForStatement(ir.ForStatement forStatement) { |
| 449 assert(isReachable); | 465 assert(isReachable); |
| (...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1312 if (_unexpectedForeignArguments(invocation, 1, 1)) { | 1328 if (_unexpectedForeignArguments(invocation, 1, 1)) { |
| 1313 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. | 1329 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1314 return; | 1330 return; |
| 1315 } | 1331 } |
| 1316 | 1332 |
| 1317 List<HInstruction> inputs = _visitArguments(invocation.arguments); | 1333 List<HInstruction> inputs = _visitArguments(invocation.arguments); |
| 1318 | 1334 |
| 1319 String isolateName = backend.namer.staticStateHolder; | 1335 String isolateName = backend.namer.staticStateHolder; |
| 1320 SideEffects sideEffects = new SideEffects.empty(); | 1336 SideEffects sideEffects = new SideEffects.empty(); |
| 1321 sideEffects.setAllSideEffects(); | 1337 sideEffects.setAllSideEffects(); |
| 1322 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), | 1338 push(new HForeignCode( |
| 1323 backend.dynamicType, inputs, | 1339 js.js.parseForeignJS("$isolateName = #"), backend.dynamicType, inputs, |
| 1324 nativeBehavior: native.NativeBehavior.CHANGES_OTHER, | 1340 nativeBehavior: native.NativeBehavior.CHANGES_OTHER, |
| 1325 effects: sideEffects)); | 1341 effects: sideEffects)); |
| 1326 } | 1342 } |
| 1327 | 1343 |
| 1328 void handleForeignJsGetStaticState(ir.StaticInvocation invocation) { | 1344 void handleForeignJsGetStaticState(ir.StaticInvocation invocation) { |
| 1329 if (_unexpectedForeignArguments(invocation, 0, 0)) { | 1345 if (_unexpectedForeignArguments(invocation, 0, 0)) { |
| 1330 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. | 1346 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1331 return; | 1347 return; |
| 1332 } | 1348 } |
| 1333 | 1349 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1555 if (selector.isGetter) { | 1571 if (selector.isGetter) { |
| 1556 push(new HInvokeDynamicGetter(selector, mask, null, inputs, type)); | 1572 push(new HInvokeDynamicGetter(selector, mask, null, inputs, type)); |
| 1557 } else if (selector.isSetter) { | 1573 } else if (selector.isSetter) { |
| 1558 push(new HInvokeDynamicSetter(selector, mask, null, inputs, type)); | 1574 push(new HInvokeDynamicSetter(selector, mask, null, inputs, type)); |
| 1559 } else { | 1575 } else { |
| 1560 push(new HInvokeDynamicMethod( | 1576 push(new HInvokeDynamicMethod( |
| 1561 selector, mask, inputs, type, isIntercepted)); | 1577 selector, mask, inputs, type, isIntercepted)); |
| 1562 } | 1578 } |
| 1563 } | 1579 } |
| 1564 | 1580 |
| 1581 @override |
| 1582 void visitFunctionExpression(ir.FunctionExpression funcExpression) { |
| 1583 LocalFunctionElement methodElement = astAdapter.getElement(funcExpression); |
| 1584 ClosureClassMap nestedClosureData = compiler.closureToClassMapper |
| 1585 .getClosureToClassMapping(methodElement.resolvedAst); |
| 1586 assert(nestedClosureData != null); |
| 1587 assert(nestedClosureData.closureClassElement != null); |
| 1588 ClosureClassElement closureClassElement = |
| 1589 nestedClosureData.closureClassElement; |
| 1590 FunctionElement callElement = nestedClosureData.callElement; |
| 1591 // TODO(ahe): This should be registered in codegen, not here. |
| 1592 // TODO(johnniwinther): Is [registerStaticUse] equivalent to |
| 1593 // [addToWorkList]? |
| 1594 registry?.registerStaticUse(new StaticUse.foreignUse(callElement)); |
| 1595 |
| 1596 List<HInstruction> capturedVariables = <HInstruction>[]; |
| 1597 closureClassElement.closureFields.forEach((ClosureFieldElement field) { |
| 1598 Local capturedLocal = |
| 1599 nestedClosureData.getLocalVariableForClosureField(field); |
| 1600 assert(capturedLocal != null); |
| 1601 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
| 1602 }); |
| 1603 |
| 1604 TypeMask type = |
| 1605 new TypeMask.nonNullExact(closureClassElement, compiler.closedWorld); |
| 1606 // TODO(efortuna): Add source information here. |
| 1607 push(new HCreate(closureClassElement, capturedVariables, type)); |
| 1608 |
| 1609 registry?.registerInstantiatedClosure(methodElement); |
| 1610 } |
| 1611 |
| 1565 // TODO(het): Decide when to inline | 1612 // TODO(het): Decide when to inline |
| 1566 @override | 1613 @override |
| 1567 void visitMethodInvocation(ir.MethodInvocation invocation) { | 1614 void visitMethodInvocation(ir.MethodInvocation invocation) { |
| 1568 // Handle `x == null` specially. When these come from null-aware operators, | 1615 // Handle `x == null` specially. When these come from null-aware operators, |
| 1569 // there is no mapping in the astAdapter. | 1616 // there is no mapping in the astAdapter. |
| 1570 if (_handleEqualsNull(invocation)) return; | 1617 if (_handleEqualsNull(invocation)) return; |
| 1571 invocation.receiver.accept(this); | 1618 invocation.receiver.accept(this); |
| 1572 HInstruction receiver = pop(); | 1619 HInstruction receiver = pop(); |
| 1573 | 1620 |
| 1574 _pushDynamicInvocation( | 1621 _pushDynamicInvocation( |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1725 push(new HNot(popBoolified(), backend.boolType)); | 1772 push(new HNot(popBoolified(), backend.boolType)); |
| 1726 } | 1773 } |
| 1727 | 1774 |
| 1728 @override | 1775 @override |
| 1729 void visitStringConcatenation(ir.StringConcatenation stringConcat) { | 1776 void visitStringConcatenation(ir.StringConcatenation stringConcat) { |
| 1730 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); | 1777 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); |
| 1731 stringConcat.accept(stringBuilder); | 1778 stringConcat.accept(stringBuilder); |
| 1732 stack.add(stringBuilder.result); | 1779 stack.add(stringBuilder.result); |
| 1733 } | 1780 } |
| 1734 } | 1781 } |
| OLD | NEW |