Chromium Code Reviews| 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 '../constants/expressions.dart'; | 7 import '../constants/expressions.dart'; |
| 8 import '../constants/values.dart' show PrimitiveConstantValue; | 8 import '../constants/values.dart' show PrimitiveConstantValue; |
| 9 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 10 import '../dart2jslib.dart'; | 10 import '../dart2jslib.dart'; |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 // TODO(johnniwinther): Type [nodes] as `Iterable<N>` when `NodeList` uses | 368 // TODO(johnniwinther): Type [nodes] as `Iterable<N>` when `NodeList` uses |
| 369 // `List` instead of `Link`. | 369 // `List` instead of `Link`. |
| 370 SubbuildFunction subbuildSequence(/*Iterable<N>*/ nodes) { | 370 SubbuildFunction subbuildSequence(/*Iterable<N>*/ nodes) { |
| 371 return (IrBuilder builder) { | 371 return (IrBuilder builder) { |
| 372 return withBuilder(builder, () => builder.buildSequence(nodes, build)); | 372 return withBuilder(builder, () => builder.buildSequence(nodes, build)); |
| 373 }; | 373 }; |
| 374 } | 374 } |
| 375 } | 375 } |
| 376 | 376 |
| 377 /// Shared state between delimited IrBuilders within the same function. | 377 /// Shared state between delimited IrBuilders within the same function. |
| 378 class IrBuilderDelimitedState { | 378 class IrBuilderSharedState { |
| 379 final ConstantSystem constantSystem; | 379 final ConstantSystem constantSystem; |
| 380 | 380 |
| 381 /// A stack of collectors for breaks. | 381 /// A stack of collectors for breaks. |
| 382 final List<JumpCollector> breakCollectors = <JumpCollector>[]; | 382 final List<JumpCollector> breakCollectors = <JumpCollector>[]; |
| 383 | 383 |
| 384 /// A stack of collectors for continues. | 384 /// A stack of collectors for continues. |
| 385 final List<JumpCollector> continueCollectors = <JumpCollector>[]; | 385 final List<JumpCollector> continueCollectors = <JumpCollector>[]; |
| 386 | 386 |
| 387 final List<ConstDeclaration> localConstants = <ConstDeclaration>[]; | 387 final List<ConstDeclaration> localConstants = <ConstDeclaration>[]; |
| 388 | 388 |
| 389 final ExecutableElement currentElement; | 389 final ExecutableElement currentElement; |
| 390 | 390 |
| 391 final ir.Continuation returnContinuation = new ir.Continuation.retrn(); | 391 final ir.Continuation returnContinuation = new ir.Continuation.retrn(); |
| 392 ir.Parameter _thisParameter; | 392 ir.Parameter _thisParameter; |
| 393 ir.Parameter enclosingMethodThisParameter; | 393 ir.Parameter enclosingMethodThisParameter; |
| 394 | 394 |
| 395 final List<ir.Definition> functionParameters = <ir.Definition>[]; | 395 final List<ir.Definition> functionParameters = <ir.Definition>[]; |
| 396 | 396 |
| 397 IrBuilderDelimitedState(this.constantSystem, this.currentElement); | 397 IrBuilderSharedState(this.constantSystem, this.currentElement); |
| 398 | 398 |
| 399 ir.Parameter get thisParameter => _thisParameter; | 399 ir.Parameter get thisParameter => _thisParameter; |
| 400 void set thisParameter(ir.Parameter value) { | 400 void set thisParameter(ir.Parameter value) { |
| 401 assert(_thisParameter == null); | 401 assert(_thisParameter == null); |
| 402 _thisParameter = value; | 402 _thisParameter = value; |
| 403 } | 403 } |
| 404 } | 404 } |
| 405 | 405 |
| 406 class ThisParameterLocal implements Local { | 406 class ThisParameterLocal implements Local { |
| 407 final ExecutableElement executableContext; | 407 final ExecutableElement executableContext; |
| 408 ThisParameterLocal(this.executableContext); | 408 ThisParameterLocal(this.executableContext); |
| 409 String get name => 'this'; | 409 String get name => 'this'; |
| 410 toString() => 'ThisParameterLocal($executableContext)'; | 410 toString() => 'ThisParameterLocal($executableContext)'; |
| 411 } | 411 } |
| 412 | 412 |
| 413 /// A factory for building the cps IR. | 413 /// A factory for building the cps IR. |
| 414 /// | 414 /// |
| 415 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured | 415 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured |
| 416 /// variables in different ways. | 416 /// variables in different ways. |
| 417 abstract class IrBuilder { | 417 abstract class IrBuilder { |
| 418 IrBuilder _makeInstance(); | 418 IrBuilder _makeInstance(); |
| 419 | 419 |
| 420 /// True if [local] should currently be accessed from a [ir.MutableVariable]. | |
| 421 bool isInMutableVariable(Local local); | |
| 422 | |
| 423 /// Creates a [ir.MutableVariable] for the given local. | |
| 424 void makeMutableVariable(Local local); | |
| 425 | |
| 426 /// Remove an [ir.MutableVariable] for a local. | |
| 427 /// | |
| 428 /// Subsequent access to the local will be direct rather than through the | |
| 429 /// mutable variable. This is used for variables that do not spend their | |
| 430 /// entire lifetime as mutable variables (e.g., variables that are boxed | |
| 431 /// in mutable variables for a try block). | |
| 432 void removeMutableVariable(Local local); | |
| 433 | |
| 434 void declareLocalVariable(LocalVariableElement element, | 420 void declareLocalVariable(LocalVariableElement element, |
| 435 {ir.Primitive initialValue}); | 421 {ir.Primitive initialValue}); |
| 436 | 422 |
| 437 /// Called when entering a nested function with free variables. | 423 /// Called when entering a nested function with free variables. |
| 438 /// | 424 /// |
| 439 /// The free variables must subsequently be accessible using [buildLocalGet] | 425 /// The free variables must subsequently be accessible using [buildLocalGet] |
| 440 /// and [buildLocalSet]. | 426 /// and [buildLocalSet]. |
| 441 void _enterClosureEnvironment(ClosureEnvironment env); | 427 void _enterClosureEnvironment(ClosureEnvironment env); |
| 442 | 428 |
| 443 /// Called when entering a function body or loop body. | 429 /// Called when entering a function body or loop body. |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 474 /// | 460 /// |
| 475 /// If inside a closure class, [buildThis] will redirect access through | 461 /// If inside a closure class, [buildThis] will redirect access through |
| 476 /// closure fields in order to access the receiver from the enclosing method. | 462 /// closure fields in order to access the receiver from the enclosing method. |
| 477 ir.Primitive buildThis(); | 463 ir.Primitive buildThis(); |
| 478 | 464 |
| 479 // TODO(johnniwinther): Make these field final and remove the default values | 465 // TODO(johnniwinther): Make these field final and remove the default values |
| 480 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin. | 466 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin. |
| 481 | 467 |
| 482 final List<ir.Parameter> _parameters = <ir.Parameter>[]; | 468 final List<ir.Parameter> _parameters = <ir.Parameter>[]; |
| 483 | 469 |
| 484 IrBuilderDelimitedState state; | 470 IrBuilderSharedState state; |
| 485 | 471 |
| 486 /// A map from variable indexes to their values. | 472 /// A map from variable indexes to their values. |
| 487 /// | 473 /// |
| 488 /// [BoxLocal]s map to their box. [LocalElement]s that are boxed are not | 474 /// [BoxLocal]s map to their box. [LocalElement]s that are boxed are not |
| 489 /// in the map; look up their [BoxLocal] instead. | 475 /// in the map; look up their [BoxLocal] instead. |
| 490 Environment environment; | 476 Environment environment; |
| 491 | 477 |
| 478 /// A map from mutable local variables to their [ir.MutableVariable]s. | |
| 479 /// | |
| 480 /// Mutable variables are treated as boxed. Writes to them are observable | |
| 481 /// side effects. | |
| 482 Map<Local, ir.MutableVariable> mutableVariables; | |
| 483 | |
| 484 /// True if [local] should currently be accessed from a [ir.MutableVariable]. | |
| 485 bool isInMutableVariable(Local local) { | |
| 486 return mutableVariables.containsKey(local); | |
| 487 } | |
| 488 | |
| 489 /// Creates a [ir.MutableVariable] for the given local. | |
| 490 void makeMutableVariable(Local local) { | |
| 491 mutableVariables[local] = | |
| 492 new ir.MutableVariable(local.executableContext, local); | |
| 493 } | |
| 494 | |
| 495 /// Remove an [ir.MutableVariable] for a local. | |
| 496 /// | |
| 497 /// Subsequent access to the local will be direct rather than through the | |
| 498 /// mutable variable. | |
| 499 void removeMutableVariable(Local local) { | |
| 500 mutableVariables.remove(local); | |
| 501 } | |
| 502 | |
| 503 /// Gets the [MutableVariable] containing the value of [local]. | |
| 504 ir.MutableVariable getMutableVariable(Local local) { | |
| 505 return mutableVariables[local]; | |
| 506 } | |
| 507 | |
| 492 // The IR builder maintains a context, which is an expression with a hole in | 508 // The IR builder maintains a context, which is an expression with a hole in |
| 493 // it. The hole represents the focus where new expressions can be added. | 509 // it. The hole represents the focus where new expressions can be added. |
| 494 // The context is implemented by 'root' which is the root of the expression | 510 // The context is implemented by 'root' which is the root of the expression |
| 495 // and 'current' which is the expression that immediately contains the hole. | 511 // and 'current' which is the expression that immediately contains the hole. |
| 496 // Not all expressions have a hole (e.g., invocations, which always occur in | 512 // Not all expressions have a hole (e.g., invocations, which always occur in |
| 497 // tail position, do not have a hole). Expressions with a hole have a plug | 513 // tail position, do not have a hole). Expressions with a hole have a plug |
| 498 // method. | 514 // method. |
| 499 // | 515 // |
| 500 // Conceptually, visiting a statement takes a context as input and returns | 516 // Conceptually, visiting a statement takes a context as input and returns |
| 501 // either a new context or else an expression without a hole if all | 517 // either a new context or else an expression without a hole if all |
| 502 // control-flow paths through the statement have exited. An expression | 518 // control-flow paths through the statement have exited. An expression |
| 503 // without a hole is represented by a (root, current) pair where root is the | 519 // without a hole is represented by a (root, current) pair where root is the |
| 504 // expression and current is null. | 520 // expression and current is null. |
| 505 // | 521 // |
| 506 // Conceptually again, visiting an expression takes a context as input and | 522 // Conceptually again, visiting an expression takes a context as input and |
| 507 // returns either a pair of a new context and a definition denoting | 523 // returns either a pair of a new context and a definition denoting |
| 508 // the expression's value, or else an expression without a hole if all | 524 // the expression's value, or else an expression without a hole if all |
| 509 // control-flow paths through the expression have exited. | 525 // control-flow paths through the expression have exited. |
| 510 // | 526 // |
| 511 // We do not pass contexts as arguments or return them. Rather we use the | 527 // We do not pass contexts as arguments or return them. Rather we use the |
| 512 // current context (root, current) as the visitor state and mutate current. | 528 // current context (root, current) as the visitor state and mutate current. |
| 513 // Visiting a statement returns null; visiting an expression returns the | 529 // Visiting a statement returns null; visiting an expression returns the |
| 514 // primitive denoting its value. | 530 // primitive denoting its value. |
| 515 | 531 |
| 516 ir.Expression _root = null; | 532 ir.Expression _root = null; |
| 517 ir.Expression _current = null; | 533 ir.Expression _current = null; |
| 518 | 534 |
| 519 /// Initialize a new top-level IR builder. | 535 /// Initialize a new top-level IR builder. |
| 520 void _init(ConstantSystem constantSystem, ExecutableElement currentElement) { | 536 void _init(ConstantSystem constantSystem, ExecutableElement currentElement) { |
| 521 state = new IrBuilderDelimitedState(constantSystem, currentElement); | 537 state = new IrBuilderSharedState(constantSystem, currentElement); |
| 522 environment = new Environment.empty(); | 538 environment = new Environment.empty(); |
| 539 mutableVariables = <Local, ir.MutableVariable>{}; | |
| 523 } | 540 } |
| 524 | 541 |
| 525 /// Construct a delimited visitor for visiting a subtree. | 542 /// Construct a delimited visitor for visiting a subtree. |
| 526 /// | 543 /// |
| 527 /// Build a subterm that is not (yet) connected to the CPS term. The | 544 /// Build a subterm that is not (yet) connected to the CPS term. The |
| 528 /// delimited visitor has its own has its own context for building an IR | 545 /// delimited visitor has its own has its own context for building an IR |
| 529 /// expression, so the built expression is not plugged into the parent's | 546 /// expression, so the built expression is not plugged into the parent's |
| 530 /// context. It has its own compile-time environment mapping local | 547 /// context. It has its own compile-time environment mapping local |
| 531 /// variables to their values. If an optional environment argument is | 548 /// variables to their values. If an optional environment argument is |
| 532 /// supplied, it is used as the builder's initial environment. Otherwise | 549 /// supplied, it is used as the builder's initial environment. Otherwise |
| 533 /// the environment is initially a copy of the parent builder's environment. | 550 /// the environment is initially a copy of the parent builder's environment. |
| 534 IrBuilder makeDelimitedBuilder([Environment env = null]) { | 551 IrBuilder makeDelimitedBuilder([Environment env = null]) { |
| 535 return _makeInstance() | 552 return _makeInstance() |
| 536 ..state = state | 553 ..state = state |
| 537 ..environment = env != null ? env : new Environment.from(environment); | 554 ..environment = env != null ? env : new Environment.from(environment) |
| 555 ..mutableVariables = mutableVariables; | |
| 538 } | 556 } |
| 539 | 557 |
| 540 /// Construct a builder for making constructor field initializers. | 558 /// Construct a builder for making constructor field initializers. |
| 541 IrBuilder makeInitializerBuilder() { | 559 IrBuilder makeInitializerBuilder() { |
| 542 return _makeInstance() | 560 return _makeInstance() |
| 543 ..state = new IrBuilderDelimitedState(state.constantSystem, | 561 ..state = new IrBuilderSharedState(state.constantSystem, |
| 544 state.currentElement) | 562 state.currentElement) |
| 545 ..environment = new Environment.from(environment); | 563 ..environment = new Environment.from(environment) |
| 564 ..mutableVariables = mutableVariables; | |
| 546 } | 565 } |
| 547 | 566 |
| 548 /// Construct a builder for an inner function. | 567 /// Construct a builder for an inner function. |
| 549 IrBuilder makeInnerFunctionBuilder(ExecutableElement currentElement) { | 568 IrBuilder makeInnerFunctionBuilder(ExecutableElement currentElement) { |
| 550 IrBuilderDelimitedState innerState = | 569 IrBuilderSharedState innerState = |
| 551 new IrBuilderDelimitedState(state.constantSystem, currentElement) | 570 new IrBuilderSharedState(state.constantSystem, currentElement) |
| 552 ..enclosingMethodThisParameter = state.enclosingMethodThisParameter; | 571 ..enclosingMethodThisParameter = state.enclosingMethodThisParameter; |
| 553 return _makeInstance() | 572 return _makeInstance() |
| 554 ..state = innerState | 573 ..state = innerState |
| 555 ..environment = new Environment.empty(); | 574 ..environment = new Environment.empty() |
| 575 ..mutableVariables = <Local, ir.MutableVariable>{}; | |
| 556 } | 576 } |
| 557 | 577 |
| 558 bool get isOpen => _root == null || _current != null; | 578 bool get isOpen => _root == null || _current != null; |
| 559 | 579 |
| 560 | 580 |
| 561 void buildFieldInitializerHeader({ClosureScope closureScope}) { | 581 void buildFieldInitializerHeader({ClosureScope closureScope}) { |
| 562 _enterScope(closureScope); | 582 _enterScope(closureScope); |
| 563 } | 583 } |
| 564 | 584 |
| 565 List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters, | 585 List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters, |
| (...skipping 1141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1707 // of mutable bindings for the variables assigned in the try. The join- | 1727 // of mutable bindings for the variables assigned in the try. The join- |
| 1708 // point continuation is not in the scope of these mutable bindings. | 1728 // point continuation is not in the scope of these mutable bindings. |
| 1709 // The tryBlock is in the scope of a binding for the catch handler. Each | 1729 // The tryBlock is in the scope of a binding for the catch handler. Each |
| 1710 // instruction (specifically, each call) in the tryBlock is in the dynamic | 1730 // instruction (specifically, each call) in the tryBlock is in the dynamic |
| 1711 // scope of the handler. The mutable bindings are dereferenced at the end | 1731 // scope of the handler. The mutable bindings are dereferenced at the end |
| 1712 // of the try block and at the beginning of the catch block, so the | 1732 // of the try block and at the beginning of the catch block, so the |
| 1713 // variables are unboxed in the catch block and at the join point. | 1733 // variables are unboxed in the catch block and at the join point. |
| 1714 JumpCollector join = new ForwardJumpCollector(environment); | 1734 JumpCollector join = new ForwardJumpCollector(environment); |
| 1715 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); | 1735 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); |
| 1716 | 1736 |
| 1717 // Variables that are boxed due to being captured in a closure are boxed | 1737 // Variables treated as mutable in a try are not mutable outside of it. |
| 1718 // for their entire lifetime, and so they do not need to be boxed on | 1738 // Work with a copy of the outer builder's mutable variables. |
| 1719 // entry to any try block. They are not filtered out before this because | 1739 tryCatchBuilder.mutableVariables = |
| 1720 // we can not identify all of them in the same pass where we identify the | 1740 new Map<Local, ir.MutableVariable>.from(mutableVariables); |
| 1721 // variables assigned in the try (they may be captured by a closure after | |
| 1722 // the try statement). | |
| 1723 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) { | 1741 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) { |
| 1724 assert(!tryCatchBuilder.isInMutableVariable(variable)); | 1742 assert(!tryCatchBuilder.isInMutableVariable(variable)); |
| 1725 ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable); | 1743 ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable); |
| 1726 tryCatchBuilder.makeMutableVariable(variable); | 1744 tryCatchBuilder.makeMutableVariable(variable); |
| 1727 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); | 1745 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); |
| 1728 } | 1746 } |
| 1729 | 1747 |
| 1730 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1748 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1731 | 1749 |
| 1732 void interceptJumps(JumpCollector collector) { | 1750 void interceptJumps(JumpCollector collector) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1743 tryBuilder.jumpTo(join); | 1761 tryBuilder.jumpTo(join); |
| 1744 restoreJumps(join); | 1762 restoreJumps(join); |
| 1745 } | 1763 } |
| 1746 tryBuilder.state.breakCollectors.forEach(restoreJumps); | 1764 tryBuilder.state.breakCollectors.forEach(restoreJumps); |
| 1747 tryBuilder.state.continueCollectors.forEach(restoreJumps); | 1765 tryBuilder.state.continueCollectors.forEach(restoreJumps); |
| 1748 | 1766 |
| 1749 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1767 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1750 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) { | 1768 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) { |
| 1751 assert(catchBuilder.isInMutableVariable(variable)); | 1769 assert(catchBuilder.isInMutableVariable(variable)); |
| 1752 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable); | 1770 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable); |
| 1753 // Note that we remove the variable from the set of mutable variables | 1771 // After this point, the variables that were boxed on entry to the try |
| 1754 // here (and not above for the try body). This is because the set of | 1772 // are no longer treated as mutable. |
| 1755 // mutable variables is global for the whole function and not local to | |
| 1756 // a delimited builder. | |
| 1757 catchBuilder.removeMutableVariable(variable); | 1773 catchBuilder.removeMutableVariable(variable); |
| 1758 catchBuilder.environment.update(variable, value); | 1774 catchBuilder.environment.update(variable, value); |
| 1759 } | 1775 } |
| 1760 | 1776 |
| 1761 // TODO(kmillikin): Handle multiple catch clauses. | 1777 // TODO(kmillikin): Handle multiple catch clauses. |
| 1762 assert(catchClauseInfos.length == 1); | 1778 assert(catchClauseInfos.length == 1); |
| 1763 for (CatchClauseInfo catchClauseInfo in catchClauseInfos) { | 1779 for (CatchClauseInfo catchClauseInfo in catchClauseInfos) { |
| 1764 LocalVariableElement exceptionVariable = | 1780 LocalVariableElement exceptionVariable = |
| 1765 catchClauseInfo.exceptionVariable; | 1781 catchClauseInfo.exceptionVariable; |
| 1766 ir.Parameter exceptionParameter = new ir.Parameter(exceptionVariable); | 1782 ir.Parameter exceptionParameter = new ir.Parameter(exceptionVariable); |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2033 environment = join.environment; | 2049 environment = join.environment; |
| 2034 environment.discard(1); | 2050 environment.discard(1); |
| 2035 // There is always a join parameter for the result value, because it | 2051 // There is always a join parameter for the result value, because it |
| 2036 // is different on at least two paths. | 2052 // is different on at least two paths. |
| 2037 return join.continuation.parameters.last; | 2053 return join.continuation.parameters.last; |
| 2038 } | 2054 } |
| 2039 } | 2055 } |
| 2040 | 2056 |
| 2041 /// Shared state between DartIrBuilders within the same method. | 2057 /// Shared state between DartIrBuilders within the same method. |
| 2042 class DartIrBuilderSharedState { | 2058 class DartIrBuilderSharedState { |
| 2043 /// Maps local variables to their corresponding [MutableVariable] object. | |
| 2044 final Map<Local, ir.MutableVariable> local2mutable = | |
| 2045 <Local, ir.MutableVariable>{}; | |
| 2046 | |
| 2047 /// Creates a [MutableVariable] for the given local. | |
| 2048 void makeMutableVariable(Local local) { | |
| 2049 ir.MutableVariable variable = | |
| 2050 new ir.MutableVariable(local.executableContext, local); | |
| 2051 local2mutable[local] = variable; | |
| 2052 } | |
| 2053 | |
| 2054 /// [MutableVariable]s that should temporarily be treated as registers. | 2059 /// [MutableVariable]s that should temporarily be treated as registers. |
| 2055 final Set<Local> registerizedMutableVariables = new Set<Local>(); | 2060 final Set<Local> registerizedMutableVariables = new Set<Local>(); |
| 2056 | |
| 2057 DartIrBuilderSharedState(Set<Local> capturedVariables) { | |
| 2058 capturedVariables.forEach(makeMutableVariable); | |
| 2059 } | |
| 2060 } | 2061 } |
| 2061 | 2062 |
| 2062 /// Dart-specific subclass of [IrBuilder]. | 2063 /// Dart-specific subclass of [IrBuilder]. |
| 2063 /// | 2064 /// |
| 2064 /// Inner functions are represented by a [FunctionDefinition] with the | 2065 /// Inner functions are represented by a [FunctionDefinition] with the |
| 2065 /// IR for the inner function nested inside. | 2066 /// IR for the inner function nested inside. |
| 2066 /// | 2067 /// |
| 2067 /// Captured variables are translated to ref cells (see [MutableVariable]) | 2068 /// Captured variables are translated to ref cells (see [MutableVariable]) |
| 2068 /// using [GetMutableVariable] and [SetMutableVariable]. | 2069 /// using [GetMutableVariable] and [SetMutableVariable]. |
| 2069 class DartIrBuilder extends IrBuilder { | 2070 class DartIrBuilder extends IrBuilder { |
| 2070 final DartIrBuilderSharedState dartState; | 2071 final DartIrBuilderSharedState dartState = new DartIrBuilderSharedState(); |
| 2071 | 2072 |
| 2072 IrBuilder _makeInstance() => new DartIrBuilder._blank(dartState); | 2073 IrBuilder _makeInstance() => new DartIrBuilder._blank(dartState); |
| 2073 DartIrBuilder._blank(this.dartState); | 2074 DartIrBuilder._blank(this.dartState); |
| 2074 | 2075 |
| 2075 DartIrBuilder(ConstantSystem constantSystem, | 2076 DartIrBuilder(ConstantSystem constantSystem, |
| 2076 ExecutableElement currentElement, | 2077 ExecutableElement currentElement, |
| 2077 Set<Local> capturedVariables) | 2078 Set<Local> capturedVariables) { |
| 2078 : dartState = new DartIrBuilderSharedState(capturedVariables) { | |
| 2079 _init(constantSystem, currentElement); | 2079 _init(constantSystem, currentElement); |
| 2080 capturedVariables.forEach(makeMutableVariable); | |
| 2080 } | 2081 } |
| 2081 | 2082 |
| 2083 @override | |
| 2082 bool isInMutableVariable(Local local) { | 2084 bool isInMutableVariable(Local local) { |
| 2083 return dartState.local2mutable.containsKey(local) && | 2085 return mutableVariables.containsKey(local) && |
| 2084 !dartState.registerizedMutableVariables.contains(local); | 2086 !dartState.registerizedMutableVariables.contains(local); |
| 2085 } | 2087 } |
| 2086 | 2088 |
| 2087 void makeMutableVariable(Local local) { | |
| 2088 dartState.makeMutableVariable(local); | |
| 2089 } | |
| 2090 | |
| 2091 void removeMutableVariable(Local local) { | |
| 2092 dartState.local2mutable.remove(local); | |
| 2093 } | |
| 2094 | |
| 2095 /// Gets the [MutableVariable] containing the value of [local]. | |
| 2096 ir.MutableVariable getMutableVariable(Local local) { | |
| 2097 return dartState.local2mutable[local]; | |
| 2098 } | |
| 2099 | |
| 2100 void _enterScope(ClosureScope scope) { | 2089 void _enterScope(ClosureScope scope) { |
| 2101 assert(scope == null); | 2090 assert(scope == null); |
| 2102 } | 2091 } |
| 2103 | 2092 |
| 2104 void _enterClosureEnvironment(ClosureEnvironment env) { | 2093 void _enterClosureEnvironment(ClosureEnvironment env) { |
| 2105 assert(env == null); | 2094 assert(env == null); |
| 2106 } | 2095 } |
| 2107 | 2096 |
| 2108 void _enterForLoopInitializer(ClosureScope scope, | 2097 void _enterForLoopInitializer(ClosureScope scope, |
| 2109 List<LocalElement> loopVariables) { | 2098 List<LocalElement> loopVariables) { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 2137 // Move captured loop variables back into the local environment. | 2126 // Move captured loop variables back into the local environment. |
| 2138 // The update expression will use the values we put in the environment, | 2127 // The update expression will use the values we put in the environment, |
| 2139 // and then the environments for the initializer and update will be | 2128 // and then the environments for the initializer and update will be |
| 2140 // joined at the head of the body. | 2129 // joined at the head of the body. |
| 2141 for (LocalElement loopVariable in loopVariables) { | 2130 for (LocalElement loopVariable in loopVariables) { |
| 2142 if (isInMutableVariable(loopVariable)) { | 2131 if (isInMutableVariable(loopVariable)) { |
| 2143 ir.MutableVariable mutableVariable = getMutableVariable(loopVariable); | 2132 ir.MutableVariable mutableVariable = getMutableVariable(loopVariable); |
| 2144 ir.Primitive value = | 2133 ir.Primitive value = |
| 2145 addPrimitive(new ir.GetMutableVariable(mutableVariable)); | 2134 addPrimitive(new ir.GetMutableVariable(mutableVariable)); |
| 2146 environment.update(loopVariable, value); | 2135 environment.update(loopVariable, value); |
| 2147 dartState.registerizedMutableVariables.add(loopVariable); | 2136 dartState.registerizedMutableVariables.add(loopVariable); |
|
asgerf
2015/04/20 08:46:10
We should be able to get rid of registerizedMutabl
| |
| 2148 } | 2137 } |
| 2149 } | 2138 } |
| 2150 } | 2139 } |
| 2151 | 2140 |
| 2152 void _createFunctionParameter(Local parameterElement) { | 2141 void _createFunctionParameter(Local parameterElement) { |
| 2153 ir.Parameter parameter = new ir.Parameter(parameterElement); | 2142 ir.Parameter parameter = new ir.Parameter(parameterElement); |
| 2154 _parameters.add(parameter); | 2143 _parameters.add(parameter); |
| 2155 if (isInMutableVariable(parameterElement)) { | 2144 if (isInMutableVariable(parameterElement)) { |
| 2156 state.functionParameters.add(getMutableVariable(parameterElement)); | 2145 state.functionParameters.add(getMutableVariable(parameterElement)); |
| 2157 } else { | 2146 } else { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2284 | 2273 |
| 2285 IrBuilder _makeInstance() => new JsIrBuilder._blank(program, jsState); | 2274 IrBuilder _makeInstance() => new JsIrBuilder._blank(program, jsState); |
| 2286 JsIrBuilder._blank(this.program, this.jsState); | 2275 JsIrBuilder._blank(this.program, this.jsState); |
| 2287 | 2276 |
| 2288 JsIrBuilder(this.program, ConstantSystem constantSystem, | 2277 JsIrBuilder(this.program, ConstantSystem constantSystem, |
| 2289 ExecutableElement currentElement) | 2278 ExecutableElement currentElement) |
| 2290 : jsState = new JsIrBuilderSharedState() { | 2279 : jsState = new JsIrBuilderSharedState() { |
| 2291 _init(constantSystem, currentElement); | 2280 _init(constantSystem, currentElement); |
| 2292 } | 2281 } |
| 2293 | 2282 |
| 2294 Map<ast.TryStatement, TryStatementInfo> get tryStatements => null; | |
| 2295 Set<Local> get mutableCapturedVariables => null; | |
| 2296 bool isInMutableVariable(Local local) => false; | |
| 2297 void makeMutableVariable(Local local) {} | |
| 2298 void removeMutableVariable(Local local) {} | |
| 2299 | |
| 2300 void enterInitializers() { | 2283 void enterInitializers() { |
| 2301 assert(jsState.inInitializers == false); | 2284 assert(jsState.inInitializers == false); |
| 2302 jsState.inInitializers = true; | 2285 jsState.inInitializers = true; |
| 2303 } | 2286 } |
| 2304 | 2287 |
| 2305 void leaveInitializers() { | 2288 void leaveInitializers() { |
| 2306 assert(jsState.inInitializers == true); | 2289 assert(jsState.inInitializers == true); |
| 2307 jsState.inInitializers = false; | 2290 jsState.inInitializers = false; |
| 2308 } | 2291 } |
| 2309 | 2292 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2383 {ir.Primitive initialValue}) { | 2366 {ir.Primitive initialValue}) { |
| 2384 assert(isOpen); | 2367 assert(isOpen); |
| 2385 if (initialValue == null) { | 2368 if (initialValue == null) { |
| 2386 initialValue = buildNullLiteral(); | 2369 initialValue = buildNullLiteral(); |
| 2387 } | 2370 } |
| 2388 ClosureLocation location = jsState.boxedVariables[variableElement]; | 2371 ClosureLocation location = jsState.boxedVariables[variableElement]; |
| 2389 if (location != null) { | 2372 if (location != null) { |
| 2390 add(new ir.SetField(environment.lookup(location.box), | 2373 add(new ir.SetField(environment.lookup(location.box), |
| 2391 location.field, | 2374 location.field, |
| 2392 initialValue)); | 2375 initialValue)); |
| 2376 } else if (isInMutableVariable(variableElement)) { | |
| 2377 add(new ir.LetMutable(getMutableVariable(variableElement), | |
| 2378 initialValue)); | |
| 2393 } else { | 2379 } else { |
| 2394 initialValue.useElementAsHint(variableElement); | 2380 initialValue.useElementAsHint(variableElement); |
| 2395 environment.extend(variableElement, initialValue); | 2381 environment.extend(variableElement, initialValue); |
| 2396 } | 2382 } |
| 2397 } | 2383 } |
| 2398 | 2384 |
| 2399 /// Add [functionElement] to the environment with provided [definition]. | 2385 /// Add [functionElement] to the environment with provided [definition]. |
| 2400 void declareLocalFunction(LocalFunctionElement functionElement, | 2386 void declareLocalFunction(LocalFunctionElement functionElement, |
| 2401 ClosureClassElement classElement) { | 2387 ClosureClassElement classElement) { |
| 2402 ir.Primitive closure = buildFunctionExpression(classElement); | 2388 ir.Primitive closure = buildFunctionExpression(classElement); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2659 } | 2645 } |
| 2660 | 2646 |
| 2661 /// Synthetic parameter to a JavaScript factory method that takes the type | 2647 /// Synthetic parameter to a JavaScript factory method that takes the type |
| 2662 /// argument given for the type variable [variable]. | 2648 /// argument given for the type variable [variable]. |
| 2663 class TypeInformationParameter implements Local { | 2649 class TypeInformationParameter implements Local { |
| 2664 final TypeVariableElement variable; | 2650 final TypeVariableElement variable; |
| 2665 final ExecutableElement executableContext; | 2651 final ExecutableElement executableContext; |
| 2666 TypeInformationParameter(this.variable, this.executableContext); | 2652 TypeInformationParameter(this.variable, this.executableContext); |
| 2667 String get name => variable.name; | 2653 String get name => variable.name; |
| 2668 } | 2654 } |
| OLD | NEW |