Chromium Code Reviews| 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 class SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
| 6 | 6 |
| 7 final JavaScriptBackend backend; | 7 final JavaScriptBackend backend; |
| 8 | 8 |
| 9 SsaCodeGeneratorTask(JavaScriptBackend backend) | 9 SsaCodeGeneratorTask(JavaScriptBackend backend) |
| 10 : this.backend = backend, | 10 : this.backend = backend, |
| 11 super(backend.compiler); | 11 super(backend.compiler); |
| 12 String get name => 'SSA code generator'; | 12 String get name => 'SSA code generator'; |
| 13 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; | 13 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; |
| 14 | 14 |
| 15 | 15 |
| 16 js.Fun buildJavaScriptFunction(FunctionElement element, | 16 js.Fun buildJavaScriptFunction(FunctionElement element, |
| 17 List<js.Parameter> parameters, | 17 List<js.Parameter> parameters, |
| 18 js.Block body) { | 18 js.Block body) { |
| 19 FunctionExpression expression = element.cachedNode; | 19 FunctionExpression expression = element.cachedNode; |
| 20 js.Fun result = new js.Fun(parameters, body); | 20 js.Fun result = new js.Fun(parameters, body); |
| 21 result.sourcePosition = expression.getBeginToken(); | 21 Element sourceElement = element.patch == null ? element : element.patch; |
|
ahe
2012/09/08 08:55:50
Another TODO for Johnni.
podivilov
2012/09/10 11:13:23
Done.
| |
| 22 result.endSourcePosition = expression.getEndToken(); | 22 SourceFile sourceFile = sourceElement.getCompilationUnit().script.file; |
| 23 result.sourcePosition = new SourceFileLocation( | |
| 24 sourceFile, expression.getBeginToken()); | |
| 25 result.endSourcePosition = new SourceFileLocation( | |
| 26 sourceFile, expression.getEndToken()); | |
| 23 return result; | 27 return result; |
| 24 } | 28 } |
| 25 | 29 |
| 26 CodeBuffer prettyPrint(js.Node node, Element positionElement) { | 30 CodeBuffer prettyPrint(js.Node node) { |
| 27 return js.prettyPrint(node, compiler, positionElement); | 31 return js.prettyPrint(node, compiler); |
| 28 } | 32 } |
| 29 | 33 |
| 30 CodeBuffer generateCode(WorkItem work, HGraph graph) { | 34 CodeBuffer generateCode(WorkItem work, HGraph graph) { |
| 31 if (work.element.isField()) { | 35 if (work.element.isField()) { |
| 32 return generateLazyInitializer(work, graph); | 36 return generateLazyInitializer(work, graph); |
| 33 } else { | 37 } else { |
| 34 return generateMethod(work, graph); | 38 return generateMethod(work, graph); |
| 35 } | 39 } |
| 36 } | 40 } |
| 37 | 41 |
| 38 CodeBuffer generateLazyInitializer(work, graph) { | 42 CodeBuffer generateLazyInitializer(work, graph) { |
| 39 return measure(() { | 43 return measure(() { |
| 40 compiler.tracer.traceGraph("codegen", graph); | 44 compiler.tracer.traceGraph("codegen", graph); |
| 41 List<js.Parameter> parameters = <js.Parameter>[]; | 45 List<js.Parameter> parameters = <js.Parameter>[]; |
| 42 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( | 46 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( |
| 43 backend, work, parameters, new Map<Element, String>()); | 47 backend, work, parameters, new Map<Element, String>()); |
| 44 codegen.visitGraph(graph); | 48 codegen.visitGraph(graph); |
| 45 js.Block body = codegen.body; | 49 js.Block body = codegen.body; |
| 46 Element element = work.element; | |
| 47 js.Fun fun = new js.Fun(parameters, body); | 50 js.Fun fun = new js.Fun(parameters, body); |
| 48 return prettyPrint(fun, element); | 51 return prettyPrint(fun); |
| 49 }); | 52 }); |
| 50 } | 53 } |
| 51 | 54 |
| 52 CodeBuffer generateMethod(WorkItem work, HGraph graph) { | 55 CodeBuffer generateMethod(WorkItem work, HGraph graph) { |
| 53 return measure(() { | 56 return measure(() { |
| 54 JavaScriptItemCompilationContext context = work.compilationContext; | 57 JavaScriptItemCompilationContext context = work.compilationContext; |
| 55 HTypeMap types = context.types; | 58 HTypeMap types = context.types; |
| 56 graph.exit.predecessors.forEach((block) { | 59 graph.exit.predecessors.forEach((block) { |
| 57 assert(block.last is HGoto || block.last is HReturn); | 60 assert(block.last is HGoto || block.last is HReturn); |
| 58 if (block.last is HReturn) { | 61 if (block.last is HReturn) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 81 ClassElement enclosingClass = element.getEnclosingClass(); | 84 ClassElement enclosingClass = element.getEnclosingClass(); |
| 82 if (element.isInstanceMember() | 85 if (element.isInstanceMember() |
| 83 && enclosingClass.isNative() | 86 && enclosingClass.isNative() |
| 84 && native.isOverriddenMethod( | 87 && native.isOverriddenMethod( |
| 85 element, enclosingClass, nativeEmitter)) { | 88 element, enclosingClass, nativeEmitter)) { |
| 86 // Record that this method is overridden. In case of optional | 89 // Record that this method is overridden. In case of optional |
| 87 // arguments, the emitter will generate stubs to handle them, | 90 // arguments, the emitter will generate stubs to handle them, |
| 88 // and needs to know if the method is overridden. | 91 // and needs to know if the method is overridden. |
| 89 nativeEmitter.overriddenMethods.add(element); | 92 nativeEmitter.overriddenMethods.add(element); |
| 90 StringBuffer buffer = new StringBuffer(); | 93 StringBuffer buffer = new StringBuffer(); |
| 91 String codeString = prettyPrint(codegen.body, work.element).toString(); | 94 String codeString = prettyPrint(codegen.body).toString(); |
| 92 native.generateMethodWithPrototypeCheckForElement( | 95 native.generateMethodWithPrototypeCheckForElement( |
| 93 compiler, buffer, element, codeString, parametersString); | 96 compiler, buffer, element, codeString, parametersString); |
| 94 js.Node nativeCode = new js.LiteralStatement(buffer.toString()); | 97 js.Node nativeCode = new js.LiteralStatement(buffer.toString()); |
| 95 body = new js.Block(<js.Statement>[nativeCode]); | 98 body = new js.Block(<js.Statement>[nativeCode]); |
| 96 } else { | 99 } else { |
| 97 body = codegen.body; | 100 body = codegen.body; |
| 98 } | 101 } |
| 99 js.Fun fun = buildJavaScriptFunction(element, parameters, body); | 102 js.Fun fun = buildJavaScriptFunction(element, parameters, body); |
| 100 return prettyPrint(fun, work.element); | 103 return prettyPrint(fun); |
| 101 }); | 104 }); |
| 102 } | 105 } |
| 103 | 106 |
| 104 void addTypeParameters(Element element, | 107 void addTypeParameters(Element element, |
| 105 List<js.Parameter> parameters, | 108 List<js.Parameter> parameters, |
| 106 Map<Element, String> parameterNames) { | 109 Map<Element, String> parameterNames) { |
| 107 if (element.isFactoryConstructor() || element.isGenerativeConstructor()) { | 110 if (element.isFactoryConstructor() || element.isGenerativeConstructor()) { |
| 108 ClassElement cls = element.enclosingElement; | 111 ClassElement cls = element.enclosingElement; |
| 109 cls.typeVariables.forEach((TypeVariableType typeVariable) { | 112 cls.typeVariables.forEach((TypeVariableType typeVariable) { |
| 110 String name = typeVariable.element.name.slowToString(); | 113 String name = typeVariable.element.name.slowToString(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 133 | 136 |
| 134 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator( | 137 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator( |
| 135 backend, work, parameters, parameterNames); | 138 backend, work, parameters, parameterNames); |
| 136 codegen.visitGraph(graph); | 139 codegen.visitGraph(graph); |
| 137 | 140 |
| 138 js.Block body = new js.Block(<js.Statement>[]); | 141 js.Block body = new js.Block(<js.Statement>[]); |
| 139 if (codegen.setup != null) body.statements.add(codegen.setup); | 142 if (codegen.setup != null) body.statements.add(codegen.setup); |
| 140 body.statements.add(codegen.body); | 143 body.statements.add(codegen.body); |
| 141 js.Fun fun = | 144 js.Fun fun = |
| 142 buildJavaScriptFunction(work.element, codegen.newParameters, body); | 145 buildJavaScriptFunction(work.element, codegen.newParameters, body); |
| 143 return prettyPrint(fun, work.element); | 146 return prettyPrint(fun); |
| 144 }); | 147 }); |
| 145 } | 148 } |
| 146 | 149 |
| 147 Map<Element, String> getParameterNames(WorkItem work) { | 150 Map<Element, String> getParameterNames(WorkItem work) { |
| 148 Map<Element, String> parameterNames = new LinkedHashMap<Element, String>(); | 151 Map<Element, String> parameterNames = new LinkedHashMap<Element, String>(); |
| 149 FunctionElement function = work.element; | 152 FunctionElement function = work.element; |
| 150 | 153 |
| 151 // The dom/html libraries have inline JS code that reference | 154 // The dom/html libraries have inline JS code that reference |
| 152 // parameter names directly. Long-term such code will be rejected. | 155 // parameter names directly. Long-term such code will be rejected. |
| 153 // Now, just don't mangle the parameter name. | 156 // Now, just don't mangle the parameter name. |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 | 334 |
| 332 js.Expression pop() { | 335 js.Expression pop() { |
| 333 return expressionStack.removeLast(); | 336 return expressionStack.removeLast(); |
| 334 } | 337 } |
| 335 | 338 |
| 336 attachLocationToLast(HInstruction instruction) { | 339 attachLocationToLast(HInstruction instruction) { |
| 337 attachLocation(expressionStack.last(), instruction); | 340 attachLocation(expressionStack.last(), instruction); |
| 338 } | 341 } |
| 339 | 342 |
| 340 js.Node attachLocation(js.Node jsNode, HInstruction instruction) { | 343 js.Node attachLocation(js.Node jsNode, HInstruction instruction) { |
| 341 if (instruction.sourcePosition !== null) { | 344 jsNode.sourcePosition = instruction.sourcePosition; |
| 342 jsNode.sourcePosition = instruction.sourcePosition; | |
| 343 } | |
| 344 return jsNode; | 345 return jsNode; |
| 345 } | 346 } |
| 346 | 347 |
| 347 js.Node attachLocationRange(js.Node jsNode, Node node) { | 348 js.Node attachLocationRange(js.Node jsNode, |
| 348 jsNode.sourcePosition = node.getBeginToken(); | 349 SourceFileLocation sourcePosition, |
| 349 jsNode.endSourcePosition = node.getEndToken(); | 350 SourceFileLocation endSourcePosition) { |
| 351 jsNode.sourcePosition = sourcePosition; | |
| 352 jsNode.endSourcePosition = endSourcePosition; | |
| 350 return jsNode; | 353 return jsNode; |
| 351 } | 354 } |
| 352 | 355 |
| 353 abstract visitTypeGuard(HTypeGuard node); | 356 abstract visitTypeGuard(HTypeGuard node); |
| 354 abstract visitBailoutTarget(HBailoutTarget node); | 357 abstract visitBailoutTarget(HBailoutTarget node); |
| 355 | 358 |
| 356 abstract beginGraph(HGraph graph); | 359 abstract beginGraph(HGraph graph); |
| 357 abstract endGraph(HGraph graph); | 360 abstract endGraph(HGraph graph); |
| 358 | 361 |
| 359 abstract beginLoop(HBasicBlock block); | 362 abstract beginLoop(HBasicBlock block); |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 923 currentContainer = oldContainer; | 926 currentContainer = oldContainer; |
| 924 body = unwrapStatement(body); | 927 body = unwrapStatement(body); |
| 925 loop = new js.Do(body, jsCondition); | 928 loop = new js.Do(body, jsCondition); |
| 926 break; | 929 break; |
| 927 } | 930 } |
| 928 default: | 931 default: |
| 929 compiler.internalError( | 932 compiler.internalError( |
| 930 'Unexpected loop kind: ${info.kind}', | 933 'Unexpected loop kind: ${info.kind}', |
| 931 instruction: condition.conditionExpression); | 934 instruction: condition.conditionExpression); |
| 932 } | 935 } |
| 933 attachLocationRange(loop, info.sourcePosition); | 936 attachLocationRange(loop, info.sourcePosition, info.endSourcePosition); |
| 934 pushStatement(wrapIntoLabels(loop, info.labels)); | 937 pushStatement(wrapIntoLabels(loop, info.labels)); |
| 935 return true; | 938 return true; |
| 936 } | 939 } |
| 937 | 940 |
| 938 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) { | 941 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) { |
| 939 preLabeledBlock(labeledBlockInfo); | 942 preLabeledBlock(labeledBlockInfo); |
| 940 Link<Element> continueOverrides = const EmptyLink<Element>(); | 943 Link<Element> continueOverrides = const EmptyLink<Element>(); |
| 941 | 944 |
| 942 js.Block oldContainer = currentContainer; | 945 js.Block oldContainer = currentContainer; |
| 943 js.Block body = new js.Block.empty(); | 946 js.Block body = new js.Block.empty(); |
| (...skipping 1634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2578 currentContainer = new js.Block.empty(); | 2581 currentContainer = new js.Block.empty(); |
| 2579 } | 2582 } |
| 2580 | 2583 |
| 2581 void endLoop(HBasicBlock block) { | 2584 void endLoop(HBasicBlock block) { |
| 2582 js.Statement body = currentContainer; | 2585 js.Statement body = currentContainer; |
| 2583 currentContainer = oldContainerStack.removeLast(); | 2586 currentContainer = oldContainerStack.removeLast(); |
| 2584 body = unwrapStatement(body); | 2587 body = unwrapStatement(body); |
| 2585 js.While loop = new js.While(new js.LiteralBool(true), body); | 2588 js.While loop = new js.While(new js.LiteralBool(true), body); |
| 2586 | 2589 |
| 2587 HLoopInformation info = block.loopInformation; | 2590 HLoopInformation info = block.loopInformation; |
| 2588 attachLocationRange(loop, info.loopBlockInformation.sourcePosition); | 2591 attachLocationRange(loop, |
| 2592 info.loopBlockInformation.sourcePosition, | |
| 2593 info.loopBlockInformation.endSourcePosition); | |
| 2589 pushStatement(wrapIntoLabels(loop, info.labels)); | 2594 pushStatement(wrapIntoLabels(loop, info.labels)); |
| 2590 } | 2595 } |
| 2591 | 2596 |
| 2592 void handleLoopCondition(HLoopBranch node) { | 2597 void handleLoopCondition(HLoopBranch node) { |
| 2593 use(node.inputs[0]); | 2598 use(node.inputs[0]); |
| 2594 pushStatement(new js.If.noElse(pop(), new js.Break(null)), node); | 2599 pushStatement(new js.If.noElse(pop(), new js.Break(null)), node); |
| 2595 } | 2600 } |
| 2596 | 2601 |
| 2597 | 2602 |
| 2598 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2603 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2832 HLoopInformation info = header.loopInformation; | 2837 HLoopInformation info = header.loopInformation; |
| 2833 if (header.hasBailoutTargets()) { | 2838 if (header.hasBailoutTargets()) { |
| 2834 endBailoutSwitch(); | 2839 endBailoutSwitch(); |
| 2835 if (info.target != null) breakAction.remove(info.target); | 2840 if (info.target != null) breakAction.remove(info.target); |
| 2836 } | 2841 } |
| 2837 | 2842 |
| 2838 js.Statement body = unwrapStatement(currentContainer); | 2843 js.Statement body = unwrapStatement(currentContainer); |
| 2839 currentContainer = oldContainerStack.removeLast(); | 2844 currentContainer = oldContainerStack.removeLast(); |
| 2840 | 2845 |
| 2841 js.Statement result = new js.While(new js.LiteralBool(true), body); | 2846 js.Statement result = new js.While(new js.LiteralBool(true), body); |
| 2842 attachLocationRange(result, info.loopBlockInformation.sourcePosition); | 2847 attachLocationRange(result, |
| 2848 info.loopBlockInformation.sourcePosition, | |
| 2849 info.loopBlockInformation.endSourcePosition); | |
| 2843 result = new js.LabeledStatement(loopLabel, result); | 2850 result = new js.LabeledStatement(loopLabel, result); |
| 2844 result = wrapIntoLabels(result, info.labels); | 2851 result = wrapIntoLabels(result, info.labels); |
| 2845 pushStatement(result); | 2852 pushStatement(result); |
| 2846 } | 2853 } |
| 2847 | 2854 |
| 2848 void handleLoopCondition(HLoopBranch node) { | 2855 void handleLoopCondition(HLoopBranch node) { |
| 2849 use(node.inputs[0]); | 2856 use(node.inputs[0]); |
| 2850 js.Expression test = new js.Prefix('!', pop()); | 2857 js.Expression test = new js.Prefix('!', pop()); |
| 2851 js.Statement then = new js.Break(currentLabel()); | 2858 js.Statement then = new js.Break(currentLabel()); |
| 2852 pushStatement(new js.If.noElse(test, then), node); | 2859 pushStatement(new js.If.noElse(test, then), node); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2934 if (leftType.canBeNull() && rightType.canBeNull()) { | 2941 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 2935 if (left.isConstantNull() || right.isConstantNull() || | 2942 if (left.isConstantNull() || right.isConstantNull() || |
| 2936 (leftType.isPrimitive() && leftType == rightType)) { | 2943 (leftType.isPrimitive() && leftType == rightType)) { |
| 2937 return '=='; | 2944 return '=='; |
| 2938 } | 2945 } |
| 2939 return null; | 2946 return null; |
| 2940 } else { | 2947 } else { |
| 2941 return '==='; | 2948 return '==='; |
| 2942 } | 2949 } |
| 2943 } | 2950 } |
| OLD | NEW |