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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 dart2js.ir_builder; 5 library dart2js.ir_builder;
6 6
7 import '../closure.dart' as closure; 7 import '../closure.dart' as closure;
8 import '../common.dart'; 8 import '../common.dart';
9 import '../common/names.dart' show 9 import '../common/names.dart' show Names, Selectors;
10 Names, 10 import '../compile_time_constants.dart' show BackendConstantEnvironment;
11 Selectors;
12 import '../compile_time_constants.dart' show
13 BackendConstantEnvironment;
14 import '../constants/constant_system.dart'; 11 import '../constants/constant_system.dart';
15 import '../constants/values.dart' show 12 import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
16 ConstantValue,
17 PrimitiveConstantValue;
18 import '../dart_types.dart'; 13 import '../dart_types.dart';
19 import '../elements/elements.dart'; 14 import '../elements/elements.dart';
20 import '../io/source_information.dart'; 15 import '../io/source_information.dart';
21 import '../js/js.dart' as js show 16 import '../js/js.dart' as js
22 js, 17 show
23 objectLiteral, 18 js,
24 Expression, 19 objectLiteral,
25 LiteralStatement, 20 Expression,
26 Template, 21 LiteralStatement,
27 InterpolatedExpression, 22 Template,
28 isIdentityTemplate; 23 InterpolatedExpression,
29 import '../native/native.dart' show 24 isIdentityTemplate;
30 NativeBehavior; 25 import '../native/native.dart' show NativeBehavior;
31 import '../tree/tree.dart' as ast; 26 import '../tree/tree.dart' as ast;
32 import '../types/types.dart' show 27 import '../types/types.dart' show TypeMask;
33 TypeMask; 28 import '../universe/call_structure.dart' show CallStructure;
34 import '../universe/call_structure.dart' show 29 import '../universe/selector.dart' show Selector, SelectorKind;
35 CallStructure;
36 import '../universe/selector.dart' show
37 Selector,
38 SelectorKind;
39 30
40 import 'cps_ir_builder_task.dart' show 31 import 'cps_ir_builder_task.dart' show GlobalProgramInformation;
41 GlobalProgramInformation;
42 import 'cps_ir_nodes.dart' as ir; 32 import 'cps_ir_nodes.dart' as ir;
43 33
44
45 /// A mapping from variable elements to their compile-time values. 34 /// A mapping from variable elements to their compile-time values.
46 /// 35 ///
47 /// Map elements denoted by parameters and local variables to the 36 /// Map elements denoted by parameters and local variables to the
48 /// [ir.Primitive] that is their value. Parameters and locals are 37 /// [ir.Primitive] that is their value. Parameters and locals are
49 /// assigned indexes which can be used to refer to them. 38 /// assigned indexes which can be used to refer to them.
50 class Environment { 39 class Environment {
51 /// A map from locals to their environment index. 40 /// A map from locals to their environment index.
52 final Map<Local, int> variable2index; 41 final Map<Local, int> variable2index;
53 42
54 /// A reverse map from environment indexes to the variable. 43 /// A reverse map from environment indexes to the variable.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 ir.Primitive value = index2value.last; 92 ir.Primitive value = index2value.last;
104 // The map from variables to their index are shared, so we cannot remove 93 // The map from variables to their index are shared, so we cannot remove
105 // the mapping in `variable2index`. 94 // the mapping in `variable2index`.
106 index2variable.length -= count; 95 index2variable.length -= count;
107 index2value.length -= count; 96 index2value.length -= count;
108 return value; 97 return value;
109 } 98 }
110 99
111 ir.Primitive lookup(Local element) { 100 ir.Primitive lookup(Local element) {
112 assert(invariant(element, variable2index.containsKey(element), 101 assert(invariant(element, variable2index.containsKey(element),
113 message: "Unknown variable: $element.")); 102 message: "Unknown variable: $element."));
114 return index2value[variable2index[element]]; 103 return index2value[variable2index[element]];
115 } 104 }
116 105
117 void update(Local element, ir.Primitive value) { 106 void update(Local element, ir.Primitive value) {
118 index2value[variable2index[element]] = value; 107 index2value[variable2index[element]] = value;
119 } 108 }
120 109
121 /// Verify that the variable2index and index2variable maps agree up to the 110 /// Verify that the variable2index and index2variable maps agree up to the
122 /// index [length] exclusive. 111 /// index [length] exclusive.
123 bool sameDomain(int length, Environment other) { 112 bool sameDomain(int length, Environment other) {
(...skipping 27 matching lines...) Expand all
151 final Environment _continuationEnvironment; 140 final Environment _continuationEnvironment;
152 141
153 final List<Iterable<LocalVariableElement>> _boxedTryVariables = 142 final List<Iterable<LocalVariableElement>> _boxedTryVariables =
154 <Iterable<LocalVariableElement>>[]; 143 <Iterable<LocalVariableElement>>[];
155 144
156 /// Construct a collector for a given environment and optionally a target. 145 /// Construct a collector for a given environment and optionally a target.
157 /// 146 ///
158 /// The environment is the one in effect at the point where the jump's 147 /// The environment is the one in effect at the point where the jump's
159 /// continuation will be bound. Continuations can take an extra argument 148 /// continuation will be bound. Continuations can take an extra argument
160 /// (see [addJump]). 149 /// (see [addJump]).
161 JumpCollector(this._continuationEnvironment, this.target, 150 JumpCollector(
162 bool hasExtraArgument) { 151 this._continuationEnvironment, this.target, bool hasExtraArgument) {
163 if (hasExtraArgument) _continuationEnvironment.extend(null, null); 152 if (hasExtraArgument) _continuationEnvironment.extend(null, null);
164 } 153 }
165 154
166 /// Construct a collector for collecting only return jumps. 155 /// Construct a collector for collecting only return jumps.
167 /// 156 ///
168 /// There is no jump target, it is implicitly the exit from the function. 157 /// There is no jump target, it is implicitly the exit from the function.
169 /// There is no environment at the destination. 158 /// There is no environment at the destination.
170 JumpCollector.retrn(this._continuation) 159 JumpCollector.retrn(this._continuation)
171 : _continuationEnvironment = null, target = null; 160 : _continuationEnvironment = null,
161 target = null;
172 162
173 /// Construct a collector for collecting goto jumps. 163 /// Construct a collector for collecting goto jumps.
174 /// 164 ///
175 /// There is no continuation or environment at the destination. 165 /// There is no continuation or environment at the destination.
176 JumpCollector.goto(this.target) : _continuationEnvironment = null; 166 JumpCollector.goto(this.target) : _continuationEnvironment = null;
177 167
178 /// True if the collector has not recorded any jumps to its continuation. 168 /// True if the collector has not recorded any jumps to its continuation.
179 bool get isEmpty; 169 bool get isEmpty;
180 170
181 /// The continuation encapsulated by this collector. 171 /// The continuation encapsulated by this collector.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 263
274 Environment get environment { 264 Environment get environment {
275 if (_continuation == null) _setContinuation(); 265 if (_continuation == null) _setContinuation();
276 return _continuationEnvironment; 266 return _continuationEnvironment;
277 } 267 }
278 268
279 void addJump(IrBuilder builder, 269 void addJump(IrBuilder builder,
280 [ir.Primitive value, SourceInformation sourceInformation]) { 270 [ir.Primitive value, SourceInformation sourceInformation]) {
281 assert(_continuation == null); 271 assert(_continuation == null);
282 _buildTryExit(builder); 272 _buildTryExit(builder);
283 ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized( 273 ir.InvokeContinuation invoke =
284 isEscapingTry: isEscapingTry); 274 new ir.InvokeContinuation.uninitialized(isEscapingTry: isEscapingTry);
285 builder.add(invoke); 275 builder.add(invoke);
286 _invocations.add(invoke); 276 _invocations.add(invoke);
287 // Truncate the environment at the invocation site so it only includes 277 // Truncate the environment at the invocation site so it only includes
288 // values that will be continuation arguments. If an extra value is passed 278 // values that will be continuation arguments. If an extra value is passed
289 // it will already be included in the continuation environment, but it is 279 // it will already be included in the continuation environment, but it is
290 // not present in the invocation environment. 280 // not present in the invocation environment.
291 int delta = builder.environment.length - _continuationEnvironment.length; 281 int delta = builder.environment.length - _continuationEnvironment.length;
292 if (value != null) ++delta; 282 if (value != null) ++delta;
293 if (delta > 0) builder.environment.discard(delta); 283 if (delta > 0) builder.environment.discard(delta);
294 if (value != null) builder.environment.extend(null, value); 284 if (value != null) builder.environment.extend(null, value);
(...skipping 14 matching lines...) Expand all
309 // that has a different value (from the environment in scope at the 299 // that has a different value (from the environment in scope at the
310 // continuation binding) on some path. `_environment` is initially a copy 300 // continuation binding) on some path. `_environment` is initially a copy
311 // of the environment in scope at the continuation binding. Compute the 301 // of the environment in scope at the continuation binding. Compute the
312 // continuation parameters and add them to `_environment` so it will become 302 // continuation parameters and add them to `_environment` so it will become
313 // the one in scope for the continuation body. 303 // the one in scope for the continuation body.
314 List<ir.Parameter> parameters = <ir.Parameter>[]; 304 List<ir.Parameter> parameters = <ir.Parameter>[];
315 if (_invocationEnvironments.isNotEmpty) { 305 if (_invocationEnvironments.isNotEmpty) {
316 int length = _continuationEnvironment.length; 306 int length = _continuationEnvironment.length;
317 for (int varIndex = 0; varIndex < length; ++varIndex) { 307 for (int varIndex = 0; varIndex < length; ++varIndex) {
318 for (Environment invocationEnvironment in _invocationEnvironments) { 308 for (Environment invocationEnvironment in _invocationEnvironments) {
319 assert(invocationEnvironment.sameDomain(length, 309 assert(invocationEnvironment.sameDomain(
320 _continuationEnvironment)); 310 length, _continuationEnvironment));
321 if (invocationEnvironment[varIndex] != 311 if (invocationEnvironment[varIndex] !=
322 _continuationEnvironment[varIndex]) { 312 _continuationEnvironment[varIndex]) {
323 ir.Parameter parameter = new ir.Parameter( 313 ir.Parameter parameter = new ir.Parameter(
324 _continuationEnvironment.index2variable[varIndex]); 314 _continuationEnvironment.index2variable[varIndex]);
325 _continuationEnvironment.index2value[varIndex] = parameter; 315 _continuationEnvironment.index2value[varIndex] = parameter;
326 parameters.add(parameter); 316 parameters.add(parameter);
327 break; 317 break;
328 } 318 }
329 } 319 }
330 } 320 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 isEmpty = false; 382 isEmpty = false;
393 _buildTryExit(builder); 383 _buildTryExit(builder);
394 // Truncate the environment at the invocation site so it only includes 384 // Truncate the environment at the invocation site so it only includes
395 // values that will be continuation arguments. If an extra value is passed 385 // values that will be continuation arguments. If an extra value is passed
396 // it will already be included in the continuation environment, but it is 386 // it will already be included in the continuation environment, but it is
397 // not present in the invocation environment. 387 // not present in the invocation environment.
398 int delta = builder.environment.length - _continuationEnvironment.length; 388 int delta = builder.environment.length - _continuationEnvironment.length;
399 if (value != null) ++delta; 389 if (value != null) ++delta;
400 if (delta > 0) builder.environment.discard(delta); 390 if (delta > 0) builder.environment.discard(delta);
401 if (value != null) builder.environment.extend(null, value); 391 if (value != null) builder.environment.extend(null, value);
402 builder.add(new ir.InvokeContinuation(_continuation, 392 builder.add(new ir.InvokeContinuation(
403 builder.environment.index2value, 393 _continuation, builder.environment.index2value,
404 isRecursive: true, 394 isRecursive: true, isEscapingTry: isEscapingTry));
405 isEscapingTry: isEscapingTry));
406 builder._current = null; 395 builder._current = null;
407 } 396 }
408 } 397 }
409 398
410 /// Collect 'return' jumps. 399 /// Collect 'return' jumps.
411 /// 400 ///
412 /// A return jump is one that targets the return continuation of a function. 401 /// A return jump is one that targets the return continuation of a function.
413 /// Thus, returns from inside try/finally are not return jumps because they are 402 /// Thus, returns from inside try/finally are not return jumps because they are
414 /// intercepted by a block that contains the finally handler code. 403 /// intercepted by a block that contains the finally handler code.
415 class ReturnJumpCollector extends JumpCollector { 404 class ReturnJumpCollector extends JumpCollector {
416 bool isEmpty = true; 405 bool isEmpty = true;
417 ir.Continuation get continuation => _continuation; 406 ir.Continuation get continuation => _continuation;
418 Environment environment = null; 407 Environment environment = null;
419 408
420 /// Construct a return jump collector for a given return continuation. 409 /// Construct a return jump collector for a given return continuation.
421 ReturnJumpCollector(ir.Continuation continuation) : super.retrn(continuation); 410 ReturnJumpCollector(ir.Continuation continuation) : super.retrn(continuation);
422 411
423 void addJump(IrBuilder builder, 412 void addJump(IrBuilder builder,
424 [ir.Primitive value, SourceInformation sourceInformation]) { 413 [ir.Primitive value, SourceInformation sourceInformation]) {
425 isEmpty = false; 414 isEmpty = false;
426 builder.add(new ir.InvokeContinuation(continuation, <ir.Primitive>[value], 415 builder.add(new ir.InvokeContinuation(continuation, <ir.Primitive>[value],
427 isEscapingTry: isEscapingTry, 416 isEscapingTry: isEscapingTry, sourceInformation: sourceInformation));
428 sourceInformation: sourceInformation));
429 builder._current = null; 417 builder._current = null;
430 } 418 }
431 } 419 }
432 420
433 /// Collect 'goto' jumps, continue to a labeled case from within a switch. 421 /// Collect 'goto' jumps, continue to a labeled case from within a switch.
434 /// 422 ///
435 /// These jumps are unrestricted within the switch. They can be forward or 423 /// These jumps are unrestricted within the switch. They can be forward or
436 /// backward. They are implemented by assigning to a state variable. 424 /// backward. They are implemented by assigning to a state variable.
437 class GotoJumpCollector extends JumpCollector { 425 class GotoJumpCollector extends JumpCollector {
438 bool isEmpty = true; 426 bool isEmpty = true;
439 final ir.Continuation continuation = null; 427 final ir.Continuation continuation = null;
440 final Environment environment = null; 428 final Environment environment = null;
441 429
442 int _stateVariableIndex; 430 int _stateVariableIndex;
443 int _stateValue; 431 int _stateValue;
444 JumpCollector _breakJoin; 432 JumpCollector _breakJoin;
445 433
446 GotoJumpCollector(JumpTarget target, this._stateVariableIndex, 434 GotoJumpCollector(JumpTarget target, this._stateVariableIndex,
447 this._stateValue, this._breakJoin) : super.goto(target); 435 this._stateValue, this._breakJoin)
436 : super.goto(target);
448 437
449 void addJump(IrBuilder builder, 438 void addJump(IrBuilder builder,
450 [ir.Primitive value, SourceInformation sourceInformation]) { 439 [ir.Primitive value, SourceInformation sourceInformation]) {
451 isEmpty = false; 440 isEmpty = false;
452 ir.Primitive constant = builder.buildIntegerConstant(_stateValue); 441 ir.Primitive constant = builder.buildIntegerConstant(_stateValue);
453 builder.environment.index2value[_stateVariableIndex] = constant; 442 builder.environment.index2value[_stateVariableIndex] = constant;
454 builder.jumpTo(_breakJoin); 443 builder.jumpTo(_breakJoin);
455 } 444 }
456 } 445 }
457 446
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 /// Mutable variables are treated as boxed. Writes to them are observable 581 /// Mutable variables are treated as boxed. Writes to them are observable
593 /// side effects. 582 /// side effects.
594 Map<Local, ir.MutableVariable> mutableVariables; 583 Map<Local, ir.MutableVariable> mutableVariables;
595 584
596 ir.Expression root = null; 585 ir.Expression root = null;
597 ir.Expression _current = null; 586 ir.Expression _current = null;
598 587
599 GlobalProgramInformation get program => state.program; 588 GlobalProgramInformation get program => state.program;
600 589
601 IrBuilder(GlobalProgramInformation program, 590 IrBuilder(GlobalProgramInformation program,
602 BackendConstantEnvironment constants, 591 BackendConstantEnvironment constants, ExecutableElement currentElement)
603 ExecutableElement currentElement) 592 : state = new IrBuilderSharedState(program, constants, currentElement),
604 : state = new IrBuilderSharedState(program, constants, currentElement), 593 environment = new Environment.empty(),
605 environment = new Environment.empty(), 594 mutableVariables = <Local, ir.MutableVariable>{};
606 mutableVariables = <Local, ir.MutableVariable>{};
607 595
608 IrBuilder._internal(this.state, this.environment, this.mutableVariables); 596 IrBuilder._internal(this.state, this.environment, this.mutableVariables);
609 597
610 /// Construct a delimited visitor for visiting a subtree. 598 /// Construct a delimited visitor for visiting a subtree.
611 /// 599 ///
612 /// Build a subterm that is not (yet) connected to the CPS term. The 600 /// Build a subterm that is not (yet) connected to the CPS term. The
613 /// delimited visitor has its own has its own context for building an IR 601 /// delimited visitor has its own has its own context for building an IR
614 /// expression, so the built expression is not plugged into the parent's 602 /// expression, so the built expression is not plugged into the parent's
615 /// context. It has its own compile-time environment mapping local 603 /// context. It has its own compile-time environment mapping local
616 /// variables to their values. If an optional environment argument is 604 /// variables to their values. If an optional environment argument is
617 /// supplied, it is used as the builder's initial environment. Otherwise 605 /// supplied, it is used as the builder's initial environment. Otherwise
618 /// the environment is initially a copy of the parent builder's environment. 606 /// the environment is initially a copy of the parent builder's environment.
619 IrBuilder makeDelimitedBuilder([Environment env = null]) { 607 IrBuilder makeDelimitedBuilder([Environment env = null]) {
620 return new IrBuilder._internal( 608 return new IrBuilder._internal(
621 state, 609 state,
622 env != null ? env : new Environment.from(environment), 610 env != null ? env : new Environment.from(environment),
623 mutableVariables); 611 mutableVariables);
624 } 612 }
625 613
626 /// True if [local] should currently be accessed from a [ir.MutableVariable]. 614 /// True if [local] should currently be accessed from a [ir.MutableVariable].
627 bool isInMutableVariable(Local local) { 615 bool isInMutableVariable(Local local) {
628 return mutableVariables.containsKey(local); 616 return mutableVariables.containsKey(local);
629 } 617 }
630 618
631 /// Creates a [ir.MutableVariable] for the given local. 619 /// Creates a [ir.MutableVariable] for the given local.
632 void makeMutableVariable(Local local) { 620 void makeMutableVariable(Local local) {
633 mutableVariables[local] = 621 mutableVariables[local] = new ir.MutableVariable(local);
634 new ir.MutableVariable(local);
635 } 622 }
636 623
637 /// Remove an [ir.MutableVariable] for a local. 624 /// Remove an [ir.MutableVariable] for a local.
638 /// 625 ///
639 /// Subsequent access to the local will be direct rather than through the 626 /// Subsequent access to the local will be direct rather than through the
640 /// mutable variable. 627 /// mutable variable.
641 void removeMutableVariable(Local local) { 628 void removeMutableVariable(Local local) {
642 mutableVariables.remove(local); 629 mutableVariables.remove(local);
643 } 630 }
644 631
645 /// Gets the [MutableVariable] containing the value of [local]. 632 /// Gets the [MutableVariable] containing the value of [local].
646 ir.MutableVariable getMutableVariable(Local local) { 633 ir.MutableVariable getMutableVariable(Local local) {
647 return mutableVariables[local]; 634 return mutableVariables[local];
648 } 635 }
649 636
650 bool get isOpen => root == null || _current != null; 637 bool get isOpen => root == null || _current != null;
651 638
652 List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters, 639 List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters,
653 {ClosureScope closureScope, 640 {ClosureScope closureScope, ClosureEnvironment env}) {
654 ClosureEnvironment env}) {
655 _createThisParameter(); 641 _createThisParameter();
656 _enterClosureEnvironment(env); 642 _enterClosureEnvironment(env);
657 _enterScope(closureScope); 643 _enterScope(closureScope);
658 parameters.forEach(_createFunctionParameter); 644 parameters.forEach(_createFunctionParameter);
659 return _parameters; 645 return _parameters;
660 } 646 }
661 647
662 /// Creates a parameter for [local] and adds it to the current environment. 648 /// Creates a parameter for [local] and adds it to the current environment.
663 ir.Parameter _createLocalParameter(Local local) { 649 ir.Parameter _createLocalParameter(Local local) {
664 ir.Parameter parameter = new ir.Parameter(local); 650 ir.Parameter parameter = new ir.Parameter(local);
(...skipping 15 matching lines...) Expand all
680 _current = _current.plug(expr); 666 _current = _current.plug(expr);
681 } 667 }
682 } 668 }
683 669
684 /// Create and add a new [LetPrim] for [primitive]. 670 /// Create and add a new [LetPrim] for [primitive].
685 ir.Primitive addPrimitive(ir.Primitive primitive) { 671 ir.Primitive addPrimitive(ir.Primitive primitive) {
686 add(new ir.LetPrim(primitive)); 672 add(new ir.LetPrim(primitive));
687 return primitive; 673 return primitive;
688 } 674 }
689 675
690 ir.Primitive buildInvokeStatic(Element element, 676 ir.Primitive buildInvokeStatic(Element element, Selector selector,
691 Selector selector, 677 List<ir.Primitive> arguments, SourceInformation sourceInformation) {
692 List<ir.Primitive> arguments,
693 SourceInformation sourceInformation) {
694 assert(!element.isLocal); 678 assert(!element.isLocal);
695 assert(!element.isInstanceMember); 679 assert(!element.isInstanceMember);
696 assert(isOpen); 680 assert(isOpen);
697 if (program.isJsInterop(element)) { 681 if (program.isJsInterop(element)) {
698 return buildInvokeJsInteropMember(element, arguments, sourceInformation); 682 return buildInvokeJsInteropMember(element, arguments, sourceInformation);
699 } 683 }
700 return addPrimitive( 684 return addPrimitive(
701 new ir.InvokeStatic(element, selector, arguments, sourceInformation)); 685 new ir.InvokeStatic(element, selector, arguments, sourceInformation));
702 } 686 }
703 687
704 ir.Primitive _buildInvokeSuper(Element target, 688 ir.Primitive _buildInvokeSuper(Element target, Selector selector,
705 Selector selector, 689 List<ir.Primitive> arguments, SourceInformation sourceInformation) {
706 List<ir.Primitive> arguments,
707 SourceInformation sourceInformation) {
708 assert(target.isInstanceMember); 690 assert(target.isInstanceMember);
709 assert(isOpen); 691 assert(isOpen);
710 return addPrimitive(new ir.InvokeMethodDirectly( 692 return addPrimitive(new ir.InvokeMethodDirectly(
711 buildThis(), target, selector, arguments, sourceInformation)); 693 buildThis(), target, selector, arguments, sourceInformation));
712 } 694 }
713 695
714 ir.Primitive _buildInvokeDynamic(ir.Primitive receiver, 696 ir.Primitive _buildInvokeDynamic(
715 Selector selector, 697 ir.Primitive receiver,
716 TypeMask mask, 698 Selector selector,
717 List<ir.Primitive> arguments, 699 TypeMask mask,
718 SourceInformation sourceInformation) { 700 List<ir.Primitive> arguments,
701 SourceInformation sourceInformation) {
719 assert(isOpen); 702 assert(isOpen);
720 return addPrimitive(new ir.InvokeMethod( 703 return addPrimitive(new ir.InvokeMethod(receiver, selector, mask, arguments,
721 receiver, selector, mask, arguments,
722 sourceInformation: sourceInformation)); 704 sourceInformation: sourceInformation));
723 } 705 }
724 706
725 ir.Primitive _buildInvokeCall(ir.Primitive target, 707 ir.Primitive _buildInvokeCall(
726 CallStructure callStructure, 708 ir.Primitive target,
727 TypeMask mask, 709 CallStructure callStructure,
728 List<ir.Definition> arguments, 710 TypeMask mask,
729 SourceInformation sourceInformation) { 711 List<ir.Definition> arguments,
712 SourceInformation sourceInformation) {
730 Selector selector = callStructure.callSelector; 713 Selector selector = callStructure.callSelector;
731 return _buildInvokeDynamic( 714 return _buildInvokeDynamic(
732 target, selector, mask, arguments, sourceInformation); 715 target, selector, mask, arguments, sourceInformation);
733 } 716 }
734 717
735 ir.Primitive buildStaticNoSuchMethod( 718 ir.Primitive buildStaticNoSuchMethod(Selector selector,
736 Selector selector, 719 List<ir.Primitive> arguments, SourceInformation sourceInformation) {
737 List<ir.Primitive> arguments,
738 SourceInformation sourceInformation) {
739 ir.Primitive receiver = buildStringConstant(''); 720 ir.Primitive receiver = buildStringConstant('');
740 ir.Primitive name = buildStringConstant(selector.name); 721 ir.Primitive name = buildStringConstant(selector.name);
741 ir.Primitive argumentList = buildListLiteral(null, arguments); 722 ir.Primitive argumentList = buildListLiteral(null, arguments);
742 ir.Primitive expectedArgumentNames = buildNullConstant(); 723 ir.Primitive expectedArgumentNames = buildNullConstant();
743 return buildStaticFunctionInvocation( 724 return buildStaticFunctionInvocation(
744 program.throwNoSuchMethod, 725 program.throwNoSuchMethod,
745 <ir.Primitive>[receiver, name, argumentList, expectedArgumentNames], 726 <ir.Primitive>[receiver, name, argumentList, expectedArgumentNames],
746 sourceInformation); 727 sourceInformation);
747 } 728 }
748 729
749 /// Create a [ir.Constant] from [value] and add it to the CPS term. 730 /// Create a [ir.Constant] from [value] and add it to the CPS term.
750 ir.Constant buildConstant(ConstantValue value, 731 ir.Constant buildConstant(ConstantValue value,
751 {SourceInformation sourceInformation}) { 732 {SourceInformation sourceInformation}) {
752 assert(isOpen); 733 assert(isOpen);
753 return addPrimitive( 734 return addPrimitive(
754 new ir.Constant(value, sourceInformation: sourceInformation)); 735 new ir.Constant(value, sourceInformation: sourceInformation));
755 } 736 }
756 737
757 /// Create an integer constant and add it to the CPS term. 738 /// Create an integer constant and add it to the CPS term.
758 ir.Constant buildIntegerConstant(int value) { 739 ir.Constant buildIntegerConstant(int value) {
759 return buildConstant(state.constantSystem.createInt(value)); 740 return buildConstant(state.constantSystem.createInt(value));
760 } 741 }
761 742
(...skipping 18 matching lines...) Expand all
780 state.constantSystem.createString(new ast.DartString.literal(value))); 761 state.constantSystem.createString(new ast.DartString.literal(value)));
781 } 762 }
782 763
783 /// Create a string constant and add it to the CPS term. 764 /// Create a string constant and add it to the CPS term.
784 ir.Constant buildDartStringConstant(ast.DartString value) { 765 ir.Constant buildDartStringConstant(ast.DartString value) {
785 return buildConstant(state.constantSystem.createString(value)); 766 return buildConstant(state.constantSystem.createString(value));
786 } 767 }
787 768
788 /// Creates a non-constant list literal of the provided [type] and with the 769 /// Creates a non-constant list literal of the provided [type] and with the
789 /// provided [values]. 770 /// provided [values].
790 ir.Primitive buildListLiteral(InterfaceType type, 771 ir.Primitive buildListLiteral(
791 Iterable<ir.Primitive> values, 772 InterfaceType type, Iterable<ir.Primitive> values,
792 {TypeMask allocationSiteType}) { 773 {TypeMask allocationSiteType}) {
793 assert(isOpen); 774 assert(isOpen);
794 return addPrimitive(new ir.LiteralList(type, values.toList(), 775 return addPrimitive(new ir.LiteralList(type, values.toList(),
795 allocationSiteType: allocationSiteType)); 776 allocationSiteType: allocationSiteType));
796 } 777 }
797 778
798 /// Creates a conditional expression with the provided [condition] where the 779 /// Creates a conditional expression with the provided [condition] where the
799 /// then and else expression are created through the [buildThenExpression] 780 /// then and else expression are created through the [buildThenExpression]
800 /// and [buildElseExpression] functions, respectively. 781 /// and [buildElseExpression] functions, respectively.
801 ir.Primitive buildConditional( 782 ir.Primitive buildConditional(
802 ir.Primitive condition, 783 ir.Primitive condition,
(...skipping 22 matching lines...) Expand all
825 // Build the term 806 // Build the term
826 // let cont join(x, ..., result) = [] in 807 // let cont join(x, ..., result) = [] in
827 // let cont then() = [[thenPart]]; join(v, ...) 808 // let cont then() = [[thenPart]]; join(v, ...)
828 // and else() = [[elsePart]]; join(v, ...) 809 // and else() = [[elsePart]]; join(v, ...)
829 // in 810 // in
830 // if condition (then, else) 811 // if condition (then, else)
831 ir.Continuation thenContinuation = new ir.Continuation([]); 812 ir.Continuation thenContinuation = new ir.Continuation([]);
832 ir.Continuation elseContinuation = new ir.Continuation([]); 813 ir.Continuation elseContinuation = new ir.Continuation([]);
833 thenContinuation.body = thenBuilder.root; 814 thenContinuation.body = thenBuilder.root;
834 elseContinuation.body = elseBuilder.root; 815 elseContinuation.body = elseBuilder.root;
835 add(new ir.LetCont(join.continuation, 816 add(new ir.LetCont(
836 new ir.LetCont.two(thenContinuation, elseContinuation, 817 join.continuation,
837 new ir.Branch.strict(condition, 818 new ir.LetCont.two(
838 thenContinuation, 819 thenContinuation,
839 elseContinuation, 820 elseContinuation,
840 sourceInformation)))); 821 new ir.Branch.strict(condition, thenContinuation, elseContinuation,
822 sourceInformation))));
841 environment = join.environment; 823 environment = join.environment;
842 return environment.discard(1); 824 return environment.discard(1);
843 } 825 }
844 826
845 /** 827 /**
846 * Add an explicit `return null` for functions that don't have a return 828 * Add an explicit `return null` for functions that don't have a return
847 * statement on each branch. This includes functions with an empty body, 829 * statement on each branch. This includes functions with an empty body,
848 * such as `foo(){ }`. 830 * such as `foo(){ }`.
849 */ 831 */
850 void _ensureReturn() { 832 void _ensureReturn() {
851 if (!isOpen) return; 833 if (!isOpen) return;
852 ir.Constant constant = buildNullConstant(); 834 ir.Constant constant = buildNullConstant();
853 add(new ir.InvokeContinuation(state.returnContinuation, [constant])); 835 add(new ir.InvokeContinuation(state.returnContinuation, [constant]));
854 _current = null; 836 _current = null;
855 } 837 }
856 838
857 /// Create a [ir.FunctionDefinition] using [root] as the body. 839 /// Create a [ir.FunctionDefinition] using [root] as the body.
858 /// 840 ///
859 /// The protocol for building a function is: 841 /// The protocol for building a function is:
860 /// 1. Call [buildFunctionHeader]. 842 /// 1. Call [buildFunctionHeader].
861 /// 2. Call `buildXXX` methods to build the body. 843 /// 2. Call `buildXXX` methods to build the body.
862 /// 3. Call [makeFunctionDefinition] to finish. 844 /// 3. Call [makeFunctionDefinition] to finish.
863 ir.FunctionDefinition makeFunctionDefinition( 845 ir.FunctionDefinition makeFunctionDefinition(
864 SourceInformation sourceInformation) { 846 SourceInformation sourceInformation) {
865 _ensureReturn(); 847 _ensureReturn();
866 return new ir.FunctionDefinition( 848 return new ir.FunctionDefinition(state.currentElement, state.thisParameter,
867 state.currentElement, 849 state.functionParameters, state.returnContinuation, root,
868 state.thisParameter,
869 state.functionParameters,
870 state.returnContinuation,
871 root,
872 sourceInformation: sourceInformation); 850 sourceInformation: sourceInformation);
873 } 851 }
874 852
875 /// Create a invocation of the [method] on the super class where the call 853 /// Create a invocation of the [method] on the super class where the call
876 /// structure is defined [callStructure] and the argument values are defined 854 /// structure is defined [callStructure] and the argument values are defined
877 /// by [arguments]. 855 /// by [arguments].
878 ir.Primitive buildSuperMethodInvocation( 856 ir.Primitive buildSuperMethodInvocation(
879 MethodElement method, 857 MethodElement method,
880 CallStructure callStructure, 858 CallStructure callStructure,
881 List<ir.Primitive> arguments, 859 List<ir.Primitive> arguments,
882 SourceInformation sourceInformation) { 860 SourceInformation sourceInformation) {
883 // TODO(johnniwinther): This shouldn't be necessary. 861 // TODO(johnniwinther): This shouldn't be necessary.
884 SelectorKind kind = Elements.isOperatorName(method.name) 862 SelectorKind kind = Elements.isOperatorName(method.name)
885 ? SelectorKind.OPERATOR : SelectorKind.CALL; 863 ? SelectorKind.OPERATOR
886 Selector selector = 864 : SelectorKind.CALL;
887 new Selector(kind, method.memberName, callStructure); 865 Selector selector = new Selector(kind, method.memberName, callStructure);
888 return _buildInvokeSuper(method, selector, arguments, sourceInformation); 866 return _buildInvokeSuper(method, selector, arguments, sourceInformation);
889 } 867 }
890 868
891 /// Create a read access of the [method] on the super class, i.e. a 869 /// Create a read access of the [method] on the super class, i.e. a
892 /// closurization of [method]. 870 /// closurization of [method].
893 ir.Primitive buildSuperMethodGet(MethodElement method, 871 ir.Primitive buildSuperMethodGet(
894 SourceInformation sourceInformation) { 872 MethodElement method, SourceInformation sourceInformation) {
895 // TODO(johnniwinther): This should have its own ir node. 873 // TODO(johnniwinther): This should have its own ir node.
896 return _buildInvokeSuper( 874 return _buildInvokeSuper(method, new Selector.getter(method.memberName),
897 method, 875 const <ir.Primitive>[], sourceInformation);
898 new Selector.getter(method.memberName),
899 const <ir.Primitive>[],
900 sourceInformation);
901 } 876 }
902 877
903 /// Create a getter invocation of the [getter] on the super class. 878 /// Create a getter invocation of the [getter] on the super class.
904 ir.Primitive buildSuperGetterGet(MethodElement getter, 879 ir.Primitive buildSuperGetterGet(
905 SourceInformation sourceInformation) { 880 MethodElement getter, SourceInformation sourceInformation) {
906 // TODO(johnniwinther): This should have its own ir node. 881 // TODO(johnniwinther): This should have its own ir node.
907 return _buildInvokeSuper( 882 return _buildInvokeSuper(getter, new Selector.getter(getter.memberName),
908 getter, 883 const <ir.Primitive>[], sourceInformation);
909 new Selector.getter(getter.memberName),
910 const <ir.Primitive>[],
911 sourceInformation);
912 } 884 }
913 885
914 /// Create an setter invocation of the [setter] on the super class with 886 /// Create an setter invocation of the [setter] on the super class with
915 /// [value]. 887 /// [value].
916 ir.Primitive buildSuperSetterSet(MethodElement setter, 888 ir.Primitive buildSuperSetterSet(MethodElement setter, ir.Primitive value,
917 ir.Primitive value, 889 SourceInformation sourceInformation) {
918 SourceInformation sourceInformation) {
919 // TODO(johnniwinther): This should have its own ir node. 890 // TODO(johnniwinther): This should have its own ir node.
920 _buildInvokeSuper( 891 _buildInvokeSuper(setter, new Selector.setter(setter.memberName),
921 setter, 892 <ir.Primitive>[value], sourceInformation);
922 new Selector.setter(setter.memberName),
923 <ir.Primitive>[value],
924 sourceInformation);
925 return value; 893 return value;
926 } 894 }
927 895
928 /// Create an invocation of the index [method] on the super class with 896 /// Create an invocation of the index [method] on the super class with
929 /// the provided [index]. 897 /// the provided [index].
930 ir.Primitive buildSuperIndex(MethodElement method, 898 ir.Primitive buildSuperIndex(MethodElement method, ir.Primitive index,
931 ir.Primitive index, 899 SourceInformation sourceInformation) {
932 SourceInformation sourceInformation) {
933 return _buildInvokeSuper( 900 return _buildInvokeSuper(
934 method, new Selector.index(), <ir.Primitive>[index], 901 method, new Selector.index(), <ir.Primitive>[index], sourceInformation);
935 sourceInformation);
936 } 902 }
937 903
938 /// Create an invocation of the index set [method] on the super class with 904 /// Create an invocation of the index set [method] on the super class with
939 /// the provided [index] and [value]. 905 /// the provided [index] and [value].
940 ir.Primitive buildSuperIndexSet(MethodElement method, 906 ir.Primitive buildSuperIndexSet(MethodElement method, ir.Primitive index,
941 ir.Primitive index, 907 ir.Primitive value, SourceInformation sourceInformation) {
942 ir.Primitive value,
943 SourceInformation sourceInformation) {
944 _buildInvokeSuper(method, new Selector.indexSet(), 908 _buildInvokeSuper(method, new Selector.indexSet(),
945 <ir.Primitive>[index, value], sourceInformation); 909 <ir.Primitive>[index, value], sourceInformation);
946 return value; 910 return value;
947 } 911 }
948 912
949 /// Create a dynamic invocation on [receiver] where the method name and 913 /// Create a dynamic invocation on [receiver] where the method name and
950 /// argument structure are defined by [selector] and the argument values are 914 /// argument structure are defined by [selector] and the argument values are
951 /// defined by [arguments]. 915 /// defined by [arguments].
952 ir.Primitive buildDynamicInvocation(ir.Primitive receiver, 916 ir.Primitive buildDynamicInvocation(
953 Selector selector, 917 ir.Primitive receiver,
954 TypeMask mask, 918 Selector selector,
955 List<ir.Primitive> arguments, 919 TypeMask mask,
956 SourceInformation sourceInformation) { 920 List<ir.Primitive> arguments,
921 SourceInformation sourceInformation) {
957 return _buildInvokeDynamic( 922 return _buildInvokeDynamic(
958 receiver, selector, mask, arguments, sourceInformation); 923 receiver, selector, mask, arguments, sourceInformation);
959 } 924 }
960 925
961 /// Create a dynamic getter invocation on [receiver] where the getter name is 926 /// Create a dynamic getter invocation on [receiver] where the getter name is
962 /// defined by [selector]. 927 /// defined by [selector].
963 ir.Primitive buildDynamicGet(ir.Primitive receiver, 928 ir.Primitive buildDynamicGet(ir.Primitive receiver, Selector selector,
964 Selector selector, 929 TypeMask mask, SourceInformation sourceInformation) {
965 TypeMask mask,
966 SourceInformation sourceInformation) {
967 assert(selector.isGetter); 930 assert(selector.isGetter);
968 FieldElement field = program.locateSingleField(selector, mask); 931 FieldElement field = program.locateSingleField(selector, mask);
969 if (field != null) { 932 if (field != null) {
970 // If the world says this resolves to a unique field, then it MUST be 933 // If the world says this resolves to a unique field, then it MUST be
971 // treated as a field access, since the getter might not be emitted. 934 // treated as a field access, since the getter might not be emitted.
972 return buildFieldGet(receiver, field, sourceInformation); 935 return buildFieldGet(receiver, field, sourceInformation);
973 } else { 936 } else {
974 return _buildInvokeDynamic( 937 return _buildInvokeDynamic(
975 receiver, selector, mask, const <ir.Primitive>[], sourceInformation); 938 receiver, selector, mask, const <ir.Primitive>[], sourceInformation);
976 } 939 }
977 } 940 }
978 941
979 /// Create a dynamic setter invocation on [receiver] where the setter name and 942 /// Create a dynamic setter invocation on [receiver] where the setter name and
980 /// argument are defined by [selector] and [value], respectively. 943 /// argument are defined by [selector] and [value], respectively.
981 ir.Primitive buildDynamicSet(ir.Primitive receiver, 944 ir.Primitive buildDynamicSet(ir.Primitive receiver, Selector selector,
982 Selector selector, 945 TypeMask mask, ir.Primitive value, SourceInformation sourceInformation) {
983 TypeMask mask,
984 ir.Primitive value,
985 SourceInformation sourceInformation) {
986 assert(selector.isSetter); 946 assert(selector.isSetter);
987 FieldElement field = program.locateSingleField(selector, mask); 947 FieldElement field = program.locateSingleField(selector, mask);
988 if (field != null) { 948 if (field != null) {
989 // If the world says this resolves to a unique field, then it MUST be 949 // If the world says this resolves to a unique field, then it MUST be
990 // treated as a field access, since the setter might not be emitted. 950 // treated as a field access, since the setter might not be emitted.
991 buildFieldSet(receiver, field, value, sourceInformation); 951 buildFieldSet(receiver, field, value, sourceInformation);
992 } else { 952 } else {
993 _buildInvokeDynamic(receiver, selector, mask, <ir.Primitive>[value], 953 _buildInvokeDynamic(
994 sourceInformation); 954 receiver, selector, mask, <ir.Primitive>[value], sourceInformation);
995 } 955 }
996 return value; 956 return value;
997 } 957 }
998 958
999 /// Create a dynamic index set invocation on [receiver] with the provided 959 /// Create a dynamic index set invocation on [receiver] with the provided
1000 /// [index] and [value]. 960 /// [index] and [value].
1001 ir.Primitive buildDynamicIndexSet(ir.Primitive receiver, 961 ir.Primitive buildDynamicIndexSet(
1002 TypeMask mask, 962 ir.Primitive receiver,
1003 ir.Primitive index, 963 TypeMask mask,
1004 ir.Primitive value, 964 ir.Primitive index,
1005 SourceInformation sourceInformation) { 965 ir.Primitive value,
1006 _buildInvokeDynamic( 966 SourceInformation sourceInformation) {
1007 receiver, new Selector.indexSet(), mask, <ir.Primitive>[index, value], 967 _buildInvokeDynamic(receiver, new Selector.indexSet(), mask,
1008 sourceInformation); 968 <ir.Primitive>[index, value], sourceInformation);
1009 return value; 969 return value;
1010 } 970 }
1011 971
1012 /// Create an invocation of the local [function] where argument structure is 972 /// Create an invocation of the local [function] where argument structure is
1013 /// defined by [callStructure] and the argument values are defined by 973 /// defined by [callStructure] and the argument values are defined by
1014 /// [arguments]. 974 /// [arguments].
1015 ir.Primitive buildLocalFunctionInvocation( 975 ir.Primitive buildLocalFunctionInvocation(
1016 LocalFunctionElement function, 976 LocalFunctionElement function,
1017 CallStructure callStructure, 977 CallStructure callStructure,
1018 List<ir.Primitive> arguments, 978 List<ir.Primitive> arguments,
1019 SourceInformation sourceInformation) { 979 SourceInformation sourceInformation) {
1020 // TODO(johnniwinther): Maybe this should have its own ir node. 980 // TODO(johnniwinther): Maybe this should have its own ir node.
1021 return buildCallInvocation( 981 return buildCallInvocation(
1022 buildLocalGet(function), callStructure, arguments, 982 buildLocalGet(function), callStructure, arguments, sourceInformation);
1023 sourceInformation);
1024 } 983 }
1025 984
1026 /// Create a static invocation of [function]. 985 /// Create a static invocation of [function].
1027 /// 986 ///
1028 /// The arguments are not named and their values are defined by [arguments]. 987 /// The arguments are not named and their values are defined by [arguments].
1029 ir.Primitive buildStaticFunctionInvocation( 988 ir.Primitive buildStaticFunctionInvocation(MethodElement function,
1030 MethodElement function, 989 List<ir.Primitive> arguments, SourceInformation sourceInformation) {
1031 List<ir.Primitive> arguments,
1032 SourceInformation sourceInformation) {
1033 Selector selector = new Selector.call( 990 Selector selector = new Selector.call(
1034 function.memberName, new CallStructure(arguments.length)); 991 function.memberName, new CallStructure(arguments.length));
1035 return buildInvokeStatic(function, selector, arguments, sourceInformation); 992 return buildInvokeStatic(function, selector, arguments, sourceInformation);
1036 } 993 }
1037 994
1038 /// Create a getter invocation of the static [getter]. 995 /// Create a getter invocation of the static [getter].
1039 ir.Primitive buildStaticGetterGet(MethodElement getter, 996 ir.Primitive buildStaticGetterGet(
1040 SourceInformation sourceInformation) { 997 MethodElement getter, SourceInformation sourceInformation) {
1041 Selector selector = new Selector.getter(getter.memberName); 998 Selector selector = new Selector.getter(getter.memberName);
1042 return buildInvokeStatic( 999 return buildInvokeStatic(
1043 getter, selector, const <ir.Primitive>[], sourceInformation); 1000 getter, selector, const <ir.Primitive>[], sourceInformation);
1044 } 1001 }
1045 1002
1046 /// Create a write access to the static [field] with the [value]. 1003 /// Create a write access to the static [field] with the [value].
1047 ir.Primitive buildStaticFieldSet(FieldElement field, 1004 ir.Primitive buildStaticFieldSet(FieldElement field, ir.Primitive value,
1048 ir.Primitive value, 1005 SourceInformation sourceInformation) {
1049 SourceInformation sourceInformation) {
1050 addPrimitive(new ir.SetStatic(field, value, sourceInformation)); 1006 addPrimitive(new ir.SetStatic(field, value, sourceInformation));
1051 return value; 1007 return value;
1052 } 1008 }
1053 1009
1054 /// Create a setter invocation of the static [setter] with the [value]. 1010 /// Create a setter invocation of the static [setter] with the [value].
1055 ir.Primitive buildStaticSetterSet(MethodElement setter, 1011 ir.Primitive buildStaticSetterSet(MethodElement setter, ir.Primitive value,
1056 ir.Primitive value, 1012 SourceInformation sourceInformation) {
1057 SourceInformation sourceInformation) {
1058 Selector selector = new Selector.setter(setter.memberName); 1013 Selector selector = new Selector.setter(setter.memberName);
1059 buildInvokeStatic( 1014 buildInvokeStatic(
1060 setter, selector, <ir.Primitive>[value], sourceInformation); 1015 setter, selector, <ir.Primitive>[value], sourceInformation);
1061 return value; 1016 return value;
1062 } 1017 }
1063 1018
1064 /// Create an erroneous invocation where argument structure is defined by 1019 /// Create an erroneous invocation where argument structure is defined by
1065 /// [selector] and the argument values are defined by [arguments]. 1020 /// [selector] and the argument values are defined by [arguments].
1066 // TODO(johnniwinther): Make this more fine-grained. 1021 // TODO(johnniwinther): Make this more fine-grained.
1067 ir.Primitive buildErroneousInvocation( 1022 ir.Primitive buildErroneousInvocation(Element element, Selector selector,
1068 Element element, 1023 List<ir.Primitive> arguments, SourceInformation sourceInformation) {
1069 Selector selector,
1070 List<ir.Primitive> arguments,
1071 SourceInformation sourceInformation) {
1072 // TODO(johnniwinther): This should have its own ir node. 1024 // TODO(johnniwinther): This should have its own ir node.
1073 return buildInvokeStatic(element, selector, arguments, sourceInformation); 1025 return buildInvokeStatic(element, selector, arguments, sourceInformation);
1074 } 1026 }
1075 1027
1076 /// Concatenate string values. The arguments must be strings. 1028 /// Concatenate string values. The arguments must be strings.
1077 ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments, 1029 ir.Primitive buildStringConcatenation(
1078 SourceInformation sourceInformation) { 1030 List<ir.Primitive> arguments, SourceInformation sourceInformation) {
1079 assert(isOpen); 1031 assert(isOpen);
1080 return addPrimitive(new ir.ApplyBuiltinOperator( 1032 return addPrimitive(new ir.ApplyBuiltinOperator(
1081 ir.BuiltinOperator.StringConcatenate, 1033 ir.BuiltinOperator.StringConcatenate, arguments, sourceInformation));
1082 arguments,
1083 sourceInformation));
1084 } 1034 }
1085 1035
1086 /// Create an invocation of the `call` method of [functionExpression], where 1036 /// Create an invocation of the `call` method of [functionExpression], where
1087 /// the structure of arguments are given by [callStructure]. 1037 /// the structure of arguments are given by [callStructure].
1088 // TODO(johnniwinther): This should take a [TypeMask]. 1038 // TODO(johnniwinther): This should take a [TypeMask].
1089 ir.Primitive buildCallInvocation( 1039 ir.Primitive buildCallInvocation(
1090 ir.Primitive functionExpression, 1040 ir.Primitive functionExpression,
1091 CallStructure callStructure, 1041 CallStructure callStructure,
1092 List<ir.Definition> arguments, 1042 List<ir.Definition> arguments,
1093 SourceInformation sourceInformation) { 1043 SourceInformation sourceInformation) {
1094 return _buildInvokeCall( 1044 return _buildInvokeCall(
1095 functionExpression, callStructure, null, arguments, sourceInformation); 1045 functionExpression, callStructure, null, arguments, sourceInformation);
1096 } 1046 }
1097 1047
1098 /// Creates an if-then-else statement with the provided [condition] where the 1048 /// Creates an if-then-else statement with the provided [condition] where the
1099 /// then and else branches are created through the [buildThenPart] and 1049 /// then and else branches are created through the [buildThenPart] and
1100 /// [buildElsePart] functions, respectively. 1050 /// [buildElsePart] functions, respectively.
1101 /// 1051 ///
1102 /// An if-then statement is created if [buildElsePart] is a no-op. 1052 /// An if-then statement is created if [buildElsePart] is a no-op.
1103 // TODO(johnniwinther): Unify implementation with [buildConditional] and 1053 // TODO(johnniwinther): Unify implementation with [buildConditional] and
1104 // [_buildLogicalOperator]. 1054 // [_buildLogicalOperator].
1105 void buildIf(ir.Primitive condition, 1055 void buildIf(
1106 void buildThenPart(IrBuilder builder), 1056 ir.Primitive condition,
1107 void buildElsePart(IrBuilder builder), 1057 void buildThenPart(IrBuilder builder),
1108 SourceInformation sourceInformation) { 1058 void buildElsePart(IrBuilder builder),
1059 SourceInformation sourceInformation) {
1109 assert(isOpen); 1060 assert(isOpen);
1110 1061
1111 // The then and else parts are delimited. 1062 // The then and else parts are delimited.
1112 IrBuilder thenBuilder = makeDelimitedBuilder(); 1063 IrBuilder thenBuilder = makeDelimitedBuilder();
1113 IrBuilder elseBuilder = makeDelimitedBuilder(); 1064 IrBuilder elseBuilder = makeDelimitedBuilder();
1114 buildThenPart(thenBuilder); 1065 buildThenPart(thenBuilder);
1115 buildElsePart(elseBuilder); 1066 buildElsePart(elseBuilder);
1116 1067
1117 // Build the term 1068 // Build the term
1118 // (Result =) let cont then() = [[thenPart]] 1069 // (Result =) let cont then() = [[thenPart]]
1119 // and else() = [[elsePart]] 1070 // and else() = [[elsePart]]
1120 // in 1071 // in
1121 // if condition (then, else) 1072 // if condition (then, else)
1122 ir.Continuation thenContinuation = new ir.Continuation([]); 1073 ir.Continuation thenContinuation = new ir.Continuation([]);
1123 ir.Continuation elseContinuation = new ir.Continuation([]); 1074 ir.Continuation elseContinuation = new ir.Continuation([]);
1124 // If exactly one of the then and else continuation bodies is open (i.e., 1075 // If exactly one of the then and else continuation bodies is open (i.e.,
1125 // the other one has an exit on all paths), then Continuation.plug expects 1076 // the other one has an exit on all paths), then Continuation.plug expects
1126 // that continuation to be listed first. Arbitrarily use [then, else] 1077 // that continuation to be listed first. Arbitrarily use [then, else]
1127 // order otherwise. 1078 // order otherwise.
1128 List<ir.Continuation> arms = !thenBuilder.isOpen && elseBuilder.isOpen 1079 List<ir.Continuation> arms = !thenBuilder.isOpen && elseBuilder.isOpen
1129 ? <ir.Continuation>[elseContinuation, thenContinuation] 1080 ? <ir.Continuation>[elseContinuation, thenContinuation]
1130 : <ir.Continuation>[thenContinuation, elseContinuation]; 1081 : <ir.Continuation>[thenContinuation, elseContinuation];
1131 1082
1132 ir.Expression result = 1083 ir.Expression result = new ir.LetCont.many(
1133 new ir.LetCont.many(arms, 1084 arms,
1134 new ir.Branch.strict(condition, 1085 new ir.Branch.strict(
1135 thenContinuation, 1086 condition, thenContinuation, elseContinuation, sourceInformation));
1136 elseContinuation,
1137 sourceInformation));
1138 1087
1139 JumpCollector join; // Null if there is no join. 1088 JumpCollector join; // Null if there is no join.
1140 if (thenBuilder.isOpen && elseBuilder.isOpen) { 1089 if (thenBuilder.isOpen && elseBuilder.isOpen) {
1141 // There is a join-point continuation. Build the term 1090 // There is a join-point continuation. Build the term
1142 // 'let cont join(x, ...) = [] in Result' and plug invocations of the 1091 // 'let cont join(x, ...) = [] in Result' and plug invocations of the
1143 // join-point continuation into the then and else continuations. 1092 // join-point continuation into the then and else continuations.
1144 join = new ForwardJumpCollector(environment); 1093 join = new ForwardJumpCollector(environment);
1145 thenBuilder.jumpTo(join); 1094 thenBuilder.jumpTo(join);
1146 elseBuilder.jumpTo(join); 1095 elseBuilder.jumpTo(join);
1147 result = new ir.LetCont(join.continuation, result); 1096 result = new ir.LetCont(join.continuation, result);
1148 } 1097 }
1149 1098
(...skipping 24 matching lines...) Expand all
1174 } 1123 }
1175 } 1124 }
1176 1125
1177 void jumpTo(JumpCollector collector, 1126 void jumpTo(JumpCollector collector,
1178 [ir.Primitive value, SourceInformation sourceInformation]) { 1127 [ir.Primitive value, SourceInformation sourceInformation]) {
1179 collector.addJump(this, value, sourceInformation); 1128 collector.addJump(this, value, sourceInformation);
1180 } 1129 }
1181 1130
1182 void addRecursiveContinuation(BackwardJumpCollector collector) { 1131 void addRecursiveContinuation(BackwardJumpCollector collector) {
1183 assert(environment.length == collector.environment.length); 1132 assert(environment.length == collector.environment.length);
1184 add(new ir.LetCont(collector.continuation, 1133 add(new ir.LetCont(
1185 new ir.InvokeContinuation(collector.continuation, 1134 collector.continuation,
1186 environment.index2value))); 1135 new ir.InvokeContinuation(
1136 collector.continuation, environment.index2value)));
1187 environment = collector.environment; 1137 environment = collector.environment;
1188 } 1138 }
1189 1139
1190 /// Creates a for loop in which the initializer, condition, body, update are 1140 /// Creates a for loop in which the initializer, condition, body, update are
1191 /// created by [buildInitializer], [buildCondition], [buildBody] and 1141 /// created by [buildInitializer], [buildCondition], [buildBody] and
1192 /// [buildUpdate], respectively. 1142 /// [buildUpdate], respectively.
1193 /// 1143 ///
1194 /// The jump [target] is used to identify which `break` and `continue` 1144 /// The jump [target] is used to identify which `break` and `continue`
1195 /// statements that have this `for` statement as their target. 1145 /// statements that have this `for` statement as their target.
1196 /// 1146 ///
1197 /// The [closureScope] identifies variables that should be boxed in this loop. 1147 /// The [closureScope] identifies variables that should be boxed in this loop.
1198 /// This includes variables declared inside the body of the loop as well as 1148 /// This includes variables declared inside the body of the loop as well as
1199 /// in the for-loop initializer. 1149 /// in the for-loop initializer.
1200 /// 1150 ///
1201 /// [loopVariables] is the list of variables declared in the for-loop 1151 /// [loopVariables] is the list of variables declared in the for-loop
1202 /// initializer. 1152 /// initializer.
1203 void buildFor({SubbuildFunction buildInitializer, 1153 void buildFor(
1204 SubbuildFunction buildCondition, 1154 {SubbuildFunction buildInitializer,
1205 SourceInformation conditionSourceInformation, 1155 SubbuildFunction buildCondition,
1206 SubbuildFunction buildBody, 1156 SourceInformation conditionSourceInformation,
1207 SubbuildFunction buildUpdate, 1157 SubbuildFunction buildBody,
1208 JumpTarget target, 1158 SubbuildFunction buildUpdate,
1209 ClosureScope closureScope, 1159 JumpTarget target,
1210 List<LocalElement> loopVariables}) { 1160 ClosureScope closureScope,
1161 List<LocalElement> loopVariables}) {
1211 assert(isOpen); 1162 assert(isOpen);
1212 1163
1213 // For loops use four named continuations: the entry to the condition, 1164 // For loops use four named continuations: the entry to the condition,
1214 // the entry to the body, the loop exit, and the loop successor (break). 1165 // the entry to the body, the loop exit, and the loop successor (break).
1215 // The CPS translation of 1166 // The CPS translation of
1216 // [[for (initializer; condition; update) body; successor]] is: 1167 // [[for (initializer; condition; update) body; successor]] is:
1217 // 1168 //
1218 // _enterForLoopInitializer(); 1169 // _enterForLoopInitializer();
1219 // [[initializer]]; 1170 // [[initializer]];
1220 // let cont loop(x, ...) = 1171 // let cont loop(x, ...) =
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1283 updateBuilder = makeDelimitedBuilder(continueCollector.environment); 1234 updateBuilder = makeDelimitedBuilder(continueCollector.environment);
1284 } else { 1235 } else {
1285 updateBuilder = innerBodyBuilder; 1236 updateBuilder = innerBodyBuilder;
1286 } 1237 }
1287 updateBuilder._enterForLoopUpdate(closureScope, loopVariables); 1238 updateBuilder._enterForLoopUpdate(closureScope, loopVariables);
1288 buildUpdate(updateBuilder); 1239 buildUpdate(updateBuilder);
1289 if (updateBuilder.isOpen) updateBuilder.jumpTo(loop); 1240 if (updateBuilder.isOpen) updateBuilder.jumpTo(loop);
1290 // Connect the inner and outer body builders. This is done only after 1241 // Connect the inner and outer body builders. This is done only after
1291 // it is guaranteed that the updateBuilder has a non-empty term. 1242 // it is guaranteed that the updateBuilder has a non-empty term.
1292 if (hasContinues) { 1243 if (hasContinues) {
1293 outerBodyBuilder.add(new ir.LetCont(continueCollector.continuation, 1244 outerBodyBuilder.add(new ir.LetCont(
1294 innerBodyBuilder.root)); 1245 continueCollector.continuation, innerBodyBuilder.root));
1295 continueCollector.continuation.body = updateBuilder.root; 1246 continueCollector.continuation.body = updateBuilder.root;
1296 } else { 1247 } else {
1297 outerBodyBuilder.add(innerBodyBuilder.root); 1248 outerBodyBuilder.add(innerBodyBuilder.root);
1298 } 1249 }
1299 1250
1300 // Create loop exit and body entry continuations and a branch to them. 1251 // Create loop exit and body entry continuations and a branch to them.
1301 ir.Continuation exitContinuation = new ir.Continuation([]); 1252 ir.Continuation exitContinuation = new ir.Continuation([]);
1302 ir.Continuation bodyContinuation = new ir.Continuation([]); 1253 ir.Continuation bodyContinuation = new ir.Continuation([]);
1303 bodyContinuation.body = outerBodyBuilder.root; 1254 bodyContinuation.body = outerBodyBuilder.root;
1304 // Note the order of continuations: the first one is the one that will 1255 // Note the order of continuations: the first one is the one that will
1305 // be filled by LetCont.plug. 1256 // be filled by LetCont.plug.
1306 ir.LetCont branch = 1257 ir.LetCont branch = new ir.LetCont.two(
1307 new ir.LetCont.two(exitContinuation, bodyContinuation, 1258 exitContinuation,
1308 new ir.Branch.strict(condition, 1259 bodyContinuation,
1309 bodyContinuation, 1260 new ir.Branch.strict(condition, bodyContinuation, exitContinuation,
1310 exitContinuation, 1261 conditionSourceInformation));
1311 conditionSourceInformation));
1312 // If there are breaks in the body, then there must be a join-point 1262 // If there are breaks in the body, then there must be a join-point
1313 // continuation for the normal exit and the breaks. Otherwise, the 1263 // continuation for the normal exit and the breaks. Otherwise, the
1314 // successor is translated in the hole in the exit continuation. 1264 // successor is translated in the hole in the exit continuation.
1315 bool hasBreaks = !breakCollector.isEmpty; 1265 bool hasBreaks = !breakCollector.isEmpty;
1316 ir.LetCont letBreak; 1266 ir.LetCont letBreak;
1317 if (hasBreaks) { 1267 if (hasBreaks) {
1318 IrBuilder exitBuilder = makeDelimitedBuilder(); 1268 IrBuilder exitBuilder = makeDelimitedBuilder();
1319 exitBuilder.jumpTo(breakCollector); 1269 exitBuilder.jumpTo(breakCollector);
1320 exitContinuation.body = exitBuilder.root; 1270 exitContinuation.body = exitBuilder.root;
1321 letBreak = new ir.LetCont(breakCollector.continuation, branch); 1271 letBreak = new ir.LetCont(breakCollector.continuation, branch);
(...skipping 13 matching lines...) Expand all
1335 /// creates its declaration and [variableElement] is the element for 1285 /// creates its declaration and [variableElement] is the element for
1336 /// the declared variable, 1286 /// the declared variable,
1337 /// 2) `v` is predeclared statically known variable, that is top-level, 1287 /// 2) `v` is predeclared statically known variable, that is top-level,
1338 /// static, or local variable, in which case [variableElement] is the 1288 /// static, or local variable, in which case [variableElement] is the
1339 /// variable element, and [variableSelector] defines its write access, 1289 /// variable element, and [variableSelector] defines its write access,
1340 /// 3) `v` is an instance variable in which case [variableSelector] 1290 /// 3) `v` is an instance variable in which case [variableSelector]
1341 /// defines its write access. 1291 /// defines its write access.
1342 /// [buildBody] creates the body, `b`, of the loop. The jump [target] is used 1292 /// [buildBody] creates the body, `b`, of the loop. The jump [target] is used
1343 /// to identify which `break` and `continue` statements that have this for-in 1293 /// to identify which `break` and `continue` statements that have this for-in
1344 /// statement as their target. 1294 /// statement as their target.
1345 void buildForIn({SubbuildFunction buildExpression, 1295 void buildForIn(
1346 SubbuildFunction buildVariableDeclaration, 1296 {SubbuildFunction buildExpression,
1347 Element variableElement, 1297 SubbuildFunction buildVariableDeclaration,
1348 Selector variableSelector, 1298 Element variableElement,
1349 TypeMask variableMask, 1299 Selector variableSelector,
1350 SourceInformation variableSetSourceInformation, 1300 TypeMask variableMask,
1351 TypeMask currentMask, 1301 SourceInformation variableSetSourceInformation,
1352 SourceInformation currentSourceInformation, 1302 TypeMask currentMask,
1353 TypeMask iteratorMask, 1303 SourceInformation currentSourceInformation,
1354 SourceInformation iteratorSourceInformation, 1304 TypeMask iteratorMask,
1355 TypeMask moveNextMask, 1305 SourceInformation iteratorSourceInformation,
1356 SourceInformation moveNextSourceInformation, 1306 TypeMask moveNextMask,
1357 SubbuildFunction buildBody, 1307 SourceInformation moveNextSourceInformation,
1358 JumpTarget target, 1308 SubbuildFunction buildBody,
1359 ClosureScope closureScope, 1309 JumpTarget target,
1360 SourceInformation conditionSourceInformation}) { 1310 ClosureScope closureScope,
1311 SourceInformation conditionSourceInformation}) {
1361 // The for-in loop 1312 // The for-in loop
1362 // 1313 //
1363 // for (a in e) s; 1314 // for (a in e) s;
1364 // 1315 //
1365 // Is compiled analogously to: 1316 // Is compiled analogously to:
1366 // 1317 //
1367 // it = e.iterator; 1318 // it = e.iterator;
1368 // while (it.moveNext()) { 1319 // while (it.moveNext()) {
1369 // var a = it.current; 1320 // var a = it.current;
1370 // s; 1321 // s;
1371 // } 1322 // }
1372 1323
1373 // Fill the current hole with: 1324 // Fill the current hole with:
1374 // let prim expressionReceiver = [[e]] in 1325 // let prim expressionReceiver = [[e]] in
1375 // let cont iteratorInvoked(iterator) = 1326 // let cont iteratorInvoked(iterator) =
1376 // [ ] 1327 // [ ]
1377 // in expressionReceiver.iterator () iteratorInvoked 1328 // in expressionReceiver.iterator () iteratorInvoked
1378 ir.Primitive expressionReceiver = buildExpression(this); 1329 ir.Primitive expressionReceiver = buildExpression(this);
1379 List<ir.Primitive> emptyArguments = <ir.Primitive>[]; 1330 List<ir.Primitive> emptyArguments = <ir.Primitive>[];
1380 ir.Primitive iterator = addPrimitive( 1331 ir.Primitive iterator = addPrimitive(new ir.InvokeMethod(
1381 new ir.InvokeMethod(expressionReceiver, 1332 expressionReceiver, Selectors.iterator, iteratorMask, emptyArguments));
1382 Selectors.iterator,
1383 iteratorMask,
1384 emptyArguments));
1385 1333
1386 // Fill with: 1334 // Fill with:
1387 // let cont loop(x, ...) = 1335 // let cont loop(x, ...) =
1388 // let cont moveNextInvoked(condition) = 1336 // let cont moveNextInvoked(condition) =
1389 // [ ] 1337 // [ ]
1390 // in iterator.moveNext () moveNextInvoked 1338 // in iterator.moveNext () moveNextInvoked
1391 // in loop(v, ...) 1339 // in loop(v, ...)
1392 JumpCollector loop = new BackwardJumpCollector(environment, target: target); 1340 JumpCollector loop = new BackwardJumpCollector(environment, target: target);
1393 addRecursiveContinuation(loop); 1341 addRecursiveContinuation(loop);
1394 ir.Primitive condition = addPrimitive( 1342 ir.Primitive condition = addPrimitive(new ir.InvokeMethod(
1395 new ir.InvokeMethod(iterator, 1343 iterator, Selectors.moveNext, moveNextMask, emptyArguments));
1396 Selectors.moveNext,
1397 moveNextMask,
1398 emptyArguments));
1399 1344
1400 // As a delimited term, build: 1345 // As a delimited term, build:
1401 // <<BODY>> = 1346 // <<BODY>> =
1402 // _enterScope(); 1347 // _enterScope();
1403 // [[variableDeclaration]] 1348 // [[variableDeclaration]]
1404 // let cont currentInvoked(currentValue) = 1349 // let cont currentInvoked(currentValue) =
1405 // [[a = currentValue]]; 1350 // [[a = currentValue]];
1406 // [ ] 1351 // [ ]
1407 // in iterator.current () currentInvoked 1352 // in iterator.current () currentInvoked
1408 IrBuilder bodyBuilder = makeDelimitedBuilder(); 1353 IrBuilder bodyBuilder = makeDelimitedBuilder();
1409 bodyBuilder._enterScope(closureScope); 1354 bodyBuilder._enterScope(closureScope);
1410 if (buildVariableDeclaration != null) { 1355 if (buildVariableDeclaration != null) {
1411 buildVariableDeclaration(bodyBuilder); 1356 buildVariableDeclaration(bodyBuilder);
1412 } 1357 }
1413 ir.Primitive currentValue = bodyBuilder.addPrimitive( 1358 ir.Primitive currentValue = bodyBuilder.addPrimitive(new ir.InvokeMethod(
1414 new ir.InvokeMethod( 1359 iterator, Selectors.current, currentMask, emptyArguments,
1415 iterator, 1360 sourceInformation: currentSourceInformation));
1416 Selectors.current,
1417 currentMask,
1418 emptyArguments,
1419 sourceInformation: currentSourceInformation));
1420 // TODO(johnniwinther): Extract this as a provided strategy. 1361 // TODO(johnniwinther): Extract this as a provided strategy.
1421 if (Elements.isLocal(variableElement)) { 1362 if (Elements.isLocal(variableElement)) {
1422 bodyBuilder.buildLocalVariableSet( 1363 bodyBuilder.buildLocalVariableSet(
1423 variableElement, 1364 variableElement, currentValue, variableSetSourceInformation);
1424 currentValue,
1425 variableSetSourceInformation);
1426 } else if (Elements.isError(variableElement) || 1365 } else if (Elements.isError(variableElement) ||
1427 Elements.isMalformed(variableElement)) { 1366 Elements.isMalformed(variableElement)) {
1428 Selector selector = new Selector.setter( 1367 Selector selector = new Selector.setter(
1429 new Name(variableElement.name, variableElement.library)); 1368 new Name(variableElement.name, variableElement.library));
1430 List<ir.Primitive> value = <ir.Primitive>[currentValue]; 1369 List<ir.Primitive> value = <ir.Primitive>[currentValue];
1431 // Note the comparison below. It can be the case that an element isError 1370 // Note the comparison below. It can be the case that an element isError
1432 // and isMalformed. 1371 // and isMalformed.
1433 if (Elements.isError(variableElement)) { 1372 if (Elements.isError(variableElement)) {
1434 bodyBuilder.buildStaticNoSuchMethod(selector, value, 1373 bodyBuilder.buildStaticNoSuchMethod(
1435 variableSetSourceInformation); 1374 selector, value, variableSetSourceInformation);
1436 } else { 1375 } else {
1437 bodyBuilder.buildErroneousInvocation( 1376 bodyBuilder.buildErroneousInvocation(
1438 variableElement, selector, value, variableSetSourceInformation); 1377 variableElement, selector, value, variableSetSourceInformation);
1439 } 1378 }
1440 } else if (Elements.isStaticOrTopLevel(variableElement)) { 1379 } else if (Elements.isStaticOrTopLevel(variableElement)) {
1441 if (variableElement.isField) { 1380 if (variableElement.isField) {
1442 bodyBuilder.addPrimitive( 1381 bodyBuilder.addPrimitive(new ir.SetStatic(
1443 new ir.SetStatic( 1382 variableElement, currentValue, variableSetSourceInformation));
1444 variableElement, currentValue, variableSetSourceInformation));
1445 } else { 1383 } else {
1446 bodyBuilder.buildStaticSetterSet( 1384 bodyBuilder.buildStaticSetterSet(
1447 variableElement, currentValue, variableSetSourceInformation); 1385 variableElement, currentValue, variableSetSourceInformation);
1448 } 1386 }
1449 } else { 1387 } else {
1450 ir.Primitive receiver = bodyBuilder.buildThis(); 1388 ir.Primitive receiver = bodyBuilder.buildThis();
1451 assert(receiver != null); 1389 assert(receiver != null);
1452 bodyBuilder.buildDynamicSet( 1390 bodyBuilder.buildDynamicSet(receiver, variableSelector, variableMask,
1453 receiver, variableSelector, variableMask, currentValue, 1391 currentValue, variableSetSourceInformation);
1454 variableSetSourceInformation);
1455 } 1392 }
1456 1393
1457 // Translate the body in the hole in the delimited term above, and add 1394 // Translate the body in the hole in the delimited term above, and add
1458 // a jump to the loop if control flow is live after the body. 1395 // a jump to the loop if control flow is live after the body.
1459 JumpCollector breakCollector = 1396 JumpCollector breakCollector =
1460 new ForwardJumpCollector(environment, target: target); 1397 new ForwardJumpCollector(environment, target: target);
1461 state.breakCollectors.add(breakCollector); 1398 state.breakCollectors.add(breakCollector);
1462 state.continueCollectors.add(loop); 1399 state.continueCollectors.add(loop);
1463 buildBody(bodyBuilder); 1400 buildBody(bodyBuilder);
1464 assert(state.breakCollectors.last == breakCollector); 1401 assert(state.breakCollectors.last == breakCollector);
1465 assert(state.continueCollectors.last == loop); 1402 assert(state.continueCollectors.last == loop);
1466 state.breakCollectors.removeLast(); 1403 state.breakCollectors.removeLast();
1467 state.continueCollectors.removeLast(); 1404 state.continueCollectors.removeLast();
1468 if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop); 1405 if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop);
1469 1406
1470 // Create body entry and loop exit continuations and a branch to them. 1407 // Create body entry and loop exit continuations and a branch to them.
1471 // 1408 //
1472 // let cont exit() = [ ] 1409 // let cont exit() = [ ]
1473 // and body() = <<BODY>> 1410 // and body() = <<BODY>>
1474 // in branch condition (body, exit) 1411 // in branch condition (body, exit)
1475 ir.Continuation exitContinuation = new ir.Continuation([]); 1412 ir.Continuation exitContinuation = new ir.Continuation([]);
1476 ir.Continuation bodyContinuation = new ir.Continuation([]); 1413 ir.Continuation bodyContinuation = new ir.Continuation([]);
1477 bodyContinuation.body = bodyBuilder.root; 1414 bodyContinuation.body = bodyBuilder.root;
1478 // Note the order of continuations: the first one is the one that will 1415 // Note the order of continuations: the first one is the one that will
1479 // be filled by LetCont.plug. 1416 // be filled by LetCont.plug.
1480 ir.LetCont branch = 1417 ir.LetCont branch = new ir.LetCont.two(
1481 new ir.LetCont.two(exitContinuation, bodyContinuation, 1418 exitContinuation,
1482 new ir.Branch.strict(condition, 1419 bodyContinuation,
1483 bodyContinuation, 1420 new ir.Branch.strict(condition, bodyContinuation, exitContinuation,
1484 exitContinuation, 1421 conditionSourceInformation));
1485 conditionSourceInformation));
1486 // If there are breaks in the body, then there must be a join-point 1422 // If there are breaks in the body, then there must be a join-point
1487 // continuation for the normal exit and the breaks. Otherwise, the 1423 // continuation for the normal exit and the breaks. Otherwise, the
1488 // successor is translated in the hole in the exit continuation. 1424 // successor is translated in the hole in the exit continuation.
1489 bool hasBreaks = !breakCollector.isEmpty; 1425 bool hasBreaks = !breakCollector.isEmpty;
1490 ir.LetCont letBreak; 1426 ir.LetCont letBreak;
1491 if (hasBreaks) { 1427 if (hasBreaks) {
1492 IrBuilder exitBuilder = makeDelimitedBuilder(); 1428 IrBuilder exitBuilder = makeDelimitedBuilder();
1493 exitBuilder.jumpTo(breakCollector); 1429 exitBuilder.jumpTo(breakCollector);
1494 exitContinuation.body = exitBuilder.root; 1430 exitContinuation.body = exitBuilder.root;
1495 letBreak = new ir.LetCont(breakCollector.continuation, branch); 1431 letBreak = new ir.LetCont(breakCollector.continuation, branch);
1496 add(letBreak); 1432 add(letBreak);
1497 environment = breakCollector.environment; 1433 environment = breakCollector.environment;
1498 } else { 1434 } else {
1499 add(branch); 1435 add(branch);
1500 } 1436 }
1501 } 1437 }
1502 1438
1503 /// Creates a while loop in which the condition and body are created by 1439 /// Creates a while loop in which the condition and body are created by
1504 /// [buildCondition] and [buildBody], respectively. 1440 /// [buildCondition] and [buildBody], respectively.
1505 /// 1441 ///
1506 /// The jump [target] is used to identify which `break` and `continue` 1442 /// The jump [target] is used to identify which `break` and `continue`
1507 /// statements that have this `while` statement as their target. 1443 /// statements that have this `while` statement as their target.
1508 void buildWhile({SubbuildFunction buildCondition, 1444 void buildWhile(
1509 SubbuildFunction buildBody, 1445 {SubbuildFunction buildCondition,
1510 JumpTarget target, 1446 SubbuildFunction buildBody,
1511 ClosureScope closureScope, 1447 JumpTarget target,
1512 SourceInformation sourceInformation}) { 1448 ClosureScope closureScope,
1449 SourceInformation sourceInformation}) {
1513 assert(isOpen); 1450 assert(isOpen);
1514 // While loops use four named continuations: the entry to the body, the 1451 // While loops use four named continuations: the entry to the body, the
1515 // loop exit, the loop back edge (continue), and the loop exit (break). 1452 // loop exit, the loop back edge (continue), and the loop exit (break).
1516 // The CPS translation of [[while (condition) body; successor]] is: 1453 // The CPS translation of [[while (condition) body; successor]] is:
1517 // 1454 //
1518 // let cont continue(x, ...) = 1455 // let cont continue(x, ...) =
1519 // let prim cond = [[condition]] in 1456 // let prim cond = [[condition]] in
1520 // let cont break(x, ...) = [[successor]] in 1457 // let cont break(x, ...) = [[successor]] in
1521 // let cont exit() = break(v, ...) 1458 // let cont exit() = break(v, ...)
1522 // and body() = 1459 // and body() =
(...skipping 24 matching lines...) Expand all
1547 state.breakCollectors.removeLast(); 1484 state.breakCollectors.removeLast();
1548 state.continueCollectors.removeLast(); 1485 state.continueCollectors.removeLast();
1549 if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop); 1486 if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop);
1550 1487
1551 // Create body entry and loop exit continuations and a branch to them. 1488 // Create body entry and loop exit continuations and a branch to them.
1552 ir.Continuation exitContinuation = new ir.Continuation([]); 1489 ir.Continuation exitContinuation = new ir.Continuation([]);
1553 ir.Continuation bodyContinuation = new ir.Continuation([]); 1490 ir.Continuation bodyContinuation = new ir.Continuation([]);
1554 bodyContinuation.body = bodyBuilder.root; 1491 bodyContinuation.body = bodyBuilder.root;
1555 // Note the order of continuations: the first one is the one that will 1492 // Note the order of continuations: the first one is the one that will
1556 // be filled by LetCont.plug. 1493 // be filled by LetCont.plug.
1557 ir.LetCont branch = 1494 ir.LetCont branch = new ir.LetCont.two(
1558 new ir.LetCont.two(exitContinuation, bodyContinuation, 1495 exitContinuation,
1559 new ir.Branch.strict(condition, 1496 bodyContinuation,
1560 bodyContinuation, 1497 new ir.Branch.strict(
1561 exitContinuation, 1498 condition, bodyContinuation, exitContinuation, sourceInformation));
1562 sourceInformation));
1563 // If there are breaks in the body, then there must be a join-point 1499 // If there are breaks in the body, then there must be a join-point
1564 // continuation for the normal exit and the breaks. Otherwise, the 1500 // continuation for the normal exit and the breaks. Otherwise, the
1565 // successor is translated in the hole in the exit continuation. 1501 // successor is translated in the hole in the exit continuation.
1566 bool hasBreaks = !breakCollector.isEmpty; 1502 bool hasBreaks = !breakCollector.isEmpty;
1567 ir.LetCont letBreak; 1503 ir.LetCont letBreak;
1568 if (hasBreaks) { 1504 if (hasBreaks) {
1569 IrBuilder exitBuilder = makeDelimitedBuilder(); 1505 IrBuilder exitBuilder = makeDelimitedBuilder();
1570 exitBuilder.jumpTo(breakCollector); 1506 exitBuilder.jumpTo(breakCollector);
1571 exitContinuation.body = exitBuilder.root; 1507 exitContinuation.body = exitBuilder.root;
1572 letBreak = new ir.LetCont(breakCollector.continuation, branch); 1508 letBreak = new ir.LetCont(breakCollector.continuation, branch);
1573 add(letBreak); 1509 add(letBreak);
1574 environment = breakCollector.environment; 1510 environment = breakCollector.environment;
1575 } else { 1511 } else {
1576 add(branch); 1512 add(branch);
1577 } 1513 }
1578 } 1514 }
1579 1515
1580
1581 /// Creates a do-while loop. 1516 /// Creates a do-while loop.
1582 /// 1517 ///
1583 /// The body and condition are created by [buildBody] and [buildCondition]. 1518 /// The body and condition are created by [buildBody] and [buildCondition].
1584 /// The jump target [target] is the target of `break` and `continue` 1519 /// The jump target [target] is the target of `break` and `continue`
1585 /// statements in the body that have the loop as their target. 1520 /// statements in the body that have the loop as their target.
1586 /// [closureScope] contains all the variables declared in the loop (but not 1521 /// [closureScope] contains all the variables declared in the loop (but not
1587 /// declared in some inner closure scope). 1522 /// declared in some inner closure scope).
1588 void buildDoWhile({SubbuildFunction buildBody, 1523 void buildDoWhile(
1589 SubbuildFunction buildCondition, 1524 {SubbuildFunction buildBody,
1590 JumpTarget target, 1525 SubbuildFunction buildCondition,
1591 ClosureScope closureScope, 1526 JumpTarget target,
1592 SourceInformation sourceInformation}) { 1527 ClosureScope closureScope,
1528 SourceInformation sourceInformation}) {
1593 assert(isOpen); 1529 assert(isOpen);
1594 // The CPS translation of [[do body; while (condition); successor]] is: 1530 // The CPS translation of [[do body; while (condition); successor]] is:
1595 // 1531 //
1596 // let cont break(x, ...) = [[successor]] in 1532 // let cont break(x, ...) = [[successor]] in
1597 // let cont rec loop(x, ...) = 1533 // let cont rec loop(x, ...) =
1598 // let cont continue(x, ...) = 1534 // let cont continue(x, ...) =
1599 // let prim cond = [[condition]] in 1535 // let prim cond = [[condition]] in
1600 // let cont exit() = break(v, ...) 1536 // let cont exit() = break(v, ...)
1601 // and repeat() = loop(v, ...) 1537 // and repeat() = loop(v, ...)
1602 // in branch cond (repeat, exit) 1538 // in branch cond (repeat, exit)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1635 1571
1636 ir.Continuation exitContinuation = new ir.Continuation([]); 1572 ir.Continuation exitContinuation = new ir.Continuation([]);
1637 IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder(); 1573 IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder();
1638 exitBuilder.jumpTo(breakCollector); 1574 exitBuilder.jumpTo(breakCollector);
1639 exitContinuation.body = exitBuilder.root; 1575 exitContinuation.body = exitBuilder.root;
1640 ir.Continuation repeatContinuation = new ir.Continuation([]); 1576 ir.Continuation repeatContinuation = new ir.Continuation([]);
1641 IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder(); 1577 IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder();
1642 repeatBuilder.jumpTo(loop); 1578 repeatBuilder.jumpTo(loop);
1643 repeatContinuation.body = repeatBuilder.root; 1579 repeatContinuation.body = repeatBuilder.root;
1644 1580
1645 continueBuilder.add( 1581 continueBuilder.add(new ir.LetCont.two(
1646 new ir.LetCont.two(exitContinuation, repeatContinuation, 1582 exitContinuation,
1647 new ir.Branch.strict(condition, 1583 repeatContinuation,
1648 repeatContinuation, 1584 new ir.Branch.strict(condition, repeatContinuation, exitContinuation,
1649 exitContinuation, 1585 sourceInformation)));
1650 sourceInformation)));
1651 continueCollector.continuation.body = continueBuilder.root; 1586 continueCollector.continuation.body = continueBuilder.root;
1652 1587
1653 // Construct the loop continuation (i.e., the body and condition). 1588 // Construct the loop continuation (i.e., the body and condition).
1654 // <Loop> = 1589 // <Loop> =
1655 // let cont continue(x, ...) = 1590 // let cont continue(x, ...) =
1656 // <Continue> 1591 // <Continue>
1657 // in [[body]]; continue(v, ...) 1592 // in [[body]]; continue(v, ...)
1658 loopBuilder.add( 1593 loopBuilder
1659 new ir.LetCont(continueCollector.continuation, 1594 .add(new ir.LetCont(continueCollector.continuation, bodyBuilder.root));
1660 bodyBuilder.root));
1661 1595
1662 // And tie it all together. 1596 // And tie it all together.
1663 add(new ir.LetCont(breakCollector.continuation, loopBuilder.root)); 1597 add(new ir.LetCont(breakCollector.continuation, loopBuilder.root));
1664 environment = breakCollector.environment; 1598 environment = breakCollector.environment;
1665 } 1599 }
1666 1600
1667 void buildSimpleSwitch(JumpCollector join, 1601 void buildSimpleSwitch(JumpCollector join, List<SwitchCaseInfo> cases,
1668 List<SwitchCaseInfo> cases, 1602 SubbuildFunction buildDefaultBody) {
1669 SubbuildFunction buildDefaultBody) {
1670 IrBuilder casesBuilder = makeDelimitedBuilder(); 1603 IrBuilder casesBuilder = makeDelimitedBuilder();
1671 for (SwitchCaseInfo caseInfo in cases) { 1604 for (SwitchCaseInfo caseInfo in cases) {
1672 ir.Primitive condition = caseInfo.buildCondition(casesBuilder); 1605 ir.Primitive condition = caseInfo.buildCondition(casesBuilder);
1673 IrBuilder thenBuilder = makeDelimitedBuilder(); 1606 IrBuilder thenBuilder = makeDelimitedBuilder();
1674 caseInfo.buildBody(thenBuilder); 1607 caseInfo.buildBody(thenBuilder);
1675 ir.Continuation thenContinuation = new ir.Continuation([]); 1608 ir.Continuation thenContinuation = new ir.Continuation([]);
1676 thenContinuation.body = thenBuilder.root; 1609 thenContinuation.body = thenBuilder.root;
1677 ir.Continuation elseContinuation = new ir.Continuation([]); 1610 ir.Continuation elseContinuation = new ir.Continuation([]);
1678 // A LetCont.two term has a hole as the body of the first listed 1611 // A LetCont.two term has a hole as the body of the first listed
1679 // continuation, to be plugged by the translation. Therefore put the 1612 // continuation, to be plugged by the translation. Therefore put the
1680 // else continuation first. 1613 // else continuation first.
1681 casesBuilder.add( 1614 casesBuilder.add(new ir.LetCont.two(
1682 new ir.LetCont.two(elseContinuation, thenContinuation, 1615 elseContinuation,
1683 new ir.Branch.strict(condition, 1616 thenContinuation,
1684 thenContinuation, 1617 new ir.Branch.strict(condition, thenContinuation, elseContinuation,
1685 elseContinuation, 1618 caseInfo.sourceInformation)));
1686 caseInfo.sourceInformation)));
1687 } 1619 }
1688 1620
1689 if (buildDefaultBody == null) { 1621 if (buildDefaultBody == null) {
1690 casesBuilder.jumpTo(join); 1622 casesBuilder.jumpTo(join);
1691 } else { 1623 } else {
1692 buildDefaultBody(casesBuilder); 1624 buildDefaultBody(casesBuilder);
1693 } 1625 }
1694 1626
1695 if (!join.isEmpty) { 1627 if (!join.isEmpty) {
1696 add(new ir.LetCont(join.continuation, casesBuilder.root)); 1628 add(new ir.LetCont(join.continuation, casesBuilder.root));
(...skipping 11 matching lines...) Expand all
1708 /// 1640 ///
1709 /// The translation treats try/finally and try/catch/finally as if they 1641 /// The translation treats try/finally and try/catch/finally as if they
1710 /// were macro-expanded into try/catch. This utility function generates 1642 /// were macro-expanded into try/catch. This utility function generates
1711 /// that try/catch. The function is parameterized over a list of variables 1643 /// that try/catch. The function is parameterized over a list of variables
1712 /// that should be boxed on entry to the try, and over functions to emit 1644 /// that should be boxed on entry to the try, and over functions to emit
1713 /// code for entering the try, building the try body, leaving the try body, 1645 /// code for entering the try, building the try body, leaving the try body,
1714 /// building the catch body, and leaving the entire try/catch. 1646 /// building the catch body, and leaving the entire try/catch.
1715 /// 1647 ///
1716 /// Please see the function's implementation for where these functions are 1648 /// Please see the function's implementation for where these functions are
1717 /// called. 1649 /// called.
1718 void _helpBuildTryCatch(TryStatementInfo variables, 1650 void _helpBuildTryCatch(
1651 TryStatementInfo variables,
1719 void enterTry(IrBuilder builder), 1652 void enterTry(IrBuilder builder),
1720 SubbuildFunction buildTryBlock, 1653 SubbuildFunction buildTryBlock,
1721 void leaveTry(IrBuilder builder), 1654 void leaveTry(IrBuilder builder),
1722 List<ir.Parameter> buildCatch(IrBuilder builder, JumpCollector join), 1655 List<ir.Parameter> buildCatch(IrBuilder builder, JumpCollector join),
1723 void leaveTryCatch(IrBuilder builder, JumpCollector join, 1656 void leaveTryCatch(
1724 ir.Expression body)) { 1657 IrBuilder builder, JumpCollector join, ir.Expression body)) {
1725 JumpCollector join = new ForwardJumpCollector(environment); 1658 JumpCollector join = new ForwardJumpCollector(environment);
1726 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); 1659 IrBuilder tryCatchBuilder = makeDelimitedBuilder();
1727 1660
1728 // Variables treated as mutable in a try are not mutable outside of it. 1661 // Variables treated as mutable in a try are not mutable outside of it.
1729 // Work with a copy of the outer builder's mutable variables. 1662 // Work with a copy of the outer builder's mutable variables.
1730 tryCatchBuilder.mutableVariables = 1663 tryCatchBuilder.mutableVariables =
1731 new Map<Local, ir.MutableVariable>.from(mutableVariables); 1664 new Map<Local, ir.MutableVariable>.from(mutableVariables);
1732 for (LocalVariableElement variable in variables.boxedOnEntry) { 1665 for (LocalVariableElement variable in variables.boxedOnEntry) {
1733 assert(!tryCatchBuilder.isInMutableVariable(variable)); 1666 assert(!tryCatchBuilder.isInMutableVariable(variable));
1734 ir.Primitive value = tryCatchBuilder.buildLocalGet(variable); 1667 ir.Primitive value = tryCatchBuilder.buildLocalGet(variable);
(...skipping 17 matching lines...) Expand all
1752 ir.Primitive value = catchBuilder.buildLocalGet(variable); 1685 ir.Primitive value = catchBuilder.buildLocalGet(variable);
1753 // After this point, the variables that were boxed on entry to the try 1686 // After this point, the variables that were boxed on entry to the try
1754 // are no longer treated as mutable. 1687 // are no longer treated as mutable.
1755 catchBuilder.removeMutableVariable(variable); 1688 catchBuilder.removeMutableVariable(variable);
1756 catchBuilder.environment.update(variable, value); 1689 catchBuilder.environment.update(variable, value);
1757 } 1690 }
1758 1691
1759 List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join); 1692 List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join);
1760 ir.Continuation catchContinuation = new ir.Continuation(catchParameters); 1693 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1761 catchContinuation.body = catchBuilder.root; 1694 catchContinuation.body = catchBuilder.root;
1762 tryCatchBuilder.add( 1695 tryCatchBuilder.add(new ir.LetHandler(catchContinuation, tryBuilder.root));
1763 new ir.LetHandler(catchContinuation, tryBuilder.root));
1764 1696
1765 leaveTryCatch(this, join, tryCatchBuilder.root); 1697 leaveTryCatch(this, join, tryCatchBuilder.root);
1766 } 1698 }
1767 1699
1768 /// Translates a try/catch. 1700 /// Translates a try/catch.
1769 /// 1701 ///
1770 /// [variables] provides information on local variables declared and boxed 1702 /// [variables] provides information on local variables declared and boxed
1771 /// within the try body. 1703 /// within the try body.
1772 /// [buildTryBlock] builds the try block. 1704 /// [buildTryBlock] builds the try block.
1773 /// [catchClauseInfos] provides access to the catch type, exception variable, 1705 /// [catchClauseInfos] provides access to the catch type, exception variable,
1774 /// and stack trace variable, and a function for building the catch block. 1706 /// and stack trace variable, and a function for building the catch block.
1775 void buildTryCatch(TryStatementInfo variables, 1707 void buildTryCatch(TryStatementInfo variables, SubbuildFunction buildTryBlock,
1776 SubbuildFunction buildTryBlock, 1708 List<CatchClauseInfo> catchClauseInfos) {
1777 List<CatchClauseInfo> catchClauseInfos) {
1778 assert(isOpen); 1709 assert(isOpen);
1779 // Catch handlers are in scope for their body. The CPS translation of 1710 // Catch handlers are in scope for their body. The CPS translation of
1780 // [[try tryBlock catch (ex, st) catchBlock; successor]] is: 1711 // [[try tryBlock catch (ex, st) catchBlock; successor]] is:
1781 // 1712 //
1782 // let cont join(v0, v1, ...) = [[successor]] in 1713 // let cont join(v0, v1, ...) = [[successor]] in
1783 // let mutable m0 = x0 in 1714 // let mutable m0 = x0 in
1784 // let mutable m1 = x1 in 1715 // let mutable m1 = x1 in
1785 // ... 1716 // ...
1786 // let handler catch_(ex, st) = 1717 // let handler catch_(ex, st) =
1787 // let prim p0 = GetMutable(m0) in 1718 // let prim p0 = GetMutable(m0) in
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1821 // On exit from try of try/catch, update the builder's state to reflect 1752 // On exit from try of try/catch, update the builder's state to reflect
1822 // the variables that are no longer boxed. 1753 // the variables that are no longer boxed.
1823 void restoreJump(JumpCollector collector) { 1754 void restoreJump(JumpCollector collector) {
1824 collector.leaveTry(); 1755 collector.leaveTry();
1825 } 1756 }
1826 builder.state.breakCollectors.forEach(restoreJump); 1757 builder.state.breakCollectors.forEach(restoreJump);
1827 builder.state.continueCollectors.forEach(restoreJump); 1758 builder.state.continueCollectors.forEach(restoreJump);
1828 restoreJump(builder.state.returnCollector); 1759 restoreJump(builder.state.returnCollector);
1829 } 1760 }
1830 1761
1831 List<ir.Parameter> buildCatch(IrBuilder builder, 1762 List<ir.Parameter> buildCatch(IrBuilder builder, JumpCollector join) {
1832 JumpCollector join) {
1833 // Translate the catch clauses. Multiple clauses are translated as if 1763 // Translate the catch clauses. Multiple clauses are translated as if
1834 // they were explicitly cascaded if/else type tests. 1764 // they were explicitly cascaded if/else type tests.
1835 1765
1836 // Handlers are always translated as having both exception and stack trace 1766 // Handlers are always translated as having both exception and stack trace
1837 // parameters. Multiple clauses do not have to use the same names for 1767 // parameters. Multiple clauses do not have to use the same names for
1838 // them. Choose the first of each as the name hint for the respective 1768 // them. Choose the first of each as the name hint for the respective
1839 // handler parameter. 1769 // handler parameter.
1840 ir.Parameter exceptionParameter = 1770 ir.Parameter exceptionParameter =
1841 new ir.Parameter(catchClauseInfos.first.exceptionVariable); 1771 new ir.Parameter(catchClauseInfos.first.exceptionVariable);
1842 LocalVariableElement traceVariable; 1772 LocalVariableElement traceVariable;
(...skipping 21 matching lines...) Expand all
1864 clauseBuilder.declareLocalVariable(clause.stackTraceVariable, 1794 clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
1865 initialValue: traceParameter); 1795 initialValue: traceParameter);
1866 } 1796 }
1867 clause.buildCatchBlock(clauseBuilder); 1797 clause.buildCatchBlock(clauseBuilder);
1868 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join); 1798 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1869 return clauseBuilder.root; 1799 return clauseBuilder.root;
1870 } 1800 }
1871 1801
1872 // Expand multiple catch clauses into an explicit if/then/else. Iterate 1802 // Expand multiple catch clauses into an explicit if/then/else. Iterate
1873 // them in reverse so the current block becomes the next else block. 1803 // them in reverse so the current block becomes the next else block.
1874 ir.Expression catchBody = (catchAll == null) 1804 ir.Expression catchBody =
1875 ? new ir.Rethrow() 1805 (catchAll == null) ? new ir.Rethrow() : buildCatchClause(catchAll);
1876 : buildCatchClause(catchAll);
1877 for (CatchClauseInfo clause in catchClauseInfos.reversed) { 1806 for (CatchClauseInfo clause in catchClauseInfos.reversed) {
1878 ir.Continuation thenContinuation = new ir.Continuation([]); 1807 ir.Continuation thenContinuation = new ir.Continuation([]);
1879 ir.Continuation elseContinuation = new ir.Continuation([]); 1808 ir.Continuation elseContinuation = new ir.Continuation([]);
1880 thenContinuation.body = buildCatchClause(clause); 1809 thenContinuation.body = buildCatchClause(clause);
1881 elseContinuation.body = catchBody; 1810 elseContinuation.body = catchBody;
1882 1811
1883 // Build the type test guarding this clause. We can share the 1812 // Build the type test guarding this clause. We can share the
1884 // environment with the nested builder because this part cannot mutate 1813 // environment with the nested builder because this part cannot mutate
1885 // it. 1814 // it.
1886 IrBuilder checkBuilder = builder.makeDelimitedBuilder(environment); 1815 IrBuilder checkBuilder = builder.makeDelimitedBuilder(environment);
1887 ir.Primitive typeMatches = 1816 ir.Primitive typeMatches = checkBuilder.buildTypeOperator(
1888 checkBuilder.buildTypeOperator(exceptionParameter, 1817 exceptionParameter, clause.type, clause.sourceInformation,
1889 clause.type, 1818 isTypeTest: true);
1890 clause.sourceInformation, 1819 checkBuilder.add(new ir.LetCont.two(
1891 isTypeTest: true); 1820 thenContinuation,
1892 checkBuilder.add(new ir.LetCont.two(thenContinuation, elseContinuation, 1821 elseContinuation,
1893 new ir.Branch.strict(typeMatches, 1822 new ir.Branch.strict(typeMatches, thenContinuation,
1894 thenContinuation, 1823 elseContinuation, clause.sourceInformation)));
1895 elseContinuation,
1896 clause.sourceInformation)));
1897 catchBody = checkBuilder.root; 1824 catchBody = checkBuilder.root;
1898 } 1825 }
1899 builder.add(catchBody); 1826 builder.add(catchBody);
1900 1827
1901 return <ir.Parameter>[exceptionParameter, traceParameter]; 1828 return <ir.Parameter>[exceptionParameter, traceParameter];
1902 } 1829 }
1903 1830
1904 void leaveTryCatch(IrBuilder builder, JumpCollector join, 1831 void leaveTryCatch(
1905 ir.Expression body) { 1832 IrBuilder builder, JumpCollector join, ir.Expression body) {
1906 // Add the binding for the join-point continuation and continue the 1833 // Add the binding for the join-point continuation and continue the
1907 // translation in its body. 1834 // translation in its body.
1908 builder.add(new ir.LetCont(join.continuation, body)); 1835 builder.add(new ir.LetCont(join.continuation, body));
1909 builder.environment = join.environment; 1836 builder.environment = join.environment;
1910 } 1837 }
1911 1838
1912 _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry, 1839 _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry, buildCatch,
1913 buildCatch, leaveTryCatch); 1840 leaveTryCatch);
1914 } 1841 }
1915 1842
1916 /// Translates a try/finally. 1843 /// Translates a try/finally.
1917 /// 1844 ///
1918 /// [variables] provides information on local variables declared and boxed 1845 /// [variables] provides information on local variables declared and boxed
1919 /// within the try body. 1846 /// within the try body.
1920 /// [buildTryBlock] builds the try block. 1847 /// [buildTryBlock] builds the try block.
1921 /// [buildFinallyBlock] builds the finally block. 1848 /// [buildFinallyBlock] builds the finally block.
1922 void buildTryFinally(TryStatementInfo variables, 1849 void buildTryFinally(TryStatementInfo variables,
1923 SubbuildFunction buildTryBlock, 1850 SubbuildFunction buildTryBlock, SubbuildFunction buildFinallyBlock) {
1924 SubbuildFunction buildFinallyBlock) {
1925 assert(isOpen); 1851 assert(isOpen);
1926 // Try/finally is implemented in terms of try/catch and by duplicating the 1852 // Try/finally is implemented in terms of try/catch and by duplicating the
1927 // code for finally at all exits. The encoding is: 1853 // code for finally at all exits. The encoding is:
1928 // 1854 //
1929 // try tryBlock finally finallyBlock 1855 // try tryBlock finally finallyBlock
1930 // ==> 1856 // ==>
1931 // try tryBlock catch (ex, st) { finallyBlock; rethrow } finallyBlock 1857 // try tryBlock catch (ex, st) { finallyBlock; rethrow } finallyBlock
1932 // 1858 //
1933 // Where in tryBlock, all of the break, continue, and return exits are 1859 // Where in tryBlock, all of the break, continue, and return exits are
1934 // translated as jumps to continuations (bound outside the catch handler) 1860 // translated as jumps to continuations (bound outside the catch handler)
(...skipping 10 matching lines...) Expand all
1945 JumpCollector interceptJump(JumpCollector collector) { 1871 JumpCollector interceptJump(JumpCollector collector) {
1946 JumpCollector result = 1872 JumpCollector result =
1947 new ForwardJumpCollector(environment, target: collector.target); 1873 new ForwardJumpCollector(environment, target: collector.target);
1948 result.enterTry(variables.boxedOnEntry); 1874 result.enterTry(variables.boxedOnEntry);
1949 return result; 1875 return result;
1950 } 1876 }
1951 savedBreaks = builder.state.breakCollectors; 1877 savedBreaks = builder.state.breakCollectors;
1952 savedContinues = builder.state.continueCollectors; 1878 savedContinues = builder.state.continueCollectors;
1953 savedReturn = builder.state.returnCollector; 1879 savedReturn = builder.state.returnCollector;
1954 1880
1955 builder.state.breakCollectors = newBreaks = 1881 builder.state.breakCollectors =
1956 savedBreaks.map(interceptJump).toList(); 1882 newBreaks = savedBreaks.map(interceptJump).toList();
1957 builder.state.continueCollectors = newContinues = 1883 builder.state.continueCollectors =
1958 savedContinues.map(interceptJump).toList(); 1884 newContinues = savedContinues.map(interceptJump).toList();
1959 builder.state.returnCollector = newReturn = 1885 builder.state.returnCollector = newReturn =
1960 new ForwardJumpCollector(environment, hasExtraArgument: true) 1886 new ForwardJumpCollector(environment, hasExtraArgument: true)
1961 ..enterTry(variables.boxedOnEntry); 1887 ..enterTry(variables.boxedOnEntry);
1962 } 1888 }
1963 1889
1964 void leaveTry(IrBuilder builder) { 1890 void leaveTry(IrBuilder builder) {
1965 // On exit from the try of try/finally, update the builder's state to 1891 // On exit from the try of try/finally, update the builder's state to
1966 // reflect the variables that are no longer boxed and restore the 1892 // reflect the variables that are no longer boxed and restore the
1967 // original, unintercepted break, continue, and return targets. 1893 // original, unintercepted break, continue, and return targets.
1968 void restoreJump(JumpCollector collector) { 1894 void restoreJump(JumpCollector collector) {
1969 collector.leaveTry(); 1895 collector.leaveTry();
1970 } 1896 }
1971 newBreaks.forEach(restoreJump); 1897 newBreaks.forEach(restoreJump);
1972 newContinues.forEach(restoreJump); 1898 newContinues.forEach(restoreJump);
1973 newReturn.leaveTry(); 1899 newReturn.leaveTry();
1974 builder.state.breakCollectors = savedBreaks; 1900 builder.state.breakCollectors = savedBreaks;
1975 builder.state.continueCollectors = savedContinues; 1901 builder.state.continueCollectors = savedContinues;
1976 builder.state.returnCollector = savedReturn; 1902 builder.state.returnCollector = savedReturn;
1977 } 1903 }
1978 1904
1979 List<ir.Parameter> buildCatch(IrBuilder builder, 1905 List<ir.Parameter> buildCatch(IrBuilder builder, JumpCollector join) {
1980 JumpCollector join) {
1981 // The catch block of the try/catch used for try/finally is the finally 1906 // The catch block of the try/catch used for try/finally is the finally
1982 // code followed by a rethrow. 1907 // code followed by a rethrow.
1983 buildFinallyBlock(builder); 1908 buildFinallyBlock(builder);
1984 if (builder.isOpen) { 1909 if (builder.isOpen) {
1985 builder.add(new ir.Rethrow()); 1910 builder.add(new ir.Rethrow());
1986 builder._current = null; 1911 builder._current = null;
1987 } 1912 }
1988 return <ir.Parameter>[new ir.Parameter(null), new ir.Parameter(null)]; 1913 return <ir.Parameter>[new ir.Parameter(null), new ir.Parameter(null)];
1989 } 1914 }
1990 1915
1991 void leaveTryCatch(IrBuilder builder, JumpCollector join, 1916 void leaveTryCatch(
1992 ir.Expression body) { 1917 IrBuilder builder, JumpCollector join, ir.Expression body) {
1993 // Build a list of continuations for jumps from the try block and 1918 // Build a list of continuations for jumps from the try block and
1994 // duplicate the finally code before jumping to the actual target. 1919 // duplicate the finally code before jumping to the actual target.
1995 List<ir.Continuation> exits = <ir.Continuation>[join.continuation]; 1920 List<ir.Continuation> exits = <ir.Continuation>[join.continuation];
1996 void addJump(JumpCollector newCollector, 1921 void addJump(
1997 JumpCollector originalCollector) { 1922 JumpCollector newCollector, JumpCollector originalCollector) {
1998 if (newCollector.isEmpty) return; 1923 if (newCollector.isEmpty) return;
1999 IrBuilder builder = makeDelimitedBuilder(newCollector.environment); 1924 IrBuilder builder = makeDelimitedBuilder(newCollector.environment);
2000 buildFinallyBlock(builder); 1925 buildFinallyBlock(builder);
2001 if (builder.isOpen) builder.jumpTo(originalCollector); 1926 if (builder.isOpen) builder.jumpTo(originalCollector);
2002 newCollector.continuation.body = builder.root; 1927 newCollector.continuation.body = builder.root;
2003 exits.add(newCollector.continuation); 1928 exits.add(newCollector.continuation);
2004 } 1929 }
2005 for (int i = 0; i < newBreaks.length; ++i) { 1930 for (int i = 0; i < newBreaks.length; ++i) {
2006 addJump(newBreaks[i], savedBreaks[i]); 1931 addJump(newBreaks[i], savedBreaks[i]);
2007 } 1932 }
2008 for (int i = 0; i < newContinues.length; ++i) { 1933 for (int i = 0; i < newContinues.length; ++i) {
2009 addJump(newContinues[i], savedContinues[i]); 1934 addJump(newContinues[i], savedContinues[i]);
2010 } 1935 }
2011 if (!newReturn.isEmpty) { 1936 if (!newReturn.isEmpty) {
2012 IrBuilder builder = makeDelimitedBuilder(newReturn.environment); 1937 IrBuilder builder = makeDelimitedBuilder(newReturn.environment);
2013 ir.Primitive value = builder.environment.discard(1); 1938 ir.Primitive value = builder.environment.discard(1);
2014 buildFinallyBlock(builder); 1939 buildFinallyBlock(builder);
2015 if (builder.isOpen) builder.buildReturn(value: value); 1940 if (builder.isOpen) builder.buildReturn(value: value);
2016 newReturn.continuation.body = builder.root; 1941 newReturn.continuation.body = builder.root;
2017 exits.add(newReturn.continuation); 1942 exits.add(newReturn.continuation);
2018 } 1943 }
2019 builder.add(new ir.LetCont.many(exits, body)); 1944 builder.add(new ir.LetCont.many(exits, body));
2020 builder.environment = join.environment; 1945 builder.environment = join.environment;
2021 buildFinallyBlock(builder); 1946 buildFinallyBlock(builder);
2022 } 1947 }
2023 1948
2024 _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry, 1949 _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry, buildCatch,
2025 buildCatch, leaveTryCatch); 1950 leaveTryCatch);
2026 } 1951 }
2027 1952
2028 /// Create a return statement `return value;` or `return;` if [value] is 1953 /// Create a return statement `return value;` or `return;` if [value] is
2029 /// null. 1954 /// null.
2030 void buildReturn({ir.Primitive value, SourceInformation sourceInformation}) { 1955 void buildReturn({ir.Primitive value, SourceInformation sourceInformation}) {
2031 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 1956 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
2032 // where (C', x) = Build(e, C) 1957 // where (C', x) = Build(e, C)
2033 // 1958 //
2034 // Return without a subexpression is translated as if it were return null. 1959 // Return without a subexpression is translated as if it were return null.
2035 assert(isOpen); 1960 assert(isOpen);
2036 if (value == null) { 1961 if (value == null) {
2037 value = buildNullConstant(); 1962 value = buildNullConstant();
2038 } 1963 }
2039 jumpTo(state.returnCollector, value, sourceInformation); 1964 jumpTo(state.returnCollector, value, sourceInformation);
2040 } 1965 }
2041 1966
2042 /// Generate the body for a native function [function] that is annotated with 1967 /// Generate the body for a native function [function] that is annotated with
2043 /// an implementation in JavaScript (provided as string in [javaScriptCode]). 1968 /// an implementation in JavaScript (provided as string in [javaScriptCode]).
2044 void buildNativeFunctionBody( 1969 void buildNativeFunctionBody(FunctionElement function, String javaScriptCode,
2045 FunctionElement function,
2046 String javaScriptCode,
2047 SourceInformation sourceInformation) { 1970 SourceInformation sourceInformation) {
2048 NativeBehavior behavior = new NativeBehavior(); 1971 NativeBehavior behavior = new NativeBehavior();
2049 behavior.sideEffects.setAllSideEffects(); 1972 behavior.sideEffects.setAllSideEffects();
2050 // Generate a [ForeignCode] statement from the given native code. 1973 // Generate a [ForeignCode] statement from the given native code.
2051 buildForeignCode( 1974 buildForeignCode(
2052 js.js.statementTemplateYielding( 1975 js.js
2053 new js.LiteralStatement(javaScriptCode)), 1976 .statementTemplateYielding(new js.LiteralStatement(javaScriptCode)),
2054 <ir.Primitive>[], 1977 <ir.Primitive>[],
2055 behavior, 1978 behavior,
2056 sourceInformation); 1979 sourceInformation);
2057 } 1980 }
2058 1981
2059 /// Generate the body for a native function that redirects to a native 1982 /// Generate the body for a native function that redirects to a native
2060 /// JavaScript function, getter, or setter. 1983 /// JavaScript function, getter, or setter.
2061 /// 1984 ///
2062 /// Generates a call to the real target, which is given by [functions]'s 1985 /// Generates a call to the real target, which is given by [functions]'s
2063 /// `fixedBackendName`, passing all parameters as arguments. The target can 1986 /// `fixedBackendName`, passing all parameters as arguments. The target can
2064 /// be the JavaScript implementation of a function, getter, or setter. 1987 /// be the JavaScript implementation of a function, getter, or setter.
2065 void buildRedirectingNativeFunctionBody(FunctionElement function, 1988 void buildRedirectingNativeFunctionBody(FunctionElement function, String name,
2066 String name, 1989 SourceInformation sourceInformation) {
2067 SourceInformation sourceInformation) {
2068 List<ir.Primitive> arguments = <ir.Primitive>[]; 1990 List<ir.Primitive> arguments = <ir.Primitive>[];
2069 NativeBehavior behavior = new NativeBehavior(); 1991 NativeBehavior behavior = new NativeBehavior();
2070 behavior.sideEffects.setAllSideEffects(); 1992 behavior.sideEffects.setAllSideEffects();
2071 program.addNativeMethod(function); 1993 program.addNativeMethod(function);
2072 // Construct the access of the target element. 1994 // Construct the access of the target element.
2073 String code = function.isInstanceMember ? '#.$name' : name; 1995 String code = function.isInstanceMember ? '#.$name' : name;
2074 if (function.isInstanceMember) { 1996 if (function.isInstanceMember) {
2075 arguments.add(state.thisParameter); 1997 arguments.add(state.thisParameter);
2076 } 1998 }
2077 // Collect all parameters of the function and templates for them to be 1999 // Collect all parameters of the function and templates for them to be
2078 // inserted into the JavaScript code. 2000 // inserted into the JavaScript code.
2079 List<String> argumentTemplates = <String>[]; 2001 List<String> argumentTemplates = <String>[];
2080 function.functionSignature.forEachParameter((ParameterElement parameter) { 2002 function.functionSignature.forEachParameter((ParameterElement parameter) {
2081 ir.Primitive input = environment.lookup(parameter); 2003 ir.Primitive input = environment.lookup(parameter);
2082 DartType type = program.unaliasType(parameter.type); 2004 DartType type = program.unaliasType(parameter.type);
2083 if (type is FunctionType) { 2005 if (type is FunctionType) {
2084 // The parameter type is a function type either directly or through 2006 // The parameter type is a function type either directly or through
2085 // typedef(s). 2007 // typedef(s).
2086 ir.Constant arity = buildIntegerConstant(type.computeArity()); 2008 ir.Constant arity = buildIntegerConstant(type.computeArity());
2087 input = buildStaticFunctionInvocation( 2009 input = buildStaticFunctionInvocation(program.closureConverter,
2088 program.closureConverter, <ir.Primitive>[input, arity], 2010 <ir.Primitive>[input, arity], sourceInformation);
2089 sourceInformation);
2090 } 2011 }
2091 arguments.add(input); 2012 arguments.add(input);
2092 argumentTemplates.add('#'); 2013 argumentTemplates.add('#');
2093 }); 2014 });
2094 // Construct the application of parameters for functions and setters. 2015 // Construct the application of parameters for functions and setters.
2095 if (function.kind == ElementKind.FUNCTION) { 2016 if (function.kind == ElementKind.FUNCTION) {
2096 code = "$code(${argumentTemplates.join(', ')})"; 2017 code = "$code(${argumentTemplates.join(', ')})";
2097 } else if (function.kind == ElementKind.SETTER) { 2018 } else if (function.kind == ElementKind.SETTER) {
2098 code = "$code = ${argumentTemplates.single}"; 2019 code = "$code = ${argumentTemplates.single}";
2099 } else { 2020 } else {
2100 assert(argumentTemplates.isEmpty); 2021 assert(argumentTemplates.isEmpty);
2101 assert(function.kind == ElementKind.GETTER); 2022 assert(function.kind == ElementKind.GETTER);
2102 } 2023 }
2103 // Generate the [ForeignCode] expression and a return statement to return 2024 // Generate the [ForeignCode] expression and a return statement to return
2104 // its value. 2025 // its value.
2105 ir.Primitive value = buildForeignCode( 2026 ir.Primitive value = buildForeignCode(
2106 js.js.uncachedExpressionTemplate(code), 2027 js.js.uncachedExpressionTemplate(code),
2107 arguments, 2028 arguments,
2108 behavior, 2029 behavior,
2109 sourceInformation, 2030 sourceInformation,
2110 type: program.getTypeMaskForNativeFunction(function)); 2031 type: program.getTypeMaskForNativeFunction(function));
2111 buildReturn(value: value, sourceInformation: sourceInformation); 2032 buildReturn(value: value, sourceInformation: sourceInformation);
2112 } 2033 }
2113 2034
2114 static _isNotNull(ir.Primitive value) => 2035 static _isNotNull(ir.Primitive value) =>
2115 !(value is ir.Constant && value.value.isNull); 2036 !(value is ir.Constant && value.value.isNull);
2116 2037
2117 /// Builds a call to a resolved js-interop element. 2038 /// Builds a call to a resolved js-interop element.
2118 ir.Primitive buildInvokeJsInteropMember( 2039 ir.Primitive buildInvokeJsInteropMember(FunctionElement element,
2119 FunctionElement element, 2040 List<ir.Primitive> arguments, SourceInformation sourceInformation) {
2120 List<ir.Primitive> arguments,
2121 SourceInformation sourceInformation) {
2122 program.addNativeMethod(element); 2041 program.addNativeMethod(element);
2123 String target = program.getJsInteropTargetPath(element); 2042 String target = program.getJsInteropTargetPath(element);
2124 // Strip off trailing arguments that were not specified. 2043 // Strip off trailing arguments that were not specified.
2125 // TODO(jacobr,sigmund): assert that the trailing arguments are all null. 2044 // TODO(jacobr,sigmund): assert that the trailing arguments are all null.
2126 // TODO(jacobr): rewrite named arguments to an object literal matching 2045 // TODO(jacobr): rewrite named arguments to an object literal matching
2127 // the factory constructor case. 2046 // the factory constructor case.
2128 var inputs = arguments.where(_isNotNull).toList(); 2047 var inputs = arguments.where(_isNotNull).toList();
2129 2048
2130 var behavior = new NativeBehavior()..sideEffects.setAllSideEffects(); 2049 var behavior = new NativeBehavior()..sideEffects.setAllSideEffects();
2131 DartType type = element.isConstructor ? 2050 DartType type = element.isConstructor
2132 element.enclosingClass.thisType : element.type.returnType; 2051 ? element.enclosingClass.thisType
2052 : element.type.returnType;
2133 // Native behavior effects here are similar to native/behavior.dart. 2053 // Native behavior effects here are similar to native/behavior.dart.
2134 // The return type is dynamic if we don't trust js-interop type 2054 // The return type is dynamic if we don't trust js-interop type
2135 // declarations. 2055 // declarations.
2136 behavior.typesReturned.add( 2056 behavior.typesReturned.add(
2137 program.trustJSInteropTypeAnnotations ? type : const DynamicType()); 2057 program.trustJSInteropTypeAnnotations ? type : const DynamicType());
2138 2058
2139 // The allocation effects include the declared type if it is native (which 2059 // The allocation effects include the declared type if it is native (which
2140 // includes js interop types). 2060 // includes js interop types).
2141 if (type.element != null && program.isNative(type.element)) { 2061 if (type.element != null && program.isNative(type.element)) {
2142 behavior.typesInstantiated.add(type); 2062 behavior.typesInstantiated.add(type);
2143 } 2063 }
2144 2064
2145 // It also includes any other JS interop type if we don't trust the 2065 // It also includes any other JS interop type if we don't trust the
2146 // annotation or if is declared too broad. 2066 // annotation or if is declared too broad.
2147 if (!program.trustJSInteropTypeAnnotations || type.isObject || 2067 if (!program.trustJSInteropTypeAnnotations ||
2068 type.isObject ||
2148 type.isDynamic) { 2069 type.isDynamic) {
2149 behavior.typesInstantiated.add(program.jsJavascriptObjectType); 2070 behavior.typesInstantiated.add(program.jsJavascriptObjectType);
2150 } 2071 }
2151 2072
2152 String code; 2073 String code;
2153 if (element.isGetter) { 2074 if (element.isGetter) {
2154 code = target; 2075 code = target;
2155 } else if (element.isSetter) { 2076 } else if (element.isSetter) {
2156 code = "$target = #"; 2077 code = "$target = #";
2157 } else { 2078 } else {
2158 var args = new List.filled(inputs.length, '#').join(','); 2079 var args = new List.filled(inputs.length, '#').join(',');
2159 code = element.isConstructor ? "new $target($args)" : "$target($args)"; 2080 code = element.isConstructor ? "new $target($args)" : "$target($args)";
2160 } 2081 }
2161 return buildForeignCode(js.js.parseForeignJS(code), 2082 return buildForeignCode(
2162 inputs, behavior, sourceInformation); 2083 js.js.parseForeignJS(code), inputs, behavior, sourceInformation);
2163 // TODO(sigmund): should we record the source-information here? 2084 // TODO(sigmund): should we record the source-information here?
2164 } 2085 }
2165 2086
2166 /// Builds an object literal that results from invoking a factory constructor 2087 /// Builds an object literal that results from invoking a factory constructor
2167 /// of a js-interop anonymous type. 2088 /// of a js-interop anonymous type.
2168 ir.Primitive buildJsInteropObjectLiteral( 2089 ir.Primitive buildJsInteropObjectLiteral(ConstructorElement constructor,
2169 ConstructorElement constructor, 2090 List<ir.Primitive> arguments, SourceInformation sourceInformation) {
2170 List<ir.Primitive> arguments,
2171 SourceInformation sourceInformation) {
2172 assert(program.isJsInteropAnonymous(constructor)); 2091 assert(program.isJsInteropAnonymous(constructor));
2173 program.addNativeMethod(constructor); 2092 program.addNativeMethod(constructor);
2174 FunctionSignature params = constructor.functionSignature; 2093 FunctionSignature params = constructor.functionSignature;
2175 int i = 0; 2094 int i = 0;
2176 var filteredArguments = <ir.Primitive>[]; 2095 var filteredArguments = <ir.Primitive>[];
2177 var entries = new Map<String, js.Expression>(); 2096 var entries = new Map<String, js.Expression>();
2178 params.orderedForEachParameter((ParameterElement parameter) { 2097 params.orderedForEachParameter((ParameterElement parameter) {
2179 // TODO(jacobr): throw if parameter names do not match names of property 2098 // TODO(jacobr): throw if parameter names do not match names of property
2180 // names in the class. 2099 // names in the class.
2181 assert (parameter.isNamed); 2100 assert(parameter.isNamed);
2182 ir.Primitive argument = arguments[i++]; 2101 ir.Primitive argument = arguments[i++];
2183 if (_isNotNull(argument)) { 2102 if (_isNotNull(argument)) {
2184 filteredArguments.add(argument); 2103 filteredArguments.add(argument);
2185 entries[parameter.name] = 2104 entries[parameter.name] =
2186 new js.InterpolatedExpression(filteredArguments.length - 1); 2105 new js.InterpolatedExpression(filteredArguments.length - 1);
2187 } 2106 }
2188 }); 2107 });
2189 var code = new js.Template(null, js.objectLiteral(entries)); 2108 var code = new js.Template(null, js.objectLiteral(entries));
2190 var behavior = new NativeBehavior(); 2109 var behavior = new NativeBehavior();
2191 if (program.trustJSInteropTypeAnnotations) { 2110 if (program.trustJSInteropTypeAnnotations) {
(...skipping 21 matching lines...) Expand all
2213 // TODO(johnniwinther): Type [nodes] as `Iterable` when `NodeList` uses 2132 // TODO(johnniwinther): Type [nodes] as `Iterable` when `NodeList` uses
2214 // `List` instead of `Link`. 2133 // `List` instead of `Link`.
2215 void buildSequence(var nodes, BuildFunction build) { 2134 void buildSequence(var nodes, BuildFunction build) {
2216 for (var node in nodes) { 2135 for (var node in nodes) {
2217 if (!isOpen) return; 2136 if (!isOpen) return;
2218 build(node); 2137 build(node);
2219 } 2138 }
2220 } 2139 }
2221 2140
2222 /// Creates a labeled statement 2141 /// Creates a labeled statement
2223 void buildLabeledStatement({SubbuildFunction buildBody, 2142 void buildLabeledStatement({SubbuildFunction buildBody, JumpTarget target}) {
2224 JumpTarget target}) {
2225 JumpCollector join = new ForwardJumpCollector(environment, target: target); 2143 JumpCollector join = new ForwardJumpCollector(environment, target: target);
2226 IrBuilder innerBuilder = makeDelimitedBuilder(); 2144 IrBuilder innerBuilder = makeDelimitedBuilder();
2227 innerBuilder.state.breakCollectors.add(join); 2145 innerBuilder.state.breakCollectors.add(join);
2228 buildBody(innerBuilder); 2146 buildBody(innerBuilder);
2229 innerBuilder.state.breakCollectors.removeLast(); 2147 innerBuilder.state.breakCollectors.removeLast();
2230 bool hasBreaks = !join.isEmpty; 2148 bool hasBreaks = !join.isEmpty;
2231 if (hasBreaks) { 2149 if (hasBreaks) {
2232 if (innerBuilder.isOpen) innerBuilder.jumpTo(join); 2150 if (innerBuilder.isOpen) innerBuilder.jumpTo(join);
2233 add(new ir.LetCont(join.continuation, innerBuilder.root)); 2151 add(new ir.LetCont(join.continuation, innerBuilder.root));
2234 environment = join.environment; 2152 environment = join.environment;
(...skipping 15 matching lines...) Expand all
2250 } 2168 }
2251 2169
2252 // Build(ContinueStatement L, C) = C[InvokeContinuation(...)] 2170 // Build(ContinueStatement L, C) = C[InvokeContinuation(...)]
2253 // 2171 //
2254 // The continuation and arguments are filled in later after translating 2172 // The continuation and arguments are filled in later after translating
2255 // the body containing the continue. 2173 // the body containing the continue.
2256 bool buildContinue(JumpTarget target) { 2174 bool buildContinue(JumpTarget target) {
2257 return buildJumpInternal(target, state.continueCollectors); 2175 return buildJumpInternal(target, state.continueCollectors);
2258 } 2176 }
2259 2177
2260 bool buildJumpInternal(JumpTarget target, 2178 bool buildJumpInternal(
2261 Iterable<JumpCollector> collectors) { 2179 JumpTarget target, Iterable<JumpCollector> collectors) {
2262 assert(isOpen); 2180 assert(isOpen);
2263 for (JumpCollector collector in collectors) { 2181 for (JumpCollector collector in collectors) {
2264 if (target == collector.target) { 2182 if (target == collector.target) {
2265 jumpTo(collector); 2183 jumpTo(collector);
2266 return true; 2184 return true;
2267 } 2185 }
2268 } 2186 }
2269 return false; 2187 return false;
2270 } 2188 }
2271 2189
(...skipping 12 matching lines...) Expand all
2284 } 2202 }
2285 2203
2286 void buildRethrow() { 2204 void buildRethrow() {
2287 assert(isOpen); 2205 assert(isOpen);
2288 add(new ir.Rethrow()); 2206 add(new ir.Rethrow());
2289 _current = null; 2207 _current = null;
2290 } 2208 }
2291 2209
2292 /// Create a negation of [condition]. 2210 /// Create a negation of [condition].
2293 ir.Primitive buildNegation( 2211 ir.Primitive buildNegation(
2294 ir.Primitive condition, 2212 ir.Primitive condition, SourceInformation sourceInformation) {
2295 SourceInformation sourceInformation) {
2296 // ! e is translated as e ? false : true 2213 // ! e is translated as e ? false : true
2297 2214
2298 // Add a continuation parameter for the result of the expression. 2215 // Add a continuation parameter for the result of the expression.
2299 ir.Parameter resultParameter = new ir.Parameter(null); 2216 ir.Parameter resultParameter = new ir.Parameter(null);
2300 2217
2301 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]); 2218 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]);
2302 ir.Continuation thenContinuation = new ir.Continuation([]); 2219 ir.Continuation thenContinuation = new ir.Continuation([]);
2303 ir.Continuation elseContinuation = new ir.Continuation([]); 2220 ir.Continuation elseContinuation = new ir.Continuation([]);
2304 2221
2305 ir.Constant makeBoolConstant(bool value) { 2222 ir.Constant makeBoolConstant(bool value) {
2306 return new ir.Constant(state.constantSystem.createBool(value)); 2223 return new ir.Constant(state.constantSystem.createBool(value));
2307 } 2224 }
2308 2225
2309 ir.Constant trueConstant = makeBoolConstant(true); 2226 ir.Constant trueConstant = makeBoolConstant(true);
2310 ir.Constant falseConstant = makeBoolConstant(false); 2227 ir.Constant falseConstant = makeBoolConstant(false);
2311 2228
2312 thenContinuation.body = new ir.LetPrim(falseConstant) 2229 thenContinuation.body = new ir.LetPrim(falseConstant)
2313 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); 2230 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant]));
2314 elseContinuation.body = new ir.LetPrim(trueConstant) 2231 elseContinuation.body = new ir.LetPrim(trueConstant)
2315 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); 2232 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant]));
2316 2233
2317 add(new ir.LetCont(joinContinuation, 2234 add(new ir.LetCont(
2318 new ir.LetCont.two(thenContinuation, elseContinuation, 2235 joinContinuation,
2319 new ir.Branch.strict(condition, 2236 new ir.LetCont.two(
2320 thenContinuation, 2237 thenContinuation,
2321 elseContinuation, 2238 elseContinuation,
2322 sourceInformation)))); 2239 new ir.Branch.strict(condition, thenContinuation, elseContinuation,
2240 sourceInformation))));
2323 return resultParameter; 2241 return resultParameter;
2324 } 2242 }
2325 2243
2326 /// Create a lazy and/or expression. [leftValue] is the value of the left 2244 /// Create a lazy and/or expression. [leftValue] is the value of the left
2327 /// operand and [buildRightValue] is called to process the value of the right 2245 /// operand and [buildRightValue] is called to process the value of the right
2328 /// operand in the context of its own [IrBuilder]. 2246 /// operand in the context of its own [IrBuilder].
2329 ir.Primitive buildLogicalOperator( 2247 ir.Primitive buildLogicalOperator(
2330 ir.Primitive leftValue, 2248 ir.Primitive leftValue,
2331 ir.Primitive buildRightValue(IrBuilder builder), 2249 ir.Primitive buildRightValue(IrBuilder builder),
2332 SourceInformation sourceInformation, 2250 SourceInformation sourceInformation,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2369 emptyBuilder.jumpTo(join, leftBool); 2287 emptyBuilder.jumpTo(join, leftBool);
2370 rightTrueBuilder.jumpTo(join, rightTrue); 2288 rightTrueBuilder.jumpTo(join, rightTrue);
2371 rightFalseBuilder.jumpTo(join, rightFalse); 2289 rightFalseBuilder.jumpTo(join, rightFalse);
2372 ir.Continuation leftTrueContinuation = new ir.Continuation([]); 2290 ir.Continuation leftTrueContinuation = new ir.Continuation([]);
2373 ir.Continuation leftFalseContinuation = new ir.Continuation([]); 2291 ir.Continuation leftFalseContinuation = new ir.Continuation([]);
2374 ir.Continuation rightTrueContinuation = new ir.Continuation([]); 2292 ir.Continuation rightTrueContinuation = new ir.Continuation([]);
2375 ir.Continuation rightFalseContinuation = new ir.Continuation([]); 2293 ir.Continuation rightFalseContinuation = new ir.Continuation([]);
2376 rightTrueContinuation.body = rightTrueBuilder.root; 2294 rightTrueContinuation.body = rightTrueBuilder.root;
2377 rightFalseContinuation.body = rightFalseBuilder.root; 2295 rightFalseContinuation.body = rightFalseBuilder.root;
2378 // The right subexpression has two continuations. 2296 // The right subexpression has two continuations.
2379 rightBuilder.add( 2297 rightBuilder.add(new ir.LetCont.two(
2380 new ir.LetCont.two(rightTrueContinuation, rightFalseContinuation, 2298 rightTrueContinuation,
2381 new ir.Branch.strict(rightValue, 2299 rightFalseContinuation,
2382 rightTrueContinuation, 2300 new ir.Branch.strict(rightValue, rightTrueContinuation,
2383 rightFalseContinuation, 2301 rightFalseContinuation, sourceInformation)));
2384 sourceInformation)));
2385 // Depending on the operator, the left subexpression's continuations are 2302 // Depending on the operator, the left subexpression's continuations are
2386 // either the right subexpression or an invocation of the join-point 2303 // either the right subexpression or an invocation of the join-point
2387 // continuation. 2304 // continuation.
2388 if (isLazyOr) { 2305 if (isLazyOr) {
2389 leftTrueContinuation.body = emptyBuilder.root; 2306 leftTrueContinuation.body = emptyBuilder.root;
2390 leftFalseContinuation.body = rightBuilder.root; 2307 leftFalseContinuation.body = rightBuilder.root;
2391 } else { 2308 } else {
2392 leftTrueContinuation.body = rightBuilder.root; 2309 leftTrueContinuation.body = rightBuilder.root;
2393 leftFalseContinuation.body = emptyBuilder.root; 2310 leftFalseContinuation.body = emptyBuilder.root;
2394 } 2311 }
2395 2312
2396 add(new ir.LetCont(join.continuation, 2313 add(new ir.LetCont(
2397 new ir.LetCont.two(leftTrueContinuation, leftFalseContinuation, 2314 join.continuation,
2398 new ir.Branch.strict(leftValue, 2315 new ir.LetCont.two(
2399 leftTrueContinuation, 2316 leftTrueContinuation,
2400 leftFalseContinuation, 2317 leftFalseContinuation,
2401 sourceInformation)))); 2318 new ir.Branch.strict(leftValue, leftTrueContinuation,
2319 leftFalseContinuation, sourceInformation))));
2402 environment = join.environment; 2320 environment = join.environment;
2403 return environment.discard(1); 2321 return environment.discard(1);
2404 } 2322 }
2405 2323
2406 ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y, 2324 ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y,
2407 {SourceInformation sourceInformation}) { 2325 {SourceInformation sourceInformation}) {
2408 return addPrimitive(new ir.ApplyBuiltinOperator( 2326 return addPrimitive(new ir.ApplyBuiltinOperator(
2409 ir.BuiltinOperator.Identical, <ir.Primitive>[x, y], 2327 ir.BuiltinOperator.Identical, <ir.Primitive>[x, y], sourceInformation));
2410 sourceInformation));
2411 } 2328 }
2412 2329
2413 /// Called when entering a nested function with free variables. 2330 /// Called when entering a nested function with free variables.
2414 /// 2331 ///
2415 /// The free variables must subsequently be accessible using [buildLocalGet] 2332 /// The free variables must subsequently be accessible using [buildLocalGet]
2416 /// and [buildLocalSet]. 2333 /// and [buildLocalSet].
2417 void _enterClosureEnvironment(ClosureEnvironment env) { 2334 void _enterClosureEnvironment(ClosureEnvironment env) {
2418 if (env == null) return; 2335 if (env == null) return;
2419 2336
2420 // Obtain a reference to the function object (this). 2337 // Obtain a reference to the function object (this).
2421 ir.Parameter thisPrim = state.thisParameter; 2338 ir.Parameter thisPrim = state.thisParameter;
2422 2339
2423 // Obtain access to the free variables. 2340 // Obtain access to the free variables.
2424 env.freeVariables.forEach((Local local, ClosureLocation location) { 2341 env.freeVariables.forEach((Local local, ClosureLocation location) {
2425 if (location.isBox) { 2342 if (location.isBox) {
2426 // Boxed variables are loaded from their box on-demand. 2343 // Boxed variables are loaded from their box on-demand.
2427 state.boxedVariables[local] = location; 2344 state.boxedVariables[local] = location;
2428 } else { 2345 } else {
2429 // Unboxed variables are loaded from the function object immediately. 2346 // Unboxed variables are loaded from the function object immediately.
2430 // This includes BoxLocals which are themselves unboxed variables. 2347 // This includes BoxLocals which are themselves unboxed variables.
2431 environment.extend(local, 2348 environment.extend(
2432 addPrimitive(new ir.GetField(thisPrim, location.field))); 2349 local, addPrimitive(new ir.GetField(thisPrim, location.field)));
2433 } 2350 }
2434 }); 2351 });
2435 2352
2436 // If the function captures a reference to the receiver from the 2353 // If the function captures a reference to the receiver from the
2437 // enclosing method, remember which primitive refers to the receiver object. 2354 // enclosing method, remember which primitive refers to the receiver object.
2438 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) { 2355 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) {
2439 state.enclosingThis = environment.lookup(env.thisLocal); 2356 state.enclosingThis = environment.lookup(env.thisLocal);
2440 } 2357 }
2441 2358
2442 // If the function has a self-reference, use the value of `this`. 2359 // If the function has a self-reference, use the value of `this`.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2475 2392
2476 /// Add the given function parameter to the IR, and bind it in the environment 2393 /// Add the given function parameter to the IR, and bind it in the environment
2477 /// or put it in its box, if necessary. 2394 /// or put it in its box, if necessary.
2478 void _createFunctionParameter(Local parameterElement) { 2395 void _createFunctionParameter(Local parameterElement) {
2479 ir.Parameter parameter = new ir.Parameter(parameterElement); 2396 ir.Parameter parameter = new ir.Parameter(parameterElement);
2480 _parameters.add(parameter); 2397 _parameters.add(parameter);
2481 state.functionParameters.add(parameter); 2398 state.functionParameters.add(parameter);
2482 ClosureLocation location = state.boxedVariables[parameterElement]; 2399 ClosureLocation location = state.boxedVariables[parameterElement];
2483 if (location != null) { 2400 if (location != null) {
2484 addPrimitive(new ir.SetField( 2401 addPrimitive(new ir.SetField(
2485 environment.lookup(location.box), 2402 environment.lookup(location.box), location.field, parameter));
2486 location.field,
2487 parameter));
2488 } else { 2403 } else {
2489 environment.extend(parameterElement, parameter); 2404 environment.extend(parameterElement, parameter);
2490 } 2405 }
2491 } 2406 }
2492 2407
2493 void _createThisParameter() { 2408 void _createThisParameter() {
2494 assert(state.thisParameter == null); 2409 assert(state.thisParameter == null);
2495 if (Elements.isStaticOrTopLevel(state.currentElement)) return; 2410 if (Elements.isStaticOrTopLevel(state.currentElement)) return;
2496 if (state.currentElement.isLocal) return; 2411 if (state.currentElement.isLocal) return;
2497 state.thisParameter = 2412 state.thisParameter =
2498 new ir.Parameter(new ThisParameterLocal(state.currentElement)); 2413 new ir.Parameter(new ThisParameterLocal(state.currentElement));
2499 } 2414 }
2500 2415
2501 void declareLocalVariable(LocalElement variableElement, 2416 void declareLocalVariable(LocalElement variableElement,
2502 {ir.Primitive initialValue}) { 2417 {ir.Primitive initialValue}) {
2503 assert(isOpen); 2418 assert(isOpen);
2504 if (initialValue == null) { 2419 if (initialValue == null) {
2505 initialValue = buildNullConstant(); 2420 initialValue = buildNullConstant();
2506 } 2421 }
2507 ClosureLocation location = state.boxedVariables[variableElement]; 2422 ClosureLocation location = state.boxedVariables[variableElement];
2508 if (location != null) { 2423 if (location != null) {
2509 addPrimitive(new ir.SetField( 2424 addPrimitive(new ir.SetField(
2510 environment.lookup(location.box), 2425 environment.lookup(location.box), location.field, initialValue));
2511 location.field,
2512 initialValue));
2513 } else if (isInMutableVariable(variableElement)) { 2426 } else if (isInMutableVariable(variableElement)) {
2514 add(new ir.LetMutable( 2427 add(new ir.LetMutable(getMutableVariable(variableElement), initialValue));
2515 getMutableVariable(variableElement),
2516 initialValue));
2517 } else { 2428 } else {
2518 initialValue.useElementAsHint(variableElement); 2429 initialValue.useElementAsHint(variableElement);
2519 environment.extend(variableElement, initialValue); 2430 environment.extend(variableElement, initialValue);
2520 } 2431 }
2521 } 2432 }
2522 2433
2523 /// Add [functionElement] to the environment with provided [definition]. 2434 /// Add [functionElement] to the environment with provided [definition].
2524 void declareLocalFunction(LocalFunctionElement functionElement, 2435 void declareLocalFunction(
2525 closure.ClosureClassElement classElement, 2436 LocalFunctionElement functionElement,
2526 SourceInformation sourceInformation) { 2437 closure.ClosureClassElement classElement,
2438 SourceInformation sourceInformation) {
2527 ir.Primitive closure = 2439 ir.Primitive closure =
2528 buildFunctionExpression(classElement, sourceInformation); 2440 buildFunctionExpression(classElement, sourceInformation);
2529 declareLocalVariable(functionElement, initialValue: closure); 2441 declareLocalVariable(functionElement, initialValue: closure);
2530 } 2442 }
2531 2443
2532 ir.Primitive buildFunctionExpression(closure.ClosureClassElement classElement, 2444 ir.Primitive buildFunctionExpression(closure.ClosureClassElement classElement,
2533 SourceInformation sourceInformation) { 2445 SourceInformation sourceInformation) {
2534 List<ir.Primitive> arguments = <ir.Primitive>[]; 2446 List<ir.Primitive> arguments = <ir.Primitive>[];
2535 for (closure.ClosureFieldElement field in classElement.closureFields) { 2447 for (closure.ClosureFieldElement field in classElement.closureFields) {
2536 // Captured 'this' and type variables are not always available as locals 2448 // Captured 'this' and type variables are not always available as locals
2537 // in the environment, so treat those specially. 2449 // in the environment, so treat those specially.
2538 ir.Primitive value; 2450 ir.Primitive value;
2539 if (field.local is closure.ThisLocal) { 2451 if (field.local is closure.ThisLocal) {
2540 value = buildThis(); 2452 value = buildThis();
2541 } else if (field.local is closure.TypeVariableLocal) { 2453 } else if (field.local is closure.TypeVariableLocal) {
2542 closure.TypeVariableLocal variable = field.local; 2454 closure.TypeVariableLocal variable = field.local;
2543 value = buildTypeVariableAccess(variable.typeVariable); 2455 value = buildTypeVariableAccess(variable.typeVariable);
2544 } else { 2456 } else {
2545 value = environment.lookup(field.local); 2457 value = environment.lookup(field.local);
2546 } 2458 }
2547 arguments.add(value); 2459 arguments.add(value);
2548 } 2460 }
2549 return addPrimitive(new ir.CreateInstance( 2461 return addPrimitive(new ir.CreateInstance(
2550 classElement, arguments, null, sourceInformation)); 2462 classElement, arguments, null, sourceInformation));
2551 } 2463 }
2552 2464
2553 /// Create a read access of [local] function, variable, or parameter. 2465 /// Create a read access of [local] function, variable, or parameter.
2554 // TODO(johnniwinther): Make [sourceInformation] mandatory. 2466 // TODO(johnniwinther): Make [sourceInformation] mandatory.
2555 ir.Primitive buildLocalGet( 2467 ir.Primitive buildLocalGet(LocalElement local,
2556 LocalElement local,
2557 {SourceInformation sourceInformation}) { 2468 {SourceInformation sourceInformation}) {
2558 assert(isOpen); 2469 assert(isOpen);
2559 ClosureLocation location = state.boxedVariables[local]; 2470 ClosureLocation location = state.boxedVariables[local];
2560 if (location != null) { 2471 if (location != null) {
2561 ir.Primitive result = new ir.GetField( 2472 ir.Primitive result = new ir.GetField(
2562 environment.lookup(location.box), 2473 environment.lookup(location.box), location.field,
2563 location.field,
2564 sourceInformation: sourceInformation); 2474 sourceInformation: sourceInformation);
2565 result.useElementAsHint(local); 2475 result.useElementAsHint(local);
2566 return addPrimitive(result); 2476 return addPrimitive(result);
2567 } else if (isInMutableVariable(local)) { 2477 } else if (isInMutableVariable(local)) {
2568 return addPrimitive( 2478 return addPrimitive(new ir.GetMutable(getMutableVariable(local),
2569 new ir.GetMutable( 2479 sourceInformation: sourceInformation));
2570 getMutableVariable(local), sourceInformation: sourceInformation));
2571 } else { 2480 } else {
2572 return environment.lookup(local); 2481 return environment.lookup(local);
2573 } 2482 }
2574 } 2483 }
2575 2484
2576 /// Create a write access to [local] variable or parameter with the provided 2485 /// Create a write access to [local] variable or parameter with the provided
2577 /// [value]. 2486 /// [value].
2578 ir.Primitive buildLocalVariableSet( 2487 ir.Primitive buildLocalVariableSet(LocalElement local, ir.Primitive value,
2579 LocalElement local,
2580 ir.Primitive value,
2581 SourceInformation sourceInformation) { 2488 SourceInformation sourceInformation) {
2582 assert(isOpen); 2489 assert(isOpen);
2583 ClosureLocation location = state.boxedVariables[local]; 2490 ClosureLocation location = state.boxedVariables[local];
2584 if (location != null) { 2491 if (location != null) {
2585 addPrimitive(new ir.SetField( 2492 addPrimitive(new ir.SetField(
2586 environment.lookup(location.box), 2493 environment.lookup(location.box), location.field, value,
2587 location.field,
2588 value,
2589 sourceInformation: sourceInformation)); 2494 sourceInformation: sourceInformation));
2590 } else if (isInMutableVariable(local)) { 2495 } else if (isInMutableVariable(local)) {
2591 addPrimitive(new ir.SetMutable( 2496 addPrimitive(new ir.SetMutable(getMutableVariable(local), value,
2592 getMutableVariable(local),
2593 value,
2594 sourceInformation: sourceInformation)); 2497 sourceInformation: sourceInformation));
2595 } else { 2498 } else {
2596 value.useElementAsHint(local); 2499 value.useElementAsHint(local);
2597 environment.update(local, value); 2500 environment.update(local, value);
2598 } 2501 }
2599 return value; 2502 return value;
2600 } 2503 }
2601 2504
2602 /// Called before building the initializer of a for-loop. 2505 /// Called before building the initializer of a for-loop.
2603 /// 2506 ///
2604 /// The loop variables will subsequently be declared using 2507 /// The loop variables will subsequently be declared using
2605 /// [declareLocalVariable]. 2508 /// [declareLocalVariable].
2606 void _enterForLoopInitializer(ClosureScope scope, 2509 void _enterForLoopInitializer(
2607 List<LocalElement> loopVariables) { 2510 ClosureScope scope, List<LocalElement> loopVariables) {
2608 if (scope == null) return; 2511 if (scope == null) return;
2609 // If there are no boxed loop variables, don't create the box here, let 2512 // If there are no boxed loop variables, don't create the box here, let
2610 // it be created inside the body instead. 2513 // it be created inside the body instead.
2611 if (scope.boxedLoopVariables.isEmpty) return; 2514 if (scope.boxedLoopVariables.isEmpty) return;
2612 _enterScope(scope); 2515 _enterScope(scope);
2613 } 2516 }
2614 2517
2615 /// Called before building the body of a for-loop. 2518 /// Called before building the body of a for-loop.
2616 void _enterForLoopBody(ClosureScope scope, 2519 void _enterForLoopBody(ClosureScope scope, List<LocalElement> loopVariables) {
2617 List<LocalElement> loopVariables) {
2618 if (scope == null) return; 2520 if (scope == null) return;
2619 // If there are boxed loop variables, the box has already been created 2521 // If there are boxed loop variables, the box has already been created
2620 // at the initializer. 2522 // at the initializer.
2621 if (!scope.boxedLoopVariables.isEmpty) return; 2523 if (!scope.boxedLoopVariables.isEmpty) return;
2622 _enterScope(scope); 2524 _enterScope(scope);
2623 } 2525 }
2624 2526
2625 /// Called before building the update of a for-loop. 2527 /// Called before building the update of a for-loop.
2626 void _enterForLoopUpdate(ClosureScope scope, 2528 void _enterForLoopUpdate(
2627 List<LocalElement> loopVariables) { 2529 ClosureScope scope, List<LocalElement> loopVariables) {
2628 if (scope == null) return; 2530 if (scope == null) return;
2629 // If there are no boxed loop variables, then the box is created inside the 2531 // If there are no boxed loop variables, then the box is created inside the
2630 // body, so there is no need to explicitly renew it. 2532 // body, so there is no need to explicitly renew it.
2631 if (scope.boxedLoopVariables.isEmpty) return; 2533 if (scope.boxedLoopVariables.isEmpty) return;
2632 ir.Primitive box = environment.lookup(scope.box); 2534 ir.Primitive box = environment.lookup(scope.box);
2633 ir.Primitive newBox = addPrimitive(new ir.CreateBox()); 2535 ir.Primitive newBox = addPrimitive(new ir.CreateBox());
2634 newBox.useElementAsHint(scope.box); 2536 newBox.useElementAsHint(scope.box);
2635 for (VariableElement loopVar in scope.boxedLoopVariables) { 2537 for (VariableElement loopVar in scope.boxedLoopVariables) {
2636 ClosureLocation location = scope.capturedVariables[loopVar]; 2538 ClosureLocation location = scope.capturedVariables[loopVar];
2637 ir.Primitive value = addPrimitive(new ir.GetField(box, location.field)); 2539 ir.Primitive value = addPrimitive(new ir.GetField(box, location.field));
2638 addPrimitive(new ir.SetField(newBox, location.field, value)); 2540 addPrimitive(new ir.SetField(newBox, location.field, value));
2639 } 2541 }
2640 environment.update(scope.box, newBox); 2542 environment.update(scope.box, newBox);
2641 } 2543 }
2642 2544
2643 /// Creates an access to the receiver from the current (or enclosing) method. 2545 /// Creates an access to the receiver from the current (or enclosing) method.
2644 /// 2546 ///
2645 /// If inside a closure class, [buildThis] will redirect access through 2547 /// If inside a closure class, [buildThis] will redirect access through
2646 /// closure fields in order to access the receiver from the enclosing method. 2548 /// closure fields in order to access the receiver from the enclosing method.
2647 ir.Primitive buildThis() { 2549 ir.Primitive buildThis() {
2648 if (state.enclosingThis != null) return state.enclosingThis; 2550 if (state.enclosingThis != null) return state.enclosingThis;
2649 assert(state.thisParameter != null); 2551 assert(state.thisParameter != null);
2650 return state.thisParameter; 2552 return state.thisParameter;
2651 } 2553 }
2652 2554
2653 ir.Primitive buildFieldGet( 2555 ir.Primitive buildFieldGet(ir.Primitive receiver, FieldElement target,
2654 ir.Primitive receiver,
2655 FieldElement target,
2656 SourceInformation sourceInformation) { 2556 SourceInformation sourceInformation) {
2657 return addPrimitive(new ir.GetField(receiver, target, 2557 return addPrimitive(new ir.GetField(receiver, target,
2658 sourceInformation: sourceInformation, 2558 sourceInformation: sourceInformation,
2659 isFinal: program.fieldNeverChanges(target))); 2559 isFinal: program.fieldNeverChanges(target)));
2660 } 2560 }
2661 2561
2662 void buildFieldSet(ir.Primitive receiver, 2562 void buildFieldSet(ir.Primitive receiver, FieldElement target,
2663 FieldElement target, 2563 ir.Primitive value, SourceInformation sourceInformation) {
2664 ir.Primitive value, 2564 addPrimitive(new ir.SetField(receiver, target, value,
2665 SourceInformation sourceInformation) { 2565 sourceInformation: sourceInformation));
2666 addPrimitive(new ir.SetField(
2667 receiver, target, value, sourceInformation: sourceInformation));
2668 } 2566 }
2669 2567
2670 ir.Primitive buildSuperFieldGet( 2568 ir.Primitive buildSuperFieldGet(
2671 FieldElement target, 2569 FieldElement target, SourceInformation sourceInformation) {
2672 SourceInformation sourceInformation) { 2570 return addPrimitive(new ir.GetField(buildThis(), target,
2673 return addPrimitive( 2571 sourceInformation: sourceInformation));
2674 new ir.GetField(
2675 buildThis(), target, sourceInformation: sourceInformation));
2676 } 2572 }
2677 2573
2678 ir.Primitive buildSuperFieldSet( 2574 ir.Primitive buildSuperFieldSet(FieldElement target, ir.Primitive value,
2679 FieldElement target,
2680 ir.Primitive value,
2681 SourceInformation sourceInformation) { 2575 SourceInformation sourceInformation) {
2682 addPrimitive( 2576 addPrimitive(new ir.SetField(buildThis(), target, value,
2683 new ir.SetField( 2577 sourceInformation: sourceInformation));
2684 buildThis(), target, value, sourceInformation: sourceInformation));
2685 return value; 2578 return value;
2686 } 2579 }
2687 2580
2688 /// Loads parameters to a constructor body into the environment. 2581 /// Loads parameters to a constructor body into the environment.
2689 /// 2582 ///
2690 /// The header for a constructor body differs from other functions in that 2583 /// The header for a constructor body differs from other functions in that
2691 /// some parameters are already boxed, and the box is passed as an argument 2584 /// some parameters are already boxed, and the box is passed as an argument
2692 /// instead of being created in the header. 2585 /// instead of being created in the header.
2693 void buildConstructorBodyHeader(Iterable<Local> parameters, 2586 void buildConstructorBodyHeader(
2694 ClosureScope closureScope) { 2587 Iterable<Local> parameters, ClosureScope closureScope) {
2695 _createThisParameter(); 2588 _createThisParameter();
2696 for (Local param in parameters) { 2589 for (Local param in parameters) {
2697 ir.Parameter parameter = _createLocalParameter(param); 2590 ir.Parameter parameter = _createLocalParameter(param);
2698 state.functionParameters.add(parameter); 2591 state.functionParameters.add(parameter);
2699 } 2592 }
2700 if (closureScope != null) { 2593 if (closureScope != null) {
2701 state.boxedVariables.addAll(closureScope.capturedVariables); 2594 state.boxedVariables.addAll(closureScope.capturedVariables);
2702 } 2595 }
2703 } 2596 }
2704 2597
(...skipping 19 matching lines...) Expand all
2724 return buildInvokeJsInteropMember(element, arguments, sourceInformation); 2617 return buildInvokeJsInteropMember(element, arguments, sourceInformation);
2725 } 2618 }
2726 if (program.requiresRuntimeTypesFor(cls)) { 2619 if (program.requiresRuntimeTypesFor(cls)) {
2727 InterfaceType interface = type; 2620 InterfaceType interface = type;
2728 Iterable<ir.Primitive> typeArguments = 2621 Iterable<ir.Primitive> typeArguments =
2729 interface.typeArguments.map((DartType argument) { 2622 interface.typeArguments.map((DartType argument) {
2730 return type.treatAsRaw 2623 return type.treatAsRaw
2731 ? buildNullConstant() 2624 ? buildNullConstant()
2732 : buildTypeExpression(argument); 2625 : buildTypeExpression(argument);
2733 }); 2626 });
2734 arguments = new List<ir.Primitive>.from(arguments) 2627 arguments = new List<ir.Primitive>.from(arguments)..addAll(typeArguments);
2735 ..addAll(typeArguments);
2736 } 2628 }
2737 return addPrimitive(new ir.InvokeConstructor( 2629 return addPrimitive(new ir.InvokeConstructor(
2738 type, element, selector, arguments, sourceInformation, 2630 type, element, selector, arguments, sourceInformation,
2739 allocationSiteType: allocationSiteType)); 2631 allocationSiteType: allocationSiteType));
2740 } 2632 }
2741 2633
2742 ir.Primitive buildTypeExpression(DartType type) { 2634 ir.Primitive buildTypeExpression(DartType type) {
2743 type = program.unaliasType(type); 2635 type = program.unaliasType(type);
2744 if (type is TypeVariableType) { 2636 if (type is TypeVariableType) {
2745 return buildTypeVariableAccess(type); 2637 return buildTypeVariableAccess(type);
2746 } else if (type is InterfaceType || type is FunctionType) { 2638 } else if (type is InterfaceType || type is FunctionType) {
2747 List<ir.Primitive> arguments = <ir.Primitive>[]; 2639 List<ir.Primitive> arguments = <ir.Primitive>[];
2748 type.forEachTypeVariable((TypeVariableType variable) { 2640 type.forEachTypeVariable((TypeVariableType variable) {
2749 ir.Primitive value = buildTypeVariableAccess(variable); 2641 ir.Primitive value = buildTypeVariableAccess(variable);
2750 arguments.add(value); 2642 arguments.add(value);
2751 }); 2643 });
2752 return addPrimitive(new ir.TypeExpression(ir.TypeExpressionKind.COMPLETE, 2644 return addPrimitive(new ir.TypeExpression(
2753 type, arguments)); 2645 ir.TypeExpressionKind.COMPLETE, type, arguments));
2754 } else if (type.treatAsDynamic) { 2646 } else if (type.treatAsDynamic) {
2755 return buildNullConstant(); 2647 return buildNullConstant();
2756 } else { 2648 } else {
2757 // TypedefType can reach here, and possibly other things. 2649 // TypedefType can reach here, and possibly other things.
2758 throw 'unimplemented translation of type expression $type (${type.kind})'; 2650 throw 'unimplemented translation of type expression $type (${type.kind})';
2759 } 2651 }
2760 } 2652 }
2761 2653
2762 /// Obtains the internal type representation of the type held in [variable]. 2654 /// Obtains the internal type representation of the type held in [variable].
2763 /// 2655 ///
2764 /// The value of [variable] is taken from the current receiver object, or 2656 /// The value of [variable] is taken from the current receiver object, or
2765 /// if we are currently building a constructor field initializer, from the 2657 /// if we are currently building a constructor field initializer, from the
2766 /// corresponding type argument (field initializers are evaluated before the 2658 /// corresponding type argument (field initializers are evaluated before the
2767 /// receiver object is created). 2659 /// receiver object is created).
2768 ir.Primitive buildTypeVariableAccess(TypeVariableType variable, 2660 ir.Primitive buildTypeVariableAccess(TypeVariableType variable,
2769 {SourceInformation sourceInformation}) { 2661 {SourceInformation sourceInformation}) {
2770 // If the local exists in the environment, use that. 2662 // If the local exists in the environment, use that.
2771 // This is put here when we are inside a constructor or field initializer, 2663 // This is put here when we are inside a constructor or field initializer,
2772 // (or possibly a closure inside one of these). 2664 // (or possibly a closure inside one of these).
2773 Local local = new closure.TypeVariableLocal(variable, state.currentElement); 2665 Local local = new closure.TypeVariableLocal(variable, state.currentElement);
2774 if (environment.contains(local)) { 2666 if (environment.contains(local)) {
2775 return environment.lookup(local); 2667 return environment.lookup(local);
2776 } 2668 }
2777 2669
2778 // If the type variable is not in a local, read its value from the 2670 // If the type variable is not in a local, read its value from the
2779 // receiver object. 2671 // receiver object.
2780 ir.Primitive target = buildThis(); 2672 ir.Primitive target = buildThis();
2781 return addPrimitive( 2673 return addPrimitive(
2782 new ir.ReadTypeVariable(variable, target, sourceInformation)); 2674 new ir.ReadTypeVariable(variable, target, sourceInformation));
2783 } 2675 }
2784 2676
2785 /// Make the given type variable accessible through the local environment 2677 /// Make the given type variable accessible through the local environment
2786 /// with the value of [binding]. 2678 /// with the value of [binding].
2787 void declareTypeVariable(TypeVariableType variable, DartType binding) { 2679 void declareTypeVariable(TypeVariableType variable, DartType binding) {
2788 environment.extend( 2680 environment.extend(
2789 new closure.TypeVariableLocal(variable, state.currentElement), 2681 new closure.TypeVariableLocal(variable, state.currentElement),
2790 buildTypeExpression(binding)); 2682 buildTypeExpression(binding));
2791 } 2683 }
2792 2684
2793 /// Reifies the value of [variable] on the current receiver object. 2685 /// Reifies the value of [variable] on the current receiver object.
2794 ir.Primitive buildReifyTypeVariable(TypeVariableType variable, 2686 ir.Primitive buildReifyTypeVariable(
2795 SourceInformation sourceInformation) { 2687 TypeVariableType variable, SourceInformation sourceInformation) {
2796 ir.Primitive typeArgument = 2688 ir.Primitive typeArgument =
2797 buildTypeVariableAccess(variable, sourceInformation: sourceInformation); 2689 buildTypeVariableAccess(variable, sourceInformation: sourceInformation);
2798 return addPrimitive( 2690 return addPrimitive(
2799 new ir.ReifyRuntimeType(typeArgument, sourceInformation)); 2691 new ir.ReifyRuntimeType(typeArgument, sourceInformation));
2800 } 2692 }
2801 2693
2802 ir.Primitive buildInvocationMirror(Selector selector, 2694 ir.Primitive buildInvocationMirror(
2803 List<ir.Primitive> arguments) { 2695 Selector selector, List<ir.Primitive> arguments) {
2804 return addPrimitive(new ir.CreateInvocationMirror(selector, arguments)); 2696 return addPrimitive(new ir.CreateInvocationMirror(selector, arguments));
2805 } 2697 }
2806 2698
2807 ir.Primitive buildForeignCode(js.Template codeTemplate, 2699 ir.Primitive buildForeignCode(
2808 List<ir.Primitive> arguments, 2700 js.Template codeTemplate,
2809 NativeBehavior behavior, 2701 List<ir.Primitive> arguments,
2810 SourceInformation sourceInformation, 2702 NativeBehavior behavior,
2811 {Element dependency, 2703 SourceInformation sourceInformation,
2812 TypeMask type}) { 2704 {Element dependency,
2705 TypeMask type}) {
2813 assert(behavior != null); 2706 assert(behavior != null);
2814 if (type == null) { 2707 if (type == null) {
2815 type = program.getTypeMaskForForeign(behavior); 2708 type = program.getTypeMaskForForeign(behavior);
2816 } 2709 }
2817 if (js.isIdentityTemplate(codeTemplate) && !program.isArrayType(type)) { 2710 if (js.isIdentityTemplate(codeTemplate) && !program.isArrayType(type)) {
2818 // JS expression is just a refinement. 2711 // JS expression is just a refinement.
2819 // Do not do this for arrays - those are special because array types can 2712 // Do not do this for arrays - those are special because array types can
2820 // change after creation. The input and output must therefore be modeled 2713 // change after creation. The input and output must therefore be modeled
2821 // as distinct values. 2714 // as distinct values.
2822 return addPrimitive(new ir.Refinement(arguments.single, type)); 2715 return addPrimitive(new ir.Refinement(arguments.single, type));
2823 } 2716 }
2824 ir.Primitive result = addPrimitive(new ir.ForeignCode( 2717 ir.Primitive result = addPrimitive(new ir.ForeignCode(
2825 codeTemplate, 2718 codeTemplate, type, arguments, behavior, sourceInformation,
2826 type,
2827 arguments,
2828 behavior,
2829 sourceInformation,
2830 dependency: dependency)); 2719 dependency: dependency));
2831 if (!codeTemplate.isExpression) { 2720 if (!codeTemplate.isExpression) {
2832 // Close the term if this is a "throw" expression or native body. 2721 // Close the term if this is a "throw" expression or native body.
2833 add(new ir.Unreachable()); 2722 add(new ir.Unreachable());
2834 _current = null; 2723 _current = null;
2835 } 2724 }
2836 return result; 2725 return result;
2837 } 2726 }
2838 2727
2839 /// Creates a type test or type cast of [value] against [type]. 2728 /// Creates a type test or type cast of [value] against [type].
2840 ir.Primitive buildTypeOperator(ir.Primitive value, 2729 ir.Primitive buildTypeOperator(
2841 DartType type, 2730 ir.Primitive value, DartType type, SourceInformation sourceInformation,
2842 SourceInformation sourceInformation, 2731 {bool isTypeTest}) {
2843 {bool isTypeTest}) {
2844 assert(isOpen); 2732 assert(isOpen);
2845 assert(isTypeTest != null); 2733 assert(isTypeTest != null);
2846 2734
2847 type = program.unaliasType(type); 2735 type = program.unaliasType(type);
2848 2736
2849 if (type.isMalformed) { 2737 if (type.isMalformed) {
2850 ErroneousElement element = type.element; 2738 ErroneousElement element = type.element;
2851 ir.Primitive message = buildStringConstant(element.message); 2739 ir.Primitive message = buildStringConstant(element.message);
2852 return buildStaticFunctionInvocation( 2740 return buildStaticFunctionInvocation(program.throwTypeErrorHelper,
2853 program.throwTypeErrorHelper, 2741 <ir.Primitive>[message], sourceInformation);
2854 <ir.Primitive>[message],
2855 sourceInformation);
2856 } 2742 }
2857 2743
2858 List<ir.Primitive> typeArguments = const <ir.Primitive>[]; 2744 List<ir.Primitive> typeArguments = const <ir.Primitive>[];
2859 if (type is GenericType && type.typeArguments.isNotEmpty) { 2745 if (type is GenericType && type.typeArguments.isNotEmpty) {
2860 typeArguments = type.typeArguments.map(buildTypeExpression).toList(); 2746 typeArguments = type.typeArguments.map(buildTypeExpression).toList();
2861 } else if (type is TypeVariableType) { 2747 } else if (type is TypeVariableType) {
2862 typeArguments = <ir.Primitive>[buildTypeVariableAccess(type)]; 2748 typeArguments = <ir.Primitive>[buildTypeVariableAccess(type)];
2863 } else if (type is FunctionType) { 2749 } else if (type is FunctionType) {
2864 typeArguments = <ir.Primitive>[buildTypeExpression(type)]; 2750 typeArguments = <ir.Primitive>[buildTypeExpression(type)];
2865 } 2751 }
(...skipping 18 matching lines...) Expand all
2884 return value; 2770 return value;
2885 } 2771 }
2886 return addPrimitive(new ir.TypeCast(value, type, typeArguments)); 2772 return addPrimitive(new ir.TypeCast(value, type, typeArguments));
2887 } 2773 }
2888 } 2774 }
2889 2775
2890 /// Create an if-null expression. This is equivalent to a conditional 2776 /// Create an if-null expression. This is equivalent to a conditional
2891 /// expression whose result is either [value] if [value] is not null, or 2777 /// expression whose result is either [value] if [value] is not null, or
2892 /// `right` if [value] is null. Only when [value] is null, [buildRight] is 2778 /// `right` if [value] is null. Only when [value] is null, [buildRight] is
2893 /// evaluated to produce the `right` value. 2779 /// evaluated to produce the `right` value.
2894 ir.Primitive buildIfNull(ir.Primitive value, 2780 ir.Primitive buildIfNull(
2895 ir.Primitive buildRight(IrBuilder builder), 2781 ir.Primitive value,
2896 SourceInformation sourceInformation) { 2782 ir.Primitive buildRight(IrBuilder builder),
2897 ir.Primitive condition = 2783 SourceInformation sourceInformation) {
2898 _buildCheckNull(value, sourceInformation); 2784 ir.Primitive condition = _buildCheckNull(value, sourceInformation);
2899 return buildConditional( 2785 return buildConditional(
2900 condition, buildRight, (_) => value, sourceInformation); 2786 condition, buildRight, (_) => value, sourceInformation);
2901 } 2787 }
2902 2788
2903 /// Create a conditional send. This is equivalent to a conditional expression 2789 /// Create a conditional send. This is equivalent to a conditional expression
2904 /// that checks if [receiver] is null, if so, it returns null, otherwise it 2790 /// that checks if [receiver] is null, if so, it returns null, otherwise it
2905 /// evaluates the [buildSend] expression. 2791 /// evaluates the [buildSend] expression.
2906 ir.Primitive buildIfNotNullSend(ir.Primitive receiver, 2792 ir.Primitive buildIfNotNullSend(
2907 ir.Primitive buildSend(IrBuilder builder), 2793 ir.Primitive receiver,
2908 SourceInformation sourceInformation) { 2794 ir.Primitive buildSend(IrBuilder builder),
2909 ir.Primitive condition = 2795 SourceInformation sourceInformation) {
2910 _buildCheckNull(receiver, sourceInformation); 2796 ir.Primitive condition = _buildCheckNull(receiver, sourceInformation);
2911 return buildConditional( 2797 return buildConditional(
2912 condition, (_) => receiver, buildSend, sourceInformation); 2798 condition, (_) => receiver, buildSend, sourceInformation);
2913 } 2799 }
2914 2800
2915 /// Creates a type test checking whether [value] is null. 2801 /// Creates a type test checking whether [value] is null.
2916 ir.Primitive _buildCheckNull(ir.Primitive value, 2802 ir.Primitive _buildCheckNull(
2917 SourceInformation sourceInformation) { 2803 ir.Primitive value, SourceInformation sourceInformation) {
2918 assert(isOpen); 2804 assert(isOpen);
2919 return buildIdentical(value, buildNullConstant(), 2805 return buildIdentical(value, buildNullConstant(),
2920 sourceInformation: sourceInformation); 2806 sourceInformation: sourceInformation);
2921 } 2807 }
2922 } 2808 }
2923 2809
2924 /// Location of a variable relative to a given closure. 2810 /// Location of a variable relative to a given closure.
2925 class ClosureLocation { 2811 class ClosureLocation {
2926 /// If not `null`, this location is [box].[field]. 2812 /// If not `null`, this location is [box].[field].
2927 /// The location of [box] can be obtained separately from an 2813 /// The location of [box] can be obtained separately from an
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
3010 new Set<LocalVariableElement>(); 2896 new Set<LocalVariableElement>();
3011 } 2897 }
3012 2898
3013 class CatchClauseInfo { 2899 class CatchClauseInfo {
3014 final DartType type; 2900 final DartType type;
3015 final LocalVariableElement exceptionVariable; 2901 final LocalVariableElement exceptionVariable;
3016 final LocalVariableElement stackTraceVariable; 2902 final LocalVariableElement stackTraceVariable;
3017 final SubbuildFunction buildCatchBlock; 2903 final SubbuildFunction buildCatchBlock;
3018 final SourceInformation sourceInformation; 2904 final SourceInformation sourceInformation;
3019 2905
3020 CatchClauseInfo({this.type, 2906 CatchClauseInfo(
3021 this.exceptionVariable, 2907 {this.type,
3022 this.stackTraceVariable, 2908 this.exceptionVariable,
3023 this.buildCatchBlock, 2909 this.stackTraceVariable,
3024 this.sourceInformation}); 2910 this.buildCatchBlock,
2911 this.sourceInformation});
3025 } 2912 }
3026 2913
3027 class SwitchCaseInfo { 2914 class SwitchCaseInfo {
3028 final SubbuildFunction buildCondition; 2915 final SubbuildFunction buildCondition;
3029 final SubbuildFunction buildBody; 2916 final SubbuildFunction buildBody;
3030 final SourceInformation sourceInformation; 2917 final SourceInformation sourceInformation;
3031 2918
3032 SwitchCaseInfo(this.buildCondition, this.buildBody, this.sourceInformation); 2919 SwitchCaseInfo(this.buildCondition, this.buildBody, this.sourceInformation);
3033 } 2920 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_fragment.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698