| 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 925 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 JumpTarget target, | 936 JumpTarget target, |
| 937 ClosureScope closureScope, | 937 ClosureScope closureScope, |
| 938 List<LocalElement> loopVariables}) { | 938 List<LocalElement> loopVariables}) { |
| 939 assert(isOpen); | 939 assert(isOpen); |
| 940 | 940 |
| 941 // For loops use four named continuations: the entry to the condition, | 941 // For loops use four named continuations: the entry to the condition, |
| 942 // the entry to the body, the loop exit, and the loop successor (break). | 942 // the entry to the body, the loop exit, and the loop successor (break). |
| 943 // The CPS translation of | 943 // The CPS translation of |
| 944 // [[for (initializer; condition; update) body; successor]] is: | 944 // [[for (initializer; condition; update) body; successor]] is: |
| 945 // | 945 // |
| 946 // _enterForLoopInitializer(); |
| 946 // [[initializer]]; | 947 // [[initializer]]; |
| 947 // let cont loop(x, ...) = | 948 // let cont loop(x, ...) = |
| 948 // let prim cond = [[condition]] in | 949 // let prim cond = [[condition]] in |
| 949 // let cont break() = [[successor]] in | 950 // let cont break() = [[successor]] in |
| 950 // let cont exit() = break(v, ...) in | 951 // let cont exit() = break(v, ...) in |
| 951 // let cont body() = | 952 // let cont body() = |
| 952 // let cont continue(x, ...) = [[update]]; loop(v, ...) in | 953 // _enterForLoopBody(); |
| 953 // [[body]]; continue(v, ...) in | 954 // let cont continue(x, ...) = |
| 955 // _enterForLoopUpdate(); |
| 956 // [[update]]; |
| 957 // loop(v, ...) in |
| 958 // [[body]]; |
| 959 // continue(v, ...) in |
| 954 // branch cond (body, exit) in | 960 // branch cond (body, exit) in |
| 955 // loop(v, ...) | 961 // loop(v, ...) |
| 956 // | 962 // |
| 957 // If there are no breaks in the body, the break continuation is inlined | 963 // If there are no breaks in the body, the break continuation is inlined |
| 958 // in the exit continuation (i.e., the translation of the successor | 964 // in the exit continuation (i.e., the translation of the successor |
| 959 // statement occurs in the exit continuation). If there is only one | 965 // statement occurs in the exit continuation). If there is only one |
| 960 // invocation of the continue continuation (i.e., no continues in the | 966 // invocation of the continue continuation (i.e., no continues in the |
| 961 // body), the continue continuation is inlined in the body. | 967 // body), the continue continuation is inlined in the body. |
| 962 | 968 |
| 963 _enterForLoopInitializer(closureScope, loopVariables); | 969 _enterForLoopInitializer(closureScope, loopVariables); |
| 964 | 970 |
| 965 buildInitializer(this); | 971 buildInitializer(this); |
| 966 | 972 |
| 967 IrBuilder condBuilder = makeRecursiveBuilder(); | 973 IrBuilder condBuilder = makeRecursiveBuilder(); |
| 968 ir.Primitive condition = buildCondition(condBuilder); | 974 ir.Primitive condition = buildCondition(condBuilder); |
| 969 if (condition == null) { | 975 if (condition == null) { |
| 970 // If the condition is empty then the body is entered unconditionally. | 976 // If the condition is empty then the body is entered unconditionally. |
| 971 condition = condBuilder.buildBooleanLiteral(true); | 977 condition = condBuilder.buildBooleanLiteral(true); |
| 972 } | 978 } |
| 973 | 979 |
| 974 JumpCollector breakCollector = new JumpCollector(target); | 980 JumpCollector breakCollector = new JumpCollector(target); |
| 975 JumpCollector continueCollector = new JumpCollector(target); | 981 JumpCollector continueCollector = new JumpCollector(target); |
| 976 state.breakCollectors.add(breakCollector); | 982 state.breakCollectors.add(breakCollector); |
| 977 state.continueCollectors.add(continueCollector); | 983 state.continueCollectors.add(continueCollector); |
| 978 | 984 |
| 979 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder(); | 985 IrBuilder outerBodyBuilder = condBuilder.makeDelimitedBuilder(); |
| 986 outerBodyBuilder._enterForLoopBody(closureScope, loopVariables); |
| 980 | 987 |
| 981 bodyBuilder._enterForLoopBody(closureScope, loopVariables); | 988 IrBuilder innerBodyBuilder = outerBodyBuilder.makeDelimitedBuilder(); |
| 982 | 989 |
| 983 buildBody(bodyBuilder); | 990 buildBody(innerBodyBuilder); |
| 984 assert(state.breakCollectors.last == breakCollector); | 991 assert(state.breakCollectors.last == breakCollector); |
| 985 assert(state.continueCollectors.last == continueCollector); | 992 assert(state.continueCollectors.last == continueCollector); |
| 986 state.breakCollectors.removeLast(); | 993 state.breakCollectors.removeLast(); |
| 987 state.continueCollectors.removeLast(); | 994 state.continueCollectors.removeLast(); |
| 988 | 995 |
| 989 // The binding of the continue continuation should occur as late as | 996 // The binding of the continue continuation should occur as late as |
| 990 // possible, that is, at the nearest common ancestor of all the continue | 997 // possible, that is, at the nearest common ancestor of all the continue |
| 991 // sites in the body. However, that is difficult to compute here, so it | 998 // sites in the body. However, that is difficult to compute here, so it |
| 992 // is instead placed just outside the body of the body continuation. | 999 // is instead placed just outside the body of the body continuation. |
| 993 bool hasContinues = !continueCollector.isEmpty; | 1000 bool hasContinues = !continueCollector.isEmpty; |
| 994 IrBuilder updateBuilder = hasContinues | 1001 IrBuilder updateBuilder = hasContinues |
| 995 ? condBuilder.makeRecursiveBuilder() | 1002 ? outerBodyBuilder.makeRecursiveBuilder() |
| 996 : bodyBuilder; | 1003 : innerBodyBuilder; |
| 997 updateBuilder._enterForLoopUpdate(closureScope, loopVariables); | 1004 updateBuilder._enterForLoopUpdate(closureScope, loopVariables); |
| 998 buildUpdate(updateBuilder); | 1005 buildUpdate(updateBuilder); |
| 999 | 1006 |
| 1000 // Create body entry and loop exit continuations and a branch to them. | 1007 // Create body entry and loop exit continuations and a branch to them. |
| 1001 ir.Continuation bodyContinuation = new ir.Continuation([]); | 1008 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 1002 ir.Continuation exitContinuation = new ir.Continuation([]); | 1009 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 1003 // Note the order of continuations: the first one is the one that will | 1010 // Note the order of continuations: the first one is the one that will |
| 1004 // be filled by LetCont.plug. | 1011 // be filled by LetCont.plug. |
| 1005 ir.LetCont branch = | 1012 ir.LetCont branch = |
| 1006 new ir.LetCont.many(<ir.Continuation>[exitContinuation, | 1013 new ir.LetCont.many(<ir.Continuation>[exitContinuation, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1017 condBuilder.add(letJoin); | 1024 condBuilder.add(letJoin); |
| 1018 condBuilder._current = branch; | 1025 condBuilder._current = branch; |
| 1019 } else { | 1026 } else { |
| 1020 condBuilder.add(branch); | 1027 condBuilder.add(branch); |
| 1021 } | 1028 } |
| 1022 ir.Continuation continueContinuation; | 1029 ir.Continuation continueContinuation; |
| 1023 if (hasContinues) { | 1030 if (hasContinues) { |
| 1024 // If there are continues in the body, we need a named continue | 1031 // If there are continues in the body, we need a named continue |
| 1025 // continuation as a join point. | 1032 // continuation as a join point. |
| 1026 continueContinuation = new ir.Continuation(updateBuilder._parameters); | 1033 continueContinuation = new ir.Continuation(updateBuilder._parameters); |
| 1027 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); | 1034 if (innerBodyBuilder.isOpen) continueCollector.addJump(innerBodyBuilder); |
| 1028 invokeFullJoin(continueContinuation, continueCollector); | 1035 invokeFullJoin(continueContinuation, continueCollector); |
| 1029 } | 1036 } |
| 1030 ir.Continuation loopContinuation = | 1037 ir.Continuation loopContinuation = |
| 1031 new ir.Continuation(condBuilder._parameters); | 1038 new ir.Continuation(condBuilder._parameters); |
| 1032 if (updateBuilder.isOpen) { | 1039 if (updateBuilder.isOpen) { |
| 1033 JumpCollector backEdges = new JumpCollector(null); | 1040 JumpCollector backEdges = new JumpCollector(null); |
| 1034 backEdges.addJump(updateBuilder); | 1041 backEdges.addJump(updateBuilder); |
| 1035 invokeFullJoin(loopContinuation, backEdges, recursive: true); | 1042 invokeFullJoin(loopContinuation, backEdges, recursive: true); |
| 1036 } | 1043 } |
| 1037 | 1044 |
| 1038 // Fill in the body and possible continue continuation bodies. Do this | 1045 // Fill in the body and possible continue continuation bodies. Do this |
| 1039 // only after it is guaranteed that they are not empty. | 1046 // only after it is guaranteed that they are not empty. |
| 1040 if (hasContinues) { | 1047 if (hasContinues) { |
| 1041 continueContinuation.body = updateBuilder._root; | 1048 continueContinuation.body = updateBuilder._root; |
| 1042 bodyContinuation.body = | 1049 outerBodyBuilder.add(new ir.LetCont(continueContinuation, |
| 1043 new ir.LetCont(continueContinuation, | 1050 innerBodyBuilder._root)); |
| 1044 bodyBuilder._root); | |
| 1045 } else { | 1051 } else { |
| 1046 bodyContinuation.body = bodyBuilder._root; | 1052 outerBodyBuilder.add(innerBodyBuilder._root); |
| 1047 } | 1053 } |
| 1054 bodyContinuation.body = outerBodyBuilder._root; |
| 1048 | 1055 |
| 1049 loopContinuation.body = condBuilder._root; | 1056 loopContinuation.body = condBuilder._root; |
| 1050 add(new ir.LetCont(loopContinuation, | 1057 add(new ir.LetCont(loopContinuation, |
| 1051 new ir.InvokeContinuation(loopContinuation, | 1058 new ir.InvokeContinuation(loopContinuation, |
| 1052 environment.index2value))); | 1059 environment.index2value))); |
| 1053 if (hasBreaks) { | 1060 if (hasBreaks) { |
| 1054 _current = branch; | 1061 _current = branch; |
| 1055 environment = condBuilder.environment; | 1062 environment = condBuilder.environment; |
| 1056 breakCollector.addJump(this); | 1063 breakCollector.addJump(this); |
| 1057 letJoin.continuations = | 1064 letJoin.continuations = |
| (...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2111 final Map<Local, ClosureLocation> freeVariables; | 2118 final Map<Local, ClosureLocation> freeVariables; |
| 2112 | 2119 |
| 2113 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); | 2120 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); |
| 2114 } | 2121 } |
| 2115 | 2122 |
| 2116 class TryStatementInfo { | 2123 class TryStatementInfo { |
| 2117 final Set<LocalVariableElement> declared = new Set<LocalVariableElement>(); | 2124 final Set<LocalVariableElement> declared = new Set<LocalVariableElement>(); |
| 2118 final Set<LocalVariableElement> boxedOnEntry = | 2125 final Set<LocalVariableElement> boxedOnEntry = |
| 2119 new Set<LocalVariableElement>(); | 2126 new Set<LocalVariableElement>(); |
| 2120 } | 2127 } |
| OLD | NEW |