| 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 final SsaCodeGeneratorTask generator; | 8 final SsaCodeGeneratorTask generator; |
| 9 final SsaBuilderTask builder; | 9 final SsaBuilderTask builder; |
| 10 final SsaOptimizerTask optimizer; | 10 final SsaOptimizerTask optimizer; |
| (...skipping 4067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4078 compiler.internalError(node.argumentsNode, | 4078 compiler.internalError(node.argumentsNode, |
| 4079 'At least two arguments expected.'); | 4079 'At least two arguments expected.'); |
| 4080 } | 4080 } |
| 4081 native.NativeBehavior nativeBehavior = | 4081 native.NativeBehavior nativeBehavior = |
| 4082 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | 4082 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
| 4083 | 4083 |
| 4084 List<HInstruction> inputs = <HInstruction>[]; | 4084 List<HInstruction> inputs = <HInstruction>[]; |
| 4085 addGenericSendArgumentsToList(link.tail.tail, inputs); | 4085 addGenericSendArgumentsToList(link.tail.tail, inputs); |
| 4086 | 4086 |
| 4087 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { | 4087 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { |
| 4088 compiler.reportError( | 4088 compiler.reportErrorMessage( |
| 4089 node, MessageKind.GENERIC, | 4089 node, MessageKind.GENERIC, |
| 4090 {'text': | 4090 {'text': |
| 4091 'Mismatch between number of placeholders' | 4091 'Mismatch between number of placeholders' |
| 4092 ' and number of arguments.'}); | 4092 ' and number of arguments.'}); |
| 4093 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. | 4093 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 4094 return; | 4094 return; |
| 4095 } | 4095 } |
| 4096 | 4096 |
| 4097 TypeMask ssaType = | 4097 TypeMask ssaType = |
| 4098 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | 4098 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4148 } | 4148 } |
| 4149 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); | 4149 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); |
| 4150 } | 4150 } |
| 4151 } | 4151 } |
| 4152 | 4152 |
| 4153 void handleForeignJsGetFlag(ast.Send node) { | 4153 void handleForeignJsGetFlag(ast.Send node) { |
| 4154 List<ast.Node> arguments = node.arguments.toList(); | 4154 List<ast.Node> arguments = node.arguments.toList(); |
| 4155 ast.Node argument; | 4155 ast.Node argument; |
| 4156 switch (arguments.length) { | 4156 switch (arguments.length) { |
| 4157 case 0: | 4157 case 0: |
| 4158 compiler.reportError( | 4158 compiler.reportErrorMessage( |
| 4159 node, MessageKind.GENERIC, | 4159 node, MessageKind.GENERIC, |
| 4160 {'text': 'Error: Expected one argument to JS_GET_FLAG.'}); | 4160 {'text': 'Error: Expected one argument to JS_GET_FLAG.'}); |
| 4161 return; | 4161 return; |
| 4162 case 1: | 4162 case 1: |
| 4163 argument = arguments[0]; | 4163 argument = arguments[0]; |
| 4164 break; | 4164 break; |
| 4165 default: | 4165 default: |
| 4166 for (int i = 1; i < arguments.length; i++) { | 4166 for (int i = 1; i < arguments.length; i++) { |
| 4167 compiler.reportError( | 4167 compiler.reportErrorMessage( |
| 4168 arguments[i], MessageKind.GENERIC, | 4168 arguments[i], MessageKind.GENERIC, |
| 4169 {'text': 'Error: Extra argument to JS_GET_FLAG.'}); | 4169 {'text': 'Error: Extra argument to JS_GET_FLAG.'}); |
| 4170 } | 4170 } |
| 4171 return; | 4171 return; |
| 4172 } | 4172 } |
| 4173 ast.LiteralString string = argument.asLiteralString(); | 4173 ast.LiteralString string = argument.asLiteralString(); |
| 4174 if (string == null) { | 4174 if (string == null) { |
| 4175 compiler.reportError( | 4175 compiler.reportErrorMessage( |
| 4176 argument, MessageKind.GENERIC, | 4176 argument, MessageKind.GENERIC, |
| 4177 {'text': 'Error: Expected a literal string.'}); | 4177 {'text': 'Error: Expected a literal string.'}); |
| 4178 } | 4178 } |
| 4179 String name = string.dartString.slowToString(); | 4179 String name = string.dartString.slowToString(); |
| 4180 bool value = false; | 4180 bool value = false; |
| 4181 switch (name) { | 4181 switch (name) { |
| 4182 case 'MUST_RETAIN_METADATA': | 4182 case 'MUST_RETAIN_METADATA': |
| 4183 value = backend.mustRetainMetadata; | 4183 value = backend.mustRetainMetadata; |
| 4184 break; | 4184 break; |
| 4185 case 'USE_CONTENT_SECURITY_POLICY': | 4185 case 'USE_CONTENT_SECURITY_POLICY': |
| 4186 value = compiler.useContentSecurityPolicy; | 4186 value = compiler.useContentSecurityPolicy; |
| 4187 break; | 4187 break; |
| 4188 default: | 4188 default: |
| 4189 compiler.reportError( | 4189 compiler.reportErrorMessage( |
| 4190 node, MessageKind.GENERIC, | 4190 node, MessageKind.GENERIC, |
| 4191 {'text': 'Error: Unknown internal flag "$name".'}); | 4191 {'text': 'Error: Unknown internal flag "$name".'}); |
| 4192 } | 4192 } |
| 4193 stack.add(graph.addConstantBool(value, compiler)); | 4193 stack.add(graph.addConstantBool(value, compiler)); |
| 4194 } | 4194 } |
| 4195 | 4195 |
| 4196 void handleForeignJsGetName(ast.Send node) { | 4196 void handleForeignJsGetName(ast.Send node) { |
| 4197 List<ast.Node> arguments = node.arguments.toList(); | 4197 List<ast.Node> arguments = node.arguments.toList(); |
| 4198 ast.Node argument; | 4198 ast.Node argument; |
| 4199 switch (arguments.length) { | 4199 switch (arguments.length) { |
| 4200 case 0: | 4200 case 0: |
| 4201 compiler.reportError( | 4201 compiler.reportErrorMessage( |
| 4202 node, MessageKind.GENERIC, | 4202 node, MessageKind.GENERIC, |
| 4203 {'text': 'Error: Expected one argument to JS_GET_NAME.'}); | 4203 {'text': 'Error: Expected one argument to JS_GET_NAME.'}); |
| 4204 return; | 4204 return; |
| 4205 case 1: | 4205 case 1: |
| 4206 argument = arguments[0]; | 4206 argument = arguments[0]; |
| 4207 break; | 4207 break; |
| 4208 default: | 4208 default: |
| 4209 for (int i = 1; i < arguments.length; i++) { | 4209 for (int i = 1; i < arguments.length; i++) { |
| 4210 compiler.reportError( | 4210 compiler.reportErrorMessage( |
| 4211 arguments[i], MessageKind.GENERIC, | 4211 arguments[i], MessageKind.GENERIC, |
| 4212 {'text': 'Error: Extra argument to JS_GET_NAME.'}); | 4212 {'text': 'Error: Extra argument to JS_GET_NAME.'}); |
| 4213 } | 4213 } |
| 4214 return; | 4214 return; |
| 4215 } | 4215 } |
| 4216 Element element = elements[argument]; | 4216 Element element = elements[argument]; |
| 4217 if (element == null || | 4217 if (element == null || |
| 4218 element is! FieldElement || | 4218 element is! FieldElement || |
| 4219 element.enclosingClass != backend.jsGetNameEnum) { | 4219 element.enclosingClass != backend.jsGetNameEnum) { |
| 4220 compiler.reportError( | 4220 compiler.reportErrorMessage( |
| 4221 argument, MessageKind.GENERIC, | 4221 argument, MessageKind.GENERIC, |
| 4222 {'text': 'Error: Expected a JsGetName enum value.'}); | 4222 {'text': 'Error: Expected a JsGetName enum value.'}); |
| 4223 } | 4223 } |
| 4224 EnumClassElement enumClass = element.enclosingClass; | 4224 EnumClassElement enumClass = element.enclosingClass; |
| 4225 int index = enumClass.enumValues.indexOf(element); | 4225 int index = enumClass.enumValues.indexOf(element); |
| 4226 stack.add( | 4226 stack.add( |
| 4227 addConstantStringFromName( | 4227 addConstantStringFromName( |
| 4228 backend.namer.getNameForJsGetName( | 4228 backend.namer.getNameForJsGetName( |
| 4229 argument, JsGetName.values[index]))); | 4229 argument, JsGetName.values[index]))); |
| 4230 } | 4230 } |
| 4231 | 4231 |
| 4232 void handleForeignJsBuiltin(ast.Send node) { | 4232 void handleForeignJsBuiltin(ast.Send node) { |
| 4233 List<ast.Node> arguments = node.arguments.toList(); | 4233 List<ast.Node> arguments = node.arguments.toList(); |
| 4234 ast.Node argument; | 4234 ast.Node argument; |
| 4235 if (arguments.length < 2) { | 4235 if (arguments.length < 2) { |
| 4236 compiler.reportError( | 4236 compiler.reportErrorMessage( |
| 4237 node, MessageKind.GENERIC, | 4237 node, MessageKind.GENERIC, |
| 4238 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); | 4238 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); |
| 4239 } | 4239 } |
| 4240 | 4240 |
| 4241 Element builtinElement = elements[arguments[1]]; | 4241 Element builtinElement = elements[arguments[1]]; |
| 4242 if (builtinElement == null || | 4242 if (builtinElement == null || |
| 4243 (builtinElement is! FieldElement) || | 4243 (builtinElement is! FieldElement) || |
| 4244 builtinElement.enclosingClass != backend.jsBuiltinEnum) { | 4244 builtinElement.enclosingClass != backend.jsBuiltinEnum) { |
| 4245 compiler.reportError( | 4245 compiler.reportErrorMessage( |
| 4246 argument, MessageKind.GENERIC, | 4246 argument, MessageKind.GENERIC, |
| 4247 {'text': 'Error: Expected a JsBuiltin enum value.'}); | 4247 {'text': 'Error: Expected a JsBuiltin enum value.'}); |
| 4248 } | 4248 } |
| 4249 EnumClassElement enumClass = builtinElement.enclosingClass; | 4249 EnumClassElement enumClass = builtinElement.enclosingClass; |
| 4250 int index = enumClass.enumValues.indexOf(builtinElement); | 4250 int index = enumClass.enumValues.indexOf(builtinElement); |
| 4251 | 4251 |
| 4252 js.Template template = | 4252 js.Template template = |
| 4253 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); | 4253 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); |
| 4254 | 4254 |
| 4255 List<HInstruction> compiledArguments = <HInstruction>[]; | 4255 List<HInstruction> compiledArguments = <HInstruction>[]; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4269 compiledArguments, | 4269 compiledArguments, |
| 4270 nativeBehavior: nativeBehavior)); | 4270 nativeBehavior: nativeBehavior)); |
| 4271 } | 4271 } |
| 4272 | 4272 |
| 4273 void handleForeignJsEmbeddedGlobal(ast.Send node) { | 4273 void handleForeignJsEmbeddedGlobal(ast.Send node) { |
| 4274 List<ast.Node> arguments = node.arguments.toList(); | 4274 List<ast.Node> arguments = node.arguments.toList(); |
| 4275 ast.Node globalNameNode; | 4275 ast.Node globalNameNode; |
| 4276 switch (arguments.length) { | 4276 switch (arguments.length) { |
| 4277 case 0: | 4277 case 0: |
| 4278 case 1: | 4278 case 1: |
| 4279 compiler.reportError( | 4279 compiler.reportErrorMessage( |
| 4280 node, MessageKind.GENERIC, | 4280 node, MessageKind.GENERIC, |
| 4281 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); | 4281 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); |
| 4282 return; | 4282 return; |
| 4283 case 2: | 4283 case 2: |
| 4284 // The type has been extracted earlier. We are only interested in the | 4284 // The type has been extracted earlier. We are only interested in the |
| 4285 // name in this function. | 4285 // name in this function. |
| 4286 globalNameNode = arguments[1]; | 4286 globalNameNode = arguments[1]; |
| 4287 break; | 4287 break; |
| 4288 default: | 4288 default: |
| 4289 for (int i = 2; i < arguments.length; i++) { | 4289 for (int i = 2; i < arguments.length; i++) { |
| 4290 compiler.reportError( | 4290 compiler.reportErrorMessage( |
| 4291 arguments[i], MessageKind.GENERIC, | 4291 arguments[i], MessageKind.GENERIC, |
| 4292 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); | 4292 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); |
| 4293 } | 4293 } |
| 4294 return; | 4294 return; |
| 4295 } | 4295 } |
| 4296 visit(globalNameNode); | 4296 visit(globalNameNode); |
| 4297 HInstruction globalNameHNode = pop(); | 4297 HInstruction globalNameHNode = pop(); |
| 4298 if (!globalNameHNode.isConstantString()) { | 4298 if (!globalNameHNode.isConstantString()) { |
| 4299 compiler.reportError( | 4299 compiler.reportErrorMessage( |
| 4300 arguments[1], MessageKind.GENERIC, | 4300 arguments[1], MessageKind.GENERIC, |
| 4301 {'text': 'Error: Expected String as second argument ' | 4301 {'text': 'Error: Expected String as second argument ' |
| 4302 'to JS_EMBEDDED_GLOBAL.'}); | 4302 'to JS_EMBEDDED_GLOBAL.'}); |
| 4303 return; | 4303 return; |
| 4304 } | 4304 } |
| 4305 HConstant hConstant = globalNameHNode; | 4305 HConstant hConstant = globalNameHNode; |
| 4306 StringConstantValue constant = hConstant.constant; | 4306 StringConstantValue constant = hConstant.constant; |
| 4307 String globalName = constant.primitiveValue.slowToString(); | 4307 String globalName = constant.primitiveValue.slowToString(); |
| 4308 js.Template expr = js.js.expressionTemplateYielding( | 4308 js.Template expr = js.js.expressionTemplateYielding( |
| 4309 backend.emitter.generateEmbeddedGlobalAccess(globalName)); | 4309 backend.emitter.generateEmbeddedGlobalAccess(globalName)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4326 ConstantValue argumentConstant = argumentInstruction.constant; | 4326 ConstantValue argumentConstant = argumentInstruction.constant; |
| 4327 if (argumentConstant is TypeConstantValue) { | 4327 if (argumentConstant is TypeConstantValue) { |
| 4328 ConstantValue constant = | 4328 ConstantValue constant = |
| 4329 new InterceptorConstantValue(argumentConstant.representedType); | 4329 new InterceptorConstantValue(argumentConstant.representedType); |
| 4330 HInstruction instruction = graph.addConstant(constant, compiler); | 4330 HInstruction instruction = graph.addConstant(constant, compiler); |
| 4331 stack.add(instruction); | 4331 stack.add(instruction); |
| 4332 return; | 4332 return; |
| 4333 } | 4333 } |
| 4334 } | 4334 } |
| 4335 } | 4335 } |
| 4336 compiler.reportError(node, | 4336 compiler.reportErrorMessage( |
| 4337 node, |
| 4337 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | 4338 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); |
| 4338 stack.add(graph.addConstantNull(compiler)); | 4339 stack.add(graph.addConstantNull(compiler)); |
| 4339 } | 4340 } |
| 4340 | 4341 |
| 4341 void handleForeignJsCallInIsolate(ast.Send node) { | 4342 void handleForeignJsCallInIsolate(ast.Send node) { |
| 4342 Link<ast.Node> link = node.arguments; | 4343 Link<ast.Node> link = node.arguments; |
| 4343 if (!compiler.hasIsolateSupport) { | 4344 if (!compiler.hasIsolateSupport) { |
| 4344 // If the isolate library is not used, we just invoke the | 4345 // If the isolate library is not used, we just invoke the |
| 4345 // closure. | 4346 // closure. |
| 4346 visit(link.tail.head); | 4347 visit(link.tail.head); |
| (...skipping 2536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6883 stack.add(stringBuilder.result); | 6884 stack.add(stringBuilder.result); |
| 6884 } | 6885 } |
| 6885 | 6886 |
| 6886 void visitLiteralNull(ast.LiteralNull node) { | 6887 void visitLiteralNull(ast.LiteralNull node) { |
| 6887 stack.add(graph.addConstantNull(compiler)); | 6888 stack.add(graph.addConstantNull(compiler)); |
| 6888 } | 6889 } |
| 6889 | 6890 |
| 6890 visitNodeList(ast.NodeList node) { | 6891 visitNodeList(ast.NodeList node) { |
| 6891 for (Link<ast.Node> link = node.nodes; !link.isEmpty; link = link.tail) { | 6892 for (Link<ast.Node> link = node.nodes; !link.isEmpty; link = link.tail) { |
| 6892 if (isAborted()) { | 6893 if (isAborted()) { |
| 6893 compiler.reportWarning(link.head, | 6894 compiler.reportHintMessage( |
| 6894 MessageKind.GENERIC, {'text': 'dead code'}); | 6895 link.head, |
| 6896 MessageKind.GENERIC, |
| 6897 {'text': 'dead code'}); |
| 6895 } else { | 6898 } else { |
| 6896 visit(link.head); | 6899 visit(link.head); |
| 6897 } | 6900 } |
| 6898 } | 6901 } |
| 6899 } | 6902 } |
| 6900 | 6903 |
| 6901 void visitParenthesizedExpression(ast.ParenthesizedExpression node) { | 6904 void visitParenthesizedExpression(ast.ParenthesizedExpression node) { |
| 6902 visit(node.expression); | 6905 visit(node.expression); |
| 6903 } | 6906 } |
| 6904 | 6907 |
| (...skipping 2080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8985 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8988 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 8986 unaliased.accept(this, builder); | 8989 unaliased.accept(this, builder); |
| 8987 } | 8990 } |
| 8988 | 8991 |
| 8989 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 8992 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 8990 JavaScriptBackend backend = builder.compiler.backend; | 8993 JavaScriptBackend backend = builder.compiler.backend; |
| 8991 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 8994 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 8992 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 8995 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 8993 } | 8996 } |
| 8994 } | 8997 } |
| OLD | NEW |