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