OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |