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

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 buildProcedure(target);
127 } else if (target is ir.Field) { 136 } else if (target is ir.Field) {
128 buildField(target); 137 buildField(target);
129 } else if (target is ir.Constructor) { 138 } else if (target is ir.Constructor) {
130 buildConstructor(target); 139 buildConstructor(target);
140 } else if (target is ir.FunctionExpression) {
141 buildFuncExpr(target);
142 } else {
143 throw 'No case implemented to handle $target';
131 } 144 }
132 assert(graph.isValid()); 145 assert(graph.isValid());
133 return graph; 146 return graph;
134 } 147 }
135 148
136 void buildField(ir.Field field) { 149 void buildField(ir.Field field) {
137 openFunction(); 150 openFunction();
138 if (field.initializer != null) { 151 if (field.initializer != null) {
139 field.initializer.accept(this); 152 field.initializer.accept(this);
140 } else { 153 } else {
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 type, kind, original.instructionType, reifiedType, original); 347 type, kind, original.instructionType, reifiedType, original);
335 } 348 }
336 349
337 /// Builds a SSA graph for [procedure]. 350 /// Builds a SSA graph for [procedure].
338 void buildProcedure(ir.Procedure procedure) { 351 void buildProcedure(ir.Procedure procedure) {
339 openFunction(); 352 openFunction();
340 procedure.function.body.accept(this); 353 procedure.function.body.accept(this);
341 closeFunction(); 354 closeFunction();
342 } 355 }
343 356
357 // TODO(efortuna): This function is identical to the one above. Waiting for
358 // response from Asger and Kevin on if we should implement a common interface
359 // between Procedure and FunctionExpression. Regardless, this function is
360 // definitely not permanent.
361 void buildFuncExpr(ir.FunctionExpression procedure) {
362 openFunction();
363 procedure.function.body.accept(this);
364 closeFunction();
365 }
366
344 void addImplicitInstantiation(DartType type) { 367 void addImplicitInstantiation(DartType type) {
345 if (type != null) { 368 if (type != null) {
346 currentImplicitInstantiations.add(type); 369 currentImplicitInstantiations.add(type);
347 } 370 }
348 } 371 }
349 372
350 void removeImplicitInstantiation(DartType type) { 373 void removeImplicitInstantiation(DartType type) {
351 if (type != null) { 374 if (type != null) {
352 currentImplicitInstantiations.removeLast(); 375 currentImplicitInstantiations.removeLast();
353 } 376 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 exprStatement.expression.accept(this); 449 exprStatement.expression.accept(this);
427 pop(); 450 pop();
428 } 451 }
429 452
430 @override 453 @override
431 void visitReturnStatement(ir.ReturnStatement returnStatement) { 454 void visitReturnStatement(ir.ReturnStatement returnStatement) {
432 HInstruction value; 455 HInstruction value;
433 if (returnStatement.expression == null) { 456 if (returnStatement.expression == null) {
434 value = graph.addConstantNull(compiler); 457 value = graph.addConstantNull(compiler);
435 } else { 458 } else {
436 assert(target is ir.Procedure); 459 assert(target is ir.Procedure || target is ir.FunctionExpression);
437 returnStatement.expression.accept(this); 460 returnStatement.expression.accept(this);
461 // More stupidity until we resolve the interface issue with
462 // FunctionExpressions and Procedures.
sra1 2016/12/06 02:35:41 It might be possible to simply use ir.FunctionNode
Emily Fortuna 2016/12/06 18:49:22 Done.
463 // TODO(efortuna): Remove!
464 ir.FunctionNode functionNode;
465 if (target is ir.Procedure) {
466 functionNode = (target as ir.Procedure).function;
467 } else if (target is ir.FunctionExpression) {
468 functionNode = (target as ir.FunctionExpression).function;
469 }
438 value = typeBuilder.potentiallyCheckOrTrustType(pop(), 470 value = typeBuilder.potentiallyCheckOrTrustType(pop(),
439 astAdapter.getFunctionReturnType((target as ir.Procedure).function)); 471 astAdapter.getFunctionReturnType(functionNode));
440 } 472 }
441 // TODO(het): Add source information 473 // TODO(het): Add source information
442 // TODO(het): Set a return value instead of closing the function when we 474 // TODO(het): Set a return value instead of closing the function when we
443 // support inlining. 475 // support inlining.
444 closeAndGotoExit(new HReturn(value, null)); 476 closeAndGotoExit(new HReturn(value, null));
445 } 477 }
446 478
447 @override 479 @override
448 void visitForStatement(ir.ForStatement forStatement) { 480 void visitForStatement(ir.ForStatement forStatement) {
449 assert(isReachable); 481 assert(isReachable);
(...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after
1312 if (_unexpectedForeignArguments(invocation, 1, 1)) { 1344 if (_unexpectedForeignArguments(invocation, 1, 1)) {
1313 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. 1345 stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
1314 return; 1346 return;
1315 } 1347 }
1316 1348
1317 List<HInstruction> inputs = _visitArguments(invocation.arguments); 1349 List<HInstruction> inputs = _visitArguments(invocation.arguments);
1318 1350
1319 String isolateName = backend.namer.staticStateHolder; 1351 String isolateName = backend.namer.staticStateHolder;
1320 SideEffects sideEffects = new SideEffects.empty(); 1352 SideEffects sideEffects = new SideEffects.empty();
1321 sideEffects.setAllSideEffects(); 1353 sideEffects.setAllSideEffects();
1322 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), 1354 push(new HForeignCode(
1323 backend.dynamicType, inputs, 1355 js.js.parseForeignJS("$isolateName = #"), backend.dynamicType, inputs,
1324 nativeBehavior: native.NativeBehavior.CHANGES_OTHER, 1356 nativeBehavior: native.NativeBehavior.CHANGES_OTHER,
1325 effects: sideEffects)); 1357 effects: sideEffects));
1326 } 1358 }
1327 1359
1328 void handleForeignJsGetStaticState(ir.StaticInvocation invocation) { 1360 void handleForeignJsGetStaticState(ir.StaticInvocation invocation) {
1329 if (_unexpectedForeignArguments(invocation, 0, 0)) { 1361 if (_unexpectedForeignArguments(invocation, 0, 0)) {
1330 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. 1362 stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
1331 return; 1363 return;
1332 } 1364 }
1333 1365
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1555 if (selector.isGetter) { 1587 if (selector.isGetter) {
1556 push(new HInvokeDynamicGetter(selector, mask, null, inputs, type)); 1588 push(new HInvokeDynamicGetter(selector, mask, null, inputs, type));
1557 } else if (selector.isSetter) { 1589 } else if (selector.isSetter) {
1558 push(new HInvokeDynamicSetter(selector, mask, null, inputs, type)); 1590 push(new HInvokeDynamicSetter(selector, mask, null, inputs, type));
1559 } else { 1591 } else {
1560 push(new HInvokeDynamicMethod( 1592 push(new HInvokeDynamicMethod(
1561 selector, mask, inputs, type, isIntercepted)); 1593 selector, mask, inputs, type, isIntercepted));
1562 } 1594 }
1563 } 1595 }
1564 1596
1597 @override
1598 void visitFunctionExpression(ir.FunctionExpression funcExpression) {
1599 LocalFunctionElement methodElement = astAdapter.getElement(funcExpression);
1600 ClosureClassMap nestedClosureData = compiler.closureToClassMapper
1601 .getClosureToClassMapping(methodElement.resolvedAst);
1602 assert(nestedClosureData != null);
1603 assert(nestedClosureData.closureClassElement != null);
1604 ClosureClassElement closureClassElement =
1605 nestedClosureData.closureClassElement;
1606 FunctionElement callElement = nestedClosureData.callElement;
1607 // TODO(ahe): This should be registered in codegen, not here.
1608 // TODO(johnniwinther): Is [registerStaticUse] equivalent to
1609 // [addToWorkList]?
1610 registry?.registerStaticUse(new StaticUse.foreignUse(callElement));
Harry Terkelsen 2016/12/06 18:46:36 johnni is making some changes to the registry. I w
Emily Fortuna 2016/12/06 18:49:22 Acknowledged.
1611
1612 List<HInstruction> capturedVariables = <HInstruction>[];
1613 closureClassElement.closureFields.forEach((ClosureFieldElement field) {
1614 Local capturedLocal =
1615 nestedClosureData.getLocalVariableForClosureField(field);
1616 assert(capturedLocal != null);
1617 capturedVariables.add(localsHandler.readLocal(capturedLocal));
1618 });
1619
1620 TypeMask type =
1621 new TypeMask.nonNullExact(closureClassElement, compiler.closedWorld);
1622 // TODO(efortuna): Add source information here.
1623 push(new HCreate(closureClassElement, capturedVariables, type));
1624
1625 registry?.registerInstantiatedClosure(methodElement);
1626 }
1627
1565 // TODO(het): Decide when to inline 1628 // TODO(het): Decide when to inline
1566 @override 1629 @override
1567 void visitMethodInvocation(ir.MethodInvocation invocation) { 1630 void visitMethodInvocation(ir.MethodInvocation invocation) {
1568 // Handle `x == null` specially. When these come from null-aware operators, 1631 // Handle `x == null` specially. When these come from null-aware operators,
1569 // there is no mapping in the astAdapter. 1632 // there is no mapping in the astAdapter.
1570 if (_handleEqualsNull(invocation)) return; 1633 if (_handleEqualsNull(invocation)) return;
1571 invocation.receiver.accept(this); 1634 invocation.receiver.accept(this);
1572 HInstruction receiver = pop(); 1635 HInstruction receiver = pop();
1573 1636
1574 _pushDynamicInvocation( 1637 _pushDynamicInvocation(
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1725 push(new HNot(popBoolified(), backend.boolType)); 1788 push(new HNot(popBoolified(), backend.boolType));
1726 } 1789 }
1727 1790
1728 @override 1791 @override
1729 void visitStringConcatenation(ir.StringConcatenation stringConcat) { 1792 void visitStringConcatenation(ir.StringConcatenation stringConcat) {
1730 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); 1793 KernelStringBuilder stringBuilder = new KernelStringBuilder(this);
1731 stringConcat.accept(stringBuilder); 1794 stringConcat.accept(stringBuilder);
1732 stack.add(stringBuilder.result); 1795 stack.add(stringBuilder.result);
1733 } 1796 }
1734 } 1797 }
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