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

Side by Side Diff: pkg/compiler/lib/src/ssa/builder_kernel.dart

Issue 2549233004: Handle closures, aka FunctionExpression in Kernel! (Closed)
Patch Set: . Created 4 years 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698