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_ir_builder.dart' show ThisParameterLocal; | 10 import '../../cps_ir/cps_ir_builder.dart' show ThisParameterLocal; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 if (_exceptionParameter.hasAtLeastOneUse || | 143 if (_exceptionParameter.hasAtLeastOneUse || |
144 stackTraceParameter.hasAtLeastOneUse) { | 144 stackTraceParameter.hasAtLeastOneUse) { |
145 InvokeStatic unwrapped = insertStaticCallAbove( | 145 InvokeStatic unwrapped = insertStaticCallAbove( |
146 _glue.getExceptionUnwrapper(), | 146 _glue.getExceptionUnwrapper(), |
147 [new Parameter(null)], // Dummy argument, see below. | 147 [new Parameter(null)], // Dummy argument, see below. |
148 body); | 148 body); |
149 _exceptionParameter.replaceUsesWith(unwrapped); | 149 _exceptionParameter.replaceUsesWith(unwrapped); |
150 | 150 |
151 // Replace the dummy with the exception parameter. It must be set after | 151 // Replace the dummy with the exception parameter. It must be set after |
152 // replacing all uses of [_exceptionParameter]. | 152 // replacing all uses of [_exceptionParameter]. |
153 unwrapped.arguments[0].changeTo(_exceptionParameter); | 153 unwrapped.argumentRefs[0].changeTo(_exceptionParameter); |
154 | 154 |
155 if (stackTraceParameter.hasAtLeastOneUse) { | 155 if (stackTraceParameter.hasAtLeastOneUse) { |
156 InvokeStatic stackTraceValue = insertStaticCallAbove( | 156 InvokeStatic stackTraceValue = insertStaticCallAbove( |
157 _glue.getTraceFromException(), | 157 _glue.getTraceFromException(), |
158 [_exceptionParameter], | 158 [_exceptionParameter], |
159 body); | 159 body); |
160 stackTraceParameter.replaceUsesWith(stackTraceValue); | 160 stackTraceParameter.replaceUsesWith(stackTraceValue); |
161 } | 161 } |
162 } | 162 } |
163 | 163 |
164 assert(stackTraceParameter.hasNoUses); | 164 assert(stackTraceParameter.hasNoUses); |
165 node.handler.parameters.removeLast(); | 165 node.handler.parameters.removeLast(); |
166 | 166 |
167 visit(node.handler); | 167 visit(node.handler); |
168 _exceptionParameter = previousExceptionParameter; | 168 _exceptionParameter = previousExceptionParameter; |
169 | 169 |
170 return node.body; | 170 return node.body; |
171 } | 171 } |
172 | 172 |
173 processThrow(Throw node) { | 173 processThrow(Throw node) { |
174 // The subexpression of throw is wrapped in the JavaScript output. | 174 // The subexpression of throw is wrapped in the JavaScript output. |
175 Primitive wrappedException = insertStaticCallAbove( | 175 Primitive wrappedException = insertStaticCallAbove( |
176 _glue.getWrapExceptionHelper(), | 176 _glue.getWrapExceptionHelper(), |
177 [node.value.definition], | 177 [node.value], |
178 node); | 178 node); |
179 node.value.changeTo(wrappedException); | 179 node.valueRef.changeTo(wrappedException); |
180 } | 180 } |
181 | 181 |
182 processRethrow(Rethrow node) { | 182 processRethrow(Rethrow node) { |
183 // Rethrow can only appear in a catch block. It throws that block's | 183 // Rethrow can only appear in a catch block. It throws that block's |
184 // (wrapped) caught exception. | 184 // (wrapped) caught exception. |
185 Throw replacement = new Throw(_exceptionParameter); | 185 Throw replacement = new Throw(_exceptionParameter); |
186 InteriorNode parent = node.parent; | 186 InteriorNode parent = node.parent; |
187 parent.body = replacement; | 187 parent.body = replacement; |
188 replacement.parent = parent; | 188 replacement.parent = parent; |
189 // The original rethrow does not have any references that we need to | 189 // The original rethrow does not have any references that we need to |
190 // worry about unlinking. | 190 // worry about unlinking. |
191 } | 191 } |
192 | 192 |
193 bool isNullConstant(Primitive prim) { | 193 bool isNullConstant(Primitive prim) { |
194 return prim is Constant && prim.value.isNull; | 194 return prim is Constant && prim.value.isNull; |
195 } | 195 } |
196 | 196 |
197 processInvokeMethod(InvokeMethod node) { | 197 processInvokeMethod(InvokeMethod node) { |
198 Selector selector = node.selector; | 198 Selector selector = node.selector; |
199 if (!_glue.isInterceptedSelector(selector)) return; | 199 if (!_glue.isInterceptedSelector(selector)) return; |
200 | 200 |
201 // Some platform libraries will compare non-interceptable objects against | 201 // Some platform libraries will compare non-interceptable objects against |
202 // null using the Dart == operator. These must be translated directly. | 202 // null using the Dart == operator. These must be translated directly. |
203 if (node.selector == Selectors.equals && | 203 if (node.selector == Selectors.equals && |
204 node.arguments.length == 1 && | 204 node.argumentRefs.length == 1 && |
205 isNullConstant(node.arguments[0].definition)) { | 205 isNullConstant(node.argument(0))) { |
206 node.replaceWith(new ApplyBuiltinOperator( | 206 node.replaceWith(new ApplyBuiltinOperator( |
207 BuiltinOperator.Identical, | 207 BuiltinOperator.Identical, |
208 [node.receiver.definition, node.arguments[0].definition], | 208 [node.receiver, node.argument(0)], |
209 node.sourceInformation)); | 209 node.sourceInformation)); |
210 return; | 210 return; |
211 } | 211 } |
212 | 212 |
213 Primitive receiver = node.receiver.definition; | 213 Primitive receiver = node.receiver; |
214 Primitive newReceiver; | 214 Primitive newReceiver; |
215 | 215 |
216 if (receiver == explicitReceiverParameter) { | 216 if (receiver == explicitReceiverParameter) { |
217 // If the receiver is the explicit receiver, we are calling a method in | 217 // If the receiver is the explicit receiver, we are calling a method in |
218 // the same interceptor: | 218 // the same interceptor: |
219 // Change 'receiver.foo()' to 'this.foo(receiver)'. | 219 // Change 'receiver.foo()' to 'this.foo(receiver)'. |
220 newReceiver = thisParameter; | 220 newReceiver = thisParameter; |
221 } else { | 221 } else { |
222 newReceiver = new Interceptor(receiver, node.sourceInformation); | 222 newReceiver = new Interceptor(receiver, node.sourceInformation); |
223 if (receiver.hint != null) { | 223 if (receiver.hint != null) { |
224 newReceiver.hint = new InterceptorEntity(receiver.hint); | 224 newReceiver.hint = new InterceptorEntity(receiver.hint); |
225 } | 225 } |
226 new LetPrim(newReceiver).insertAbove(node.parent); | 226 new LetPrim(newReceiver).insertAbove(node.parent); |
227 } | 227 } |
228 node.arguments.insert(0, node.receiver); | 228 node.argumentRefs.insert(0, node.receiverRef); |
229 node.receiver = new Reference<Primitive>(newReceiver)..parent = node; | 229 node.receiverRef = new Reference<Primitive>(newReceiver)..parent = node; |
230 node.callingConvention = CallingConvention.Intercepted; | 230 node.callingConvention = CallingConvention.Intercepted; |
231 } | 231 } |
232 | 232 |
233 processInvokeMethodDirectly(InvokeMethodDirectly node) { | 233 processInvokeMethodDirectly(InvokeMethodDirectly node) { |
234 if (!_glue.isInterceptedMethod(node.target)) return; | 234 if (!_glue.isInterceptedMethod(node.target)) return; |
235 | 235 |
236 Primitive receiver = node.receiver.definition; | 236 Primitive receiver = node.receiver; |
237 Primitive newReceiver; | 237 Primitive newReceiver; |
238 | 238 |
239 if (receiver == explicitReceiverParameter) { | 239 if (receiver == explicitReceiverParameter) { |
240 // If the receiver is the explicit receiver, we are calling a method in | 240 // If the receiver is the explicit receiver, we are calling a method in |
241 // the same interceptor: | 241 // the same interceptor: |
242 // Change 'receiver.foo()' to 'this.foo(receiver)'. | 242 // Change 'receiver.foo()' to 'this.foo(receiver)'. |
243 newReceiver = thisParameter; | 243 newReceiver = thisParameter; |
244 } else { | 244 } else { |
245 newReceiver = new Interceptor(receiver, node.sourceInformation); | 245 newReceiver = new Interceptor(receiver, node.sourceInformation); |
246 if (receiver.hint != null) { | 246 if (receiver.hint != null) { |
247 newReceiver.hint = new InterceptorEntity(receiver.hint); | 247 newReceiver.hint = new InterceptorEntity(receiver.hint); |
248 } | 248 } |
249 new LetPrim(newReceiver).insertAbove(node.parent); | 249 new LetPrim(newReceiver).insertAbove(node.parent); |
250 } | 250 } |
251 node.arguments.insert(0, node.receiver); | 251 node.argumentRefs.insert(0, node.receiverRef); |
252 node.receiver = new Reference<Primitive>(newReceiver)..parent = node; | 252 node.receiverRef = new Reference<Primitive>(newReceiver)..parent = node; |
253 node.callingConvention = CallingConvention.Intercepted; | 253 node.callingConvention = CallingConvention.Intercepted; |
254 } | 254 } |
255 } | 255 } |
OLD | NEW |