| 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 |