OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
9 import '../common/names.dart'; | 9 import '../common/names.dart'; |
10 import '../common/tasks.dart' show CompilerTask; | 10 import '../common/tasks.dart' show CompilerTask; |
11 import '../compiler.dart'; | 11 import '../compiler.dart'; |
| 12 import '../constants/values.dart' show StringConstantValue; |
12 import '../dart_types.dart'; | 13 import '../dart_types.dart'; |
13 import '../elements/elements.dart'; | 14 import '../elements/elements.dart'; |
14 import '../io/source_information.dart'; | 15 import '../io/source_information.dart'; |
| 16 import '../js/js.dart' as js; |
15 import '../js_backend/backend.dart' show JavaScriptBackend; | 17 import '../js_backend/backend.dart' show JavaScriptBackend; |
16 import '../kernel/kernel.dart'; | 18 import '../kernel/kernel.dart'; |
| 19 import '../native/native.dart' as native; |
17 import '../resolution/tree_elements.dart'; | 20 import '../resolution/tree_elements.dart'; |
18 import '../tree/dartstring.dart'; | 21 import '../tree/dartstring.dart'; |
19 import '../types/masks.dart'; | 22 import '../types/masks.dart'; |
20 import '../universe/selector.dart'; | 23 import '../universe/selector.dart'; |
| 24 import '../universe/side_effects.dart' show SideEffects; |
21 import 'graph_builder.dart'; | 25 import 'graph_builder.dart'; |
22 import 'kernel_ast_adapter.dart'; | 26 import 'kernel_ast_adapter.dart'; |
23 import 'kernel_string_builder.dart'; | 27 import 'kernel_string_builder.dart'; |
24 import 'locals_handler.dart'; | 28 import 'locals_handler.dart'; |
25 import 'loop_handler.dart'; | 29 import 'loop_handler.dart'; |
26 import 'nodes.dart'; | 30 import 'nodes.dart'; |
27 import 'ssa_branch_builder.dart'; | 31 import 'ssa_branch_builder.dart'; |
28 | 32 |
29 class SsaKernelBuilderTask extends CompilerTask { | 33 class SsaKernelBuilderTask extends CompilerTask { |
30 final JavaScriptBackend backend; | 34 final JavaScriptBackend backend; |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 @override | 564 @override |
561 void visitMapEntry(ir.MapEntry mapEntry) { | 565 void visitMapEntry(ir.MapEntry mapEntry) { |
562 // Visit value before the key because each will push an expression to the | 566 // Visit value before the key because each will push an expression to the |
563 // stack, so when we pop them off, the key is popped first, then the value. | 567 // stack, so when we pop them off, the key is popped first, then the value. |
564 mapEntry.value.accept(this); | 568 mapEntry.value.accept(this); |
565 mapEntry.key.accept(this); | 569 mapEntry.key.accept(this); |
566 } | 570 } |
567 | 571 |
568 @override | 572 @override |
569 void visitStaticGet(ir.StaticGet staticGet) { | 573 void visitStaticGet(ir.StaticGet staticGet) { |
570 var staticTarget = staticGet.target; | 574 ir.Member staticTarget = staticGet.target; |
571 if (staticTarget is ir.Procedure && | 575 if (staticTarget is ir.Procedure && |
572 staticTarget.kind == ir.ProcedureKind.Getter) { | 576 staticTarget.kind == ir.ProcedureKind.Getter) { |
573 // Invoke the getter | 577 // Invoke the getter |
574 _pushStaticInvocation(staticTarget, const <HInstruction>[], | 578 _pushStaticInvocation(staticTarget, const <HInstruction>[], |
575 astAdapter.returnTypeOf(staticTarget)); | 579 astAdapter.returnTypeOf(staticTarget)); |
| 580 } else if (staticTarget is ir.Field && staticTarget.isConst) { |
| 581 assert(staticTarget.initializer != null); |
| 582 stack.add(graph.addConstant( |
| 583 astAdapter.getConstantFor(staticTarget.initializer), compiler)); |
576 } else { | 584 } else { |
577 Element element = astAdapter.getElement(staticTarget).declaration; | 585 Element element = astAdapter.getElement(staticTarget).declaration; |
578 push(new HStatic(element, astAdapter.inferredTypeOf(staticTarget))); | 586 push(new HStatic(element, astAdapter.inferredTypeOf(staticTarget))); |
579 } | 587 } |
580 } | 588 } |
581 | 589 |
582 @override | 590 @override |
583 void visitStaticSet(ir.StaticSet staticSet) { | 591 void visitStaticSet(ir.StaticSet staticSet) { |
584 staticSet.value.accept(this); | 592 staticSet.value.accept(this); |
585 HInstruction value = pop(); | 593 HInstruction value = pop(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 argument.value.accept(this); | 672 argument.value.accept(this); |
665 result.add(pop()); | 673 result.add(pop()); |
666 } | 674 } |
667 | 675 |
668 return result; | 676 return result; |
669 } | 677 } |
670 | 678 |
671 @override | 679 @override |
672 void visitStaticInvocation(ir.StaticInvocation invocation) { | 680 void visitStaticInvocation(ir.StaticInvocation invocation) { |
673 ir.Procedure target = invocation.target; | 681 ir.Procedure target = invocation.target; |
| 682 if (astAdapter.isInForeignLibrary(target)) { |
| 683 handleInvokeStaticForeign(invocation, target); |
| 684 return; |
| 685 } |
674 TypeMask typeMask = astAdapter.returnTypeOf(target); | 686 TypeMask typeMask = astAdapter.returnTypeOf(target); |
675 | 687 |
676 List<HInstruction> arguments = _visitArguments(invocation.arguments); | 688 List<HInstruction> arguments = _visitArguments(invocation.arguments); |
677 | 689 |
678 _pushStaticInvocation(target, arguments, typeMask); | 690 _pushStaticInvocation(target, arguments, typeMask); |
679 } | 691 } |
680 | 692 |
| 693 void handleInvokeStaticForeign( |
| 694 ir.StaticInvocation invocation, ir.Procedure target) { |
| 695 String name = target.name.name; |
| 696 if (name == 'JS') { |
| 697 handleForeignJs(invocation); |
| 698 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { |
| 699 handleForeignJsCurrentIsolateContext(invocation); |
| 700 } else if (name == 'JS_CALL_IN_ISOLATE') { |
| 701 handleForeignJsCallInIsolate(invocation); |
| 702 } else if (name == 'DART_CLOSURE_TO_JS') { |
| 703 handleForeignDartClosureToJs(invocation, 'DART_CLOSURE_TO_JS'); |
| 704 } else if (name == 'RAW_DART_FUNCTION_REF') { |
| 705 handleForeignRawFunctionRef(invocation, 'RAW_DART_FUNCTION_REF'); |
| 706 } else if (name == 'JS_SET_STATIC_STATE') { |
| 707 handleForeignJsSetStaticState(invocation); |
| 708 } else if (name == 'JS_GET_STATIC_STATE') { |
| 709 handleForeignJsGetStaticState(invocation); |
| 710 } else if (name == 'JS_GET_NAME') { |
| 711 handleForeignJsGetName(invocation); |
| 712 } else if (name == 'JS_EMBEDDED_GLOBAL') { |
| 713 handleForeignJsEmbeddedGlobal(invocation); |
| 714 } else if (name == 'JS_BUILTIN') { |
| 715 handleForeignJsBuiltin(invocation); |
| 716 } else if (name == 'JS_GET_FLAG') { |
| 717 handleForeignJsGetFlag(invocation); |
| 718 } else if (name == 'JS_EFFECT') { |
| 719 stack.add(graph.addConstantNull(compiler)); |
| 720 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
| 721 handleJsInterceptorConstant(invocation); |
| 722 } else if (name == 'JS_STRING_CONCAT') { |
| 723 handleJsStringConcat(invocation); |
| 724 } else { |
| 725 compiler.reporter.internalError( |
| 726 astAdapter.getNode(invocation), "Unknown foreign: ${name}"); |
| 727 } |
| 728 } |
| 729 |
| 730 bool _unexpectedForeignArguments( |
| 731 ir.StaticInvocation invocation, int minPositional, [int maxPositional]) { |
| 732 |
| 733 String pluralizeArguments(int count) { |
| 734 if (count == 0) return 'no arguments'; |
| 735 if (count == 1) return 'one argument'; |
| 736 if (count == 2) return 'two arguments'; |
| 737 return '$count arguments'; |
| 738 } |
| 739 String name() => invocation.target.name.name; |
| 740 |
| 741 |
| 742 ir.Arguments arguments = invocation.arguments; |
| 743 bool bad = false; |
| 744 if (arguments.types.isNotEmpty) { |
| 745 compiler.reporter.reportErrorMessage( |
| 746 astAdapter.getNode(invocation), |
| 747 MessageKind.GENERIC, |
| 748 {'text': "Error: '${name()}' does not take type arguments."}); |
| 749 bad = true; |
| 750 } |
| 751 if (arguments.positional.length < minPositional) { |
| 752 String phrase = pluralizeArguments(minPositional); |
| 753 if (maxPositional != minPositional) phrase = 'at least $phrase'; |
| 754 compiler.reporter.reportErrorMessage( |
| 755 astAdapter.getNode(invocation), |
| 756 MessageKind.GENERIC, |
| 757 {'text': "Error: Too few arguments. '${name()}' takes $phrase."}); |
| 758 bad = true; |
| 759 } |
| 760 if (maxPositional != null && arguments.positional.length > maxPositional) { |
| 761 String phrase = pluralizeArguments(maxPositional); |
| 762 if (maxPositional != minPositional) phrase = 'at most $phrase'; |
| 763 compiler.reporter.reportErrorMessage( |
| 764 astAdapter.getNode(invocation), |
| 765 MessageKind.GENERIC, |
| 766 {'text': "Error: Too many arguments. '${name()}' takes $phrase."}); |
| 767 bad = true; |
| 768 } |
| 769 if (arguments.named.isNotEmpty) { |
| 770 compiler.reporter.reportErrorMessage( |
| 771 astAdapter.getNode(invocation), |
| 772 MessageKind.GENERIC, |
| 773 {'text': "Error: '${name()}' does not take named arguments."}); |
| 774 bad = true; |
| 775 } |
| 776 return bad; |
| 777 } |
| 778 |
| 779 /// Returns the value of the string argument. The argument must evaluate to a |
| 780 /// constant. If there is an error, the error is reported and `null` is |
| 781 /// returned. |
| 782 String _foreignConstantStringArgument( |
| 783 ir.StaticInvocation invocation, int position, String methodName, |
| 784 [String adjective = '']) { |
| 785 ir.Expression argument = invocation.arguments.positional[position]; |
| 786 argument.accept(this); |
| 787 HInstruction instruction = pop(); |
| 788 |
| 789 if (!instruction.isConstantString()) { |
| 790 compiler.reporter.reportErrorMessage( |
| 791 astAdapter.getNode(argument), MessageKind.GENERIC, { |
| 792 'text': "Error: Expected String constant as ${adjective}argument " |
| 793 "to '$methodName'." |
| 794 }); |
| 795 return null; |
| 796 } |
| 797 |
| 798 HConstant hConstant = instruction; |
| 799 StringConstantValue stringConstant = hConstant.constant; |
| 800 return stringConstant.primitiveValue.slowToString(); |
| 801 } |
| 802 |
| 803 // TODO(sra): Remove when handleInvokeStaticForeign fully implemented. |
| 804 void unhandledForeign(ir.StaticInvocation invocation) { |
| 805 ir.Procedure target = invocation.target; |
| 806 TypeMask typeMask = astAdapter.returnTypeOf(target); |
| 807 List<HInstruction> arguments = _visitArguments(invocation.arguments); |
| 808 _pushStaticInvocation(target, arguments, typeMask); |
| 809 } |
| 810 |
| 811 void handleForeignJsCurrentIsolateContext(ir.StaticInvocation invocation) { |
| 812 if (_unexpectedForeignArguments(invocation, 0, 0)) { |
| 813 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 814 return; |
| 815 } |
| 816 |
| 817 if (!compiler.hasIsolateSupport) { |
| 818 // If the isolate library is not used, we just generate code |
| 819 // to fetch the static state. |
| 820 String name = backend.namer.staticStateHolder; |
| 821 push(new HForeignCode( |
| 822 js.js.parseForeignJS(name), backend.dynamicType, <HInstruction>[], |
| 823 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
| 824 } else { |
| 825 // Call a helper method from the isolate library. The isolate library uses |
| 826 // its own isolate structure that encapsulates the isolate structure used |
| 827 // for binding to methods. |
| 828 ir.Procedure target = astAdapter.currentIsolate; |
| 829 Element element = helpers.currentIsolate; |
| 830 if (target == null) { |
| 831 compiler.reporter.internalError(node, 'Isolate library and compiler mism
atch.'); |
| 832 } |
| 833 _pushStaticInvocation(target, <HInstruction>[], backend.dynamicType); |
| 834 } |
| 835 |
| 836 /* |
| 837 if (!node.arguments.isEmpty) { |
| 838 reporter.internalError( |
| 839 node, 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.'); |
| 840 } |
| 841 |
| 842 if (!compiler.hasIsolateSupport) { |
| 843 // If the isolate library is not used, we just generate code |
| 844 // to fetch the static state. |
| 845 String name = backend.namer.staticStateHolder; |
| 846 push(new HForeignCode( |
| 847 js.js.parseForeignJS(name), backend.dynamicType, <HInstruction>[], |
| 848 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
| 849 } else { |
| 850 // Call a helper method from the isolate library. The isolate |
| 851 // library uses its own isolate structure, that encapsulates |
| 852 // Leg's isolate. |
| 853 Element element = helpers.currentIsolate; |
| 854 if (element == null) { |
| 855 reporter.internalError(node, 'Isolate library and compiler mismatch.'); |
| 856 } |
| 857 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); |
| 858 } |
| 859 */ |
| 860 } |
| 861 |
| 862 void handleForeignJsCallInIsolate(ir.StaticInvocation invocation) { |
| 863 unhandledForeign(invocation); |
| 864 } |
| 865 |
| 866 void handleForeignDartClosureToJs( |
| 867 ir.StaticInvocation invocation, String name) { |
| 868 unhandledForeign(invocation); |
| 869 } |
| 870 |
| 871 void handleForeignRawFunctionRef( |
| 872 ir.StaticInvocation invocation, String name) { |
| 873 unhandledForeign(invocation); |
| 874 } |
| 875 |
| 876 void handleForeignJsSetStaticState(ir.StaticInvocation invocation) { |
| 877 if (_unexpectedForeignArguments(invocation, 0, 0)) { |
| 878 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 879 return; |
| 880 } |
| 881 _visitArguments(invocation.arguments); |
| 882 String isolateName = backend.namer.staticStateHolder; |
| 883 SideEffects sideEffects = new SideEffects.empty(); |
| 884 sideEffects.setAllSideEffects(); |
| 885 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), |
| 886 backend.dynamicType, <HInstruction>[pop()], |
| 887 nativeBehavior: native.NativeBehavior.CHANGES_OTHER, |
| 888 effects: sideEffects)); |
| 889 } |
| 890 |
| 891 void handleForeignJsGetStaticState(ir.StaticInvocation invocation) { |
| 892 if (_unexpectedForeignArguments(invocation, 0, 0)) { |
| 893 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 894 return; |
| 895 } |
| 896 |
| 897 push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder), |
| 898 backend.dynamicType, <HInstruction>[], |
| 899 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
| 900 } |
| 901 |
| 902 void handleForeignJsGetName(ir.StaticInvocation invocation) { |
| 903 if (_unexpectedForeignArguments(invocation, 1, 1)) { |
| 904 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 905 return; |
| 906 } |
| 907 |
| 908 ir.Node argument = invocation.arguments.positional.first; |
| 909 argument.accept(this); |
| 910 HInstruction instruction = pop(); |
| 911 |
| 912 if (instruction is HConstant) { |
| 913 js.Name name = |
| 914 astAdapter.getNameForJsGetName(argument, instruction.constant); |
| 915 stack.add(graph.addConstantStringFromName(name, compiler)); |
| 916 return; |
| 917 } |
| 918 |
| 919 compiler.reporter.reportErrorMessage( |
| 920 astAdapter.getNode(argument), |
| 921 MessageKind.GENERIC, |
| 922 {'text': 'Error: Expected a JsGetName enum value.'}); |
| 923 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 924 } |
| 925 |
| 926 void handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) { |
| 927 if (_unexpectedForeignArguments(invocation, 2, 2)) { |
| 928 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 929 return; |
| 930 } |
| 931 String globalName = _foreignConstantStringArgument( |
| 932 invocation, 1, 'JS_EMBEDDED_GLOBAL', 'second '); |
| 933 js.Template expr = js.js.expressionTemplateYielding( |
| 934 backend.emitter.generateEmbeddedGlobalAccess(globalName)); |
| 935 |
| 936 native.NativeBehavior nativeBehavior = |
| 937 astAdapter.getNativeBehavior(invocation); |
| 938 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, |
| 939 message: "No NativeBehavior for $invocation")); |
| 940 |
| 941 TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior); |
| 942 push(new HForeignCode(expr, ssaType, const <HInstruction>[], |
| 943 nativeBehavior: nativeBehavior)); |
| 944 } |
| 945 |
| 946 void handleForeignJsBuiltin(ir.StaticInvocation invocation) { |
| 947 if (_unexpectedForeignArguments(invocation, 2)) { |
| 948 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 949 return; |
| 950 } |
| 951 |
| 952 List<ir.Expression> arguments = invocation.arguments.positional; |
| 953 ir.Expression nameArgument = arguments[1]; |
| 954 |
| 955 nameArgument.accept(this); |
| 956 HInstruction instruction = pop(); |
| 957 |
| 958 js.Template template; |
| 959 if (instruction is HConstant) { |
| 960 template = astAdapter.getJsBuiltinTemplate(instruction.constant); |
| 961 } |
| 962 if (template == null) { |
| 963 compiler.reporter.reportErrorMessage( |
| 964 astAdapter.getNode(nameArgument), |
| 965 MessageKind.GENERIC, |
| 966 {'text': 'Error: Expected a JsBuiltin enum value.'}); |
| 967 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 968 return; |
| 969 } |
| 970 |
| 971 List<HInstruction> inputs = <HInstruction>[]; |
| 972 for (ir.Expression argument in arguments.skip(2)) { |
| 973 argument.accept(this); |
| 974 inputs.add(pop()); |
| 975 } |
| 976 |
| 977 native.NativeBehavior nativeBehavior = |
| 978 astAdapter.getNativeBehavior(invocation); |
| 979 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, |
| 980 message: "No NativeBehavior for $invocation")); |
| 981 |
| 982 TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior); |
| 983 push(new HForeignCode(template, ssaType, inputs, |
| 984 nativeBehavior: nativeBehavior)); |
| 985 } |
| 986 |
| 987 void handleForeignJsGetFlag(ir.StaticInvocation invocation) { |
| 988 if (_unexpectedForeignArguments(invocation, 1, 1)) { |
| 989 stack.add( |
| 990 graph.addConstantBool(false, compiler)); // Result expected on stack. |
| 991 return; |
| 992 } |
| 993 String name = _foreignConstantStringArgument(invocation, 0, 'JS_GET_FLAG'); |
| 994 bool value = false; |
| 995 switch (name) { |
| 996 case 'MUST_RETAIN_METADATA': |
| 997 value = backend.mustRetainMetadata; |
| 998 break; |
| 999 case 'USE_CONTENT_SECURITY_POLICY': |
| 1000 value = compiler.options.useContentSecurityPolicy; |
| 1001 break; |
| 1002 default: |
| 1003 compiler.reporter.reportErrorMessage( |
| 1004 astAdapter.getNode(invocation), |
| 1005 MessageKind.GENERIC, |
| 1006 {'text': 'Error: Unknown internal flag "$name".'}); |
| 1007 } |
| 1008 stack.add(graph.addConstantBool(value, compiler)); |
| 1009 } |
| 1010 |
| 1011 void handleJsInterceptorConstant(ir.StaticInvocation invocation) { |
| 1012 unhandledForeign(invocation); |
| 1013 } |
| 1014 |
| 1015 void handleForeignJs(ir.StaticInvocation invocation) { |
| 1016 if (_unexpectedForeignArguments(invocation, 2)) { |
| 1017 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1018 return; |
| 1019 } |
| 1020 |
| 1021 native.NativeBehavior nativeBehavior = |
| 1022 astAdapter.getNativeBehavior(invocation); |
| 1023 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, |
| 1024 message: "No NativeBehavior for $invocation")); |
| 1025 |
| 1026 List<HInstruction> inputs = <HInstruction>[]; |
| 1027 for (ir.Expression argument in invocation.arguments.positional.skip(2)) { |
| 1028 argument.accept(this); |
| 1029 inputs.add(pop()); |
| 1030 } |
| 1031 |
| 1032 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { |
| 1033 compiler.reporter.reportErrorMessage( |
| 1034 astAdapter.getNode(invocation), MessageKind.GENERIC, { |
| 1035 'text': 'Mismatch between number of placeholders' |
| 1036 ' and number of arguments.' |
| 1037 }); |
| 1038 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1039 return; |
| 1040 } |
| 1041 |
| 1042 if (native.HasCapturedPlaceholders.check(nativeBehavior.codeTemplate.ast)) { |
| 1043 compiler.reporter.reportErrorMessage( |
| 1044 astAdapter.getNode(invocation), MessageKind.JS_PLACEHOLDER_CAPTURE); |
| 1045 } |
| 1046 |
| 1047 TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior); |
| 1048 |
| 1049 SourceInformation sourceInformation = null; |
| 1050 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs, |
| 1051 isStatement: !nativeBehavior.codeTemplate.isExpression, |
| 1052 effects: nativeBehavior.sideEffects, |
| 1053 nativeBehavior: nativeBehavior)..sourceInformation = sourceInformation); |
| 1054 } |
| 1055 |
| 1056 void handleJsStringConcat(ir.StaticInvocation invocation) { |
| 1057 if (_unexpectedForeignArguments(invocation, 2, 2)) { |
| 1058 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1059 return; |
| 1060 } |
| 1061 List<HInstruction> inputs = _visitArguments(invocation.arguments); |
| 1062 push(new HStringConcat(inputs[0], inputs[1], backend.stringType)); |
| 1063 } |
| 1064 |
681 void _pushStaticInvocation( | 1065 void _pushStaticInvocation( |
682 ir.Node target, List<HInstruction> arguments, TypeMask typeMask) { | 1066 ir.Node target, List<HInstruction> arguments, TypeMask typeMask) { |
683 HInstruction instruction = new HInvokeStatic( | 1067 HInstruction instruction = new HInvokeStatic( |
684 astAdapter.getElement(target).declaration, arguments, typeMask, | 1068 astAdapter.getElement(target).declaration, arguments, typeMask, |
685 targetCanThrow: astAdapter.getCanThrow(target)); | 1069 targetCanThrow: astAdapter.getCanThrow(target)); |
686 instruction.sideEffects = astAdapter.getSideEffects(target); | 1070 instruction.sideEffects = astAdapter.getSideEffects(target); |
687 | 1071 |
688 push(instruction); | 1072 push(instruction); |
689 } | 1073 } |
690 | 1074 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 push(new HNot(popBoolified(), backend.boolType)); | 1201 push(new HNot(popBoolified(), backend.boolType)); |
818 } | 1202 } |
819 | 1203 |
820 @override | 1204 @override |
821 void visitStringConcatenation(ir.StringConcatenation stringConcat) { | 1205 void visitStringConcatenation(ir.StringConcatenation stringConcat) { |
822 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); | 1206 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); |
823 stringConcat.accept(stringBuilder); | 1207 stringConcat.accept(stringBuilder); |
824 stack.add(stringBuilder.result); | 1208 stack.add(stringBuilder.result); |
825 } | 1209 } |
826 } | 1210 } |
OLD | NEW |