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 | 10 |
(...skipping 2506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2517 assert(type.kind != TypeKind.TYPEDEF); | 2517 assert(type.kind != TypeKind.TYPEDEF); |
2518 if (type.kind == TypeKind.FUNCTION) { | 2518 if (type.kind == TypeKind.FUNCTION) { |
2519 // TODO(5022): We currently generate $isFunction checks for | 2519 // TODO(5022): We currently generate $isFunction checks for |
2520 // function types. | 2520 // function types. |
2521 world.registerIsCheck( | 2521 world.registerIsCheck( |
2522 compiler.functionClass.computeType(compiler), work.resolutionTree); | 2522 compiler.functionClass.computeType(compiler), work.resolutionTree); |
2523 } | 2523 } |
2524 world.registerIsCheck(type, work.resolutionTree); | 2524 world.registerIsCheck(type, work.resolutionTree); |
2525 | 2525 |
2526 CheckedModeHelper helper; | 2526 CheckedModeHelper helper; |
2527 FunctionElement helperElement; | |
2528 if (node.isBooleanConversionCheck) { | 2527 if (node.isBooleanConversionCheck) { |
2529 helper = | 2528 helper = |
2530 const CheckedModeHelper('boolConversionCheck'); | 2529 const CheckedModeHelper('boolConversionCheck'); |
2531 } else { | 2530 } else { |
2532 helper = | 2531 helper = |
2533 backend.getCheckedModeHelper(type, typeCast: node.isCastTypeCheck); | 2532 backend.getCheckedModeHelper(type, typeCast: node.isCastTypeCheck); |
2534 } | 2533 } |
2535 | 2534 |
2536 push(helper.generateCall(this, node)); | 2535 if (helper == null) { |
| 2536 assert(type.kind == TypeKind.FUNCTION); |
| 2537 use(node.inputs[0]); |
| 2538 } else { |
| 2539 push(helper.generateCall(this, node)); |
| 2540 } |
2537 } | 2541 } |
2538 | 2542 |
2539 void visitTypeKnown(HTypeKnown node) { | 2543 void visitTypeKnown(HTypeKnown node) { |
2540 // [HTypeKnown] instructions are removed before generating code. | 2544 // [HTypeKnown] instructions are removed before generating code. |
2541 assert(false); | 2545 assert(false); |
2542 } | 2546 } |
| 2547 |
| 2548 void visitFunctionType(HFunctionType node) { |
| 2549 FunctionType type = node.dartType; |
| 2550 int inputCount = 0; |
| 2551 use(node.inputs[inputCount++]); |
| 2552 js.Expression returnType = pop(); |
| 2553 |
| 2554 List<js.Expression> parameterTypes = <js.Expression>[]; |
| 2555 for (var _ in type.parameterTypes) { |
| 2556 use(node.inputs[inputCount++]); |
| 2557 parameterTypes.add(pop()); |
| 2558 } |
| 2559 |
| 2560 List<js.Expression> optionalParameterTypes = <js.Expression>[]; |
| 2561 for (var _ in type.optionalParameterTypes) { |
| 2562 use(node.inputs[inputCount++]); |
| 2563 optionalParameterTypes.add(pop()); |
| 2564 } |
| 2565 |
| 2566 List<js.Property> namedParameters = <js.Property>[]; |
| 2567 for (var _ in type.namedParameters) { |
| 2568 use(node.inputs[inputCount++]); |
| 2569 js.Expression name = pop(); |
| 2570 use(node.inputs[inputCount++]); |
| 2571 namedParameters.add(new js.Property(name, pop())); |
| 2572 } |
| 2573 |
| 2574 if (namedParameters.isEmpty) { |
| 2575 var arguments = [returnType]; |
| 2576 if (!parameterTypes.isEmpty || !optionalParameterTypes.isEmpty) { |
| 2577 arguments.add(new js.ArrayInitializer.from(parameterTypes)); |
| 2578 } |
| 2579 if (!optionalParameterTypes.isEmpty) { |
| 2580 arguments.add(new js.ArrayInitializer.from(optionalParameterTypes)); |
| 2581 } |
| 2582 push(accessHelper('buildFunctionType')(arguments)); |
| 2583 } else { |
| 2584 var arguments = [ |
| 2585 returnType, |
| 2586 new js.ArrayInitializer.from(parameterTypes), |
| 2587 new js.ObjectInitializer(namedParameters)]; |
| 2588 push(accessHelper('buildNamedFunctionType')(arguments)); |
| 2589 } |
| 2590 } |
| 2591 |
| 2592 void visitReadTypeVariable(HReadTypeVariable node) { |
| 2593 TypeVariableElement element = node.dartType.element; |
| 2594 Element helperElement = compiler.findHelper('convertRtiToRuntimeType'); |
| 2595 world.registerStaticUse(helperElement); |
| 2596 |
| 2597 use(node.inputs[0]); |
| 2598 if (node.hasReceiver) { |
| 2599 if (backend.isInterceptorClass(element.getEnclosingClass())) { |
| 2600 int index = RuntimeTypes.getTypeVariableIndex(element); |
| 2601 js.Expression receiver = pop(); |
| 2602 js.Expression helper = backend.namer.elementAccess(helperElement); |
| 2603 push(helper(js.js(r'#.$builtinTypeInfo && #.$builtinTypeInfo[#]', |
| 2604 [receiver, receiver, js.js.toExpression(index)]))); |
| 2605 } else { |
| 2606 backend.emitter.registerReadTypeVariable(element); |
| 2607 push( |
| 2608 js.js('#.${backend.namer.readTypeVariableName(element)}()', pop())); |
| 2609 } |
| 2610 } else { |
| 2611 push( |
| 2612 backend.namer.elementAccess( |
| 2613 compiler.findHelper('convertRtiToRuntimeType'))(pop())); |
| 2614 } |
| 2615 } |
| 2616 |
| 2617 void visitInterfaceType(HInterfaceType node) { |
| 2618 List<js.Expression> typeArguments = <js.Expression>[]; |
| 2619 for (HInstruction type in node.inputs) { |
| 2620 use(type); |
| 2621 typeArguments.add(pop()); |
| 2622 } |
| 2623 |
| 2624 ClassElement cls = node.dartType.element; |
| 2625 var arguments = [ |
| 2626 backend.namer.elementAccess(backend.getImplementationClass(cls))]; |
| 2627 if (!typeArguments.isEmpty) { |
| 2628 arguments.add(new js.ArrayInitializer.from(typeArguments)); |
| 2629 } |
| 2630 push(accessHelper('buildInterfaceType')(arguments)); |
| 2631 } |
| 2632 |
| 2633 void visitVoidType(HVoidType node) { |
| 2634 push(accessHelper('getVoidRuntimeType')()); |
| 2635 } |
| 2636 |
| 2637 void visitDynamicType(HDynamicType node) { |
| 2638 push(accessHelper('getDynamicRuntimeType')()); |
| 2639 } |
| 2640 |
| 2641 js.PropertyAccess accessHelper(String name) { |
| 2642 Element helper = compiler.findHelper(name); |
| 2643 if (helper == null) { |
| 2644 // For mocked-up tests. |
| 2645 return js.js('(void 0).$name'); |
| 2646 } |
| 2647 world.registerStaticUse(helper); |
| 2648 return backend.namer.elementAccess(helper); |
| 2649 } |
2543 } | 2650 } |
2544 | 2651 |
2545 String singleIdentityComparison(HInstruction left, | 2652 String singleIdentityComparison(HInstruction left, |
2546 HInstruction right, | 2653 HInstruction right, |
2547 Compiler compiler) { | 2654 Compiler compiler) { |
2548 // Returns the single identity comparison (== or ===) or null if a more | 2655 // Returns the single identity comparison (== or ===) or null if a more |
2549 // complex expression is required. | 2656 // complex expression is required. |
2550 if ((left.isConstant() && left.isConstantSentinel()) || | 2657 if ((left.isConstant() && left.isConstantSentinel()) || |
2551 (right.isConstant() && right.isConstantSentinel())) return '==='; | 2658 (right.isConstant() && right.isConstantSentinel())) return '==='; |
2552 if (left.canBeNull() && right.canBeNull()) { | 2659 if (left.canBeNull() && right.canBeNull()) { |
2553 if (left.isConstantNull() || right.isConstantNull() || | 2660 if (left.isConstantNull() || right.isConstantNull() || |
2554 (left.isPrimitive(compiler) && | 2661 (left.isPrimitive(compiler) && |
2555 left.instructionType == right.instructionType)) { | 2662 left.instructionType == right.instructionType)) { |
2556 return '=='; | 2663 return '=='; |
2557 } | 2664 } |
2558 return null; | 2665 return null; |
2559 } else { | 2666 } else { |
2560 return '==='; | 2667 return '==='; |
2561 } | 2668 } |
2562 } | 2669 } |
OLD | NEW |