OLD | NEW |
1 library dart2js.unsugar_cps; | 1 library dart2js.unsugar_cps; |
2 | 2 |
3 import '../../cps_ir/cps_ir_nodes.dart'; | 3 import '../../cps_ir/cps_ir_nodes.dart'; |
4 | 4 |
5 import '../../cps_ir/optimizers.dart' show Pass; | 5 import '../../cps_ir/optimizers.dart' show Pass; |
6 import '../../constants/values.dart'; | 6 import '../../constants/values.dart'; |
7 import '../../elements/elements.dart'; | 7 import '../../elements/elements.dart'; |
8 import '../../js_backend/codegen/glue.dart'; | 8 import '../../js_backend/codegen/glue.dart'; |
9 import '../../universe/selector.dart' show Selector; | 9 import '../../universe/selector.dart' show Selector; |
10 import '../../cps_ir/cps_fragment.dart'; | 10 import '../../cps_ir/cps_fragment.dart'; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 // body; | 100 // body; |
101 // | 101 // |
102 // with | 102 // with |
103 // | 103 // |
104 // if (identical(arg, null)) | 104 // if (identical(arg, null)) |
105 // return false; | 105 // return false; |
106 // else | 106 // else |
107 // body; | 107 // body; |
108 // | 108 // |
109 CpsFragment cps = new CpsFragment(); | 109 CpsFragment cps = new CpsFragment(); |
110 Primitive isNull = cps.applyBuiltin( | 110 Primitive isNull = cps.applyBuiltin(BuiltinOperator.Identical, |
111 BuiltinOperator.Identical, | |
112 <Primitive>[function.parameters.single, cps.makeNull()]); | 111 <Primitive>[function.parameters.single, cps.makeNull()]); |
113 CpsFragment trueBranch = cps.ifTruthy(isNull); | 112 CpsFragment trueBranch = cps.ifTruthy(isNull); |
114 trueBranch.invokeContinuation(function.returnContinuation, | 113 trueBranch.invokeContinuation( |
115 <Primitive>[trueBranch.makeFalse()]); | 114 function.returnContinuation, <Primitive>[trueBranch.makeFalse()]); |
116 cps.insertAbove(function.body); | 115 cps.insertAbove(function.body); |
117 } | 116 } |
118 | 117 |
119 /// Insert a static call to [function] immediately above [node]. | 118 /// Insert a static call to [function] immediately above [node]. |
120 Primitive insertStaticCallAbove(FunctionElement function, | 119 Primitive insertStaticCallAbove( |
121 List<Primitive> arguments, Expression node) { | 120 FunctionElement function, List<Primitive> arguments, Expression node) { |
122 // TODO(johnniwinther): Come up with an implementation of SourceInformation | 121 // TODO(johnniwinther): Come up with an implementation of SourceInformation |
123 // for calls such as this one that don't appear in the original source. | 122 // for calls such as this one that don't appear in the original source. |
124 InvokeStatic invoke = new InvokeStatic( | 123 InvokeStatic invoke = new InvokeStatic( |
125 function, new Selector.fromElement(function), arguments, null); | 124 function, new Selector.fromElement(function), arguments, null); |
126 new LetPrim(invoke).insertAbove(node); | 125 new LetPrim(invoke).insertAbove(node); |
127 return invoke; | 126 return invoke; |
128 } | 127 } |
129 | 128 |
130 @override | 129 @override |
131 Expression traverseLetHandler(LetHandler node) { | 130 Expression traverseLetHandler(LetHandler node) { |
(...skipping 13 matching lines...) Expand all Loading... |
145 [new Parameter(null)], // Dummy argument, see below. | 144 [new Parameter(null)], // Dummy argument, see below. |
146 body); | 145 body); |
147 _exceptionParameter.replaceUsesWith(unwrapped); | 146 _exceptionParameter.replaceUsesWith(unwrapped); |
148 | 147 |
149 // Replace the dummy with the exception parameter. It must be set after | 148 // Replace the dummy with the exception parameter. It must be set after |
150 // replacing all uses of [_exceptionParameter]. | 149 // replacing all uses of [_exceptionParameter]. |
151 unwrapped.argumentRefs[0].changeTo(_exceptionParameter); | 150 unwrapped.argumentRefs[0].changeTo(_exceptionParameter); |
152 | 151 |
153 if (stackTraceParameter.hasAtLeastOneUse) { | 152 if (stackTraceParameter.hasAtLeastOneUse) { |
154 InvokeStatic stackTraceValue = insertStaticCallAbove( | 153 InvokeStatic stackTraceValue = insertStaticCallAbove( |
155 _glue.getTraceFromException(), | 154 _glue.getTraceFromException(), [_exceptionParameter], body); |
156 [_exceptionParameter], | |
157 body); | |
158 stackTraceParameter.replaceUsesWith(stackTraceValue); | 155 stackTraceParameter.replaceUsesWith(stackTraceValue); |
159 } | 156 } |
160 } | 157 } |
161 | 158 |
162 assert(stackTraceParameter.hasNoUses); | 159 assert(stackTraceParameter.hasNoUses); |
163 node.handler.parameters.removeLast(); | 160 node.handler.parameters.removeLast(); |
164 | 161 |
165 visit(node.handler); | 162 visit(node.handler); |
166 _exceptionParameter = previousExceptionParameter; | 163 _exceptionParameter = previousExceptionParameter; |
167 | 164 |
168 return node.body; | 165 return node.body; |
169 } | 166 } |
170 | 167 |
171 processThrow(Throw node) { | 168 processThrow(Throw node) { |
172 // The subexpression of throw is wrapped in the JavaScript output. | 169 // The subexpression of throw is wrapped in the JavaScript output. |
173 Primitive wrappedException = insertStaticCallAbove( | 170 Primitive wrappedException = insertStaticCallAbove( |
174 _glue.getWrapExceptionHelper(), | 171 _glue.getWrapExceptionHelper(), [node.value], node); |
175 [node.value], | |
176 node); | |
177 node.valueRef.changeTo(wrappedException); | 172 node.valueRef.changeTo(wrappedException); |
178 } | 173 } |
179 | 174 |
180 processRethrow(Rethrow node) { | 175 processRethrow(Rethrow node) { |
181 // Rethrow can only appear in a catch block. It throws that block's | 176 // Rethrow can only appear in a catch block. It throws that block's |
182 // (wrapped) caught exception. | 177 // (wrapped) caught exception. |
183 Throw replacement = new Throw(_exceptionParameter); | 178 Throw replacement = new Throw(_exceptionParameter); |
184 InteriorNode parent = node.parent; | 179 InteriorNode parent = node.parent; |
185 parent.body = replacement; | 180 parent.body = replacement; |
186 replacement.parent = parent; | 181 replacement.parent = parent; |
187 // The original rethrow does not have any references that we need to | 182 // The original rethrow does not have any references that we need to |
188 // worry about unlinking. | 183 // worry about unlinking. |
189 } | 184 } |
190 | 185 |
191 bool isNullConstant(Primitive prim) { | 186 bool isNullConstant(Primitive prim) { |
192 return prim is Constant && prim.value.isNull; | 187 return prim is Constant && prim.value.isNull; |
193 } | 188 } |
194 | 189 |
195 processInvokeMethod(InvokeMethod node) { | 190 processInvokeMethod(InvokeMethod node) { |
196 Selector selector = node.selector; | 191 Selector selector = node.selector; |
197 if (!_glue.isInterceptedSelector(selector)) return; | 192 if (!_glue.isInterceptedSelector(selector)) return; |
198 | 193 |
199 // Some platform libraries will compare non-interceptable objects against | 194 // Some platform libraries will compare non-interceptable objects against |
200 // null using the Dart == operator. These must be translated directly. | 195 // null using the Dart == operator. These must be translated directly. |
201 if (node.selector == Selectors.equals && | 196 if (node.selector == Selectors.equals && |
202 node.argumentRefs.length == 1 && | 197 node.argumentRefs.length == 1 && |
203 isNullConstant(node.argument(0))) { | 198 isNullConstant(node.argument(0))) { |
204 node.replaceWith(new ApplyBuiltinOperator( | 199 node.replaceWith(new ApplyBuiltinOperator(BuiltinOperator.Identical, |
205 BuiltinOperator.Identical, | 200 [node.receiver, node.argument(0)], node.sourceInformation)); |
206 [node.receiver, node.argument(0)], | |
207 node.sourceInformation)); | |
208 return; | 201 return; |
209 } | 202 } |
210 | 203 |
211 Primitive receiver = node.receiver; | 204 Primitive receiver = node.receiver; |
212 Primitive interceptor; | 205 Primitive interceptor; |
213 | 206 |
214 if (receiver == receiverParameter && receiverInterceptor != null) { | 207 if (receiver == receiverParameter && receiverInterceptor != null) { |
215 // TODO(asgerf): This could be done by GVN. | 208 // TODO(asgerf): This could be done by GVN. |
216 // If the receiver is 'this', we are calling a method in | 209 // If the receiver is 'this', we are calling a method in |
217 // the same interceptor: | 210 // the same interceptor: |
(...skipping 25 matching lines...) Expand all Loading... |
243 interceptor = new Interceptor(receiver, node.sourceInformation); | 236 interceptor = new Interceptor(receiver, node.sourceInformation); |
244 if (receiver.hint != null) { | 237 if (receiver.hint != null) { |
245 interceptor.hint = new InterceptorEntity(receiver.hint); | 238 interceptor.hint = new InterceptorEntity(receiver.hint); |
246 } | 239 } |
247 new LetPrim(interceptor).insertAbove(node.parent); | 240 new LetPrim(interceptor).insertAbove(node.parent); |
248 } | 241 } |
249 assert(node.interceptorRef == null); | 242 assert(node.interceptorRef == null); |
250 node.makeIntercepted(interceptor); | 243 node.makeIntercepted(interceptor); |
251 } | 244 } |
252 } | 245 } |
OLD | NEW |