Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Side by Side Diff: pkg/compiler/lib/src/ssa/builder_kernel.dart

Issue 2411793007: Revert "Build CFG for various JS() foreign methods" (Closed)
Patch Set: Redo "Build CFG for various JS() foreign methods" Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/kernel/kernel_visitor.dart ('k') | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698