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 2558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2569 helper = | 2569 helper = |
2570 backend.getCheckedModeHelper(type, typeCast: node.isCastTypeCheck); | 2570 backend.getCheckedModeHelper(type, typeCast: node.isCastTypeCheck); |
2571 } | 2571 } |
2572 | 2572 |
2573 push(helper.generateCall(this, node)); | 2573 push(helper.generateCall(this, node)); |
2574 } | 2574 } |
2575 | 2575 |
2576 void visitTypeKnown(HTypeKnown node) { | 2576 void visitTypeKnown(HTypeKnown node) { |
2577 use(node.checkedInput); | 2577 use(node.checkedInput); |
2578 } | 2578 } |
| 2579 |
| 2580 void visitFunctionType(HFunctionType node) { |
| 2581 node.dartType.accept(new TypeBuilder(node.inputs), this); |
| 2582 } |
| 2583 |
| 2584 void visitReadTypeVariable(HReadTypeVariable node) { |
| 2585 TypeVariableElement element = node.dartType.element; |
| 2586 Element helperElement = compiler.findHelper('convertRtiToRuntimeType'); |
| 2587 world.registerStaticUse(helperElement); |
| 2588 |
| 2589 use(node.inputs[0]); |
| 2590 if (node.hasReceiver) { |
| 2591 if (backend.isInterceptorClass(element.getEnclosingClass())) { |
| 2592 int index = RuntimeTypes.getTypeVariableIndex(element); |
| 2593 js.Expression receiver = pop(); |
| 2594 js.Expression helper = backend.namer.elementAccess(helperElement); |
| 2595 push(helper(js.js(r'#.$builtinTypeInfo && #.$builtinTypeInfo[#]', |
| 2596 [receiver, receiver, js.js.toExpression(index)]))); |
| 2597 } else { |
| 2598 backend.emitter.registerReadTypeVariable(element); |
| 2599 push(js.js('#.${backend.namer.readTypeVariableName(element)}()', pop()))
; |
| 2600 } |
| 2601 } else { |
| 2602 push( |
| 2603 backend.namer.elementAccess( |
| 2604 compiler.findHelper('convertRtiToRuntimeType'))(pop())); |
| 2605 } |
| 2606 } |
| 2607 } |
| 2608 |
| 2609 class TypeBuilder implements DartTypeVisitor<dynamic, SsaCodeGenerator> { |
| 2610 final List<HInstruction> typeVariables; |
| 2611 int lastUsedTypeVariable = -1; |
| 2612 |
| 2613 TypeBuilder(this.typeVariables); |
| 2614 |
| 2615 HReadTypeVariable nextTypeVariable(TypeVariableType type) { |
| 2616 HReadTypeVariable instruction = typeVariables[++lastUsedTypeVariable]; |
| 2617 assert(instruction.dartType == type); |
| 2618 return instruction; |
| 2619 } |
| 2620 |
| 2621 void visitType(DartType type, A argument) { |
| 2622 throw 'Internal error $type'; |
| 2623 } |
| 2624 |
| 2625 void visitVoidType(VoidType type, SsaCodeGenerator generator) { |
| 2626 generator.push(accessHelper('getVoidRuntimeType', generator)()); |
| 2627 } |
| 2628 |
| 2629 void visitTypeVariableType(TypeVariableType type, |
| 2630 SsaCodeGenerator generator) { |
| 2631 generator.use(nextTypeVariable(type)); |
| 2632 } |
| 2633 |
| 2634 void visitFunctionType(FunctionType type, SsaCodeGenerator generator) { |
| 2635 type.returnType.accept(this, generator); |
| 2636 js.Node returnType = generator.pop(); |
| 2637 |
| 2638 List<js.Expression> parameterTypes = <js.Expression>[]; |
| 2639 for (DartType parameter in type.parameterTypes) { |
| 2640 parameter.accept(this, generator); |
| 2641 parameterTypes.add(generator.pop()); |
| 2642 } |
| 2643 |
| 2644 List<js.Expression> optionalParameterTypes = <js.Expression>[]; |
| 2645 for (DartType parameter in type.optionalParameterTypes) { |
| 2646 parameter.accept(this, generator); |
| 2647 optionalParameterTypes.add(generator.pop()); |
| 2648 } |
| 2649 |
| 2650 Link<DartType> namedParameterTypes = type.namedParameterTypes; |
| 2651 List<js.Property> namedParameters = <js.Property>[]; |
| 2652 for (String name in type.namedParameters) { |
| 2653 namedParameterTypes.head.accept(this, generator); |
| 2654 namedParameters.add(new js.Property(js.string(name), generator.pop())); |
| 2655 namedParameterTypes = namedParameterTypes.tail; |
| 2656 } |
| 2657 |
| 2658 if (namedParameters.isEmpty) { |
| 2659 var arguments = [ |
| 2660 returnType, |
| 2661 new js.ArrayInitializer.from(parameterTypes)]; |
| 2662 if (!optionalParameterTypes.isEmpty) { |
| 2663 arguments.add(optionalParameterTypes); |
| 2664 } |
| 2665 generator.push(accessHelper('buildFunctionType', generator)(arguments)); |
| 2666 } else { |
| 2667 var arguments = [ |
| 2668 returnType, |
| 2669 new js.ArrayInitializer.from(parameterTypes), |
| 2670 new js.ObjectInitializer(namedParameters)]; |
| 2671 generator.push( |
| 2672 accessHelper('buildNamedFunctionType', generator)(arguments)); |
| 2673 } |
| 2674 } |
| 2675 |
| 2676 void visitMalformedType(MalformedType type, SsaCodeGenerator generator) { |
| 2677 // TODO(ahe): Discard type variables. |
| 2678 generator.push(accessHelper('getDynamicRuntimeType', generator)()); |
| 2679 } |
| 2680 |
| 2681 void visitStatementType(StatementType type, SsaCodeGenerator generator) { |
| 2682 throw 'not implemented visitStatementType($type)'; |
| 2683 } |
| 2684 |
| 2685 void visitGenericType(GenericType type, SsaCodeGenerator generator) { |
| 2686 throw 'not implemented visitGenericType($type)'; |
| 2687 } |
| 2688 |
| 2689 void visitInterfaceType(InterfaceType type, SsaCodeGenerator generator) { |
| 2690 List<js.Expression> typeArguments = <js.Expression>[]; |
| 2691 for (DartType typeArgument in type.typeArguments) { |
| 2692 typeArgument.accept(this, generator); |
| 2693 typeArguments.add(generator.pop()); |
| 2694 } |
| 2695 |
| 2696 final JavaScriptBackend backend = generator.backend; |
| 2697 final Namer namer = backend.namer; |
| 2698 |
| 2699 var arguments = [ |
| 2700 namer.elementAccess(backend.getImplementationClass(type.element)), |
| 2701 new js.ArrayInitializer.from(typeArguments)]; |
| 2702 generator.push(accessHelper('buildInterfaceType', generator)(arguments)); |
| 2703 } |
| 2704 |
| 2705 void visitTypedefType(TypedefType type, SsaCodeGenerator generator) { |
| 2706 // TODO(ahe): This doesn't work for type variables. |
| 2707 DartType unaliased = type.unalias(generator.compiler); |
| 2708 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 2709 unaliased.accept(this, generator); |
| 2710 } |
| 2711 |
| 2712 void visitDynamicType(DynamicType type, SsaCodeGenerator generator) { |
| 2713 generator.push(accessHelper('getDynamicRuntimeType', generator)()); |
| 2714 } |
| 2715 |
| 2716 js.PropertyAccess accessHelper(String name, SsaCodeGenerator generator) { |
| 2717 Element helper = generator.compiler.findHelper(name); |
| 2718 generator.world.registerStaticUse(helper); |
| 2719 return generator.backend.namer.elementAccess(helper); |
| 2720 } |
2579 } | 2721 } |
2580 | 2722 |
2581 String singleIdentityComparison(HInstruction left, | 2723 String singleIdentityComparison(HInstruction left, |
2582 HInstruction right, | 2724 HInstruction right, |
2583 Compiler compiler) { | 2725 Compiler compiler) { |
2584 // Returns the single identity comparison (== or ===) or null if a more | 2726 // Returns the single identity comparison (== or ===) or null if a more |
2585 // complex expression is required. | 2727 // complex expression is required. |
2586 if ((left.isConstant() && left.isConstantSentinel()) || | 2728 if ((left.isConstant() && left.isConstantSentinel()) || |
2587 (right.isConstant() && right.isConstantSentinel())) return '==='; | 2729 (right.isConstant() && right.isConstantSentinel())) return '==='; |
2588 HType leftType = left.instructionType; | 2730 HType leftType = left.instructionType; |
2589 HType rightType = right.instructionType; | 2731 HType rightType = right.instructionType; |
2590 if (leftType.canBeNull() && rightType.canBeNull()) { | 2732 if (leftType.canBeNull() && rightType.canBeNull()) { |
2591 if (left.isConstantNull() || right.isConstantNull() || | 2733 if (left.isConstantNull() || right.isConstantNull() || |
2592 (leftType.isPrimitive(compiler) && leftType == rightType)) { | 2734 (leftType.isPrimitive(compiler) && leftType == rightType)) { |
2593 return '=='; | 2735 return '=='; |
2594 } | 2736 } |
2595 return null; | 2737 return null; |
2596 } else { | 2738 } else { |
2597 return '==='; | 2739 return '==='; |
2598 } | 2740 } |
2599 } | 2741 } |
OLD | NEW |