| 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 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 toString() => 'ThisParameterLocal($executableContext)'; | 409 toString() => 'ThisParameterLocal($executableContext)'; |
| 410 } | 410 } |
| 411 | 411 |
| 412 /// A factory for building the cps IR. | 412 /// A factory for building the cps IR. |
| 413 /// | 413 /// |
| 414 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured | 414 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured |
| 415 /// variables in different ways. | 415 /// variables in different ways. |
| 416 abstract class IrBuilder { | 416 abstract class IrBuilder { |
| 417 IrBuilder _makeInstance(); | 417 IrBuilder _makeInstance(); |
| 418 | 418 |
| 419 // TODO(johnniwinther): Remove this from the [IrBuilder]. | |
| 420 /// A map from TryStatements in the AST to their analysis information. | |
| 421 /// | |
| 422 /// This includes which variables should be copied into [ir.MutableVariable]s | |
| 423 /// on entry to the try and copied out on exit. | |
| 424 Map<ast.TryStatement, TryStatementInfo> get tryStatements; | |
| 425 | |
| 426 /// The set of local variables that will spend their lifetime as | |
| 427 /// [ir.MutableVariable]s due to being captured by a nested function. | |
| 428 Set<Local> get mutableCapturedVariables; | |
| 429 | |
| 430 /// True if [local] should currently be accessed from a [ir.MutableVariable]. | 419 /// True if [local] should currently be accessed from a [ir.MutableVariable]. |
| 431 bool isInMutableVariable(Local local); | 420 bool isInMutableVariable(Local local); |
| 432 | 421 |
| 433 /// Creates a [ir.MutableVariable] for the given local. | 422 /// Creates a [ir.MutableVariable] for the given local. |
| 434 void makeMutableVariable(Local local); | 423 void makeMutableVariable(Local local); |
| 435 | 424 |
| 436 /// Remove an [ir.MutableVariable] for a local. | 425 /// Remove an [ir.MutableVariable] for a local. |
| 437 /// | 426 /// |
| 438 /// Subsequent access to the local will be direct rather than through the | 427 /// Subsequent access to the local will be direct rather than through the |
| 439 /// mutable variable. This is used for variables that do not spend their | 428 /// mutable variable. This is used for variables that do not spend their |
| (...skipping 1146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1586 // variables are unboxed in the catch block and at the join point. | 1575 // variables are unboxed in the catch block and at the join point. |
| 1587 JumpCollector join = new ForwardJumpCollector(environment); | 1576 JumpCollector join = new ForwardJumpCollector(environment); |
| 1588 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); | 1577 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); |
| 1589 | 1578 |
| 1590 // Variables that are boxed due to being captured in a closure are boxed | 1579 // Variables that are boxed due to being captured in a closure are boxed |
| 1591 // for their entire lifetime, and so they do not need to be boxed on | 1580 // for their entire lifetime, and so they do not need to be boxed on |
| 1592 // entry to any try block. They are not filtered out before this because | 1581 // entry to any try block. They are not filtered out before this because |
| 1593 // we can not identify all of them in the same pass where we identify the | 1582 // we can not identify all of them in the same pass where we identify the |
| 1594 // variables assigned in the try (they may be captured by a closure after | 1583 // variables assigned in the try (they may be captured by a closure after |
| 1595 // the try statement). | 1584 // the try statement). |
| 1596 Iterable<LocalVariableElement> boxedOnEntry = | 1585 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) { |
| 1597 tryStatementInfo.boxedOnEntry.where((LocalVariableElement variable) { | |
| 1598 return !tryCatchBuilder.mutableCapturedVariables.contains(variable); | |
| 1599 }); | |
| 1600 for (LocalVariableElement variable in boxedOnEntry) { | |
| 1601 assert(!tryCatchBuilder.isInMutableVariable(variable)); | 1586 assert(!tryCatchBuilder.isInMutableVariable(variable)); |
| 1602 ir.Primitive value = tryCatchBuilder.buildLocalGet(variable); | 1587 ir.Primitive value = tryCatchBuilder.buildLocalGet(variable); |
| 1603 tryCatchBuilder.makeMutableVariable(variable); | 1588 tryCatchBuilder.makeMutableVariable(variable); |
| 1604 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); | 1589 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); |
| 1605 } | 1590 } |
| 1606 | 1591 |
| 1607 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1592 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1608 | 1593 |
| 1609 void interceptJumps(JumpCollector collector) { | 1594 void interceptJumps(JumpCollector collector) { |
| 1610 collector.enterTry(boxedOnEntry); | 1595 collector.enterTry(tryStatementInfo.boxedOnEntry); |
| 1611 } | 1596 } |
| 1612 void restoreJumps(JumpCollector collector) { | 1597 void restoreJumps(JumpCollector collector) { |
| 1613 collector.leaveTry(); | 1598 collector.leaveTry(); |
| 1614 } | 1599 } |
| 1615 tryBuilder.state.breakCollectors.forEach(interceptJumps); | 1600 tryBuilder.state.breakCollectors.forEach(interceptJumps); |
| 1616 tryBuilder.state.continueCollectors.forEach(interceptJumps); | 1601 tryBuilder.state.continueCollectors.forEach(interceptJumps); |
| 1617 buildTryBlock(tryBuilder); | 1602 buildTryBlock(tryBuilder); |
| 1618 if (tryBuilder.isOpen) { | 1603 if (tryBuilder.isOpen) { |
| 1619 interceptJumps(join); | 1604 interceptJumps(join); |
| 1620 tryBuilder.jumpTo(join); | 1605 tryBuilder.jumpTo(join); |
| 1621 restoreJumps(join); | 1606 restoreJumps(join); |
| 1622 } | 1607 } |
| 1623 tryBuilder.state.breakCollectors.forEach(restoreJumps); | 1608 tryBuilder.state.breakCollectors.forEach(restoreJumps); |
| 1624 tryBuilder.state.continueCollectors.forEach(restoreJumps); | 1609 tryBuilder.state.continueCollectors.forEach(restoreJumps); |
| 1625 | 1610 |
| 1626 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1611 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1627 for (LocalVariableElement variable in boxedOnEntry) { | 1612 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) { |
| 1628 assert(catchBuilder.isInMutableVariable(variable)); | 1613 assert(catchBuilder.isInMutableVariable(variable)); |
| 1629 ir.Primitive value = catchBuilder.buildLocalGet(variable); | 1614 ir.Primitive value = catchBuilder.buildLocalGet(variable); |
| 1630 // Note that we remove the variable from the set of mutable variables | 1615 // Note that we remove the variable from the set of mutable variables |
| 1631 // here (and not above for the try body). This is because the set of | 1616 // here (and not above for the try body). This is because the set of |
| 1632 // mutable variables is global for the whole function and not local to | 1617 // mutable variables is global for the whole function and not local to |
| 1633 // a delimited builder. | 1618 // a delimited builder. |
| 1634 catchBuilder.removeMutableVariable(variable); | 1619 catchBuilder.removeMutableVariable(variable); |
| 1635 catchBuilder.environment.update(variable, value); | 1620 catchBuilder.environment.update(variable, value); |
| 1636 } | 1621 } |
| 1637 | 1622 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1895 return join.continuation.parameters.last; | 1880 return join.continuation.parameters.last; |
| 1896 } | 1881 } |
| 1897 } | 1882 } |
| 1898 | 1883 |
| 1899 /// Shared state between DartIrBuilders within the same method. | 1884 /// Shared state between DartIrBuilders within the same method. |
| 1900 class DartIrBuilderSharedState { | 1885 class DartIrBuilderSharedState { |
| 1901 /// Maps local variables to their corresponding [MutableVariable] object. | 1886 /// Maps local variables to their corresponding [MutableVariable] object. |
| 1902 final Map<Local, ir.MutableVariable> local2mutable = | 1887 final Map<Local, ir.MutableVariable> local2mutable = |
| 1903 <Local, ir.MutableVariable>{}; | 1888 <Local, ir.MutableVariable>{}; |
| 1904 | 1889 |
| 1905 // Move this to the IrBuilderVisitor. | |
| 1906 final DartCapturedVariables capturedVariables; | |
| 1907 | |
| 1908 /// Creates a [MutableVariable] for the given local. | 1890 /// Creates a [MutableVariable] for the given local. |
| 1909 void makeMutableVariable(Local local) { | 1891 void makeMutableVariable(Local local) { |
| 1910 ir.MutableVariable variable = | 1892 ir.MutableVariable variable = |
| 1911 new ir.MutableVariable(local.executableContext, local); | 1893 new ir.MutableVariable(local.executableContext, local); |
| 1912 local2mutable[local] = variable; | 1894 local2mutable[local] = variable; |
| 1913 } | 1895 } |
| 1914 | 1896 |
| 1915 /// [MutableVariable]s that should temporarily be treated as registers. | 1897 /// [MutableVariable]s that should temporarily be treated as registers. |
| 1916 final Set<Local> registerizedMutableVariables = new Set<Local>(); | 1898 final Set<Local> registerizedMutableVariables = new Set<Local>(); |
| 1917 | 1899 |
| 1918 DartIrBuilderSharedState(this.capturedVariables) { | 1900 DartIrBuilderSharedState(Set<Local> capturedVariables) { |
| 1919 capturedVariables.capturedVariables.forEach(makeMutableVariable); | 1901 capturedVariables.forEach(makeMutableVariable); |
| 1920 } | 1902 } |
| 1921 } | 1903 } |
| 1922 | 1904 |
| 1923 /// Dart-specific subclass of [IrBuilder]. | 1905 /// Dart-specific subclass of [IrBuilder]. |
| 1924 /// | 1906 /// |
| 1925 /// Inner functions are represented by a [FunctionDefinition] with the | 1907 /// Inner functions are represented by a [FunctionDefinition] with the |
| 1926 /// IR for the inner function nested inside. | 1908 /// IR for the inner function nested inside. |
| 1927 /// | 1909 /// |
| 1928 /// Captured variables are translated to ref cells (see [MutableVariable]) | 1910 /// Captured variables are translated to ref cells (see [MutableVariable]) |
| 1929 /// using [GetMutableVariable] and [SetMutableVariable]. | 1911 /// using [GetMutableVariable] and [SetMutableVariable]. |
| 1930 class DartIrBuilder extends IrBuilder { | 1912 class DartIrBuilder extends IrBuilder { |
| 1931 final DartIrBuilderSharedState dartState; | 1913 final DartIrBuilderSharedState dartState; |
| 1932 | 1914 |
| 1933 IrBuilder _makeInstance() => new DartIrBuilder._blank(dartState); | 1915 IrBuilder _makeInstance() => new DartIrBuilder._blank(dartState); |
| 1934 DartIrBuilder._blank(this.dartState); | 1916 DartIrBuilder._blank(this.dartState); |
| 1935 | 1917 |
| 1936 DartIrBuilder(ConstantSystem constantSystem, | 1918 DartIrBuilder(ConstantSystem constantSystem, |
| 1937 ExecutableElement currentElement, | 1919 ExecutableElement currentElement, |
| 1938 DartCapturedVariables capturedVariables) | 1920 Set<Local> capturedVariables) |
| 1939 : dartState = new DartIrBuilderSharedState(capturedVariables) { | 1921 : dartState = new DartIrBuilderSharedState(capturedVariables) { |
| 1940 _init(constantSystem, currentElement); | 1922 _init(constantSystem, currentElement); |
| 1941 } | 1923 } |
| 1942 | 1924 |
| 1943 Map<ast.TryStatement, TryStatementInfo> get tryStatements { | |
| 1944 return dartState.capturedVariables.tryStatements; | |
| 1945 } | |
| 1946 | |
| 1947 Set<Local> get mutableCapturedVariables { | |
| 1948 return dartState.capturedVariables.capturedVariables; | |
| 1949 } | |
| 1950 | |
| 1951 bool isInMutableVariable(Local local) { | 1925 bool isInMutableVariable(Local local) { |
| 1952 return dartState.local2mutable.containsKey(local) && | 1926 return dartState.local2mutable.containsKey(local) && |
| 1953 !dartState.registerizedMutableVariables.contains(local); | 1927 !dartState.registerizedMutableVariables.contains(local); |
| 1954 } | 1928 } |
| 1955 | 1929 |
| 1956 void makeMutableVariable(Local local) { | 1930 void makeMutableVariable(Local local) { |
| 1957 dartState.makeMutableVariable(local); | 1931 dartState.makeMutableVariable(local); |
| 1958 } | 1932 } |
| 1959 | 1933 |
| 1960 void removeMutableVariable(Local local) { | 1934 void removeMutableVariable(Local local) { |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2536 } | 2510 } |
| 2537 | 2511 |
| 2538 /// Synthetic parameter to a JavaScript factory method that takes the type | 2512 /// Synthetic parameter to a JavaScript factory method that takes the type |
| 2539 /// argument given for the type variable [variable]. | 2513 /// argument given for the type variable [variable]. |
| 2540 class TypeInformationParameter implements Local { | 2514 class TypeInformationParameter implements Local { |
| 2541 final TypeVariableElement variable; | 2515 final TypeVariableElement variable; |
| 2542 final ExecutableElement executableContext; | 2516 final ExecutableElement executableContext; |
| 2543 TypeInformationParameter(this.variable, this.executableContext); | 2517 TypeInformationParameter(this.variable, this.executableContext); |
| 2544 String get name => variable.name; | 2518 String get name => variable.name; |
| 2545 } | 2519 } |
| OLD | NEW |