| 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 SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
| 8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
| 9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
| 10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
| (...skipping 3755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3766 compiler.reportError( | 3766 compiler.reportError( |
| 3767 node, MessageKind.GENERIC, | 3767 node, MessageKind.GENERIC, |
| 3768 {'text': 'Error: Expected one argument to JS_GET_NAME.'}); | 3768 {'text': 'Error: Expected one argument to JS_GET_NAME.'}); |
| 3769 return; | 3769 return; |
| 3770 case 1: | 3770 case 1: |
| 3771 argument = arguments[0]; | 3771 argument = arguments[0]; |
| 3772 break; | 3772 break; |
| 3773 default: | 3773 default: |
| 3774 for (int i = 1; i < arguments.length; i++) { | 3774 for (int i = 1; i < arguments.length; i++) { |
| 3775 compiler.reportError( | 3775 compiler.reportError( |
| 3776 arguments[i], MessageKind.GENERIC, | 3776 arguments[i], MessageKind.GENERIC, |
| 3777 {'text': 'Error: Extra argument to JS_GET_NAME.'}); | 3777 {'text': 'Error: Extra argument to JS_GET_NAME.'}); |
| 3778 } | 3778 } |
| 3779 return; | 3779 return; |
| 3780 } | 3780 } |
| 3781 Element element = elements[argument]; | 3781 Element element = elements[argument]; |
| 3782 if (element == null || | 3782 if (element == null || |
| 3783 element is! FieldElement || | 3783 element is! FieldElement || |
| 3784 element.enclosingClass != backend.jsGetNameEnum) { | 3784 element.enclosingClass != backend.jsGetNameEnum) { |
| 3785 compiler.reportError( | 3785 compiler.reportError( |
| 3786 argument, MessageKind.GENERIC, | 3786 argument, MessageKind.GENERIC, |
| 3787 {'text': 'Error: Expected a JsGetName enum value.'}); | 3787 {'text': 'Error: Expected a JsGetName enum value.'}); |
| 3788 } | 3788 } |
| 3789 EnumClassElement enumClass = element.enclosingClass; | 3789 EnumClassElement enumClass = element.enclosingClass; |
| 3790 int index = enumClass.enumValues.indexOf(element); | 3790 int index = enumClass.enumValues.indexOf(element); |
| 3791 stack.add( | 3791 stack.add( |
| 3792 addConstantString( | 3792 addConstantString( |
| 3793 backend.namer.getNameForJsGetName( | 3793 backend.namer.getNameForJsGetName( |
| 3794 argument, JsGetName.values[index]))); | 3794 argument, JsGetName.values[index]))); |
| 3795 } | 3795 } |
| 3796 | 3796 |
| 3797 void handleForeignJsBuiltin(ast.Send node) { | |
| 3798 List<ast.Node> arguments = node.arguments.toList(); | |
| 3799 ast.Node argument; | |
| 3800 if (arguments.length < 2) { | |
| 3801 compiler.reportError( | |
| 3802 node, MessageKind.GENERIC, | |
| 3803 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); | |
| 3804 } | |
| 3805 | |
| 3806 Element builtinElement = elements[arguments[1]]; | |
| 3807 if (builtinElement == null || | |
| 3808 (builtinElement is! FieldElement) || | |
| 3809 builtinElement.enclosingClass != backend.jsBuiltinEnum) { | |
| 3810 compiler.reportError( | |
| 3811 argument, MessageKind.GENERIC, | |
| 3812 {'text': 'Error: Expected a JsBuiltin enum value.'}); | |
| 3813 } | |
| 3814 EnumClassElement enumClass = builtinElement.enclosingClass; | |
| 3815 int index = enumClass.enumValues.indexOf(builtinElement); | |
| 3816 | |
| 3817 js.Template template = | |
| 3818 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); | |
| 3819 | |
| 3820 List<HInstruction> compiledArguments = <HInstruction>[]; | |
| 3821 for (int i = 2; i < arguments.length; i++) { | |
| 3822 visit(arguments[i]); | |
| 3823 compiledArguments.add(pop()); | |
| 3824 } | |
| 3825 | |
| 3826 native.NativeBehavior nativeBehavior = | |
| 3827 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | |
| 3828 | |
| 3829 TypeMask ssaType = | |
| 3830 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | |
| 3831 | |
| 3832 push(new HForeignCode(template, | |
| 3833 ssaType, | |
| 3834 compiledArguments, | |
| 3835 nativeBehavior: nativeBehavior)); | |
| 3836 } | |
| 3837 | |
| 3838 void handleForeignJsEmbeddedGlobal(ast.Send node) { | 3797 void handleForeignJsEmbeddedGlobal(ast.Send node) { |
| 3839 List<ast.Node> arguments = node.arguments.toList(); | 3798 List<ast.Node> arguments = node.arguments.toList(); |
| 3840 ast.Node globalNameNode; | 3799 ast.Node globalNameNode; |
| 3841 switch (arguments.length) { | 3800 switch (arguments.length) { |
| 3842 case 0: | 3801 case 0: |
| 3843 case 1: | 3802 case 1: |
| 3844 compiler.reportError( | 3803 compiler.reportError( |
| 3845 node, MessageKind.GENERIC, | 3804 node, MessageKind.GENERIC, |
| 3846 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); | 3805 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); |
| 3847 return; | 3806 return; |
| 3848 case 2: | 3807 case 2: |
| 3849 // The type has been extracted earlier. We are only interested in the | 3808 // The type has been extracted earlier. We are only interested in the |
| 3850 // name in this function. | 3809 // name in this function. |
| 3851 globalNameNode = arguments[1]; | 3810 globalNameNode = arguments[1]; |
| 3852 break; | 3811 break; |
| 3853 default: | 3812 default: |
| 3854 for (int i = 2; i < arguments.length; i++) { | 3813 for (int i = 2; i < arguments.length; i++) { |
| 3855 compiler.reportError( | 3814 compiler.reportError( |
| 3856 arguments[i], MessageKind.GENERIC, | 3815 arguments[i], MessageKind.GENERIC, |
| 3857 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); | 3816 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); |
| 3858 } | 3817 } |
| 3859 return; | 3818 return; |
| 3860 } | 3819 } |
| 3861 visit(globalNameNode); | 3820 visit(arguments[1]); |
| 3862 HInstruction globalNameHNode = pop(); | 3821 HInstruction globalNameHNode = pop(); |
| 3863 if (!globalNameHNode.isConstantString()) { | 3822 if (!globalNameHNode.isConstantString()) { |
| 3864 compiler.reportError( | 3823 compiler.reportError( |
| 3865 arguments[1], MessageKind.GENERIC, | 3824 arguments[1], MessageKind.GENERIC, |
| 3866 {'text': 'Error: Expected String as second argument ' | 3825 {'text': 'Error: Expected String as second argument ' |
| 3867 'to JS_EMBEDDED_GLOBAL.'}); | 3826 'to JS_EMBEDDED_GLOBAL.'}); |
| 3868 return; | 3827 return; |
| 3869 } | 3828 } |
| 3870 HConstant hConstant = globalNameHNode; | 3829 HConstant hConstant = globalNameHNode; |
| 3871 StringConstantValue constant = hConstant.constant; | 3830 StringConstantValue constant = hConstant.constant; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3975 SideEffects sideEffects = new SideEffects.empty(); | 3934 SideEffects sideEffects = new SideEffects.empty(); |
| 3976 sideEffects.setAllSideEffects(); | 3935 sideEffects.setAllSideEffects(); |
| 3977 push(new HForeignCode( | 3936 push(new HForeignCode( |
| 3978 js.js.parseForeignJS("$isolateName = #"), | 3937 js.js.parseForeignJS("$isolateName = #"), |
| 3979 backend.dynamicType, | 3938 backend.dynamicType, |
| 3980 <HInstruction>[pop()], | 3939 <HInstruction>[pop()], |
| 3981 nativeBehavior: native.NativeBehavior.PURE, | 3940 nativeBehavior: native.NativeBehavior.PURE, |
| 3982 effects: sideEffects)); | 3941 effects: sideEffects)); |
| 3983 } | 3942 } |
| 3984 | 3943 |
| 3944 void handleForeignDartObjectJsConstructorFunction(ast.Send node) { |
| 3945 if (!node.arguments.isEmpty) { |
| 3946 compiler.internalError(node.argumentsNode, 'Too many arguments.'); |
| 3947 } |
| 3948 push(new HForeignCode( |
| 3949 js.js.expressionTemplateYielding( |
| 3950 backend.emitter.typeAccess(compiler.objectClass)), |
| 3951 backend.dynamicType, |
| 3952 <HInstruction>[])); |
| 3953 } |
| 3954 |
| 3985 void handleForeignJsCurrentIsolate(ast.Send node) { | 3955 void handleForeignJsCurrentIsolate(ast.Send node) { |
| 3986 if (!node.arguments.isEmpty) { | 3956 if (!node.arguments.isEmpty) { |
| 3987 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | 3957 compiler.internalError(node.argumentsNode, 'Too many arguments.'); |
| 3988 } | 3958 } |
| 3989 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), | 3959 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), |
| 3990 backend.dynamicType, | 3960 backend.dynamicType, |
| 3991 <HInstruction>[])); | 3961 <HInstruction>[])); |
| 3992 } | 3962 } |
| 3993 | 3963 |
| 3994 visitForeignSend(ast.Send node) { | 3964 visitForeignSend(ast.Send node) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4010 // TODO(floitsch): this should be a JS_NAME. | 3980 // TODO(floitsch): this should be a JS_NAME. |
| 4011 stack.add(addConstantString(backend.namer.operatorIsPrefix)); | 3981 stack.add(addConstantString(backend.namer.operatorIsPrefix)); |
| 4012 } else if (name == 'JS_OBJECT_CLASS_NAME') { | 3982 } else if (name == 'JS_OBJECT_CLASS_NAME') { |
| 4013 // TODO(floitsch): this should be a JS_NAME. | 3983 // TODO(floitsch): this should be a JS_NAME. |
| 4014 String name = backend.namer.runtimeTypeName(compiler.objectClass); | 3984 String name = backend.namer.runtimeTypeName(compiler.objectClass); |
| 4015 stack.add(addConstantString(name)); | 3985 stack.add(addConstantString(name)); |
| 4016 } else if (name == 'JS_NULL_CLASS_NAME') { | 3986 } else if (name == 'JS_NULL_CLASS_NAME') { |
| 4017 // TODO(floitsch): this should be a JS_NAME. | 3987 // TODO(floitsch): this should be a JS_NAME. |
| 4018 String name = backend.namer.runtimeTypeName(compiler.nullClass); | 3988 String name = backend.namer.runtimeTypeName(compiler.nullClass); |
| 4019 stack.add(addConstantString(name)); | 3989 stack.add(addConstantString(name)); |
| 3990 } else if (name == 'JS_FUNCTION_CLASS_NAME') { |
| 3991 // TODO(floitsch): this should be a JS_NAME. |
| 3992 String name = backend.namer.runtimeTypeName(compiler.functionClass); |
| 3993 stack.add(addConstantString(name)); |
| 4020 } else if (name == 'JS_OPERATOR_AS_PREFIX') { | 3994 } else if (name == 'JS_OPERATOR_AS_PREFIX') { |
| 4021 // TODO(floitsch): this should be a JS_NAME. | 3995 // TODO(floitsch): this should be a JS_NAME. |
| 4022 stack.add(addConstantString(backend.namer.operatorAsPrefix)); | 3996 stack.add(addConstantString(backend.namer.operatorAsPrefix)); |
| 4023 } else if (name == 'JS_SIGNATURE_NAME') { | 3997 } else if (name == 'JS_SIGNATURE_NAME') { |
| 4024 // TODO(floitsch): this should be a JS_NAME. | 3998 // TODO(floitsch): this should be a JS_NAME. |
| 4025 stack.add(addConstantString(backend.namer.operatorSignature)); | 3999 stack.add(addConstantString(backend.namer.operatorSignature)); |
| 4026 } else if (name == 'JS_TYPEDEF_TAG') { | 4000 } else if (name == 'JS_TYPEDEF_TAG') { |
| 4027 // TODO(floitsch): this should be a JS_NAME. | 4001 // TODO(floitsch): this should be a JS_NAME. |
| 4028 stack.add(addConstantString(backend.namer.typedefTag)); | 4002 stack.add(addConstantString(backend.namer.typedefTag)); |
| 4003 } else if (name == 'JS_FUNCTION_TYPE_TAG') { |
| 4004 // TODO(floitsch): this should be a JS_NAME. |
| 4005 stack.add(addConstantString(backend.namer.functionTypeTag)); |
| 4029 } else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') { | 4006 } else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') { |
| 4030 // TODO(floitsch): this should be a JS_NAME. | 4007 // TODO(floitsch): this should be a JS_NAME. |
| 4031 stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag)); | 4008 stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag)); |
| 4032 } else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') { | 4009 } else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') { |
| 4033 // TODO(floitsch): this should be a JS_NAME. | 4010 // TODO(floitsch): this should be a JS_NAME. |
| 4034 stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag)); | 4011 stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag)); |
| 4035 } else if (name == | 4012 } else if (name == |
| 4036 'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') { | 4013 'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') { |
| 4037 // TODO(floitsch): this should be a JS_NAME. | 4014 // TODO(floitsch): this should be a JS_NAME. |
| 4038 stack.add(addConstantString( | 4015 stack.add(addConstantString( |
| 4039 backend.namer.functionTypeRequiredParametersTag)); | 4016 backend.namer.functionTypeRequiredParametersTag)); |
| 4040 } else if (name == | 4017 } else if (name == |
| 4041 'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') { | 4018 'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') { |
| 4042 // TODO(floitsch): this should be a JS_NAME. | 4019 // TODO(floitsch): this should be a JS_NAME. |
| 4043 stack.add(addConstantString( | 4020 stack.add(addConstantString( |
| 4044 backend.namer.functionTypeOptionalParametersTag)); | 4021 backend.namer.functionTypeOptionalParametersTag)); |
| 4045 } else if (name == | 4022 } else if (name == |
| 4046 'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') { | 4023 'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') { |
| 4047 // TODO(floitsch): this should be a JS_NAME. | 4024 // TODO(floitsch): this should be a JS_NAME. |
| 4048 stack.add(addConstantString( | 4025 stack.add(addConstantString( |
| 4049 backend.namer.functionTypeNamedParametersTag)); | 4026 backend.namer.functionTypeNamedParametersTag)); |
| 4027 } else if (name == 'JS_DART_OBJECT_CONSTRUCTOR') { |
| 4028 handleForeignDartObjectJsConstructorFunction(node); |
| 4050 } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') { | 4029 } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') { |
| 4051 // TODO(floitsch): this should be a JS_NAME. | 4030 // TODO(floitsch): this should be a JS_NAME. |
| 4052 Element element = backend.findHelper('JavaScriptIndexingBehavior'); | 4031 Element element = backend.findHelper('JavaScriptIndexingBehavior'); |
| 4053 stack.add(addConstantString(backend.namer.operatorIs(element))); | 4032 stack.add(addConstantString(backend.namer.operatorIs(element))); |
| 4054 } else if (name == 'JS_CURRENT_ISOLATE') { | 4033 } else if (name == 'JS_CURRENT_ISOLATE') { |
| 4055 handleForeignJsCurrentIsolate(node); | 4034 handleForeignJsCurrentIsolate(node); |
| 4056 } else if (name == 'JS_GET_NAME') { | 4035 } else if (name == 'JS_GET_NAME') { |
| 4057 handleForeignJsGetName(node); | 4036 handleForeignJsGetName(node); |
| 4058 } else if (name == 'JS_EMBEDDED_GLOBAL') { | 4037 } else if (name == 'JS_EMBEDDED_GLOBAL') { |
| 4059 handleForeignJsEmbeddedGlobal(node); | 4038 handleForeignJsEmbeddedGlobal(node); |
| 4060 } else if (name == 'JS_BUILTIN') { | |
| 4061 handleForeignJsBuiltin(node); | |
| 4062 } else if (name == 'JS_GET_FLAG') { | 4039 } else if (name == 'JS_GET_FLAG') { |
| 4063 handleForeingJsGetFlag(node); | 4040 handleForeingJsGetFlag(node); |
| 4064 } else if (name == 'JS_EFFECT') { | 4041 } else if (name == 'JS_EFFECT') { |
| 4065 stack.add(graph.addConstantNull(compiler)); | 4042 stack.add(graph.addConstantNull(compiler)); |
| 4066 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { | 4043 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
| 4067 handleJsInterceptorConstant(node); | 4044 handleJsInterceptorConstant(node); |
| 4068 } else if (name == 'JS_STRING_CONCAT') { | 4045 } else if (name == 'JS_STRING_CONCAT') { |
| 4069 handleJsStringConcat(node); | 4046 handleJsStringConcat(node); |
| 4070 } else { | 4047 } else { |
| 4071 throw "Unknown foreign: ${selector}"; | 4048 throw "Unknown foreign: ${selector}"; |
| (...skipping 2954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7026 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 7003 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 7027 unaliased.accept(this, builder); | 7004 unaliased.accept(this, builder); |
| 7028 } | 7005 } |
| 7029 | 7006 |
| 7030 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 7007 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 7031 JavaScriptBackend backend = builder.compiler.backend; | 7008 JavaScriptBackend backend = builder.compiler.backend; |
| 7032 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 7009 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 7033 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 7010 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 7034 } | 7011 } |
| 7035 } | 7012 } |
| OLD | NEW |