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 |