| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of ssa; | 5 part of ssa; | 
| 6 | 6 | 
| 7 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { | 
| 8   SsaCodeGeneratorTask generator; | 8   SsaCodeGeneratorTask generator; | 
| 9   SsaBuilderTask builder; | 9   SsaBuilderTask builder; | 
| 10   SsaOptimizerTask optimizer; | 10   SsaOptimizerTask optimizer; | 
| (...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1290     } | 1290     } | 
| 1291     return compiledArguments; | 1291     return compiledArguments; | 
| 1292   } | 1292   } | 
| 1293 | 1293 | 
| 1294   /** | 1294   /** | 
| 1295    * Try to inline [element] within the currect context of the builder. The | 1295    * Try to inline [element] within the currect context of the builder. The | 
| 1296    * insertion point is the state of the builder. | 1296    * insertion point is the state of the builder. | 
| 1297    */ | 1297    */ | 
| 1298   bool tryInlineMethod(Element element, | 1298   bool tryInlineMethod(Element element, | 
| 1299                        Selector selector, | 1299                        Selector selector, | 
| 1300                        TypeMask mask, |  | 
| 1301                        List<HInstruction> providedArguments, | 1300                        List<HInstruction> providedArguments, | 
| 1302                        ast.Node currentNode, | 1301                        ast.Node currentNode, | 
| 1303                        {InterfaceType instanceType}) { | 1302                        {InterfaceType instanceType}) { | 
| 1304     // TODO(johnniwinther): Register this on the [registry]. Currently the | 1303     // TODO(johnniwinther): Register this on the [registry]. Currently the | 
| 1305     // [CodegenRegistry] calls the enqueuer, but [element] should _not_ be | 1304     // [CodegenRegistry] calls the enqueuer, but [element] should _not_ be | 
| 1306     // enqueued. | 1305     // enqueued. | 
| 1307     backend.registerStaticUse(element, compiler.enqueuer.codegen); | 1306     backend.registerStaticUse(element, compiler.enqueuer.codegen); | 
| 1308 | 1307 | 
| 1309     // Ensure that [element] is an implementation element. | 1308     // Ensure that [element] is an implementation element. | 
| 1310     element = element.implementation; | 1309     element = element.implementation; | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 1322 | 1321 | 
| 1323     bool meetsHardConstraints() { | 1322     bool meetsHardConstraints() { | 
| 1324       if (compiler.disableInlining) return false; | 1323       if (compiler.disableInlining) return false; | 
| 1325 | 1324 | 
| 1326       assert(invariant( | 1325       assert(invariant( | 
| 1327           currentNode != null ? currentNode : element, | 1326           currentNode != null ? currentNode : element, | 
| 1328           selector != null || | 1327           selector != null || | 
| 1329           Elements.isStaticOrTopLevel(element) || | 1328           Elements.isStaticOrTopLevel(element) || | 
| 1330           element.isGenerativeConstructorBody, | 1329           element.isGenerativeConstructorBody, | 
| 1331           message: "Missing selector for inlining of $element.")); | 1330           message: "Missing selector for inlining of $element.")); | 
| 1332       if (selector != null) { | 1331       if (selector != null && !selector.applies(function, compiler.world)) { | 
| 1333         if (!selector.applies(function, compiler.world)) return false; | 1332         return false; | 
| 1334         if (mask != null && !mask.canHit(function, selector, compiler.world)) { |  | 
| 1335           return false; |  | 
| 1336         } |  | 
| 1337       } | 1333       } | 
| 1338 | 1334 | 
| 1339       // Don't inline operator== methods if the parameter can be null. | 1335       // Don't inline operator== methods if the parameter can be null. | 
| 1340       if (element.name == '==') { | 1336       if (element.name == '==') { | 
| 1341         if (element.enclosingClass != compiler.objectClass | 1337         if (element.enclosingClass != compiler.objectClass | 
| 1342             && providedArguments[1].canBeNull()) { | 1338             && providedArguments[1].canBeNull()) { | 
| 1343           return false; | 1339           return false; | 
| 1344         } | 1340         } | 
| 1345       } | 1341       } | 
| 1346 | 1342 | 
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1445       } else { | 1441       } else { | 
| 1446         backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); | 1442         backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); | 
| 1447       } | 1443       } | 
| 1448       return canInline; | 1444       return canInline; | 
| 1449     } | 1445     } | 
| 1450 | 1446 | 
| 1451     void doInlining() { | 1447     void doInlining() { | 
| 1452       // Add an explicit null check on the receiver before doing the | 1448       // Add an explicit null check on the receiver before doing the | 
| 1453       // inlining. We use [element] to get the same name in the | 1449       // inlining. We use [element] to get the same name in the | 
| 1454       // NoSuchMethodError message as if we had called it. | 1450       // NoSuchMethodError message as if we had called it. | 
| 1455       if (element.isInstanceMember && | 1451       if (element.isInstanceMember | 
| 1456           !element.isGenerativeConstructorBody && | 1452           && !element.isGenerativeConstructorBody | 
| 1457           (mask == null || mask.isNullable)) { | 1453           && (selector.mask == null || selector.mask.isNullable)) { | 
| 1458         addWithPosition( | 1454         addWithPosition( | 
| 1459             new HFieldGet(null, providedArguments[0], backend.dynamicType, | 1455             new HFieldGet(null, providedArguments[0], backend.dynamicType, | 
| 1460                           isAssignable: false), | 1456                           isAssignable: false), | 
| 1461             currentNode); | 1457             currentNode); | 
| 1462       } | 1458       } | 
| 1463       List<HInstruction> compiledArguments = completeSendArgumentsList( | 1459       List<HInstruction> compiledArguments = completeSendArgumentsList( | 
| 1464           function, selector, providedArguments, currentNode); | 1460           function, selector, providedArguments, currentNode); | 
| 1465       enterInlinedMethod( | 1461       enterInlinedMethod( | 
| 1466           function, currentNode, compiledArguments, instanceType: instanceType); | 1462           function, currentNode, compiledArguments, instanceType: instanceType); | 
| 1467       inlinedFrom(function, () { | 1463       inlinedFrom(function, () { | 
| (...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2294         // parameters of the generative constructor body. | 2290         // parameters of the generative constructor body. | 
| 2295         currentClass.typeVariables.forEach((TypeVariableType argument) { | 2291         currentClass.typeVariables.forEach((TypeVariableType argument) { | 
| 2296           // TODO(johnniwinther): Substitute [argument] with | 2292           // TODO(johnniwinther): Substitute [argument] with | 
| 2297           // `localsHandler.substInContext(argument)`. | 2293           // `localsHandler.substInContext(argument)`. | 
| 2298           bodyCallInputs.add(localsHandler.readLocal( | 2294           bodyCallInputs.add(localsHandler.readLocal( | 
| 2299               localsHandler.getTypeVariableAsLocal(argument))); | 2295               localsHandler.getTypeVariableAsLocal(argument))); | 
| 2300         }); | 2296         }); | 
| 2301       } | 2297       } | 
| 2302 | 2298 | 
| 2303       if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining. | 2299       if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining. | 
| 2304           tryInlineMethod(body, null, null, bodyCallInputs, function)) { | 2300           tryInlineMethod(body, null, bodyCallInputs, function)) { | 
| 2305         pop(); | 2301         pop(); | 
| 2306       } else { | 2302       } else { | 
| 2307         HInvokeConstructorBody invoke = new HInvokeConstructorBody( | 2303         HInvokeConstructorBody invoke = new HInvokeConstructorBody( | 
| 2308             body.declaration, bodyCallInputs, backend.nonNullType); | 2304             body.declaration, bodyCallInputs, backend.nonNullType); | 
| 2309         invoke.sideEffects = | 2305         invoke.sideEffects = | 
| 2310             compiler.world.getSideEffectsOfElement(constructor); | 2306             compiler.world.getSideEffectsOfElement(constructor); | 
| 2311         add(invoke); | 2307         add(invoke); | 
| 2312       } | 2308       } | 
| 2313     } | 2309     } | 
| 2314     if (inliningStack.isEmpty) { | 2310     if (inliningStack.isEmpty) { | 
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2448           original, typeVariable); | 2444           original, typeVariable); | 
| 2449     } else if (type.isFunctionType) { | 2445     } else if (type.isFunctionType) { | 
| 2450       String name = kind == HTypeConversion.CAST_TYPE_CHECK | 2446       String name = kind == HTypeConversion.CAST_TYPE_CHECK | 
| 2451           ? '_asCheck' : '_assertCheck'; | 2447           ? '_asCheck' : '_assertCheck'; | 
| 2452 | 2448 | 
| 2453       List<HInstruction> arguments = | 2449       List<HInstruction> arguments = | 
| 2454           <HInstruction>[buildFunctionType(type), original]; | 2450           <HInstruction>[buildFunctionType(type), original]; | 
| 2455       pushInvokeDynamic( | 2451       pushInvokeDynamic( | 
| 2456           null, | 2452           null, | 
| 2457           new Selector.call(name, backend.jsHelperLibrary, 1), | 2453           new Selector.call(name, backend.jsHelperLibrary, 1), | 
| 2458           null, |  | 
| 2459           arguments); | 2454           arguments); | 
| 2460 | 2455 | 
| 2461       return new HTypeConversion(type, kind, original.instructionType, pop()); | 2456       return new HTypeConversion(type, kind, original.instructionType, pop()); | 
| 2462     } else { | 2457     } else { | 
| 2463       return original.convertType(compiler, type, kind); | 2458       return original.convertType(compiler, type, kind); | 
| 2464     } | 2459     } | 
| 2465   } | 2460   } | 
| 2466 | 2461 | 
| 2467   HInstruction _trustType(HInstruction original, DartType type) { | 2462   HInstruction _trustType(HInstruction original, DartType type) { | 
| 2468     assert(compiler.trustTypeAnnotations); | 2463     assert(compiler.trustTypeAnnotations); | 
| (...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3189     if (operand is HConstant) { | 3184     if (operand is HConstant) { | 
| 3190       UnaryOperation operation = constantSystem.lookupUnary(operator); | 3185       UnaryOperation operation = constantSystem.lookupUnary(operator); | 
| 3191       HConstant constant = operand; | 3186       HConstant constant = operand; | 
| 3192       ConstantValue folded = operation.fold(constant.constant); | 3187       ConstantValue folded = operation.fold(constant.constant); | 
| 3193       if (folded != null) { | 3188       if (folded != null) { | 
| 3194         stack.add(graph.addConstant(folded, compiler)); | 3189         stack.add(graph.addConstant(folded, compiler)); | 
| 3195         return; | 3190         return; | 
| 3196       } | 3191       } | 
| 3197     } | 3192     } | 
| 3198 | 3193 | 
| 3199     pushInvokeDynamic( | 3194     pushInvokeDynamic(node, elements.getSelector(node), [operand]); | 
| 3200         node, |  | 
| 3201         elements.getSelector(node), |  | 
| 3202         elements.getTypeMask(node), |  | 
| 3203         [operand]); |  | 
| 3204   } | 3195   } | 
| 3205 | 3196 | 
| 3206   @override | 3197   @override | 
| 3207   void visitBinary(ast.Send node, | 3198   void visitBinary(ast.Send node, | 
| 3208                    ast.Node left, | 3199                    ast.Node left, | 
| 3209                    BinaryOperator operator, | 3200                    BinaryOperator operator, | 
| 3210                    ast.Node right, _) { | 3201                    ast.Node right, _) { | 
| 3211     handleBinary(node, left, right); | 3202     handleBinary(node, left, right); | 
| 3212   } | 3203   } | 
| 3213 | 3204 | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 3225   void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { | 3216   void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { | 
| 3226     handleBinary(node, left, right); | 3217     handleBinary(node, left, right); | 
| 3227     pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); | 3218     pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); | 
| 3228   } | 3219   } | 
| 3229 | 3220 | 
| 3230   void handleBinary(ast.Send node, ast.Node left, ast.Node right) { | 3221   void handleBinary(ast.Send node, ast.Node left, ast.Node right) { | 
| 3231     visitBinarySend( | 3222     visitBinarySend( | 
| 3232         visitAndPop(left), | 3223         visitAndPop(left), | 
| 3233         visitAndPop(right), | 3224         visitAndPop(right), | 
| 3234         elements.getSelector(node), | 3225         elements.getSelector(node), | 
| 3235         elements.getTypeMask(node), |  | 
| 3236         node, | 3226         node, | 
| 3237         location: node.selector); | 3227         location: node.selector); | 
| 3238   } | 3228   } | 
| 3239 | 3229 | 
| 3240   /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and | 3230   /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and | 
| 3241   /// remove use of [location] for source information. | 3231   /// remove use of [location] for source information. | 
| 3242   void visitBinarySend(HInstruction left, | 3232   void visitBinarySend(HInstruction left, | 
| 3243                        HInstruction right, | 3233                        HInstruction right, | 
| 3244                        Selector selector, | 3234                        Selector selector, | 
| 3245                        TypeMask mask, |  | 
| 3246                        ast.Send send, | 3235                        ast.Send send, | 
| 3247                        {ast.Node location}) { | 3236                        {ast.Node location}) { | 
| 3248     pushInvokeDynamic(send, selector, mask, [left, right], location: location); | 3237     pushInvokeDynamic(send, selector, [left, right], location: location); | 
| 3249   } | 3238   } | 
| 3250 | 3239 | 
| 3251   HInstruction generateInstanceSendReceiver(ast.Send send) { | 3240   HInstruction generateInstanceSendReceiver(ast.Send send) { | 
| 3252     assert(Elements.isInstanceSend(send, elements)); | 3241     assert(Elements.isInstanceSend(send, elements)); | 
| 3253     if (send.receiver == null) { | 3242     if (send.receiver == null) { | 
| 3254       return localsHandler.readThis(); | 3243       return localsHandler.readThis(); | 
| 3255     } | 3244     } | 
| 3256     visit(send.receiver); | 3245     visit(send.receiver); | 
| 3257     return pop(); | 3246     return pop(); | 
| 3258   } | 3247   } | 
| 3259 | 3248 | 
| 3260   String noSuchMethodTargetSymbolString(Element error, [String prefix]) { | 3249   String noSuchMethodTargetSymbolString(Element error, [String prefix]) { | 
| 3261     String result = error.name; | 3250     String result = error.name; | 
| 3262     if (prefix == "set") return "$result="; | 3251     if (prefix == "set") return "$result="; | 
| 3263     return result; | 3252     return result; | 
| 3264   } | 3253   } | 
| 3265 | 3254 | 
| 3266   /** | 3255   /** | 
| 3267    * Returns a set of interceptor classes that contain the given | 3256    * Returns a set of interceptor classes that contain the given | 
| 3268    * [selector]. | 3257    * [selector]. | 
| 3269    */ | 3258    */ | 
| 3270   void generateInstanceGetterWithCompiledReceiver( | 3259   void generateInstanceGetterWithCompiledReceiver(ast.Send send, | 
| 3271       ast.Send send, | 3260                                                   Selector selector, | 
| 3272       Selector selector, | 3261                                                   HInstruction receiver) { | 
| 3273       TypeMask mask, |  | 
| 3274       HInstruction receiver) { |  | 
| 3275     assert(Elements.isInstanceSend(send, elements)); | 3262     assert(Elements.isInstanceSend(send, elements)); | 
| 3276     assert(selector.isGetter); | 3263     assert(selector.isGetter); | 
| 3277     pushInvokeDynamic(send, selector, mask, [receiver]); | 3264     pushInvokeDynamic(send, selector, [receiver]); | 
| 3278   } | 3265   } | 
| 3279 | 3266 | 
| 3280   /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. | 3267   /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. | 
| 3281   /// If [prefixElement] is [null] ndo nothing. | 3268   /// If [prefixElement] is [null] ndo nothing. | 
| 3282   void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, | 3269   void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, | 
| 3283                                              ast.Node location) { | 3270                                              ast.Node location) { | 
| 3284     if (prefixElement == null) return; | 3271     if (prefixElement == null) return; | 
| 3285     String loadId = | 3272     String loadId = | 
| 3286         compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport]; | 3273         compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport]; | 
| 3287     HInstruction loadIdConstant = addConstantString(loadId); | 3274     HInstruction loadIdConstant = addConstantString(loadId); | 
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3385     } else { | 3372     } else { | 
| 3386       generateIsDeferredLoadedCheckOfSend(node); | 3373       generateIsDeferredLoadedCheckOfSend(node); | 
| 3387       pushInvokeStatic(node, getter, <HInstruction>[]); | 3374       pushInvokeStatic(node, getter, <HInstruction>[]); | 
| 3388     } | 3375     } | 
| 3389   } | 3376   } | 
| 3390 | 3377 | 
| 3391   /// Generate a dynamic getter invocation. | 3378   /// Generate a dynamic getter invocation. | 
| 3392   void generateDynamicGet(ast.Send node) { | 3379   void generateDynamicGet(ast.Send node) { | 
| 3393     HInstruction receiver = generateInstanceSendReceiver(node); | 3380     HInstruction receiver = generateInstanceSendReceiver(node); | 
| 3394     generateInstanceGetterWithCompiledReceiver( | 3381     generateInstanceGetterWithCompiledReceiver( | 
| 3395         node, elements.getSelector(node), elements.getTypeMask(node), receiver); | 3382         node, elements.getSelector(node), receiver); | 
| 3396   } | 3383   } | 
| 3397 | 3384 | 
| 3398   /// Generate a closurization of the static or top level [function]. | 3385   /// Generate a closurization of the static or top level [function]. | 
| 3399   void generateStaticFunctionGet(ast.Send node, MethodElement function) { | 3386   void generateStaticFunctionGet(ast.Send node, MethodElement function) { | 
| 3400     generateIsDeferredLoadedCheckOfSend(node); | 3387     generateIsDeferredLoadedCheckOfSend(node); | 
| 3401     // TODO(5346): Try to avoid the need for calling [declaration] before | 3388     // TODO(5346): Try to avoid the need for calling [declaration] before | 
| 3402     // creating an [HStatic]. | 3389     // creating an [HStatic]. | 
| 3403     push(new HStatic(function.declaration, backend.nonNullType)); | 3390     push(new HStatic(function.declaration, backend.nonNullType)); | 
| 3404     // TODO(ahe): This should be registered in codegen. | 3391     // TODO(ahe): This should be registered in codegen. | 
| 3405     registry.registerGetOfStaticFunction(function.declaration); | 3392     registry.registerGetOfStaticFunction(function.declaration); | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 3432     // we will be able to later compress it as: | 3419     // we will be able to later compress it as: | 
| 3433     //   t1 || t1.x | 3420     //   t1 || t1.x | 
| 3434     HInstruction expression; | 3421     HInstruction expression; | 
| 3435     SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 3422     SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 
| 3436     brancher.handleConditional( | 3423     brancher.handleConditional( | 
| 3437         () { | 3424         () { | 
| 3438           expression = visitAndPop(receiver); | 3425           expression = visitAndPop(receiver); | 
| 3439           pushCheckNull(expression); | 3426           pushCheckNull(expression); | 
| 3440         }, | 3427         }, | 
| 3441         () => stack.add(expression), | 3428         () => stack.add(expression), | 
| 3442         () { | 3429         () => generateInstanceGetterWithCompiledReceiver( | 
| 3443           generateInstanceGetterWithCompiledReceiver( | 3430             node, elements.getSelector(node), expression)); | 
| 3444               node, |  | 
| 3445               elements.getSelector(node), |  | 
| 3446               elements.getTypeMask(node), |  | 
| 3447               expression); |  | 
| 3448         }); |  | 
| 3449   } | 3431   } | 
| 3450 | 3432 | 
| 3451   /// Pushes a boolean checking [expression] against null. | 3433   /// Pushes a boolean checking [expression] against null. | 
| 3452   pushCheckNull(HInstruction expression) { | 3434   pushCheckNull(HInstruction expression) { | 
| 3453     push(new HIdentity(expression, graph.addConstantNull(compiler), | 3435     push(new HIdentity(expression, graph.addConstantNull(compiler), | 
| 3454           null, backend.boolType)); | 3436           null, backend.boolType)); | 
| 3455   } | 3437   } | 
| 3456 | 3438 | 
| 3457   @override | 3439   @override | 
| 3458   void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { | 3440   void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3522       ast.Send node, | 3504       ast.Send node, | 
| 3523       FunctionElement getter, | 3505       FunctionElement getter, | 
| 3524       _) { | 3506       _) { | 
| 3525     generateStaticGetterGet(node, getter); | 3507     generateStaticGetterGet(node, getter); | 
| 3526   } | 3508   } | 
| 3527 | 3509 | 
| 3528   void generateInstanceSetterWithCompiledReceiver(ast.Send send, | 3510   void generateInstanceSetterWithCompiledReceiver(ast.Send send, | 
| 3529                                                   HInstruction receiver, | 3511                                                   HInstruction receiver, | 
| 3530                                                   HInstruction value, | 3512                                                   HInstruction value, | 
| 3531                                                   {Selector selector, | 3513                                                   {Selector selector, | 
| 3532                                                    TypeMask mask, |  | 
| 3533                                                    ast.Node location}) { | 3514                                                    ast.Node location}) { | 
| 3534     assert(send == null || Elements.isInstanceSend(send, elements)); | 3515     assert(send == null || Elements.isInstanceSend(send, elements)); | 
| 3535     if (selector == null) { | 3516     if (selector == null) { | 
| 3536       assert(send != null); | 3517       assert(send != null); | 
| 3537       selector = elements.getSelector(send); | 3518       selector = elements.getSelector(send); | 
| 3538       if (mask == null) { |  | 
| 3539         mask = elements.getTypeMask(send); |  | 
| 3540       } |  | 
| 3541     } | 3519     } | 
| 3542     if (location == null) { | 3520     if (location == null) { | 
| 3543       assert(send != null); | 3521       assert(send != null); | 
| 3544       location = send; | 3522       location = send; | 
| 3545     } | 3523     } | 
| 3546     assert(selector.isSetter); | 3524     assert(selector.isSetter); | 
| 3547     pushInvokeDynamic(location, selector, mask, [receiver, value]); | 3525     pushInvokeDynamic(location, selector, [receiver, value]); | 
| 3548     pop(); | 3526     pop(); | 
| 3549     stack.add(value); | 3527     stack.add(value); | 
| 3550   } | 3528   } | 
| 3551 | 3529 | 
| 3552   void generateNonInstanceSetter(ast.SendSet send, | 3530   void generateNonInstanceSetter(ast.SendSet send, | 
| 3553                                  Element element, | 3531                                  Element element, | 
| 3554                                  HInstruction value, | 3532                                  HInstruction value, | 
| 3555                                  {ast.Node location}) { | 3533                                  {ast.Node location}) { | 
| 3556     assert(send == null || !Elements.isInstanceSend(send, elements)); | 3534     assert(send == null || !Elements.isInstanceSend(send, elements)); | 
| 3557     if (location == null) { | 3535     if (location == null) { | 
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3672     push(new HNot(instruction, backend.boolType)); | 3650     push(new HNot(instruction, backend.boolType)); | 
| 3673   } | 3651   } | 
| 3674 | 3652 | 
| 3675   HInstruction buildIsNode(ast.Node node, | 3653   HInstruction buildIsNode(ast.Node node, | 
| 3676                            DartType type, | 3654                            DartType type, | 
| 3677                            HInstruction expression) { | 3655                            HInstruction expression) { | 
| 3678     type = localsHandler.substInContext(type).unalias(compiler); | 3656     type = localsHandler.substInContext(type).unalias(compiler); | 
| 3679     if (type.isFunctionType) { | 3657     if (type.isFunctionType) { | 
| 3680       List arguments = [buildFunctionType(type), expression]; | 3658       List arguments = [buildFunctionType(type), expression]; | 
| 3681       pushInvokeDynamic( | 3659       pushInvokeDynamic( | 
| 3682           node, | 3660           node, new Selector.call('_isTest', backend.jsHelperLibrary, 1), | 
| 3683           new Selector.call('_isTest', backend.jsHelperLibrary, 1), |  | 
| 3684           null, |  | 
| 3685           arguments); | 3661           arguments); | 
| 3686       return new HIs.compound(type, expression, pop(), backend.boolType); | 3662       return new HIs.compound(type, expression, pop(), backend.boolType); | 
| 3687     } else if (type.isTypeVariable) { | 3663     } else if (type.isTypeVariable) { | 
| 3688       HInstruction runtimeType = addTypeVariableReference(type); | 3664       HInstruction runtimeType = addTypeVariableReference(type); | 
| 3689       Element helper = backend.getCheckSubtypeOfRuntimeType(); | 3665       Element helper = backend.getCheckSubtypeOfRuntimeType(); | 
| 3690       List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 3666       List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 
| 3691       pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); | 3667       pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); | 
| 3692       HInstruction call = pop(); | 3668       HInstruction call = pop(); | 
| 3693       return new HIs.variable(type, expression, call, backend.boolType); | 3669       return new HIs.variable(type, expression, call, backend.boolType); | 
| 3694     } else if (RuntimeTypes.hasTypeArguments(type)) { | 3670     } else if (RuntimeTypes.hasTypeArguments(type)) { | 
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3796   } | 3772   } | 
| 3797 | 3773 | 
| 3798   /// Generate a dynamic method, getter or setter invocation. | 3774   /// Generate a dynamic method, getter or setter invocation. | 
| 3799   void generateDynamicSend(ast.Send node) { | 3775   void generateDynamicSend(ast.Send node) { | 
| 3800     HInstruction receiver = generateInstanceSendReceiver(node); | 3776     HInstruction receiver = generateInstanceSendReceiver(node); | 
| 3801     _generateDynamicSend(node, receiver); | 3777     _generateDynamicSend(node, receiver); | 
| 3802   } | 3778   } | 
| 3803 | 3779 | 
| 3804   void _generateDynamicSend(ast.Send node, HInstruction receiver) { | 3780   void _generateDynamicSend(ast.Send node, HInstruction receiver) { | 
| 3805     Selector selector = elements.getSelector(node); | 3781     Selector selector = elements.getSelector(node); | 
| 3806     TypeMask mask = elements.getTypeMask(node); |  | 
| 3807 | 3782 | 
| 3808     List<HInstruction> inputs = <HInstruction>[]; | 3783     List<HInstruction> inputs = <HInstruction>[]; | 
| 3809     inputs.add(receiver); | 3784     inputs.add(receiver); | 
| 3810     addDynamicSendArgumentsToList(node, inputs); | 3785     addDynamicSendArgumentsToList(node, inputs); | 
| 3811 | 3786 | 
| 3812     pushInvokeDynamic(node, selector, mask, inputs); | 3787     pushInvokeDynamic(node, selector, inputs); | 
| 3813     if (selector.isSetter || selector.isIndexSet) { | 3788     if (selector.isSetter || selector.isIndexSet) { | 
| 3814       pop(); | 3789       pop(); | 
| 3815       stack.add(inputs.last); | 3790       stack.add(inputs.last); | 
| 3816     } | 3791     } | 
| 3817   } | 3792   } | 
| 3818 | 3793 | 
| 3819   @override | 3794   @override | 
| 3820   visitDynamicPropertyInvoke( | 3795   visitDynamicPropertyInvoke( | 
| 3821       ast.Send node, | 3796       ast.Send node, | 
| 3822       ast.Node receiver, | 3797       ast.Node receiver, | 
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4166         MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | 4141         MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | 
| 4167     stack.add(graph.addConstantNull(compiler)); | 4142     stack.add(graph.addConstantNull(compiler)); | 
| 4168   } | 4143   } | 
| 4169 | 4144 | 
| 4170   void handleForeignJsCallInIsolate(ast.Send node) { | 4145   void handleForeignJsCallInIsolate(ast.Send node) { | 
| 4171     Link<ast.Node> link = node.arguments; | 4146     Link<ast.Node> link = node.arguments; | 
| 4172     if (!compiler.hasIsolateSupport) { | 4147     if (!compiler.hasIsolateSupport) { | 
| 4173       // If the isolate library is not used, we just invoke the | 4148       // If the isolate library is not used, we just invoke the | 
| 4174       // closure. | 4149       // closure. | 
| 4175       visit(link.tail.head); | 4150       visit(link.tail.head); | 
| 4176       push(new HInvokeClosure(new Selector.callClosure(0), | 4151       Selector selector = new Selector.callClosure(0); | 
|  | 4152       push(new HInvokeClosure(selector, | 
| 4177                               <HInstruction>[pop()], | 4153                               <HInstruction>[pop()], | 
| 4178                               backend.dynamicType)); | 4154                               backend.dynamicType)); | 
| 4179     } else { | 4155     } else { | 
| 4180       // Call a helper method from the isolate library. | 4156       // Call a helper method from the isolate library. | 
| 4181       Element element = backend.isolateHelperLibrary.find('_callInIsolate'); | 4157       Element element = backend.isolateHelperLibrary.find('_callInIsolate'); | 
| 4182       if (element == null) { | 4158       if (element == null) { | 
| 4183         compiler.internalError(node, | 4159         compiler.internalError(node, | 
| 4184             'Isolate library and compiler mismatch.'); | 4160             'Isolate library and compiler mismatch.'); | 
| 4185       } | 4161       } | 
| 4186       List<HInstruction> inputs = <HInstruction>[]; | 4162       List<HInstruction> inputs = <HInstruction>[]; | 
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4308     String name = selector.name; | 4284     String name = selector.name; | 
| 4309 | 4285 | 
| 4310     ClassElement cls = currentNonClosureClass; | 4286     ClassElement cls = currentNonClosureClass; | 
| 4311     Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); | 4287     Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); | 
| 4312     if (compiler.enabledInvokeOn | 4288     if (compiler.enabledInvokeOn | 
| 4313         && element.enclosingElement.declaration != compiler.objectClass) { | 4289         && element.enclosingElement.declaration != compiler.objectClass) { | 
| 4314       // Register the call as dynamic if [noSuchMethod] on the super | 4290       // Register the call as dynamic if [noSuchMethod] on the super | 
| 4315       // class is _not_ the default implementation from [Object], in | 4291       // class is _not_ the default implementation from [Object], in | 
| 4316       // case the [noSuchMethod] implementation calls | 4292       // case the [noSuchMethod] implementation calls | 
| 4317       // [JSInvocationMirror._invokeOn]. | 4293       // [JSInvocationMirror._invokeOn]. | 
| 4318       registry.registerSelectorUse(selector); | 4294       registry.registerSelectorUse(selector.asUntyped); | 
| 4319     } | 4295     } | 
| 4320     String publicName = name; | 4296     String publicName = name; | 
| 4321     if (selector.isSetter) publicName += '='; | 4297     if (selector.isSetter) publicName += '='; | 
| 4322 | 4298 | 
| 4323     ConstantValue nameConstant = constantSystem.createString( | 4299     ConstantValue nameConstant = constantSystem.createString( | 
| 4324         new ast.DartString.literal(publicName)); | 4300         new ast.DartString.literal(publicName)); | 
| 4325 | 4301 | 
| 4326     String internalName = backend.namer.invocationName(selector); | 4302     String internalName = backend.namer.invocationName(selector); | 
| 4327     ConstantValue internalNameConstant = | 4303     ConstantValue internalNameConstant = | 
| 4328         constantSystem.createString(new ast.DartString.literal(internalName)); | 4304         constantSystem.createString(new ast.DartString.literal(internalName)); | 
| (...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5324     // in if it is not used (e.g., in a try/catch). | 5300     // in if it is not used (e.g., in a try/catch). | 
| 5325     HInstruction target = pop(); | 5301     HInstruction target = pop(); | 
| 5326     generateCallInvoke(node, target); | 5302     generateCallInvoke(node, target); | 
| 5327   } | 5303   } | 
| 5328 | 5304 | 
| 5329   /// Generate a '.call' invocation on [target]. | 5305   /// Generate a '.call' invocation on [target]. | 
| 5330   void generateCallInvoke(ast.Send node, HInstruction target) { | 5306   void generateCallInvoke(ast.Send node, HInstruction target) { | 
| 5331     Selector selector = elements.getSelector(node); | 5307     Selector selector = elements.getSelector(node); | 
| 5332     List<HInstruction> inputs = <HInstruction>[target]; | 5308     List<HInstruction> inputs = <HInstruction>[target]; | 
| 5333     addDynamicSendArgumentsToList(node, inputs); | 5309     addDynamicSendArgumentsToList(node, inputs); | 
|  | 5310     Selector closureSelector = new Selector.callClosureFrom(selector); | 
| 5334     pushWithPosition( | 5311     pushWithPosition( | 
| 5335         new HInvokeClosure( | 5312         new HInvokeClosure(closureSelector, inputs, backend.dynamicType), node); | 
| 5336             new Selector.callClosureFrom(selector), |  | 
| 5337             inputs, backend.dynamicType), |  | 
| 5338         node); |  | 
| 5339   } | 5313   } | 
| 5340 | 5314 | 
| 5341   visitGetterSend(ast.Send node) { | 5315   visitGetterSend(ast.Send node) { | 
| 5342     internalError(node, "Unexpected visitGetterSend"); | 5316     internalError(node, "Unexpected visitGetterSend"); | 
| 5343   } | 5317   } | 
| 5344 | 5318 | 
| 5345   // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 5319   // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 
| 5346   internalError(Spannable node, String reason) { | 5320   internalError(Spannable node, String reason) { | 
| 5347     compiler.internalError(node, reason); | 5321     compiler.internalError(node, reason); | 
| 5348   } | 5322   } | 
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5457         String nameString = stringConstant.toDartString().slowToString(); | 5431         String nameString = stringConstant.toDartString().slowToString(); | 
| 5458         registry.registerConstSymbol(nameString); | 5432         registry.registerConstSymbol(nameString); | 
| 5459       } | 5433       } | 
| 5460     } else { | 5434     } else { | 
| 5461       handleNewSend(node); | 5435       handleNewSend(node); | 
| 5462     } | 5436     } | 
| 5463   } | 5437   } | 
| 5464 | 5438 | 
| 5465   void pushInvokeDynamic(ast.Node node, | 5439   void pushInvokeDynamic(ast.Node node, | 
| 5466                          Selector selector, | 5440                          Selector selector, | 
| 5467                          TypeMask mask, |  | 
| 5468                          List<HInstruction> arguments, | 5441                          List<HInstruction> arguments, | 
| 5469                          {ast.Node location}) { | 5442                          {ast.Node location}) { | 
| 5470     if (location == null) location = node; | 5443     if (location == null) location = node; | 
| 5471 | 5444 | 
| 5472     // We prefer to not inline certain operations on indexables, | 5445     // We prefer to not inline certain operations on indexables, | 
| 5473     // because the constant folder will handle them better and turn | 5446     // because the constant folder will handle them better and turn | 
| 5474     // them into simpler instructions that allow further | 5447     // them into simpler instructions that allow further | 
| 5475     // optimizations. | 5448     // optimizations. | 
| 5476     bool isOptimizableOperationOnIndexable(Selector selector, Element element) { | 5449     bool isOptimizableOperationOnIndexable(Selector selector, Element element) { | 
| 5477       bool isLength = selector.isGetter | 5450       bool isLength = selector.isGetter | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 5498       if (selector.isIndex) return true; | 5471       if (selector.isIndex) return true; | 
| 5499       if (selector.isIndexSet) return true; | 5472       if (selector.isIndexSet) return true; | 
| 5500       if (element == backend.jsArrayAdd | 5473       if (element == backend.jsArrayAdd | 
| 5501           || element == backend.jsArrayRemoveLast | 5474           || element == backend.jsArrayRemoveLast | 
| 5502           || element == backend.jsStringSplit) { | 5475           || element == backend.jsStringSplit) { | 
| 5503         return true; | 5476         return true; | 
| 5504       } | 5477       } | 
| 5505       return false; | 5478       return false; | 
| 5506     } | 5479     } | 
| 5507 | 5480 | 
| 5508     Element element = compiler.world.locateSingleElement(selector, mask); | 5481     Element element = compiler.world.locateSingleElement(selector); | 
| 5509     if (element != null && | 5482     if (element != null | 
| 5510         !element.isField && | 5483         && !element.isField | 
| 5511         !(element.isGetter && selector.isCall) && | 5484         && !(element.isGetter && selector.isCall) | 
| 5512         !(element.isFunction && selector.isGetter) && | 5485         && !(element.isFunction && selector.isGetter) | 
| 5513         !isOptimizableOperation(selector, element)) { | 5486         && !isOptimizableOperation(selector, element)) { | 
| 5514       if (tryInlineMethod(element, selector, mask, arguments, node)) { | 5487       if (tryInlineMethod(element, selector, arguments, node)) { | 
| 5515         return; | 5488         return; | 
| 5516       } | 5489       } | 
| 5517     } | 5490     } | 
| 5518 | 5491 | 
| 5519     HInstruction receiver = arguments[0]; | 5492     HInstruction receiver = arguments[0]; | 
| 5520     List<HInstruction> inputs = <HInstruction>[]; | 5493     List<HInstruction> inputs = <HInstruction>[]; | 
| 5521     bool isIntercepted = backend.isInterceptedSelector(selector); | 5494     bool isIntercepted = backend.isInterceptedSelector(selector); | 
| 5522     if (isIntercepted) { | 5495     if (isIntercepted) { | 
| 5523       inputs.add(invokeInterceptor(receiver)); | 5496       inputs.add(invokeInterceptor(receiver)); | 
| 5524     } | 5497     } | 
| 5525     inputs.addAll(arguments); | 5498     inputs.addAll(arguments); | 
| 5526     TypeMask type = | 5499     TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler); | 
| 5527         TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler); |  | 
| 5528     if (selector.isGetter) { | 5500     if (selector.isGetter) { | 
| 5529       pushWithPosition( | 5501       pushWithPosition( | 
| 5530           new HInvokeDynamicGetter(selector, mask, null, inputs, type), | 5502           new HInvokeDynamicGetter(selector, null, inputs, type), | 
| 5531           location); | 5503           location); | 
| 5532     } else if (selector.isSetter) { | 5504     } else if (selector.isSetter) { | 
| 5533       pushWithPosition( | 5505       pushWithPosition( | 
| 5534           new HInvokeDynamicSetter(selector, mask, null, inputs, type), | 5506           new HInvokeDynamicSetter(selector, null, inputs, type), | 
| 5535           location); | 5507           location); | 
| 5536     } else { | 5508     } else { | 
| 5537       pushWithPosition( | 5509       pushWithPosition( | 
| 5538           new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted), | 5510           new HInvokeDynamicMethod(selector, inputs, type, isIntercepted), | 
| 5539           location); | 5511           location); | 
| 5540     } | 5512     } | 
| 5541   } | 5513   } | 
| 5542 | 5514 | 
| 5543   void pushInvokeStatic(ast.Node location, | 5515   void pushInvokeStatic(ast.Node location, | 
| 5544                         Element element, | 5516                         Element element, | 
| 5545                         List<HInstruction> arguments, | 5517                         List<HInstruction> arguments, | 
| 5546                         {TypeMask typeMask, | 5518                         {TypeMask typeMask, | 
| 5547                          InterfaceType instanceType}) { | 5519                          InterfaceType instanceType}) { | 
| 5548     if (tryInlineMethod(element, null, null, arguments, location, | 5520     if (tryInlineMethod(element, null, arguments, location, | 
| 5549                         instanceType: instanceType)) { | 5521                         instanceType: instanceType)) { | 
| 5550       return; | 5522       return; | 
| 5551     } | 5523     } | 
| 5552 | 5524 | 
| 5553     if (typeMask == null) { | 5525     if (typeMask == null) { | 
| 5554       typeMask = | 5526       typeMask = | 
| 5555           TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 5527           TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 
| 5556     } | 5528     } | 
| 5557     bool targetCanThrow = !compiler.world.getCannotThrow(element); | 5529     bool targetCanThrow = !compiler.world.getCannotThrow(element); | 
| 5558     // TODO(5346): Try to avoid the need for calling [declaration] before | 5530     // TODO(5346): Try to avoid the need for calling [declaration] before | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5593     } else { | 5565     } else { | 
| 5594       type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 5566       type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 
| 5595     } | 5567     } | 
| 5596     HInstruction instruction = new HInvokeSuper( | 5568     HInstruction instruction = new HInvokeSuper( | 
| 5597         element, | 5569         element, | 
| 5598         currentNonClosureClass, | 5570         currentNonClosureClass, | 
| 5599         selector, | 5571         selector, | 
| 5600         inputs, | 5572         inputs, | 
| 5601         type, | 5573         type, | 
| 5602         isSetter: selector.isSetter || selector.isIndexSet); | 5574         isSetter: selector.isSetter || selector.isIndexSet); | 
| 5603     instruction.sideEffects = | 5575     instruction.sideEffects = compiler.world.getSideEffectsOfSelector(selector); | 
| 5604         compiler.world.getSideEffectsOfSelector(selector, null); |  | 
| 5605     return instruction; | 5576     return instruction; | 
| 5606   } | 5577   } | 
| 5607 | 5578 | 
| 5608   void handleComplexOperatorSend(ast.SendSet node, | 5579   void handleComplexOperatorSend(ast.SendSet node, | 
| 5609                                  HInstruction receiver, | 5580                                  HInstruction receiver, | 
| 5610                                  Link<ast.Node> arguments) { | 5581                                  Link<ast.Node> arguments) { | 
| 5611     HInstruction rhs; | 5582     HInstruction rhs; | 
| 5612     if (node.isPrefix || node.isPostfix) { | 5583     if (node.isPrefix || node.isPostfix) { | 
| 5613       rhs = graph.addConstantInt(1, compiler); | 5584       rhs = graph.addConstantInt(1, compiler); | 
| 5614     } else { | 5585     } else { | 
| 5615       visit(arguments.head); | 5586       visit(arguments.head); | 
| 5616       assert(arguments.tail.isEmpty); | 5587       assert(arguments.tail.isEmpty); | 
| 5617       rhs = pop(); | 5588       rhs = pop(); | 
| 5618     } | 5589     } | 
| 5619     visitBinarySend(receiver, rhs, | 5590     visitBinarySend(receiver, rhs, | 
| 5620                     elements.getOperatorSelectorInComplexSendSet(node), | 5591                     elements.getOperatorSelectorInComplexSendSet(node), | 
| 5621                     elements.getOperatorTypeMaskInComplexSendSet(node), |  | 
| 5622                     node, | 5592                     node, | 
| 5623                     location: node.assignmentOperator); | 5593                     location: node.assignmentOperator); | 
| 5624   } | 5594   } | 
| 5625 | 5595 | 
| 5626   void handleSuperSendSet(ast.SendSet node) { | 5596   void handleSuperSendSet(ast.SendSet node) { | 
| 5627     Element element = elements[node]; | 5597     Element element = elements[node]; | 
| 5628     List<HInstruction> setterInputs = <HInstruction>[]; | 5598     List<HInstruction> setterInputs = <HInstruction>[]; | 
| 5629     void generateSuperSendSet() { | 5599     void generateSuperSendSet() { | 
| 5630       Selector setterSelector = elements.getSelector(node); | 5600       Selector setterSelector = elements.getSelector(node); | 
| 5631       if (Elements.isUnresolved(element) | 5601       if (Elements.isUnresolved(element) | 
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5709       HInstruction index; | 5679       HInstruction index; | 
| 5710       if (node.isIndex) { | 5680       if (node.isIndex) { | 
| 5711         visit(arguments.head); | 5681         visit(arguments.head); | 
| 5712         arguments = arguments.tail; | 5682         arguments = arguments.tail; | 
| 5713         index = pop(); | 5683         index = pop(); | 
| 5714       } | 5684       } | 
| 5715 | 5685 | 
| 5716       pushInvokeDynamic( | 5686       pushInvokeDynamic( | 
| 5717           node, | 5687           node, | 
| 5718           elements.getGetterSelectorInComplexSendSet(node), | 5688           elements.getGetterSelectorInComplexSendSet(node), | 
| 5719           elements.getGetterTypeMaskInComplexSendSet(node), |  | 
| 5720           [receiver, index]); | 5689           [receiver, index]); | 
| 5721       HInstruction getterInstruction = pop(); | 5690       HInstruction getterInstruction = pop(); | 
| 5722       if (node.isIfNullAssignment) { | 5691       if (node.isIfNullAssignment) { | 
| 5723         // Compile x[i] ??= e as: | 5692         // Compile x[i] ??= e as: | 
| 5724         //   t1 = x[i] | 5693         //   t1 = x[i] | 
| 5725         //   if (t1 == null) | 5694         //   if (t1 == null) | 
| 5726         //      t1 = x[i] = e; | 5695         //      t1 = x[i] = e; | 
| 5727         //   result = t1 | 5696         //   result = t1 | 
| 5728         SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 5697         SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 
| 5729         brancher.handleIfNull(() => stack.add(getterInstruction), | 5698         brancher.handleIfNull(() => stack.add(getterInstruction), | 
| 5730             () { | 5699             () { | 
| 5731               visit(arguments.head); | 5700               visit(arguments.head); | 
| 5732               HInstruction value = pop(); | 5701               HInstruction value = pop(); | 
| 5733               pushInvokeDynamic( | 5702               pushInvokeDynamic( | 
| 5734                   node, | 5703                   node, elements.getSelector(node), [receiver, index, value]); | 
| 5735                   elements.getSelector(node), |  | 
| 5736                   elements.getTypeMask(node), |  | 
| 5737                   [receiver, index, value]); |  | 
| 5738               pop(); | 5704               pop(); | 
| 5739               stack.add(value); | 5705               stack.add(value); | 
| 5740             }); | 5706             }); | 
| 5741       } else { | 5707       } else { | 
| 5742         handleComplexOperatorSend(node, getterInstruction, arguments); | 5708         handleComplexOperatorSend(node, getterInstruction, arguments); | 
| 5743         HInstruction value = pop(); | 5709         HInstruction value = pop(); | 
| 5744         pushInvokeDynamic( | 5710         pushInvokeDynamic( | 
| 5745             node, | 5711             node, elements.getSelector(node), [receiver, index, value]); | 
| 5746             elements.getSelector(node), |  | 
| 5747             elements.getTypeMask(node), |  | 
| 5748             [receiver, index, value]); |  | 
| 5749         pop(); | 5712         pop(); | 
| 5750         if (node.isPostfix) { | 5713         if (node.isPostfix) { | 
| 5751           stack.add(getterInstruction); | 5714           stack.add(getterInstruction); | 
| 5752         } else { | 5715         } else { | 
| 5753           stack.add(value); | 5716           stack.add(value); | 
| 5754         } | 5717         } | 
| 5755       } | 5718       } | 
| 5756     } | 5719     } | 
| 5757   } | 5720   } | 
| 5758 | 5721 | 
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 6025         generateThrowNoSuchMethod(node, selector.source, | 5988         generateThrowNoSuchMethod(node, selector.source, | 
| 6026                                   argumentNodes: node.arguments); | 5989                                   argumentNodes: node.arguments); | 
| 6027       } | 5990       } | 
| 6028       return; | 5991       return; | 
| 6029     } | 5992     } | 
| 6030 | 5993 | 
| 6031     if (Elements.isInstanceSend(node, elements)) { | 5994     if (Elements.isInstanceSend(node, elements)) { | 
| 6032       void generateAssignment(HInstruction receiver) { | 5995       void generateAssignment(HInstruction receiver) { | 
| 6033         // desugars `e.x op= e2` to `e.x = e.x op e2` | 5996         // desugars `e.x op= e2` to `e.x = e.x op e2` | 
| 6034         generateInstanceGetterWithCompiledReceiver( | 5997         generateInstanceGetterWithCompiledReceiver( | 
| 6035             node, | 5998             node, elements.getGetterSelectorInComplexSendSet(node), receiver); | 
| 6036             elements.getGetterSelectorInComplexSendSet(node), |  | 
| 6037             elements.getGetterTypeMaskInComplexSendSet(node), |  | 
| 6038             receiver); |  | 
| 6039         HInstruction getterInstruction = pop(); | 5999         HInstruction getterInstruction = pop(); | 
| 6040         if (node.isIfNullAssignment) { | 6000         if (node.isIfNullAssignment) { | 
| 6041           SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 6001           SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 
| 6042           brancher.handleIfNull(() => stack.add(getterInstruction), | 6002           brancher.handleIfNull(() => stack.add(getterInstruction), | 
| 6043               () { | 6003               () { | 
| 6044                 visit(node.arguments.head); | 6004                 visit(node.arguments.head); | 
| 6045                 generateInstanceSetterWithCompiledReceiver( | 6005                 generateInstanceSetterWithCompiledReceiver( | 
| 6046                     node, receiver, pop()); | 6006                     node, receiver, pop()); | 
| 6047               }); | 6007               }); | 
| 6048         } else { | 6008         } else { | 
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 6479     HInstruction expression = pop(); | 6439     HInstruction expression = pop(); | 
| 6480     pushInvokeStatic(node, | 6440     pushInvokeStatic(node, | 
| 6481                      backend.getStreamIteratorConstructor(), | 6441                      backend.getStreamIteratorConstructor(), | 
| 6482                      [expression, graph.addConstantNull(compiler)]); | 6442                      [expression, graph.addConstantNull(compiler)]); | 
| 6483     streamIterator = pop(); | 6443     streamIterator = pop(); | 
| 6484 | 6444 | 
| 6485     void buildInitializer() {} | 6445     void buildInitializer() {} | 
| 6486 | 6446 | 
| 6487     HInstruction buildCondition() { | 6447     HInstruction buildCondition() { | 
| 6488       Selector selector = elements.getMoveNextSelector(node); | 6448       Selector selector = elements.getMoveNextSelector(node); | 
| 6489       TypeMask mask = elements.getMoveNextTypeMask(node); | 6449       pushInvokeDynamic(node, selector, [streamIterator]); | 
| 6490       pushInvokeDynamic(node, selector, mask, [streamIterator]); |  | 
| 6491       HInstruction future = pop(); | 6450       HInstruction future = pop(); | 
| 6492       push(new HAwait(future, new TypeMask.subclass(compiler.objectClass, | 6451       push(new HAwait(future, new TypeMask.subclass(compiler.objectClass, | 
| 6493                                                     compiler.world))); | 6452                                                     compiler.world))); | 
| 6494       return popBoolified(); | 6453       return popBoolified(); | 
| 6495     } | 6454     } | 
| 6496     void buildBody() { | 6455     void buildBody() { | 
| 6497       Selector call = elements.getCurrentSelector(node); | 6456       Selector call = elements.getCurrentSelector(node); | 
| 6498       TypeMask callMask = elements.getCurrentTypeMask(node); | 6457       pushInvokeDynamic(node, call, [streamIterator]); | 
| 6499       pushInvokeDynamic(node, call, callMask, [streamIterator]); |  | 
| 6500 | 6458 | 
| 6501       ast.Node identifier = node.declaredIdentifier; | 6459       ast.Node identifier = node.declaredIdentifier; | 
| 6502       Element variable = elements.getForInVariable(node); | 6460       Element variable = elements.getForInVariable(node); | 
| 6503       Selector selector = elements.getSelector(identifier); | 6461       Selector selector = elements.getSelector(identifier); | 
| 6504       TypeMask mask = elements.getTypeMask(identifier); |  | 
| 6505 | 6462 | 
| 6506       HInstruction value = pop(); | 6463       HInstruction value = pop(); | 
| 6507       if (identifier.asSend() != null | 6464       if (identifier.asSend() != null | 
| 6508           && Elements.isInstanceSend(identifier, elements)) { | 6465           && Elements.isInstanceSend(identifier, elements)) { | 
| 6509         HInstruction receiver = generateInstanceSendReceiver(identifier); | 6466         HInstruction receiver = generateInstanceSendReceiver(identifier); | 
| 6510         assert(receiver != null); | 6467         assert(receiver != null); | 
| 6511         generateInstanceSetterWithCompiledReceiver( | 6468         generateInstanceSetterWithCompiledReceiver( | 
| 6512             null, | 6469             null, | 
| 6513             receiver, | 6470             receiver, | 
| 6514             value, | 6471             value, | 
| 6515             selector: selector, | 6472             selector: selector, | 
| 6516             mask: mask, |  | 
| 6517             location: identifier); | 6473             location: identifier); | 
| 6518       } else { | 6474       } else { | 
| 6519         generateNonInstanceSetter( | 6475         generateNonInstanceSetter( | 
| 6520             null, variable, value, location: identifier); | 6476             null, variable, value, location: identifier); | 
| 6521       } | 6477       } | 
| 6522       pop(); // Pop the value pushed by the setter call. | 6478       pop(); // Pop the value pushed by the setter call. | 
| 6523 | 6479 | 
| 6524       visit(node.body); | 6480       visit(node.body); | 
| 6525     } | 6481     } | 
| 6526 | 6482 | 
| 6527     void buildUpdate() {}; | 6483     void buildUpdate() {}; | 
| 6528 | 6484 | 
| 6529     buildProtectedByFinally(() { | 6485     buildProtectedByFinally(() { | 
| 6530       handleLoop(node, | 6486       handleLoop(node, | 
| 6531                  buildInitializer, | 6487                  buildInitializer, | 
| 6532                  buildCondition, | 6488                  buildCondition, | 
| 6533                  buildUpdate, | 6489                  buildUpdate, | 
| 6534                  buildBody); | 6490                  buildBody); | 
| 6535     }, () { | 6491     }, () { | 
| 6536       pushInvokeDynamic(node, | 6492       pushInvokeDynamic(node, new Selector.call("cancel", null, 0), | 
| 6537           new Selector.call("cancel", null, 0), |  | 
| 6538           null, |  | 
| 6539           [streamIterator]); | 6493           [streamIterator]); | 
| 6540       push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass, | 6494       push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass, | 
| 6541           compiler.world))); | 6495           compiler.world))); | 
| 6542       pop(); | 6496       pop(); | 
| 6543     }); | 6497     }); | 
| 6544   } | 6498   } | 
| 6545 | 6499 | 
| 6546   visitSyncForIn(ast.SyncForIn node) { | 6500   visitSyncForIn(ast.SyncForIn node) { | 
| 6547     // The 'get iterator' selector for this node has the inferred receiver type. | 6501     // The 'get iterator' selector for this node has the inferred receiver type. | 
| 6548     // If the receiver supports JavaScript indexing we generate an indexing loop | 6502     // If the receiver supports JavaScript indexing we generate an indexing loop | 
| 6549     // instead of allocating an iterator object. | 6503     // instead of allocating an iterator object. | 
| 6550 | 6504 | 
| 6551     // This scheme recognizes for-in on direct lists.  It does not recognize all | 6505     // This scheme recognizes for-in on direct lists.  It does not recognize all | 
| 6552     // uses of ArrayIterator.  They still occur when the receiver is an Iterable | 6506     // uses of ArrayIterator.  They still occur when the receiver is an Iterable | 
| 6553     // with a `get iterator` method that delegate to another Iterable and the | 6507     // with a `get iterator` method that delegate to another Iterable and the | 
| 6554     // method is inlined.  We would require full scalar replacement in that | 6508     // method is inlined.  We would require full scalar replacement in that | 
| 6555     // case. | 6509     // case. | 
| 6556 | 6510 | 
| 6557     Selector selector = elements.getIteratorSelector(node); | 6511     Selector selector = elements.getIteratorSelector(node); | 
| 6558     TypeMask mask = elements.getIteratorTypeMask(node); | 6512     TypeMask mask = selector.mask; | 
| 6559 | 6513 | 
| 6560     ClassWorld classWorld = compiler.world; | 6514     ClassWorld classWorld = compiler.world; | 
| 6561     if (mask != null && mask.satisfies(backend.jsIndexableClass, classWorld)) { | 6515     if (mask != null && mask.satisfies(backend.jsIndexableClass, classWorld)) { | 
| 6562       return buildSyncForInIndexable(node, mask); | 6516       return buildSyncForInIndexable(node, mask); | 
| 6563     } | 6517     } | 
| 6564     buildSyncForInIterator(node); | 6518     buildSyncForInIterator(node); | 
| 6565   } | 6519   } | 
| 6566 | 6520 | 
| 6567   buildSyncForInIterator(ast.SyncForIn node) { | 6521   buildSyncForInIterator(ast.SyncForIn node) { | 
| 6568     // Generate a structure equivalent to: | 6522     // Generate a structure equivalent to: | 
| 6569     //   Iterator<E> $iter = <iterable>.iterator; | 6523     //   Iterator<E> $iter = <iterable>.iterator; | 
| 6570     //   while ($iter.moveNext()) { | 6524     //   while ($iter.moveNext()) { | 
| 6571     //     <declaredIdentifier> = $iter.current; | 6525     //     <declaredIdentifier> = $iter.current; | 
| 6572     //     <body> | 6526     //     <body> | 
| 6573     //   } | 6527     //   } | 
| 6574 | 6528 | 
| 6575     // The iterator is shared between initializer, condition and body. | 6529     // The iterator is shared between initializer, condition and body. | 
| 6576     HInstruction iterator; | 6530     HInstruction iterator; | 
| 6577 | 6531 | 
| 6578     void buildInitializer() { | 6532     void buildInitializer() { | 
| 6579       Selector selector = elements.getIteratorSelector(node); | 6533       Selector selector = elements.getIteratorSelector(node); | 
| 6580       TypeMask mask = elements.getIteratorTypeMask(node); |  | 
| 6581       visit(node.expression); | 6534       visit(node.expression); | 
| 6582       HInstruction receiver = pop(); | 6535       HInstruction receiver = pop(); | 
| 6583       pushInvokeDynamic(node, selector, mask, [receiver]); | 6536       pushInvokeDynamic(node, selector, [receiver]); | 
| 6584       iterator = pop(); | 6537       iterator = pop(); | 
| 6585     } | 6538     } | 
| 6586 | 6539 | 
| 6587     HInstruction buildCondition() { | 6540     HInstruction buildCondition() { | 
| 6588       Selector selector = elements.getMoveNextSelector(node); | 6541       Selector selector = elements.getMoveNextSelector(node); | 
| 6589       TypeMask mask = elements.getMoveNextTypeMask(node); | 6542       pushInvokeDynamic(node, selector, [iterator]); | 
| 6590       pushInvokeDynamic(node, selector, mask, [iterator]); |  | 
| 6591       return popBoolified(); | 6543       return popBoolified(); | 
| 6592     } | 6544     } | 
| 6593 | 6545 | 
| 6594     void buildBody() { | 6546     void buildBody() { | 
| 6595       Selector call = elements.getCurrentSelector(node); | 6547       Selector call = elements.getCurrentSelector(node); | 
| 6596       TypeMask mask = elements.getCurrentTypeMask(node); | 6548       pushInvokeDynamic(node, call, [iterator]); | 
| 6597       pushInvokeDynamic(node, call, mask, [iterator]); |  | 
| 6598       buildAssignLoopVariable(node, pop()); | 6549       buildAssignLoopVariable(node, pop()); | 
| 6599       visit(node.body); | 6550       visit(node.body); | 
| 6600     } | 6551     } | 
| 6601 | 6552 | 
| 6602     handleLoop(node, buildInitializer, buildCondition, () {}, buildBody); | 6553     handleLoop(node, buildInitializer, buildCondition, () {}, buildBody); | 
| 6603   } | 6554   } | 
| 6604 | 6555 | 
| 6605   buildAssignLoopVariable(ast.ForIn node, HInstruction value) { | 6556   buildAssignLoopVariable(ast.ForIn node, HInstruction value) { | 
| 6606     ast.Node identifier = node.declaredIdentifier; | 6557     ast.Node identifier = node.declaredIdentifier; | 
| 6607     Element variable = elements.getForInVariable(node); | 6558     Element variable = elements.getForInVariable(node); | 
| 6608     Selector selector = elements.getSelector(identifier); | 6559     Selector selector = elements.getSelector(identifier); | 
| 6609     TypeMask mask = elements.getTypeMask(identifier); |  | 
| 6610 | 6560 | 
| 6611     if (identifier.asSend() != null && | 6561     if (identifier.asSend() != null && | 
| 6612         Elements.isInstanceSend(identifier, elements)) { | 6562         Elements.isInstanceSend(identifier, elements)) { | 
| 6613       HInstruction receiver = generateInstanceSendReceiver(identifier); | 6563       HInstruction receiver = generateInstanceSendReceiver(identifier); | 
| 6614       assert(receiver != null); | 6564       assert(receiver != null); | 
| 6615       generateInstanceSetterWithCompiledReceiver( | 6565       generateInstanceSetterWithCompiledReceiver( | 
| 6616           null, | 6566           null, | 
| 6617           receiver, | 6567           receiver, | 
| 6618           value, | 6568           value, | 
| 6619           selector: selector, | 6569           selector: selector, | 
| 6620           mask: mask, |  | 
| 6621           location: identifier); | 6570           location: identifier); | 
| 6622     } else { | 6571     } else { | 
| 6623       generateNonInstanceSetter(null, variable, value, location: identifier); | 6572       generateNonInstanceSetter(null, variable, value, location: identifier); | 
| 6624     } | 6573     } | 
| 6625     pop();  // Discard the value pushed by the setter call. | 6574     pop();  // Discard the value pushed by the setter call. | 
| 6626   } | 6575   } | 
| 6627 | 6576 | 
| 6628   buildSyncForInIndexable(ast.ForIn node, TypeMask arrayType) { | 6577   buildSyncForInIndexable(ast.ForIn node, TypeMask arrayType) { | 
| 6629     // Generate a structure equivalent to: | 6578     // Generate a structure equivalent to: | 
| 6630     // | 6579     // | 
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 6690       // inserted the ConcurrentModificationError check as part of the | 6639       // inserted the ConcurrentModificationError check as part of the | 
| 6691       // condition.  It is not necessary on the first iteration since there is | 6640       // condition.  It is not necessary on the first iteration since there is | 
| 6692       // no code between calls to `get iterator` and `moveNext`, so the test is | 6641       // no code between calls to `get iterator` and `moveNext`, so the test is | 
| 6693       // moved to the loop update. | 6642       // moved to the loop update. | 
| 6694 | 6643 | 
| 6695       // Find a type for the element. Use the element type of the indexer of the | 6644       // Find a type for the element. Use the element type of the indexer of the | 
| 6696       // array, as this is stronger than the iterator's `get current` type, for | 6645       // array, as this is stronger than the iterator's `get current` type, for | 
| 6697       // example, `get current` includes null. | 6646       // example, `get current` includes null. | 
| 6698       // TODO(sra): The element type of a container type mask might be better. | 6647       // TODO(sra): The element type of a container type mask might be better. | 
| 6699       Selector selector = new Selector.index(); | 6648       Selector selector = new Selector.index(); | 
| 6700       TypeMask type = TypeMaskFactory.inferredTypeForSelector( | 6649       Selector refined = new TypedSelector(arrayType, selector, compiler.world); | 
| 6701           selector, arrayType, compiler); | 6650       TypeMask type = | 
|  | 6651           TypeMaskFactory.inferredTypeForSelector(refined, compiler); | 
| 6702 | 6652 | 
| 6703       HInstruction index = localsHandler.readLocal(indexVariable); | 6653       HInstruction index = localsHandler.readLocal(indexVariable); | 
| 6704       HInstruction value = new HIndex(array, index, null, type); | 6654       HInstruction value = new HIndex(array, index, null, type); | 
| 6705       add(value); | 6655       add(value); | 
| 6706 | 6656 | 
| 6707       buildAssignLoopVariable(node, value); | 6657       buildAssignLoopVariable(node, value); | 
| 6708       visit(node.body); | 6658       visit(node.body); | 
| 6709     } | 6659     } | 
| 6710 | 6660 | 
| 6711     void buildUpdate() { | 6661     void buildUpdate() { | 
| (...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 7608     //      conversions. | 7558     //      conversions. | 
| 7609     //   2. The value can be primitive, because the library stringifier has | 7559     //   2. The value can be primitive, because the library stringifier has | 
| 7610     //      fast-path code for most primitives. | 7560     //      fast-path code for most primitives. | 
| 7611     if (expression.canBePrimitive(compiler)) { | 7561     if (expression.canBePrimitive(compiler)) { | 
| 7612       append(stringify(node, expression)); | 7562       append(stringify(node, expression)); | 
| 7613       return; | 7563       return; | 
| 7614     } | 7564     } | 
| 7615 | 7565 | 
| 7616     // If the `toString` method is guaranteed to return a string we can call it | 7566     // If the `toString` method is guaranteed to return a string we can call it | 
| 7617     // directly. | 7567     // directly. | 
| 7618     Selector selector = new Selector.call('toString', null, 0); | 7568     Selector selector = | 
| 7619     TypeMask type = TypeMaskFactory.inferredTypeForSelector( | 7569         new TypedSelector(expression.instructionType, | 
| 7620         selector, expression.instructionType, compiler); | 7570             new Selector.call('toString', null, 0), compiler.world); | 
|  | 7571     TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler); | 
| 7621     if (type.containsOnlyString(compiler.world)) { | 7572     if (type.containsOnlyString(compiler.world)) { | 
| 7622       builder.pushInvokeDynamic( | 7573       builder.pushInvokeDynamic(node, selector, <HInstruction>[expression]); | 
| 7623           node, selector, expression.instructionType, <HInstruction>[expression]
      ); |  | 
| 7624       append(builder.pop()); | 7574       append(builder.pop()); | 
| 7625       return; | 7575       return; | 
| 7626     } | 7576     } | 
| 7627 | 7577 | 
| 7628     append(stringify(node, expression)); | 7578     append(stringify(node, expression)); | 
| 7629   } | 7579   } | 
| 7630 | 7580 | 
| 7631   void visitStringInterpolation(ast.StringInterpolation node) { | 7581   void visitStringInterpolation(ast.StringInterpolation node) { | 
| 7632     node.visitChildren(this); | 7582     node.visitChildren(this); | 
| 7633   } | 7583   } | 
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 8159     if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8109     if (unaliased is TypedefType) throw 'unable to unalias $type'; | 
| 8160     unaliased.accept(this, builder); | 8110     unaliased.accept(this, builder); | 
| 8161   } | 8111   } | 
| 8162 | 8112 | 
| 8163   void visitDynamicType(DynamicType type, SsaBuilder builder) { | 8113   void visitDynamicType(DynamicType type, SsaBuilder builder) { | 
| 8164     JavaScriptBackend backend = builder.compiler.backend; | 8114     JavaScriptBackend backend = builder.compiler.backend; | 
| 8165     ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 8115     ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 
| 8166     builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 8116     builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 
| 8167   } | 8117   } | 
| 8168 } | 8118 } | 
| OLD | NEW | 
|---|