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.safeVariablePrefixForAsyncRewrite, |
39 bodyName: name); | 39 bodyName: backend.namer.deriveAsyncBodyName(name)); |
40 } else if (element.asyncMarker == AsyncMarker.SYNC_STAR) { | 40 } else if (element.asyncMarker == AsyncMarker.SYNC_STAR) { |
41 rewriter = new SyncStarRewriter( | 41 rewriter = new SyncStarRewriter( |
42 backend.compiler, | 42 backend.compiler, |
43 backend.compiler.currentElement, | 43 backend.compiler.currentElement, |
44 endOfIteration: backend.emitter.staticFunctionAccess( | 44 endOfIteration: backend.emitter.staticFunctionAccess( |
45 backend.getEndOfIteration()), | 45 backend.getEndOfIteration()), |
46 newIterable: backend.emitter.staticFunctionAccess( | 46 newIterable: backend.emitter.staticFunctionAccess( |
47 backend.getSyncStarIterableConstructor()), | 47 backend.getSyncStarIterableConstructor()), |
48 yieldStarExpression: backend.emitter.staticFunctionAccess( | 48 yieldStarExpression: backend.emitter.staticFunctionAccess( |
49 backend.getYieldStar()), | 49 backend.getYieldStar()), |
50 uncaughtErrorExpression: backend.emitter.staticFunctionAccess( | 50 uncaughtErrorExpression: backend.emitter.staticFunctionAccess( |
51 backend.getSyncStarUncaughtError()), | 51 backend.getSyncStarUncaughtError()), |
52 safeVariableName: backend.namer.safeVariableName, | 52 safeVariableName: backend.namer.safeVariablePrefixForAsyncRewrite, |
53 bodyName: name); | 53 bodyName: backend.namer.deriveAsyncBodyName(name)); |
54 } | 54 } |
55 else if (element.asyncMarker == AsyncMarker.ASYNC_STAR) { | 55 else if (element.asyncMarker == AsyncMarker.ASYNC_STAR) { |
56 rewriter = new AsyncStarRewriter( | 56 rewriter = new AsyncStarRewriter( |
57 backend.compiler, | 57 backend.compiler, |
58 backend.compiler.currentElement, | 58 backend.compiler.currentElement, |
59 asyncStarHelper: backend.emitter.staticFunctionAccess( | 59 asyncStarHelper: backend.emitter.staticFunctionAccess( |
60 backend.getAsyncStarHelper()), | 60 backend.getAsyncStarHelper()), |
61 streamOfController: backend.emitter.staticFunctionAccess( | 61 streamOfController: backend.emitter.staticFunctionAccess( |
62 backend.getStreamOfController()), | 62 backend.getStreamOfController()), |
63 newController: backend.emitter.staticFunctionAccess( | 63 newController: backend.emitter.staticFunctionAccess( |
64 backend.getASyncStarControllerConstructor()), | 64 backend.getASyncStarControllerConstructor()), |
65 safeVariableName: backend.namer.safeVariableName, | 65 safeVariableName: backend.namer.safeVariablePrefixForAsyncRewrite, |
66 yieldExpression: backend.emitter.staticFunctionAccess( | 66 yieldExpression: backend.emitter.staticFunctionAccess( |
67 backend.getYieldSingle()), | 67 backend.getYieldSingle()), |
68 yieldStarExpression: backend.emitter.staticFunctionAccess( | 68 yieldStarExpression: backend.emitter.staticFunctionAccess( |
69 backend.getYieldStar()), | 69 backend.getYieldStar()), |
70 bodyName: name); | 70 bodyName: backend.namer.deriveAsyncBodyName(name)); |
71 } | 71 } |
72 if (rewriter != null) { | 72 if (rewriter != null) { |
73 result = rewriter.rewrite(result); | 73 result = rewriter.rewrite(result); |
74 } | 74 } |
75 } | 75 } |
76 return result; | 76 return result; |
77 } | 77 } |
78 | 78 |
79 Iterable<CompilerTask> get tasks { | 79 Iterable<CompilerTask> get tasks { |
80 return <CompilerTask>[builder, optimizer, generator]; | 80 return <CompilerTask>[builder, optimizer, generator]; |
(...skipping 3585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3666 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 3666 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
3667 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); | 3667 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); |
3668 HInstruction call = pop(); | 3668 HInstruction call = pop(); |
3669 return new HIs.variable(type, expression, call, backend.boolType); | 3669 return new HIs.variable(type, expression, call, backend.boolType); |
3670 } else if (RuntimeTypes.hasTypeArguments(type)) { | 3670 } else if (RuntimeTypes.hasTypeArguments(type)) { |
3671 ClassElement element = type.element; | 3671 ClassElement element = type.element; |
3672 Element helper = backend.getCheckSubtype(); | 3672 Element helper = backend.getCheckSubtype(); |
3673 HInstruction representations = | 3673 HInstruction representations = |
3674 buildTypeArgumentRepresentations(type); | 3674 buildTypeArgumentRepresentations(type); |
3675 add(representations); | 3675 add(representations); |
3676 String operator = backend.namer.operatorIs(element); | 3676 js.Name operator = backend.namer.operatorIs(element); |
3677 HInstruction isFieldName = addConstantString(operator); | 3677 HInstruction isFieldName = addConstantStringFromName(operator); |
3678 HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element) | 3678 HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element) |
3679 ? addConstantString(backend.namer.substitutionName(element)) | 3679 ? addConstantStringFromName(backend.namer.substitutionName(element)) |
3680 : graph.addConstantNull(compiler); | 3680 : graph.addConstantNull(compiler); |
3681 List<HInstruction> inputs = <HInstruction>[expression, | 3681 List<HInstruction> inputs = <HInstruction>[expression, |
3682 isFieldName, | 3682 isFieldName, |
3683 representations, | 3683 representations, |
3684 asFieldName]; | 3684 asFieldName]; |
3685 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); | 3685 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); |
3686 HInstruction call = pop(); | 3686 HInstruction call = pop(); |
3687 return new HIs.compound(type, expression, call, backend.boolType); | 3687 return new HIs.compound(type, expression, call, backend.boolType); |
3688 } else if (type.isMalformed) { | 3688 } else if (type.isMalformed) { |
3689 ErroneousElement element = type.element; | 3689 ErroneousElement element = type.element; |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4021 if (element == null || | 4021 if (element == null || |
4022 element is! FieldElement || | 4022 element is! FieldElement || |
4023 element.enclosingClass != backend.jsGetNameEnum) { | 4023 element.enclosingClass != backend.jsGetNameEnum) { |
4024 compiler.reportError( | 4024 compiler.reportError( |
4025 argument, MessageKind.GENERIC, | 4025 argument, MessageKind.GENERIC, |
4026 {'text': 'Error: Expected a JsGetName enum value.'}); | 4026 {'text': 'Error: Expected a JsGetName enum value.'}); |
4027 } | 4027 } |
4028 EnumClassElement enumClass = element.enclosingClass; | 4028 EnumClassElement enumClass = element.enclosingClass; |
4029 int index = enumClass.enumValues.indexOf(element); | 4029 int index = enumClass.enumValues.indexOf(element); |
4030 stack.add( | 4030 stack.add( |
4031 addConstantString( | 4031 addConstantStringFromName( |
4032 backend.namer.getNameForJsGetName( | 4032 backend.namer.getNameForJsGetName( |
4033 argument, JsGetName.values[index]))); | 4033 argument, JsGetName.values[index]))); |
4034 } | 4034 } |
4035 | 4035 |
4036 void handleForeignJsBuiltin(ast.Send node) { | 4036 void handleForeignJsBuiltin(ast.Send node) { |
4037 List<ast.Node> arguments = node.arguments.toList(); | 4037 List<ast.Node> arguments = node.arguments.toList(); |
4038 ast.Node argument; | 4038 ast.Node argument; |
4039 if (arguments.length < 2) { | 4039 if (arguments.length < 2) { |
4040 compiler.reportError( | 4040 compiler.reportError( |
4041 node, MessageKind.GENERIC, | 4041 node, MessageKind.GENERIC, |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4292 // case the [noSuchMethod] implementation calls | 4292 // case the [noSuchMethod] implementation calls |
4293 // [JSInvocationMirror._invokeOn]. | 4293 // [JSInvocationMirror._invokeOn]. |
4294 registry.registerSelectorUse(selector.asUntyped); | 4294 registry.registerSelectorUse(selector.asUntyped); |
4295 } | 4295 } |
4296 String publicName = name; | 4296 String publicName = name; |
4297 if (selector.isSetter) publicName += '='; | 4297 if (selector.isSetter) publicName += '='; |
4298 | 4298 |
4299 ConstantValue nameConstant = constantSystem.createString( | 4299 ConstantValue nameConstant = constantSystem.createString( |
4300 new ast.DartString.literal(publicName)); | 4300 new ast.DartString.literal(publicName)); |
4301 | 4301 |
4302 String internalName = backend.namer.invocationName(selector); | 4302 js.Name internalName = backend.namer.invocationName(selector); |
4303 ConstantValue internalNameConstant = | |
4304 constantSystem.createString(new ast.DartString.literal(internalName)); | |
4305 | 4303 |
4306 Element createInvocationMirror = backend.getCreateInvocationMirror(); | 4304 Element createInvocationMirror = backend.getCreateInvocationMirror(); |
4307 var argumentsInstruction = buildLiteralList(arguments); | 4305 var argumentsInstruction = buildLiteralList(arguments); |
4308 add(argumentsInstruction); | 4306 add(argumentsInstruction); |
4309 | 4307 |
4310 var argumentNames = new List<HInstruction>(); | 4308 var argumentNames = new List<HInstruction>(); |
4311 for (String argumentName in selector.namedArguments) { | 4309 for (String argumentName in selector.namedArguments) { |
4312 ConstantValue argumentNameConstant = | 4310 ConstantValue argumentNameConstant = |
4313 constantSystem.createString(new ast.DartString.literal(argumentName)); | 4311 constantSystem.createString(new ast.DartString.literal(argumentName)); |
4314 argumentNames.add(graph.addConstant(argumentNameConstant, compiler)); | 4312 argumentNames.add(graph.addConstant(argumentNameConstant, compiler)); |
4315 } | 4313 } |
4316 var argumentNamesInstruction = buildLiteralList(argumentNames); | 4314 var argumentNamesInstruction = buildLiteralList(argumentNames); |
4317 add(argumentNamesInstruction); | 4315 add(argumentNamesInstruction); |
4318 | 4316 |
4319 ConstantValue kindConstant = | 4317 ConstantValue kindConstant = |
4320 constantSystem.createInt(selector.invocationMirrorKind); | 4318 constantSystem.createInt(selector.invocationMirrorKind); |
4321 | 4319 |
4322 pushInvokeStatic(null, | 4320 pushInvokeStatic(null, |
4323 createInvocationMirror, | 4321 createInvocationMirror, |
4324 [graph.addConstant(nameConstant, compiler), | 4322 [graph.addConstant(nameConstant, compiler), |
4325 graph.addConstant(internalNameConstant, compiler), | 4323 graph.addConstantStringFromName(internalName, compiler), |
4326 graph.addConstant(kindConstant, compiler), | 4324 graph.addConstant(kindConstant, compiler), |
4327 argumentsInstruction, | 4325 argumentsInstruction, |
4328 argumentNamesInstruction], | 4326 argumentNamesInstruction], |
4329 typeMask: backend.dynamicType); | 4327 typeMask: backend.dynamicType); |
4330 | 4328 |
4331 var inputs = <HInstruction>[pop()]; | 4329 var inputs = <HInstruction>[pop()]; |
4332 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); | 4330 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); |
4333 } | 4331 } |
4334 | 4332 |
4335 /// Generate a call to a super method or constructor. | 4333 /// Generate a call to a super method or constructor. |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4581 | 4579 |
4582 HInstruction target = localsHandler.readThis(); | 4580 HInstruction target = localsHandler.readThis(); |
4583 HConstant index = graph.addConstantInt( | 4581 HConstant index = graph.addConstantInt( |
4584 RuntimeTypes.getTypeVariableIndex(variable), | 4582 RuntimeTypes.getTypeVariableIndex(variable), |
4585 compiler); | 4583 compiler); |
4586 | 4584 |
4587 if (needsSubstitutionForTypeVariableAccess(cls)) { | 4585 if (needsSubstitutionForTypeVariableAccess(cls)) { |
4588 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to | 4586 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to |
4589 // string concatenation in the implementation), and may prevent | 4587 // string concatenation in the implementation), and may prevent |
4590 // segmentation of '$'. | 4588 // segmentation of '$'. |
4591 String substitutionNameString = backend.namer.runtimeTypeName(cls); | 4589 js.Name substitutionName = backend.namer.runtimeTypeName(cls); |
4592 HInstruction substitutionName = graph.addConstantString( | 4590 HInstruction substitutionNameInstr = graph.addConstantStringFromName( |
4593 new ast.LiteralDartString(substitutionNameString), compiler); | 4591 substitutionName, compiler); |
4594 pushInvokeStatic(null, | 4592 pushInvokeStatic(null, |
4595 backend.getGetRuntimeTypeArgument(), | 4593 backend.getGetRuntimeTypeArgument(), |
4596 [target, substitutionName, index], | 4594 [target, substitutionNameInstr, index], |
4597 typeMask: backend.dynamicType); | 4595 typeMask: backend.dynamicType); |
4598 } else { | 4596 } else { |
4599 pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(), | 4597 pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(), |
4600 [target, index], | 4598 [target, index], |
4601 typeMask: backend.dynamicType); | 4599 typeMask: backend.dynamicType); |
4602 } | 4600 } |
4603 return pop(); | 4601 return pop(); |
4604 } | 4602 } |
4605 | 4603 |
4606 // TODO(karlklose): this is needed to avoid a bug where the resolved type is | 4604 // 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... |
5186 handleInvalidStaticInvoke(node, element); | 5184 handleInvalidStaticInvoke(node, element); |
5187 } else { | 5185 } else { |
5188 // TODO(ahe): Do something like [generateWrongArgumentCountError]. | 5186 // TODO(ahe): Do something like [generateWrongArgumentCountError]. |
5189 stack.add(graph.addConstantNull(compiler)); | 5187 stack.add(graph.addConstantNull(compiler)); |
5190 } | 5188 } |
5191 return; | 5189 return; |
5192 } | 5190 } |
5193 | 5191 |
5194 HConstant addConstantString(String string) { | 5192 HConstant addConstantString(String string) { |
5195 ast.DartString dartString = new ast.DartString.literal(string); | 5193 ast.DartString dartString = new ast.DartString.literal(string); |
5196 ConstantValue constant = constantSystem.createString(dartString); | 5194 return graph.addConstantString(dartString, compiler); |
5197 return graph.addConstant(constant, compiler); | 5195 } |
| 5196 |
| 5197 HConstant addConstantStringFromName(js.Name name) { |
| 5198 return graph.addConstantStringFromName(name, compiler); |
5198 } | 5199 } |
5199 | 5200 |
5200 visitClassTypeLiteralGet( | 5201 visitClassTypeLiteralGet( |
5201 ast.Send node, | 5202 ast.Send node, |
5202 ConstantExpression constant, | 5203 ConstantExpression constant, |
5203 _) { | 5204 _) { |
5204 generateConstantTypeLiteral(node); | 5205 generateConstantTypeLiteral(node); |
5205 } | 5206 } |
5206 | 5207 |
5207 visitClassTypeLiteralInvoke( | 5208 visitClassTypeLiteralInvoke( |
(...skipping 2901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8109 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8110 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
8110 unaliased.accept(this, builder); | 8111 unaliased.accept(this, builder); |
8111 } | 8112 } |
8112 | 8113 |
8113 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 8114 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
8114 JavaScriptBackend backend = builder.compiler.backend; | 8115 JavaScriptBackend backend = builder.compiler.backend; |
8115 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 8116 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
8116 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 8117 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
8117 } | 8118 } |
8118 } | 8119 } |
OLD | NEW |