| 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 1505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 environment.index2value[i] = parameters[index++]; | 1516 environment.index2value[i] = parameters[index++]; |
| 1517 } | 1517 } |
| 1518 } | 1518 } |
| 1519 | 1519 |
| 1520 return join; | 1520 return join; |
| 1521 } | 1521 } |
| 1522 } | 1522 } |
| 1523 | 1523 |
| 1524 /// Shared state between DartIrBuilders within the same method. | 1524 /// Shared state between DartIrBuilders within the same method. |
| 1525 class DartIrBuilderSharedState { | 1525 class DartIrBuilderSharedState { |
| 1526 /// Maps local variables to their corresponding [ClosureVariable] object. | 1526 /// Maps local variables to their corresponding [MutableVariable] object. |
| 1527 final Map<Local, ir.ClosureVariable> local2closure = | 1527 final Map<Local, ir.MutableVariable> local2mutable = |
| 1528 <Local, ir.ClosureVariable>{}; | 1528 <Local, ir.MutableVariable>{}; |
| 1529 | 1529 |
| 1530 /// Maps functions to the list of closure variables declared in that function. | 1530 final DartCapturedVariableInfo capturedVariables; |
| 1531 final Map<ExecutableElement, List<ir.ClosureVariable>> function2closures = | |
| 1532 <ExecutableElement, List<ir.ClosureVariable>>{}; | |
| 1533 | 1531 |
| 1534 final DartCapturedVariableInfo closureVariables; | 1532 /// Creates a [MutableVariable] for the given local. |
| 1535 | 1533 void makeMutableVariable(Local local) { |
| 1536 /// Returns the closure variables declared in the given function. | 1534 ir.MutableVariable variable = |
| 1537 List<ir.ClosureVariable> getClosureList(ExecutableElement element) { | 1535 new ir.MutableVariable(local.executableContext, local); |
| 1538 return function2closures.putIfAbsent(element, () => <ir.ClosureVariable>[]); | 1536 local2mutable[local] = variable; |
| 1539 } | 1537 } |
| 1540 | 1538 |
| 1541 /// Creates a closure variable for the given local. | 1539 /// [MutableVariable]s that should temporarily be treated as registers. |
| 1542 void makeClosureVariable(Local local) { | 1540 final Set<Local> registerizedMutableVariables = new Set<Local>(); |
| 1543 ir.ClosureVariable variable = | |
| 1544 new ir.ClosureVariable(local.executableContext, local); | |
| 1545 local2closure[local] = variable; | |
| 1546 getClosureList(local.executableContext).add(variable); | |
| 1547 } | |
| 1548 | 1541 |
| 1549 /// Closure variables that should temporarily be treated as registers. | 1542 DartIrBuilderSharedState(this.capturedVariables) { |
| 1550 final Set<Local> registerizedClosureVariables = new Set<Local>(); | 1543 capturedVariables.capturedVariables.forEach(makeMutableVariable); |
| 1551 | |
| 1552 DartIrBuilderSharedState(this.closureVariables) { | |
| 1553 closureVariables.capturedVariables.forEach(makeClosureVariable); | |
| 1554 } | 1544 } |
| 1555 } | 1545 } |
| 1556 | 1546 |
| 1557 /// Dart-specific subclass of [IrBuilder]. | 1547 /// Dart-specific subclass of [IrBuilder]. |
| 1558 /// | 1548 /// |
| 1559 /// Inner functions are represented by a [FunctionDefinition] with the | 1549 /// Inner functions are represented by a [FunctionDefinition] with the |
| 1560 /// IR for the inner function nested inside. | 1550 /// IR for the inner function nested inside. |
| 1561 /// | 1551 /// |
| 1562 /// Captured variables are translated to ref cells (see [ClosureVariable]) | 1552 /// Captured variables are translated to ref cells (see [MutableVariable]) |
| 1563 /// using [GetClosureVariable] and [SetClosureVariable]. | 1553 /// using [GetMutableVariable] and [SetMutableVariable]. |
| 1564 class DartIrBuilder extends IrBuilder { | 1554 class DartIrBuilder extends IrBuilder { |
| 1565 final DartIrBuilderSharedState dartState; | 1555 final DartIrBuilderSharedState dartState; |
| 1566 | 1556 |
| 1567 IrBuilder _makeInstance() => new DartIrBuilder._blank(dartState); | 1557 IrBuilder _makeInstance() => new DartIrBuilder._blank(dartState); |
| 1568 DartIrBuilder._blank(this.dartState); | 1558 DartIrBuilder._blank(this.dartState); |
| 1569 | 1559 |
| 1570 DartIrBuilder(ConstantSystem constantSystem, | 1560 DartIrBuilder(ConstantSystem constantSystem, |
| 1571 ExecutableElement currentElement, | 1561 ExecutableElement currentElement, |
| 1572 DartCapturedVariableInfo closureVariables) | 1562 DartCapturedVariableInfo capturedVariables) |
| 1573 : dartState = new DartIrBuilderSharedState(closureVariables) { | 1563 : dartState = new DartIrBuilderSharedState(capturedVariables) { |
| 1574 _init(constantSystem, currentElement); | 1564 _init(constantSystem, currentElement); |
| 1575 } | 1565 } |
| 1576 | 1566 |
| 1577 /// True if [local] should currently be accessed from a [ClosureVariable]. | 1567 /// True if [local] should currently be accessed from a [MutableVariable]. |
| 1578 bool isInClosureVariable(Local local) { | 1568 bool isInMutableVariable(Local local) { |
| 1579 return dartState.local2closure.containsKey(local) && | 1569 return dartState.local2mutable.containsKey(local) && |
| 1580 !dartState.registerizedClosureVariables.contains(local); | 1570 !dartState.registerizedMutableVariables.contains(local); |
| 1581 } | 1571 } |
| 1582 | 1572 |
| 1583 /// Gets the [ClosureVariable] containing the value of [local]. | 1573 /// Gets the [MutableVariable] containing the value of [local]. |
| 1584 ir.ClosureVariable getClosureVariable(Local local) { | 1574 ir.MutableVariable getMutableVariable(Local local) { |
| 1585 return dartState.local2closure[local]; | 1575 return dartState.local2mutable[local]; |
| 1586 } | 1576 } |
| 1587 | 1577 |
| 1588 void _enterScope(ClosureScope scope) { | 1578 void _enterScope(ClosureScope scope) { |
| 1589 assert(scope == null); | 1579 assert(scope == null); |
| 1590 } | 1580 } |
| 1591 | 1581 |
| 1592 void _enterClosureEnvironment(ClosureEnvironment env) { | 1582 void _enterClosureEnvironment(ClosureEnvironment env) { |
| 1593 assert(env == null); | 1583 assert(env == null); |
| 1594 } | 1584 } |
| 1595 | 1585 |
| 1596 void _enterForLoopInitializer(ClosureScope scope, | 1586 void _enterForLoopInitializer(ClosureScope scope, |
| 1597 List<LocalElement> loopVariables) { | 1587 List<LocalElement> loopVariables) { |
| 1598 assert(scope == null); | 1588 assert(scope == null); |
| 1599 for (LocalElement loopVariable in loopVariables) { | 1589 for (LocalElement loopVariable in loopVariables) { |
| 1600 if (dartState.local2closure.containsKey(loopVariable)) { | 1590 if (dartState.local2mutable.containsKey(loopVariable)) { |
| 1601 // Temporarily keep the loop variable in a primitive. | 1591 // Temporarily keep the loop variable in a primitive. |
| 1602 // The loop variable will be added to environment when | 1592 // The loop variable will be added to environment when |
| 1603 // [declareLocalVariable] is called. | 1593 // [declareLocalVariable] is called. |
| 1604 dartState.registerizedClosureVariables.add(loopVariable); | 1594 dartState.registerizedMutableVariables.add(loopVariable); |
| 1605 } | 1595 } |
| 1606 } | 1596 } |
| 1607 } | 1597 } |
| 1608 | 1598 |
| 1609 void _enterForLoopBody(ClosureScope scope, | 1599 void _enterForLoopBody(ClosureScope scope, |
| 1610 List<LocalElement> loopVariables) { | 1600 List<LocalElement> loopVariables) { |
| 1611 assert(scope == null); | 1601 assert(scope == null); |
| 1612 for (LocalElement loopVariable in loopVariables) { | 1602 for (LocalElement loopVariable in loopVariables) { |
| 1613 if (dartState.local2closure.containsKey(loopVariable)) { | 1603 if (dartState.local2mutable.containsKey(loopVariable)) { |
| 1614 // Move from primitive into ClosureVariable. | 1604 // Move from [Primitive] into [MutableVariable]. |
| 1615 dartState.registerizedClosureVariables.remove(loopVariable); | 1605 dartState.registerizedMutableVariables.remove(loopVariable); |
| 1616 add(new ir.SetClosureVariable(getClosureVariable(loopVariable), | 1606 add(new ir.LetMutable(getMutableVariable(loopVariable), |
| 1617 environment.lookup(loopVariable), | 1607 environment.lookup(loopVariable))); |
| 1618 isDeclaration: true)); | |
| 1619 } | 1608 } |
| 1620 } | 1609 } |
| 1621 } | 1610 } |
| 1622 | 1611 |
| 1623 void _enterForLoopUpdate(ClosureScope scope, | 1612 void _enterForLoopUpdate(ClosureScope scope, |
| 1624 List<LocalElement> loopVariables) { | 1613 List<LocalElement> loopVariables) { |
| 1625 assert(scope == null); | 1614 assert(scope == null); |
| 1626 // Move captured loop variables back into the local environment. | 1615 // Move captured loop variables back into the local environment. |
| 1627 // The update expression will use the values we put in the environment, | 1616 // The update expression will use the values we put in the environment, |
| 1628 // and then the environments for the initializer and update will be | 1617 // and then the environments for the initializer and update will be |
| 1629 // joined at the head of the body. | 1618 // joined at the head of the body. |
| 1630 for (LocalElement loopVariable in loopVariables) { | 1619 for (LocalElement loopVariable in loopVariables) { |
| 1631 if (isInClosureVariable(loopVariable)) { | 1620 if (isInMutableVariable(loopVariable)) { |
| 1632 ir.ClosureVariable closureVariable = getClosureVariable(loopVariable); | 1621 ir.MutableVariable mutableVariable = getMutableVariable(loopVariable); |
| 1633 ir.Primitive get = new ir.GetClosureVariable(closureVariable); | 1622 ir.Primitive get = new ir.GetMutableVariable(mutableVariable); |
| 1634 add(new ir.LetPrim(get)); | 1623 add(new ir.LetPrim(get)); |
| 1635 environment.update(loopVariable, get); | 1624 environment.update(loopVariable, get); |
| 1636 dartState.registerizedClosureVariables.add(loopVariable); | 1625 dartState.registerizedMutableVariables.add(loopVariable); |
| 1637 } | 1626 } |
| 1638 } | 1627 } |
| 1639 } | 1628 } |
| 1640 | 1629 |
| 1641 void _createFunctionParameter(ParameterElement parameterElement) { | 1630 void _createFunctionParameter(ParameterElement parameterElement) { |
| 1642 ir.Parameter parameter = new ir.Parameter(parameterElement); | 1631 ir.Parameter parameter = new ir.Parameter(parameterElement); |
| 1643 _parameters.add(parameter); | 1632 _parameters.add(parameter); |
| 1644 if (isInClosureVariable(parameterElement)) { | 1633 if (isInMutableVariable(parameterElement)) { |
| 1645 state.functionParameters.add(getClosureVariable(parameterElement)); | 1634 state.functionParameters.add(getMutableVariable(parameterElement)); |
| 1646 } else { | 1635 } else { |
| 1647 state.functionParameters.add(parameter); | 1636 state.functionParameters.add(parameter); |
| 1648 environment.extend(parameterElement, parameter); | 1637 environment.extend(parameterElement, parameter); |
| 1649 } | 1638 } |
| 1650 } | 1639 } |
| 1651 | 1640 |
| 1652 void declareLocalVariable(LocalVariableElement variableElement, | 1641 void declareLocalVariable(LocalVariableElement variableElement, |
| 1653 {ir.Primitive initialValue}) { | 1642 {ir.Primitive initialValue}) { |
| 1654 assert(isOpen); | 1643 assert(isOpen); |
| 1655 if (initialValue == null) { | 1644 if (initialValue == null) { |
| 1656 initialValue = buildNullLiteral(); | 1645 initialValue = buildNullLiteral(); |
| 1657 } | 1646 } |
| 1658 if (isInClosureVariable(variableElement)) { | 1647 if (isInMutableVariable(variableElement)) { |
| 1659 add(new ir.SetClosureVariable(getClosureVariable(variableElement), | 1648 add(new ir.LetMutable(getMutableVariable(variableElement), |
| 1660 initialValue, | 1649 initialValue)); |
| 1661 isDeclaration: true)); | |
| 1662 } else { | 1650 } else { |
| 1663 initialValue.useElementAsHint(variableElement); | 1651 initialValue.useElementAsHint(variableElement); |
| 1664 environment.extend(variableElement, initialValue); | 1652 environment.extend(variableElement, initialValue); |
| 1665 } | 1653 } |
| 1666 } | 1654 } |
| 1667 | 1655 |
| 1668 /// Add [functionElement] to the environment with provided [definition]. | 1656 /// Add [functionElement] to the environment with provided [definition]. |
| 1669 void declareLocalFunction(LocalFunctionElement functionElement, | 1657 void declareLocalFunction(LocalFunctionElement functionElement, |
| 1670 ir.FunctionDefinition definition) { | 1658 ir.FunctionDefinition definition) { |
| 1671 assert(isOpen); | 1659 assert(isOpen); |
| 1672 if (isInClosureVariable(functionElement)) { | 1660 if (isInMutableVariable(functionElement)) { |
| 1673 ir.ClosureVariable variable = getClosureVariable(functionElement); | 1661 ir.MutableVariable variable = getMutableVariable(functionElement); |
| 1674 add(new ir.DeclareFunction(variable, definition)); | 1662 add(new ir.DeclareFunction(variable, definition)); |
| 1675 } else { | 1663 } else { |
| 1676 ir.CreateFunction prim = new ir.CreateFunction(definition); | 1664 ir.CreateFunction prim = new ir.CreateFunction(definition); |
| 1677 add(new ir.LetPrim(prim)); | 1665 add(new ir.LetPrim(prim)); |
| 1678 environment.extend(functionElement, prim); | 1666 environment.extend(functionElement, prim); |
| 1679 prim.useElementAsHint(functionElement); | 1667 prim.useElementAsHint(functionElement); |
| 1680 } | 1668 } |
| 1681 } | 1669 } |
| 1682 | 1670 |
| 1683 /// Create a function expression from [definition]. | 1671 /// Create a function expression from [definition]. |
| 1684 ir.Primitive buildFunctionExpression(ir.FunctionDefinition definition) { | 1672 ir.Primitive buildFunctionExpression(ir.FunctionDefinition definition) { |
| 1685 ir.CreateFunction prim = new ir.CreateFunction(definition); | 1673 ir.CreateFunction prim = new ir.CreateFunction(definition); |
| 1686 add(new ir.LetPrim(prim)); | 1674 add(new ir.LetPrim(prim)); |
| 1687 return prim; | 1675 return prim; |
| 1688 } | 1676 } |
| 1689 | 1677 |
| 1690 /// Create a read access of [local]. | 1678 /// Create a read access of [local]. |
| 1691 ir.Primitive buildLocalGet(LocalElement local) { | 1679 ir.Primitive buildLocalGet(LocalElement local) { |
| 1692 assert(isOpen); | 1680 assert(isOpen); |
| 1693 if (isInClosureVariable(local)) { | 1681 if (isInMutableVariable(local)) { |
| 1694 // Do not use [local] as a hint on [result]. The variable should always | 1682 // Do not use [local] as a hint on [result]. The variable should always |
| 1695 // be inlined, but the hint prevents it. | 1683 // be inlined, but the hint prevents it. |
| 1696 ir.Primitive result = | 1684 ir.Primitive result = |
| 1697 new ir.GetClosureVariable(getClosureVariable(local)); | 1685 new ir.GetMutableVariable(getMutableVariable(local)); |
| 1698 add(new ir.LetPrim(result)); | 1686 add(new ir.LetPrim(result)); |
| 1699 return result; | 1687 return result; |
| 1700 } else { | 1688 } else { |
| 1701 return environment.lookup(local); | 1689 return environment.lookup(local); |
| 1702 } | 1690 } |
| 1703 } | 1691 } |
| 1704 | 1692 |
| 1705 /// Create a write access to [local] with the provided [value]. | 1693 /// Create a write access to [local] with the provided [value]. |
| 1706 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { | 1694 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { |
| 1707 assert(isOpen); | 1695 assert(isOpen); |
| 1708 if (isInClosureVariable(local)) { | 1696 if (isInMutableVariable(local)) { |
| 1709 add(new ir.SetClosureVariable(getClosureVariable(local), value)); | 1697 add(new ir.SetMutableVariable(getMutableVariable(local), value)); |
| 1710 } else { | 1698 } else { |
| 1711 value.useElementAsHint(local); | 1699 value.useElementAsHint(local); |
| 1712 environment.update(local, value); | 1700 environment.update(local, value); |
| 1713 } | 1701 } |
| 1714 return value; | 1702 return value; |
| 1715 } | 1703 } |
| 1716 | 1704 |
| 1717 ir.Primitive buildThis() { | 1705 ir.Primitive buildThis() { |
| 1718 ir.Primitive thisPrim = new ir.This(); | 1706 ir.Primitive thisPrim = new ir.This(); |
| 1719 add(new ir.LetPrim(thisPrim)); | 1707 add(new ir.LetPrim(thisPrim)); |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2028 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); | 2016 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); |
| 2029 } | 2017 } |
| 2030 | 2018 |
| 2031 /// Information about which variables are captured by a nested function. | 2019 /// Information about which variables are captured by a nested function. |
| 2032 /// | 2020 /// |
| 2033 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and | 2021 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and |
| 2034 /// [ClosureEnvironment]. | 2022 /// [ClosureEnvironment]. |
| 2035 abstract class DartCapturedVariableInfo { | 2023 abstract class DartCapturedVariableInfo { |
| 2036 Iterable<Local> get capturedVariables; | 2024 Iterable<Local> get capturedVariables; |
| 2037 } | 2025 } |
| OLD | NEW |