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

Side by Side Diff: pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart

Issue 1458703007: dart2js cps: Refactor CallExpressions into Primitives. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebase Created 5 years, 1 month 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library tree_ir_builder; 5 library tree_ir_builder;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../constants/values.dart'; 8 import '../constants/values.dart';
9 import '../cps_ir/cps_ir_nodes.dart' as cps_ir; 9 import '../cps_ir/cps_ir_nodes.dart' as cps_ir;
10 import '../elements/elements.dart'; 10 import '../elements/elements.dart';
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 if (thisParameter != null && reference.definition == thisParameter) { 110 if (thisParameter != null && reference.definition == thisParameter) {
111 return new This(); 111 return new This();
112 } 112 }
113 return new VariableUse(getVariable(reference.definition)); 113 return new VariableUse(getVariable(reference.definition));
114 } 114 }
115 115
116 Label getLabel(cps_ir.Continuation cont) { 116 Label getLabel(cps_ir.Continuation cont) {
117 return labels.putIfAbsent(cont, () => new Label()); 117 return labels.putIfAbsent(cont, () => new Label());
118 } 118 }
119 119
120 Variable addFunctionParameter(cps_ir.Definition variable) { 120 Variable addFunctionParameter(cps_ir.Parameter parameter) {
121 if (variable is cps_ir.Parameter) { 121 return getVariable(parameter);
122 return getVariable(variable);
123 } else {
124 return addMutableVariable(variable as cps_ir.MutableVariable)
125 ..isCaptured = true;
126 }
127 } 122 }
128 123
129 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { 124 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) {
130 currentElement = node.element; 125 currentElement = node.element;
131 if (parent != null) { 126 if (parent != null) {
132 // Local function's 'this' refers to enclosing method's 'this' 127 // Local function's 'this' refers to enclosing method's 'this'
133 thisParameter = parent.thisParameter; 128 thisParameter = parent.thisParameter;
134 } else { 129 } else {
135 thisParameter = node.thisParameter; 130 thisParameter = node.thisParameter;
136 } 131 }
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 Statement result = node.accept(this); // Translate the tail expression. 261 Statement result = node.accept(this); // Translate the tail expression.
267 for (NodeCallback fun in stack.reversed) { 262 for (NodeCallback fun in stack.reversed) {
268 result = fun(result); 263 result = fun(result);
269 } 264 }
270 return result; 265 return result;
271 } 266 }
272 267
273 /// Translates a CPS primitive to a tree expression. 268 /// Translates a CPS primitive to a tree expression.
274 /// 269 ///
275 /// This simply calls the visit method for the primitive. 270 /// This simply calls the visit method for the primitive.
276 Expression translatePrimitive(cps_ir.Primitive prim) { 271 translatePrimitive(cps_ir.Primitive prim) {
277 return prim.accept(this); 272 return prim.accept(this);
278 } 273 }
279 274
280 /************************ INTERIOR EXPRESSIONS ************************/ 275 /************************ INTERIOR EXPRESSIONS ************************/
281 // 276 //
282 // Visit methods for interior expressions must return a function: 277 // Visit methods for interior expressions must return a function:
283 // 278 //
284 // (Statement next) => <result statement> 279 // (Statement next) => <result statement>
285 // 280 //
286 281
287 NodeCallback visitLetPrim(cps_ir.LetPrim node) => (Statement next) { 282 NodeCallback visitLetPrim(cps_ir.LetPrim node) {
288 Variable variable = getVariable(node.primitive); 283 Variable variable = getVariable(node.primitive);
289 Expression value = translatePrimitive(node.primitive); 284 var value = translatePrimitive(node.primitive);
290 if (node.primitive.hasAtLeastOneUse) { 285 if (value is Expression) {
291 return Assign.makeStatement(variable, value, next); 286 if (node.primitive.hasAtLeastOneUse) {
287 return (Statement next) => Assign.makeStatement(variable, value, next);
288 } else {
289 return (Statement next) => new ExpressionStatement(value, next);
290 }
292 } else { 291 } else {
293 return new ExpressionStatement(value, next); 292 assert(value is NodeCallback);
293 return value;
294 } 294 }
295 }; 295 }
296 296
297 // Continuations are bound at the same level, but they have to be 297 // Continuations are bound at the same level, but they have to be
298 // translated as if nested. This is because the body can invoke any 298 // translated as if nested. This is because the body can invoke any
299 // of them from anywhere, so it must be nested inside all of them. 299 // of them from anywhere, so it must be nested inside all of them.
300 // 300 //
301 // The continuation bodies are not always translated directly here because 301 // The continuation bodies are not always translated directly here because
302 // they may have been already translated: 302 // they may have been already translated:
303 // * For singly-used continuations, the continuation's body is 303 // * For singly-used continuations, the continuation's body is
304 // translated at the site of the continuation invocation. 304 // translated at the site of the continuation invocation.
305 // * For recursive continuations, there is a single non-recursive 305 // * For recursive continuations, there is a single non-recursive
(...skipping 25 matching lines...) Expand all
331 Statement catchBody = translateExpression(node.handler.body); 331 Statement catchBody = translateExpression(node.handler.body);
332 return new Try(next, catchParameters, catchBody); 332 return new Try(next, catchParameters, catchBody);
333 }; 333 };
334 334
335 NodeCallback visitLetMutable(cps_ir.LetMutable node) { 335 NodeCallback visitLetMutable(cps_ir.LetMutable node) {
336 Variable variable = addMutableVariable(node.variable); 336 Variable variable = addMutableVariable(node.variable);
337 Expression value = getVariableUse(node.value); 337 Expression value = getVariableUse(node.value);
338 return (Statement next) => Assign.makeStatement(variable, value, next); 338 return (Statement next) => Assign.makeStatement(variable, value, next);
339 } 339 }
340 340
341
342 /************************ CALL EXPRESSIONS ************************/
343 //
344 // Visit methods for call expressions must return a function:
345 //
346 // (Statement next) => <result statement>
347 //
348 // The result statement must include an assignment to the continuation
349 // parameter, if the parameter is used.
350 //
351
352 NodeCallback makeCallExpression(cps_ir.CallExpression call,
353 Expression expression) {
354 return (Statement next) {
355 cps_ir.Parameter result = call.continuation.definition.parameters.single;
356 if (result.hasAtLeastOneUse) {
357 return Assign.makeStatement(getVariable(result), expression, next);
358 } else {
359 return new ExpressionStatement(expression, next);
360 }
361 };
362 }
363
364 NodeCallback visitInvokeStatic(cps_ir.InvokeStatic node) {
365 List<Expression> arguments = translateArguments(node.arguments);
366 Expression invoke = new InvokeStatic(node.target, node.selector, arguments,
367 node.sourceInformation);
368 return makeCallExpression(node, invoke);
369 }
370
371 NodeCallback visitInvokeMethod(cps_ir.InvokeMethod node) {
372 InvokeMethod invoke = new InvokeMethod(
373 getVariableUse(node.receiver),
374 node.selector,
375 node.mask,
376 translateArguments(node.arguments),
377 node.sourceInformation);
378 invoke.receiverIsNotNull = node.receiverIsNotNull;
379 return makeCallExpression(node, invoke);
380 }
381
382 NodeCallback visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) {
383 Expression receiver = getVariableUse(node.receiver);
384 List<Expression> arguments = translateArguments(node.arguments);
385 Expression invoke = new InvokeMethodDirectly(receiver, node.target,
386 node.selector, arguments, node.sourceInformation);
387 return makeCallExpression(node, invoke);
388 }
389
390 NodeCallback visitTypeCast(cps_ir.TypeCast node) {
391 Expression value = getVariableUse(node.value);
392 List<Expression> typeArgs = translateArguments(node.typeArguments);
393 Expression expression =
394 new TypeOperator(value, node.dartType, typeArgs, isTypeTest: false);
395 return makeCallExpression(node, expression);
396 }
397
398 NodeCallback visitInvokeConstructor(cps_ir.InvokeConstructor node) {
399 List<Expression> arguments = translateArguments(node.arguments);
400 Expression invoke = new InvokeConstructor(
401 node.dartType,
402 node.target,
403 node.selector,
404 arguments,
405 node.sourceInformation);
406 return makeCallExpression(node, invoke);
407 }
408
409 NodeCallback visitForeignCode(cps_ir.ForeignCode node) {
410 List<Expression> arguments =
411 node.arguments.map(getVariableUse).toList(growable: false);
412 if (HasCapturedArguments.check(node.codeTemplate.ast)) {
413 for (Expression arg in arguments) {
414 if (arg is VariableUse) {
415 arg.variable.isCaptured = true;
416 } else {
417 // TODO(asgerf): Avoid capture of 'this'.
418 }
419 }
420 }
421 if (node.codeTemplate.isExpression) {
422 Expression foreignCode = new ForeignExpression(
423 node.codeTemplate,
424 node.type,
425 arguments,
426 node.nativeBehavior,
427 node.dependency);
428 return makeCallExpression(node, foreignCode);
429 } else {
430 return (Statement next) {
431 assert(next is Unreachable); // We are not using the `next` statement.
432 return new ForeignStatement(
433 node.codeTemplate,
434 node.type,
435 arguments,
436 node.nativeBehavior,
437 node.dependency);
438 };
439 }
440 }
441
442 NodeCallback visitGetLazyStatic(cps_ir.GetLazyStatic node) {
443 // In the tree IR, GetStatic handles lazy fields because we do not need
444 // as fine-grained control over side effects.
445 GetStatic value = new GetStatic(node.element, node.sourceInformation);
446 return makeCallExpression(node, value);
447 }
448
449 @override
450 NodeCallback visitYield(cps_ir.Yield node) {
451 return (Statement next) {
452 return new Yield(getVariableUse(node.input), node.hasStar, next);
453 };
454 }
455
456 @override
457 NodeCallback visitAwait(cps_ir.Await node) {
458 Expression value = new Await(getVariableUse(node.input));
459 return makeCallExpression(node, value);
460 }
461
462
463 /************************** TAIL EXPRESSIONS **************************/ 341 /************************** TAIL EXPRESSIONS **************************/
464 // 342 //
465 // Visit methods for tail expressions must return a statement directly 343 // Visit methods for tail expressions must return a statement directly
466 // (not a function like interior and call expressions). 344 // (not a function like interior and call expressions).
467 345
468 Statement visitThrow(cps_ir.Throw node) { 346 Statement visitThrow(cps_ir.Throw node) {
469 Expression value = getVariableUse(node.value); 347 Expression value = getVariableUse(node.value);
470 return new Throw(value); 348 return new Throw(value);
471 } 349 }
472 350
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 return new GetIndex(getVariableUse(node.object), 569 return new GetIndex(getVariableUse(node.object),
692 getVariableUse(node.index)); 570 getVariableUse(node.index));
693 } 571 }
694 572
695 Expression visitSetIndex(cps_ir.SetIndex node) { 573 Expression visitSetIndex(cps_ir.SetIndex node) {
696 return new SetIndex(getVariableUse(node.object), 574 return new SetIndex(getVariableUse(node.object),
697 getVariableUse(node.index), 575 getVariableUse(node.index),
698 getVariableUse(node.value)); 576 getVariableUse(node.value));
699 } 577 }
700 578
579 Expression visitInvokeStatic(cps_ir.InvokeStatic node) {
580 List<Expression> arguments = translateArguments(node.arguments);
581 return new InvokeStatic(node.target, node.selector, arguments,
582 node.sourceInformation);
583 }
584
585 Expression visitInvokeMethod(cps_ir.InvokeMethod node) {
586 InvokeMethod invoke = new InvokeMethod(
587 getVariableUse(node.receiver),
588 node.selector,
589 node.mask,
590 translateArguments(node.arguments),
591 node.sourceInformation);
592 invoke.receiverIsNotNull = node.receiverIsNotNull;
593 return invoke;
594 }
595
596 Expression visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) {
597 Expression receiver = getVariableUse(node.receiver);
598 List<Expression> arguments = translateArguments(node.arguments);
599 return new InvokeMethodDirectly(receiver, node.target,
600 node.selector, arguments, node.sourceInformation);
601 }
602
603 Expression visitTypeCast(cps_ir.TypeCast node) {
604 Expression value = getVariableUse(node.value);
605 List<Expression> typeArgs = translateArguments(node.typeArguments);
606 return new TypeOperator(value, node.dartType, typeArgs, isTypeTest: false);
607 }
608
609 Expression visitInvokeConstructor(cps_ir.InvokeConstructor node) {
610 List<Expression> arguments = translateArguments(node.arguments);
611 return new InvokeConstructor(
612 node.dartType,
613 node.target,
614 node.selector,
615 arguments,
616 node.sourceInformation);
617 }
618
619 visitForeignCode(cps_ir.ForeignCode node) {
620 List<Expression> arguments =
621 node.arguments.map(getVariableUse).toList(growable: false);
622 if (HasCapturedArguments.check(node.codeTemplate.ast)) {
623 for (Expression arg in arguments) {
624 if (arg is VariableUse) {
625 arg.variable.isCaptured = true;
626 } else {
627 // TODO(asgerf): Avoid capture of 'this'.
628 }
629 }
630 }
631 if (node.codeTemplate.isExpression) {
632 return new ForeignExpression(
633 node.codeTemplate,
634 node.type,
635 arguments,
636 node.nativeBehavior,
637 node.dependency);
638 } else {
639 return (Statement next) {
640 assert(next is Unreachable); // We are not using the `next` statement.
641 return new ForeignStatement(
642 node.codeTemplate,
643 node.type,
644 arguments,
645 node.nativeBehavior,
646 node.dependency);
647 };
648 }
649 }
650
651 Expression visitGetLazyStatic(cps_ir.GetLazyStatic node) {
652 // In the tree IR, GetStatic handles lazy fields because we do not need
653 // as fine-grained control over side effects.
654 return new GetStatic(node.element, node.sourceInformation);
655 }
656
657 @override
658 NodeCallback visitYield(cps_ir.Yield node) {
659 return (Statement next) {
660 return new Yield(getVariableUse(node.input), node.hasStar, next);
661 };
662 }
663
664 @override
665 Expression visitAwait(cps_ir.Await node) {
666 return new Await(getVariableUse(node.input));
667 }
668
701 @override 669 @override
702 Expression visitRefinement(cps_ir.Refinement node) { 670 Expression visitRefinement(cps_ir.Refinement node) {
703 throw 'Unexpected Refinement node in tree builder'; 671 throw 'Unexpected Refinement node in tree builder';
704 } 672 }
705 673
706 /********** UNUSED VISIT METHODS *************/ 674 /********** UNUSED VISIT METHODS *************/
707 675
708 unexpectedNode(cps_ir.Node node) { 676 unexpectedNode(cps_ir.Node node) {
709 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node'); 677 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node');
710 } 678 }
(...skipping 23 matching lines...) Expand all
734 --enclosingFunctions; 702 --enclosingFunctions;
735 } 703 }
736 704
737 @override 705 @override
738 visitInterpolatedNode(js.InterpolatedNode node) { 706 visitInterpolatedNode(js.InterpolatedNode node) {
739 if (enclosingFunctions > 0) { 707 if (enclosingFunctions > 0) {
740 found = true; 708 found = true;
741 } 709 }
742 } 710 }
743 } 711 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/codegen/unsugar.dart ('k') | tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698