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