| 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 SsaCodeGeneratorTask extends CompilerTask { | 7 class SsaCodeGeneratorTask extends CompilerTask { |
| 8 | 8 |
| 9 final JavaScriptBackend backend; | 9 final JavaScriptBackend backend; |
| 10 final SourceInformationStrategy sourceInformationFactory; | 10 final SourceInformationStrategy sourceInformationFactory; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; | 156 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; |
| 157 | 157 |
| 158 CodegenRegistry get registry => work.registry; | 158 CodegenRegistry get registry => work.registry; |
| 159 | 159 |
| 160 native.NativeEnqueuer get nativeEnqueuer { | 160 native.NativeEnqueuer get nativeEnqueuer { |
| 161 return compiler.enqueuer.codegen.nativeEnqueuer; | 161 return compiler.enqueuer.codegen.nativeEnqueuer; |
| 162 } | 162 } |
| 163 | 163 |
| 164 DiagnosticReporter get reporter => compiler.reporter; | 164 DiagnosticReporter get reporter => compiler.reporter; |
| 165 | 165 |
| 166 CoreClasses get coreClasses => compiler.coreClasses; |
| 167 |
| 166 bool isGenerateAtUseSite(HInstruction instruction) { | 168 bool isGenerateAtUseSite(HInstruction instruction) { |
| 167 return generateAtUseSite.contains(instruction); | 169 return generateAtUseSite.contains(instruction); |
| 168 } | 170 } |
| 169 | 171 |
| 170 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) { | 172 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) { |
| 171 for (HInstruction user in instruction.usedBy) { | 173 for (HInstruction user in instruction.usedBy) { |
| 172 if (user is HPhi) { | 174 if (user is HPhi) { |
| 173 if (!phiSet.contains(user)) { | 175 if (!phiSet.contains(user)) { |
| 174 phiSet.add(user); | 176 phiSet.add(user); |
| 175 if (hasNonBitOpUser(user, phiSet)) return true; | 177 if (hasNonBitOpUser(user, phiSet)) return true; |
| (...skipping 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1540 // TODO(herhut): The namer should return the appropriate backendname here. | 1542 // TODO(herhut): The namer should return the appropriate backendname here. |
| 1541 if (target != null && !node.isInterceptedCall) { | 1543 if (target != null && !node.isInterceptedCall) { |
| 1542 if (target == backend.jsArrayAdd) { | 1544 if (target == backend.jsArrayAdd) { |
| 1543 methodName = 'push'; | 1545 methodName = 'push'; |
| 1544 } else if (target == backend.jsArrayRemoveLast) { | 1546 } else if (target == backend.jsArrayRemoveLast) { |
| 1545 methodName = 'pop'; | 1547 methodName = 'pop'; |
| 1546 } else if (target == backend.jsStringSplit) { | 1548 } else if (target == backend.jsStringSplit) { |
| 1547 methodName = 'split'; | 1549 methodName = 'split'; |
| 1548 // Split returns a List, so we make sure the backend knows the | 1550 // Split returns a List, so we make sure the backend knows the |
| 1549 // list class is instantiated. | 1551 // list class is instantiated. |
| 1550 registry.registerInstantiatedClass(compiler.listClass); | 1552 registry.registerInstantiatedClass(coreClasses.listClass); |
| 1551 } else if (backend.isNative(target) && target.isFunction | 1553 } else if (backend.isNative(target) && target.isFunction |
| 1552 && !node.isInterceptedCall) { | 1554 && !node.isInterceptedCall) { |
| 1553 // A direct (i.e. non-interceptor) native call is the result of | 1555 // A direct (i.e. non-interceptor) native call is the result of |
| 1554 // optimization. The optimization ensures any type checks or | 1556 // optimization. The optimization ensures any type checks or |
| 1555 // conversions have been satisified. | 1557 // conversions have been satisified. |
| 1556 methodName = backend.getFixedBackendName(target); | 1558 methodName = backend.getFixedBackendName(target); |
| 1557 } | 1559 } |
| 1558 } | 1560 } |
| 1559 | 1561 |
| 1560 js.Name methodLiteral; | 1562 js.Name methodLiteral; |
| (...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2269 registry.registerStaticUse(convertToString); | 2271 registry.registerStaticUse(convertToString); |
| 2270 js.Expression jsHelper = | 2272 js.Expression jsHelper = |
| 2271 backend.emitter.staticFunctionAccess(convertToString); | 2273 backend.emitter.staticFunctionAccess(convertToString); |
| 2272 use(input); | 2274 use(input); |
| 2273 push(new js.Call(jsHelper, <js.Expression>[pop()], | 2275 push(new js.Call(jsHelper, <js.Expression>[pop()], |
| 2274 sourceInformation: node.sourceInformation)); | 2276 sourceInformation: node.sourceInformation)); |
| 2275 } | 2277 } |
| 2276 } | 2278 } |
| 2277 | 2279 |
| 2278 void visitLiteralList(HLiteralList node) { | 2280 void visitLiteralList(HLiteralList node) { |
| 2279 registry.registerInstantiatedClass(compiler.listClass); | 2281 registry.registerInstantiatedClass(coreClasses.listClass); |
| 2280 generateArrayLiteral(node); | 2282 generateArrayLiteral(node); |
| 2281 } | 2283 } |
| 2282 | 2284 |
| 2283 void generateArrayLiteral(HLiteralList node) { | 2285 void generateArrayLiteral(HLiteralList node) { |
| 2284 List<js.Expression> elements = node.inputs.map((HInstruction input) { | 2286 List<js.Expression> elements = node.inputs.map((HInstruction input) { |
| 2285 use(input); | 2287 use(input); |
| 2286 return pop(); | 2288 return pop(); |
| 2287 }).toList(); | 2289 }).toList(); |
| 2288 push(new js.ArrayInitializer(elements) | 2290 push(new js.ArrayInitializer(elements) |
| 2289 .withSourceInformation(node.sourceInformation)); | 2291 .withSourceInformation(node.sourceInformation)); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2502 .withSourceInformation(sourceInformation)); | 2504 .withSourceInformation(sourceInformation)); |
| 2503 } | 2505 } |
| 2504 registry.registerInstantiatedType(type); | 2506 registry.registerInstantiatedType(type); |
| 2505 } | 2507 } |
| 2506 | 2508 |
| 2507 void handleNumberOrStringSupertypeCheck(HInstruction input, | 2509 void handleNumberOrStringSupertypeCheck(HInstruction input, |
| 2508 HInstruction interceptor, | 2510 HInstruction interceptor, |
| 2509 DartType type, | 2511 DartType type, |
| 2510 SourceInformation sourceInformation, | 2512 SourceInformation sourceInformation, |
| 2511 {bool negative: false}) { | 2513 {bool negative: false}) { |
| 2512 assert(!identical(type.element, compiler.listClass) && | 2514 assert(!identical(type.element, coreClasses.listClass) && |
| 2513 !Elements.isListSupertype(type.element, compiler) && | 2515 !Elements.isListSupertype(type.element, compiler) && |
| 2514 !Elements.isStringOnlySupertype(type.element, compiler)); | 2516 !Elements.isStringOnlySupertype(type.element, compiler)); |
| 2515 String relation = negative ? '!==' : '==='; | 2517 String relation = negative ? '!==' : '==='; |
| 2516 checkNum(input, relation, sourceInformation); | 2518 checkNum(input, relation, sourceInformation); |
| 2517 js.Expression numberTest = pop(); | 2519 js.Expression numberTest = pop(); |
| 2518 checkString(input, relation, sourceInformation); | 2520 checkString(input, relation, sourceInformation); |
| 2519 js.Expression stringTest = pop(); | 2521 js.Expression stringTest = pop(); |
| 2520 checkObject(input, relation, sourceInformation); | 2522 checkObject(input, relation, sourceInformation); |
| 2521 js.Expression objectTest = pop(); | 2523 js.Expression objectTest = pop(); |
| 2522 checkType(input, interceptor, type, sourceInformation, negative: negative); | 2524 checkType(input, interceptor, type, sourceInformation, negative: negative); |
| 2523 String combiner = negative ? '&&' : '||'; | 2525 String combiner = negative ? '&&' : '||'; |
| 2524 String combiner2 = negative ? '||' : '&&'; | 2526 String combiner2 = negative ? '||' : '&&'; |
| 2525 push(new js.Binary(combiner, | 2527 push(new js.Binary(combiner, |
| 2526 new js.Binary(combiner, numberTest, stringTest) | 2528 new js.Binary(combiner, numberTest, stringTest) |
| 2527 .withSourceInformation(sourceInformation), | 2529 .withSourceInformation(sourceInformation), |
| 2528 new js.Binary(combiner2, objectTest, pop()) | 2530 new js.Binary(combiner2, objectTest, pop()) |
| 2529 .withSourceInformation(sourceInformation)) | 2531 .withSourceInformation(sourceInformation)) |
| 2530 .withSourceInformation(sourceInformation)); | 2532 .withSourceInformation(sourceInformation)); |
| 2531 } | 2533 } |
| 2532 | 2534 |
| 2533 void handleStringSupertypeCheck(HInstruction input, | 2535 void handleStringSupertypeCheck(HInstruction input, |
| 2534 HInstruction interceptor, | 2536 HInstruction interceptor, |
| 2535 DartType type, | 2537 DartType type, |
| 2536 SourceInformation sourceInformation, | 2538 SourceInformation sourceInformation, |
| 2537 {bool negative: false}) { | 2539 {bool negative: false}) { |
| 2538 assert(!identical(type.element, compiler.listClass) | 2540 assert(!identical(type.element, coreClasses.listClass) |
| 2539 && !Elements.isListSupertype(type.element, compiler) | 2541 && !Elements.isListSupertype(type.element, compiler) |
| 2540 && !Elements.isNumberOrStringSupertype(type.element, compiler)); | 2542 && !Elements.isNumberOrStringSupertype(type.element, compiler)); |
| 2541 String relation = negative ? '!==' : '==='; | 2543 String relation = negative ? '!==' : '==='; |
| 2542 checkString(input, relation, sourceInformation); | 2544 checkString(input, relation, sourceInformation); |
| 2543 js.Expression stringTest = pop(); | 2545 js.Expression stringTest = pop(); |
| 2544 checkObject(input, relation, sourceInformation); | 2546 checkObject(input, relation, sourceInformation); |
| 2545 js.Expression objectTest = pop(); | 2547 js.Expression objectTest = pop(); |
| 2546 checkType(input, interceptor, type, sourceInformation, negative: negative); | 2548 checkType(input, interceptor, type, sourceInformation, negative: negative); |
| 2547 String combiner = negative ? '||' : '&&'; | 2549 String combiner = negative ? '||' : '&&'; |
| 2548 push(new js.Binary(negative ? '&&' : '||', | 2550 push(new js.Binary(negative ? '&&' : '||', |
| 2549 stringTest, | 2551 stringTest, |
| 2550 new js.Binary(combiner, objectTest, pop()))); | 2552 new js.Binary(combiner, objectTest, pop()))); |
| 2551 } | 2553 } |
| 2552 | 2554 |
| 2553 void handleListOrSupertypeCheck(HInstruction input, | 2555 void handleListOrSupertypeCheck(HInstruction input, |
| 2554 HInstruction interceptor, | 2556 HInstruction interceptor, |
| 2555 DartType type, | 2557 DartType type, |
| 2556 SourceInformation sourceInformation, | 2558 SourceInformation sourceInformation, |
| 2557 { bool negative: false }) { | 2559 { bool negative: false }) { |
| 2558 assert(!identical(type.element, compiler.stringClass) | 2560 assert(!identical(type.element, coreClasses.stringClass) |
| 2559 && !Elements.isStringOnlySupertype(type.element, compiler) | 2561 && !Elements.isStringOnlySupertype(type.element, compiler) |
| 2560 && !Elements.isNumberOrStringSupertype(type.element, compiler)); | 2562 && !Elements.isNumberOrStringSupertype(type.element, compiler)); |
| 2561 String relation = negative ? '!==' : '==='; | 2563 String relation = negative ? '!==' : '==='; |
| 2562 checkObject(input, relation, sourceInformation); | 2564 checkObject(input, relation, sourceInformation); |
| 2563 js.Expression objectTest = pop(); | 2565 js.Expression objectTest = pop(); |
| 2564 checkArray(input, relation); | 2566 checkArray(input, relation); |
| 2565 js.Expression arrayTest = pop(); | 2567 js.Expression arrayTest = pop(); |
| 2566 checkType(input, interceptor, type, sourceInformation, negative: negative); | 2568 checkType(input, interceptor, type, sourceInformation, negative: negative); |
| 2567 String combiner = negative ? '&&' : '||'; | 2569 String combiner = negative ? '&&' : '||'; |
| 2568 push(new js.Binary(negative ? '||' : '&&', | 2570 push(new js.Binary(negative ? '||' : '&&', |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2588 // be changed to match. | 2590 // be changed to match. |
| 2589 assert(relation == '===' || relation == '!=='); | 2591 assert(relation == '===' || relation == '!=='); |
| 2590 bool negative = relation == '!=='; | 2592 bool negative = relation == '!=='; |
| 2591 | 2593 |
| 2592 if (node.isVariableCheck || node.isCompoundCheck) { | 2594 if (node.isVariableCheck || node.isCompoundCheck) { |
| 2593 use(node.checkCall); | 2595 use(node.checkCall); |
| 2594 if (negative) push(new js.Prefix('!', pop())); | 2596 if (negative) push(new js.Prefix('!', pop())); |
| 2595 } else { | 2597 } else { |
| 2596 assert(node.isRawCheck); | 2598 assert(node.isRawCheck); |
| 2597 HInstruction interceptor = node.interceptor; | 2599 HInstruction interceptor = node.interceptor; |
| 2598 ClassElement objectClass = compiler.objectClass; | 2600 ClassElement objectClass = coreClasses.objectClass; |
| 2599 Element element = type.element; | 2601 Element element = type.element; |
| 2600 if (element == compiler.nullClass) { | 2602 if (element == coreClasses.nullClass) { |
| 2601 if (negative) { | 2603 if (negative) { |
| 2602 checkNonNull(input); | 2604 checkNonNull(input); |
| 2603 } else { | 2605 } else { |
| 2604 checkNull(input); | 2606 checkNull(input); |
| 2605 } | 2607 } |
| 2606 } else if (identical(element, objectClass) || type.treatAsDynamic) { | 2608 } else if (identical(element, objectClass) || type.treatAsDynamic) { |
| 2607 // The constant folder also does this optimization, but we make | 2609 // The constant folder also does this optimization, but we make |
| 2608 // it safe by assuming it may have not run. | 2610 // it safe by assuming it may have not run. |
| 2609 push(newLiteralBool(!negative, sourceInformation)); | 2611 push(newLiteralBool(!negative, sourceInformation)); |
| 2610 } else if (element == compiler.stringClass) { | 2612 } else if (element == coreClasses.stringClass) { |
| 2611 checkString(input, relation, sourceInformation); | 2613 checkString(input, relation, sourceInformation); |
| 2612 } else if (element == compiler.doubleClass) { | 2614 } else if (element == coreClasses.doubleClass) { |
| 2613 checkDouble(input, relation, sourceInformation); | 2615 checkDouble(input, relation, sourceInformation); |
| 2614 } else if (element == compiler.numClass) { | 2616 } else if (element == coreClasses.numClass) { |
| 2615 checkNum(input, relation, sourceInformation); | 2617 checkNum(input, relation, sourceInformation); |
| 2616 } else if (element == compiler.boolClass) { | 2618 } else if (element == coreClasses.boolClass) { |
| 2617 checkBool(input, relation, sourceInformation); | 2619 checkBool(input, relation, sourceInformation); |
| 2618 } else if (element == compiler.intClass) { | 2620 } else if (element == coreClasses.intClass) { |
| 2619 // The is check in the code tells us that it might not be an | 2621 // The is check in the code tells us that it might not be an |
| 2620 // int. So we do a typeof first to avoid possible | 2622 // int. So we do a typeof first to avoid possible |
| 2621 // deoptimizations on the JS engine due to the Math.floor check. | 2623 // deoptimizations on the JS engine due to the Math.floor check. |
| 2622 checkNum(input, relation, sourceInformation); | 2624 checkNum(input, relation, sourceInformation); |
| 2623 js.Expression numTest = pop(); | 2625 js.Expression numTest = pop(); |
| 2624 checkBigInt(input, relation, sourceInformation); | 2626 checkBigInt(input, relation, sourceInformation); |
| 2625 push(new js.Binary(negative ? '||' : '&&', numTest, pop()) | 2627 push(new js.Binary(negative ? '||' : '&&', numTest, pop()) |
| 2626 .withSourceInformation(sourceInformation)); | 2628 .withSourceInformation(sourceInformation)); |
| 2627 } else if (node.useInstanceOf) { | 2629 } else if (node.useInstanceOf) { |
| 2628 assert(interceptor == null); | 2630 assert(interceptor == null); |
| 2629 checkTypeViaInstanceof(input, type, | 2631 checkTypeViaInstanceof(input, type, |
| 2630 sourceInformation, | 2632 sourceInformation, |
| 2631 negative: negative); | 2633 negative: negative); |
| 2632 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { | 2634 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { |
| 2633 handleNumberOrStringSupertypeCheck( | 2635 handleNumberOrStringSupertypeCheck( |
| 2634 input, interceptor, type, | 2636 input, interceptor, type, |
| 2635 sourceInformation, | 2637 sourceInformation, |
| 2636 negative: negative); | 2638 negative: negative); |
| 2637 } else if (Elements.isStringOnlySupertype(element, compiler)) { | 2639 } else if (Elements.isStringOnlySupertype(element, compiler)) { |
| 2638 handleStringSupertypeCheck( | 2640 handleStringSupertypeCheck( |
| 2639 input, interceptor, type, | 2641 input, interceptor, type, |
| 2640 sourceInformation, | 2642 sourceInformation, |
| 2641 negative: negative); | 2643 negative: negative); |
| 2642 } else if (identical(element, compiler.listClass) || | 2644 } else if (identical(element, coreClasses.listClass) || |
| 2643 Elements.isListSupertype(element, compiler)) { | 2645 Elements.isListSupertype(element, compiler)) { |
| 2644 handleListOrSupertypeCheck( | 2646 handleListOrSupertypeCheck( |
| 2645 input, interceptor, type, | 2647 input, interceptor, type, |
| 2646 sourceInformation, | 2648 sourceInformation, |
| 2647 negative: negative); | 2649 negative: negative); |
| 2648 } else if (type.isFunctionType) { | 2650 } else if (type.isFunctionType) { |
| 2649 checkType(input, interceptor, type, | 2651 checkType(input, interceptor, type, |
| 2650 sourceInformation, | 2652 sourceInformation, |
| 2651 negative: negative); | 2653 negative: negative); |
| 2652 } else if ((input.canBePrimitive(compiler) | 2654 } else if ((input.canBePrimitive(compiler) |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2745 .withSourceInformation(node.sourceInformation)); | 2747 .withSourceInformation(node.sourceInformation)); |
| 2746 return; | 2748 return; |
| 2747 } | 2749 } |
| 2748 | 2750 |
| 2749 assert(node.isCheckedModeCheck || node.isCastTypeCheck); | 2751 assert(node.isCheckedModeCheck || node.isCastTypeCheck); |
| 2750 DartType type = node.typeExpression; | 2752 DartType type = node.typeExpression; |
| 2751 assert(type.kind != TypeKind.TYPEDEF); | 2753 assert(type.kind != TypeKind.TYPEDEF); |
| 2752 if (type.isFunctionType) { | 2754 if (type.isFunctionType) { |
| 2753 // TODO(5022): We currently generate $isFunction checks for | 2755 // TODO(5022): We currently generate $isFunction checks for |
| 2754 // function types. | 2756 // function types. |
| 2755 registry.registerIsCheck(compiler.functionClass.rawType); | 2757 registry.registerIsCheck(compiler.coreTypes.functionType); |
| 2756 } | 2758 } |
| 2757 registry.registerIsCheck(type); | 2759 registry.registerIsCheck(type); |
| 2758 | 2760 |
| 2759 CheckedModeHelper helper; | 2761 CheckedModeHelper helper; |
| 2760 if (node.isBooleanConversionCheck) { | 2762 if (node.isBooleanConversionCheck) { |
| 2761 helper = | 2763 helper = |
| 2762 const CheckedModeHelper('boolConversionCheck'); | 2764 const CheckedModeHelper('boolConversionCheck'); |
| 2763 } else { | 2765 } else { |
| 2764 helper = | 2766 helper = |
| 2765 backend.getCheckedModeHelper(type, typeCast: node.isCastTypeCheck); | 2767 backend.getCheckedModeHelper(type, typeCast: node.isCastTypeCheck); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2880 } | 2882 } |
| 2881 registry.registerStaticUse(helper); | 2883 registry.registerStaticUse(helper); |
| 2882 return backend.emitter.staticFunctionAccess(helper); | 2884 return backend.emitter.staticFunctionAccess(helper); |
| 2883 } | 2885 } |
| 2884 | 2886 |
| 2885 @override | 2887 @override |
| 2886 void visitRef(HRef node) { | 2888 void visitRef(HRef node) { |
| 2887 visit(node.value); | 2889 visit(node.value); |
| 2888 } | 2890 } |
| 2889 } | 2891 } |
| OLD | NEW |