| 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 |