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; |
11 | 11 |
12 SsaFunctionCompiler(JavaScriptBackend backend, | 12 SsaFunctionCompiler(JavaScriptBackend backend, |
13 SourceInformationFactory sourceInformationFactory) | 13 SourceInformationFactory sourceInformationFactory) |
14 : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory), | 14 : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory), |
15 builder = new SsaBuilderTask(backend, sourceInformationFactory), | 15 builder = new SsaBuilderTask(backend, sourceInformationFactory), |
16 optimizer = new SsaOptimizerTask(backend); | 16 optimizer = new SsaOptimizerTask(backend); |
17 | 17 |
18 /// Generates JavaScript code for `work.element`. | 18 /// Generates JavaScript code for `work.element`. |
19 /// Using the ssa builder, optimizer and codegenerator. | 19 /// Using the ssa builder, optimizer and codegenerator. |
20 js.Fun compile(CodegenWorkItem work) { | 20 js.Fun compile(CodegenWorkItem work) { |
21 HGraph graph = builder.build(work); | 21 HGraph graph = builder.build(work); |
22 optimizer.optimize(work, graph); | 22 optimizer.optimize(work, graph); |
23 Element element = work.element; | 23 Element element = work.element; |
24 js.Expression result = generator.generateCode(work, graph); | 24 js.Expression result = generator.generateCode(work, graph); |
25 if (element is FunctionElement) { | 25 if (element is FunctionElement) { |
26 JavaScriptBackend backend = builder.backend; | 26 JavaScriptBackend backend = builder.backend; |
27 | 27 |
28 AsyncRewriterBase rewriter = null; | 28 AsyncRewriterBase rewriter = null; |
29 String name = backend.namer.methodPropertyName(element); | 29 js.Name name = backend.namer.methodPropertyName(element); |
30 if (element.asyncMarker == AsyncMarker.ASYNC) { | 30 if (element.asyncMarker == AsyncMarker.ASYNC) { |
31 rewriter = new AsyncRewriter( | 31 rewriter = new AsyncRewriter( |
32 backend.compiler, | 32 backend.compiler, |
33 backend.compiler.currentElement, | 33 backend.compiler.currentElement, |
34 asyncHelper: | 34 asyncHelper: |
35 backend.emitter.staticFunctionAccess(backend.getAsyncHelper()), | 35 backend.emitter.staticFunctionAccess(backend.getAsyncHelper()), |
36 newCompleter: backend.emitter.staticFunctionAccess( | 36 newCompleter: backend.emitter.staticFunctionAccess( |
37 backend.getCompleterConstructor()), | 37 backend.getCompleterConstructor()), |
38 safeVariableName: backend.namer.safeVariableName, | 38 safeVariableName: backend.namer.safeVariableName, |
39 bodyName: name); | 39 bodyName: name); |
(...skipping 3650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3690 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 3690 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
3691 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); | 3691 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); |
3692 HInstruction call = pop(); | 3692 HInstruction call = pop(); |
3693 return new HIs.variable(type, expression, call, backend.boolType); | 3693 return new HIs.variable(type, expression, call, backend.boolType); |
3694 } else if (RuntimeTypes.hasTypeArguments(type)) { | 3694 } else if (RuntimeTypes.hasTypeArguments(type)) { |
3695 ClassElement element = type.element; | 3695 ClassElement element = type.element; |
3696 Element helper = backend.getCheckSubtype(); | 3696 Element helper = backend.getCheckSubtype(); |
3697 HInstruction representations = | 3697 HInstruction representations = |
3698 buildTypeArgumentRepresentations(type); | 3698 buildTypeArgumentRepresentations(type); |
3699 add(representations); | 3699 add(representations); |
3700 String operator = backend.namer.operatorIs(element); | 3700 js.Name operator = backend.namer.operatorIs(element); |
3701 HInstruction isFieldName = addConstantString(operator); | 3701 HInstruction isFieldName = addConstantStringFromName(operator); |
3702 HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element) | 3702 HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element) |
3703 ? addConstantString(backend.namer.substitutionName(element)) | 3703 ? addConstantStringFromName(backend.namer.substitutionName(element)) |
3704 : graph.addConstantNull(compiler); | 3704 : graph.addConstantNull(compiler); |
3705 List<HInstruction> inputs = <HInstruction>[expression, | 3705 List<HInstruction> inputs = <HInstruction>[expression, |
3706 isFieldName, | 3706 isFieldName, |
3707 representations, | 3707 representations, |
3708 asFieldName]; | 3708 asFieldName]; |
3709 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); | 3709 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); |
3710 HInstruction call = pop(); | 3710 HInstruction call = pop(); |
3711 return new HIs.compound(type, expression, call, backend.boolType); | 3711 return new HIs.compound(type, expression, call, backend.boolType); |
3712 } else if (type.isMalformed) { | 3712 } else if (type.isMalformed) { |
3713 ErroneousElement element = type.element; | 3713 ErroneousElement element = type.element; |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4046 if (element == null || | 4046 if (element == null || |
4047 element is! FieldElement || | 4047 element is! FieldElement || |
4048 element.enclosingClass != backend.jsGetNameEnum) { | 4048 element.enclosingClass != backend.jsGetNameEnum) { |
4049 compiler.reportError( | 4049 compiler.reportError( |
4050 argument, MessageKind.GENERIC, | 4050 argument, MessageKind.GENERIC, |
4051 {'text': 'Error: Expected a JsGetName enum value.'}); | 4051 {'text': 'Error: Expected a JsGetName enum value.'}); |
4052 } | 4052 } |
4053 EnumClassElement enumClass = element.enclosingClass; | 4053 EnumClassElement enumClass = element.enclosingClass; |
4054 int index = enumClass.enumValues.indexOf(element); | 4054 int index = enumClass.enumValues.indexOf(element); |
4055 stack.add( | 4055 stack.add( |
4056 addConstantString( | 4056 addConstantStringFromName( |
4057 backend.namer.getNameForJsGetName( | 4057 backend.namer.getNameForJsGetName( |
4058 argument, JsGetName.values[index]))); | 4058 argument, JsGetName.values[index]))); |
4059 } | 4059 } |
4060 | 4060 |
4061 void handleForeignJsBuiltin(ast.Send node) { | 4061 void handleForeignJsBuiltin(ast.Send node) { |
4062 List<ast.Node> arguments = node.arguments.toList(); | 4062 List<ast.Node> arguments = node.arguments.toList(); |
4063 ast.Node argument; | 4063 ast.Node argument; |
4064 if (arguments.length < 2) { | 4064 if (arguments.length < 2) { |
4065 compiler.reportError( | 4065 compiler.reportError( |
4066 node, MessageKind.GENERIC, | 4066 node, MessageKind.GENERIC, |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4316 // case the [noSuchMethod] implementation calls | 4316 // case the [noSuchMethod] implementation calls |
4317 // [JSInvocationMirror._invokeOn]. | 4317 // [JSInvocationMirror._invokeOn]. |
4318 registry.registerSelectorUse(selector); | 4318 registry.registerSelectorUse(selector); |
4319 } | 4319 } |
4320 String publicName = name; | 4320 String publicName = name; |
4321 if (selector.isSetter) publicName += '='; | 4321 if (selector.isSetter) publicName += '='; |
4322 | 4322 |
4323 ConstantValue nameConstant = constantSystem.createString( | 4323 ConstantValue nameConstant = constantSystem.createString( |
4324 new ast.DartString.literal(publicName)); | 4324 new ast.DartString.literal(publicName)); |
4325 | 4325 |
4326 String internalName = backend.namer.invocationName(selector); | 4326 js.Name internalName = backend.namer.invocationName(selector); |
4327 ConstantValue internalNameConstant = | |
4328 constantSystem.createString(new ast.DartString.literal(internalName)); | |
4329 | 4327 |
4330 Element createInvocationMirror = backend.getCreateInvocationMirror(); | 4328 Element createInvocationMirror = backend.getCreateInvocationMirror(); |
4331 var argumentsInstruction = buildLiteralList(arguments); | 4329 var argumentsInstruction = buildLiteralList(arguments); |
4332 add(argumentsInstruction); | 4330 add(argumentsInstruction); |
4333 | 4331 |
4334 var argumentNames = new List<HInstruction>(); | 4332 var argumentNames = new List<HInstruction>(); |
4335 for (String argumentName in selector.namedArguments) { | 4333 for (String argumentName in selector.namedArguments) { |
4336 ConstantValue argumentNameConstant = | 4334 ConstantValue argumentNameConstant = |
4337 constantSystem.createString(new ast.DartString.literal(argumentName)); | 4335 constantSystem.createString(new ast.DartString.literal(argumentName)); |
4338 argumentNames.add(graph.addConstant(argumentNameConstant, compiler)); | 4336 argumentNames.add(graph.addConstant(argumentNameConstant, compiler)); |
4339 } | 4337 } |
4340 var argumentNamesInstruction = buildLiteralList(argumentNames); | 4338 var argumentNamesInstruction = buildLiteralList(argumentNames); |
4341 add(argumentNamesInstruction); | 4339 add(argumentNamesInstruction); |
4342 | 4340 |
4343 ConstantValue kindConstant = | 4341 ConstantValue kindConstant = |
4344 constantSystem.createInt(selector.invocationMirrorKind); | 4342 constantSystem.createInt(selector.invocationMirrorKind); |
4345 | 4343 |
4346 pushInvokeStatic(null, | 4344 pushInvokeStatic(null, |
4347 createInvocationMirror, | 4345 createInvocationMirror, |
4348 [graph.addConstant(nameConstant, compiler), | 4346 [graph.addConstant(nameConstant, compiler), |
4349 graph.addConstant(internalNameConstant, compiler), | 4347 graph.addConstantStringFromName(internalName, compiler), |
4350 graph.addConstant(kindConstant, compiler), | 4348 graph.addConstant(kindConstant, compiler), |
4351 argumentsInstruction, | 4349 argumentsInstruction, |
4352 argumentNamesInstruction], | 4350 argumentNamesInstruction], |
4353 typeMask: backend.dynamicType); | 4351 typeMask: backend.dynamicType); |
4354 | 4352 |
4355 var inputs = <HInstruction>[pop()]; | 4353 var inputs = <HInstruction>[pop()]; |
4356 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); | 4354 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); |
4357 } | 4355 } |
4358 | 4356 |
4359 /// Generate a call to a super method or constructor. | 4357 /// Generate a call to a super method or constructor. |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4605 | 4603 |
4606 HInstruction target = localsHandler.readThis(); | 4604 HInstruction target = localsHandler.readThis(); |
4607 HConstant index = graph.addConstantInt( | 4605 HConstant index = graph.addConstantInt( |
4608 RuntimeTypes.getTypeVariableIndex(variable), | 4606 RuntimeTypes.getTypeVariableIndex(variable), |
4609 compiler); | 4607 compiler); |
4610 | 4608 |
4611 if (needsSubstitutionForTypeVariableAccess(cls)) { | 4609 if (needsSubstitutionForTypeVariableAccess(cls)) { |
4612 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to | 4610 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to |
4613 // string concatenation in the implementation), and may prevent | 4611 // string concatenation in the implementation), and may prevent |
4614 // segmentation of '$'. | 4612 // segmentation of '$'. |
4615 String substitutionNameString = backend.namer.runtimeTypeName(cls); | 4613 js.Name substitutionName = backend.namer.runtimeTypeName(cls); |
4616 HInstruction substitutionName = graph.addConstantString( | 4614 HInstruction substitutionNameInstr = graph.addConstantStringFromName( |
4617 new ast.LiteralDartString(substitutionNameString), compiler); | 4615 substitutionName, compiler); |
4618 pushInvokeStatic(null, | 4616 pushInvokeStatic(null, |
4619 backend.getGetRuntimeTypeArgument(), | 4617 backend.getGetRuntimeTypeArgument(), |
4620 [target, substitutionName, index], | 4618 [target, substitutionNameInstr, index], |
4621 typeMask: backend.dynamicType); | 4619 typeMask: backend.dynamicType); |
4622 } else { | 4620 } else { |
4623 pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(), | 4621 pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(), |
4624 [target, index], | 4622 [target, index], |
4625 typeMask: backend.dynamicType); | 4623 typeMask: backend.dynamicType); |
4626 } | 4624 } |
4627 return pop(); | 4625 return pop(); |
4628 } | 4626 } |
4629 | 4627 |
4630 // TODO(karlklose): this is needed to avoid a bug where the resolved type is | 4628 // TODO(karlklose): this is needed to avoid a bug where the resolved type is |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5210 handleInvalidStaticInvoke(node, element); | 5208 handleInvalidStaticInvoke(node, element); |
5211 } else { | 5209 } else { |
5212 // TODO(ahe): Do something like [generateWrongArgumentCountError]. | 5210 // TODO(ahe): Do something like [generateWrongArgumentCountError]. |
5213 stack.add(graph.addConstantNull(compiler)); | 5211 stack.add(graph.addConstantNull(compiler)); |
5214 } | 5212 } |
5215 return; | 5213 return; |
5216 } | 5214 } |
5217 | 5215 |
5218 HConstant addConstantString(String string) { | 5216 HConstant addConstantString(String string) { |
5219 ast.DartString dartString = new ast.DartString.literal(string); | 5217 ast.DartString dartString = new ast.DartString.literal(string); |
5220 ConstantValue constant = constantSystem.createString(dartString); | 5218 return graph.addConstantString(dartString, compiler); |
5221 return graph.addConstant(constant, compiler); | 5219 } |
| 5220 |
| 5221 HConstant addConstantStringFromName(js.Name name) { |
| 5222 return graph.addConstantStringFromName(name, compiler); |
5222 } | 5223 } |
5223 | 5224 |
5224 visitClassTypeLiteralGet( | 5225 visitClassTypeLiteralGet( |
5225 ast.Send node, | 5226 ast.Send node, |
5226 ConstantExpression constant, | 5227 ConstantExpression constant, |
5227 _) { | 5228 _) { |
5228 generateConstantTypeLiteral(node); | 5229 generateConstantTypeLiteral(node); |
5229 } | 5230 } |
5230 | 5231 |
5231 visitClassTypeLiteralInvoke( | 5232 visitClassTypeLiteralInvoke( |
(...skipping 2927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8159 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8160 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
8160 unaliased.accept(this, builder); | 8161 unaliased.accept(this, builder); |
8161 } | 8162 } |
8162 | 8163 |
8163 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 8164 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
8164 JavaScriptBackend backend = builder.compiler.backend; | 8165 JavaScriptBackend backend = builder.compiler.backend; |
8165 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 8166 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
8166 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 8167 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
8167 } | 8168 } |
8168 } | 8169 } |
OLD | NEW |