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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class SsaCodeGeneratorTask extends CompilerTask { | 7 class SsaCodeGeneratorTask extends CompilerTask { |
| 8 | 8 |
| 9 final JavaScriptBackend backend; | 9 final JavaScriptBackend backend; |
| 10 | 10 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 Token endToken; | 24 Token endToken; |
| 25 if (expression == null) { | 25 if (expression == null) { |
| 26 // Synthesized node. Use the enclosing element for the location. | 26 // Synthesized node. Use the enclosing element for the location. |
| 27 beginToken = endToken = element.position(); | 27 beginToken = endToken = element.position(); |
| 28 } else { | 28 } else { |
| 29 beginToken = expression.getBeginToken(); | 29 beginToken = expression.getBeginToken(); |
| 30 endToken = expression.getEndToken(); | 30 endToken = expression.getEndToken(); |
| 31 } | 31 } |
| 32 // TODO(podivilov): find the right sourceFile here and remove offset | 32 // TODO(podivilov): find the right sourceFile here and remove offset |
| 33 // checks below. | 33 // checks below. |
| 34 var sourcePosition, endSourcePosition; | |
| 34 if (beginToken.charOffset < sourceFile.length) { | 35 if (beginToken.charOffset < sourceFile.length) { |
| 35 node.sourcePosition = | 36 sourcePosition = new TokenSourceFileLocation(sourceFile, beginToken); |
| 36 new TokenSourceFileLocation(sourceFile, beginToken); | |
| 37 } | 37 } |
| 38 if (endToken.charOffset < sourceFile.length) { | 38 if (endToken.charOffset < sourceFile.length) { |
| 39 node.endSourcePosition = | 39 endSourcePosition = new TokenSourceFileLocation(sourceFile, endToken); |
| 40 new TokenSourceFileLocation(sourceFile, endToken); | |
| 41 } | 40 } |
| 42 return node; | 41 return node.withPosition(sourcePosition, endSourcePosition); |
| 43 } | 42 } |
| 44 | 43 |
| 45 SourceFile sourceFileOfElement(Element element) { | 44 SourceFile sourceFileOfElement(Element element) { |
| 46 // TODO(johnniwinther): remove the 'element.patch' hack. | 45 // TODO(johnniwinther): remove the 'element.patch' hack. |
| 47 FunctionElement functionElement = element.asFunctionElement(); | 46 FunctionElement functionElement = element.asFunctionElement(); |
| 48 if (functionElement != null && functionElement.patch != null) { | 47 if (functionElement != null && functionElement.patch != null) { |
| 49 element = functionElement.patch; | 48 element = functionElement.patch; |
| 50 } | 49 } |
| 51 return element.getCompilationUnit().script.file; | 50 return element.getCompilationUnit().script.file; |
| 52 } | 51 } |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 197 return hasNonBitOpUser(instruction, new Set<HPhi>()); | 196 return hasNonBitOpUser(instruction, new Set<HPhi>()); |
| 198 } | 197 } |
| 199 | 198 |
| 200 /** | 199 /** |
| 201 * If the [instruction] is not `null` it will be used to attach the position | 200 * If the [instruction] is not `null` it will be used to attach the position |
| 202 * to the [statement]. | 201 * to the [statement]. |
| 203 */ | 202 */ |
| 204 void pushStatement(js.Statement statement, [HInstruction instruction]) { | 203 void pushStatement(js.Statement statement, [HInstruction instruction]) { |
| 205 assert(expressionStack.isEmpty); | 204 assert(expressionStack.isEmpty); |
| 206 if (instruction != null) { | 205 if (instruction != null) { |
| 207 attachLocation(statement, instruction); | 206 statement = attachLocation(statement, instruction); |
| 208 } | 207 } |
| 209 currentContainer.statements.add(statement); | 208 currentContainer.statements.add(statement); |
| 210 } | 209 } |
| 211 | 210 |
| 212 void insertStatementAtStart(js.Statement statement) { | 211 void insertStatementAtStart(js.Statement statement) { |
| 213 currentContainer.statements.insert(0, statement); | 212 currentContainer.statements.insert(0, statement); |
| 214 } | 213 } |
| 215 | 214 |
| 216 /** | 215 /** |
| 217 * If the [instruction] is not `null` it will be used to attach the position | 216 * If the [instruction] is not `null` it will be used to attach the position |
| 218 * to the [expression]. | 217 * to the [expression]. |
| 219 */ | 218 */ |
| 220 pushExpressionAsStatement(js.Expression expression, | 219 pushExpressionAsStatement(js.Expression expression, |
| 221 [HInstruction instruction]) { | 220 [HInstruction instruction]) { |
| 222 pushStatement(new js.ExpressionStatement(expression), instruction); | 221 pushStatement(new js.ExpressionStatement(expression), instruction); |
| 223 } | 222 } |
| 224 | 223 |
| 225 /** | 224 /** |
| 226 * If the [instruction] is not `null` it will be used to attach the position | 225 * If the [instruction] is not `null` it will be used to attach the position |
| 227 * to the [expression]. | 226 * to the [expression]. |
| 228 */ | 227 */ |
| 229 push(js.Expression expression, [HInstruction instruction]) { | 228 push(js.Expression expression, [HInstruction instruction]) { |
| 230 if (instruction != null) { | 229 if (instruction != null) { |
| 231 attachLocation(expression, instruction); | 230 expression = attachLocation(expression, instruction); |
| 232 } | 231 } |
| 233 expressionStack.add(expression); | 232 expressionStack.add(expression); |
| 234 } | 233 } |
| 235 | 234 |
| 236 js.Expression pop() { | 235 js.Expression pop() { |
| 237 return expressionStack.removeLast(); | 236 return expressionStack.removeLast(); |
| 238 } | 237 } |
| 239 | 238 |
| 240 attachLocationToLast(HInstruction instruction) { | 239 attachLocationToLast(HInstruction instruction) { |
| 241 attachLocation(expressionStack.last, instruction); | 240 int index = expressionStack.length - 1; |
| 241 expressionStack[index] = | |
| 242 attachLocation(expressionStack[index], instruction); | |
| 242 } | 243 } |
| 243 | 244 |
| 244 js.Node attachLocation(js.Node jsNode, HInstruction instruction) { | 245 js.Node attachLocation(js.Node jsNode, HInstruction instruction) { |
| 245 jsNode.sourcePosition = instruction.sourcePosition; | 246 return jsNode.withLocation(instruction.sourcePosition); |
| 246 return jsNode; | |
| 247 } | 247 } |
| 248 | 248 |
| 249 js.Node attachLocationRange(js.Node jsNode, | 249 js.Node attachLocationRange(js.Node jsNode, |
| 250 SourceFileLocation sourcePosition, | 250 SourceFileLocation sourcePosition, |
| 251 SourceFileLocation endSourcePosition) { | 251 SourceFileLocation endSourcePosition) { |
| 252 jsNode.sourcePosition = sourcePosition; | 252 return jsNode.withPosition(sourcePosition, endSourcePosition); |
| 253 jsNode.endSourcePosition = endSourcePosition; | |
| 254 return jsNode; | |
| 255 } | 253 } |
| 256 | 254 |
| 257 void preGenerateMethod(HGraph graph) { | 255 void preGenerateMethod(HGraph graph) { |
| 258 new SsaInstructionSelection(compiler).visitGraph(graph); | 256 new SsaInstructionSelection(compiler).visitGraph(graph); |
| 259 new SsaTypeKnownRemover().visitGraph(graph); | 257 new SsaTypeKnownRemover().visitGraph(graph); |
| 260 new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph); | 258 new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph); |
| 261 new SsaConditionMerger( | 259 new SsaConditionMerger( |
| 262 generateAtUseSite, controlFlowOperators).visitGraph(graph); | 260 generateAtUseSite, controlFlowOperators).visitGraph(graph); |
| 263 SsaLiveIntervalBuilder intervalBuilder = new SsaLiveIntervalBuilder( | 261 SsaLiveIntervalBuilder intervalBuilder = new SsaLiveIntervalBuilder( |
| 264 compiler, generateAtUseSite, controlFlowOperators); | 262 compiler, generateAtUseSite, controlFlowOperators); |
| (...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 913 jsCondition = newLiteralBool(true); | 911 jsCondition = newLiteralBool(true); |
| 914 } | 912 } |
| 915 loop = new js.Do(unwrapStatement(body), jsCondition); | 913 loop = new js.Do(unwrapStatement(body), jsCondition); |
| 916 } | 914 } |
| 917 currentContainer = oldContainer; | 915 currentContainer = oldContainer; |
| 918 break; | 916 break; |
| 919 default: | 917 default: |
| 920 compiler.internalError(condition.conditionExpression, | 918 compiler.internalError(condition.conditionExpression, |
| 921 'Unexpected loop kind: ${info.kind}.'); | 919 'Unexpected loop kind: ${info.kind}.'); |
| 922 } | 920 } |
| 923 attachLocationRange(loop, info.sourcePosition, info.endSourcePosition); | 921 loop = attachLocationRange(loop, info.sourcePosition, info.endSourcePosition ); |
|
floitsch
2014/04/28 12:28:11
long line.
sra1
2014/04/28 18:24:09
Done.
| |
| 924 js.Statement result = loop; | 922 js.Statement result = loop; |
| 925 if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) { | 923 if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) { |
| 926 String continueLabelString = | 924 String continueLabelString = |
| 927 backend.namer.implicitContinueLabelName(info.target); | 925 backend.namer.implicitContinueLabelName(info.target); |
| 928 result = new js.LabeledStatement(continueLabelString, result); | 926 result = new js.LabeledStatement(continueLabelString, result); |
| 929 } | 927 } |
| 930 pushStatement(wrapIntoLabels(result, info.labels)); | 928 pushStatement(wrapIntoLabels(result, info.labels)); |
| 931 return true; | 929 return true; |
| 932 } | 930 } |
| 933 | 931 |
| (...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1994 argument.forEach((instruction) { | 1992 argument.forEach((instruction) { |
| 1995 use(instruction); | 1993 use(instruction); |
| 1996 arguments.add(pop()); | 1994 arguments.add(pop()); |
| 1997 }); | 1995 }); |
| 1998 } else { | 1996 } else { |
| 1999 location = argument; | 1997 location = argument; |
| 2000 use(argument); | 1998 use(argument); |
| 2001 arguments.add(pop()); | 1999 arguments.add(pop()); |
| 2002 } | 2000 } |
| 2003 js.Call value = new js.Call(jsHelper, arguments); | 2001 js.Call value = new js.Call(jsHelper, arguments); |
| 2004 attachLocation(value, location); | 2002 value = attachLocation(value, location); |
| 2005 // BUG(4906): Using throw/return here adds to the size of the generated code | 2003 // BUG(4906): Using throw/return here adds to the size of the generated code |
| 2006 // but it has the advantage of explicitly telling the JS engine that | 2004 // but it has the advantage of explicitly telling the JS engine that |
| 2007 // this code path will terminate abruptly. Needs more work. | 2005 // this code path will terminate abruptly. Needs more work. |
| 2008 if (helperName == 'wrapException') { | 2006 if (helperName == 'wrapException') { |
| 2009 pushStatement(new js.Throw(value)); | 2007 pushStatement(new js.Throw(value)); |
| 2010 } else { | 2008 } else { |
| 2011 pushStatement(new js.Return(value)); | 2009 pushStatement(new js.Return(value)); |
| 2012 } | 2010 } |
| 2013 } | 2011 } |
| 2014 | 2012 |
| 2015 visitThrowExpression(HThrowExpression node) { | 2013 visitThrowExpression(HThrowExpression node) { |
| 2016 HInstruction argument = node.inputs[0]; | 2014 HInstruction argument = node.inputs[0]; |
| 2017 use(argument); | 2015 use(argument); |
| 2018 | 2016 |
| 2019 Element helper = compiler.findHelper("throwExpression"); | 2017 Element helper = compiler.findHelper("throwExpression"); |
| 2020 world.registerStaticUse(helper); | 2018 world.registerStaticUse(helper); |
| 2021 | 2019 |
| 2022 js.VariableUse jsHelper = | 2020 js.VariableUse jsHelper = |
| 2023 new js.VariableUse(backend.namer.isolateAccess(helper)); | 2021 new js.VariableUse(backend.namer.isolateAccess(helper)); |
| 2024 js.Call value = new js.Call(jsHelper, [pop()]); | 2022 js.Call value = new js.Call(jsHelper, [pop()]); |
| 2025 attachLocation(value, argument); | 2023 value = attachLocation(value, argument); |
| 2026 push(value, node); | 2024 push(value, node); |
| 2027 } | 2025 } |
| 2028 | 2026 |
| 2029 void visitSwitch(HSwitch node) { | 2027 void visitSwitch(HSwitch node) { |
| 2030 // Switches are handled using [visitSwitchInfo]. | 2028 // Switches are handled using [visitSwitchInfo]. |
| 2031 } | 2029 } |
| 2032 | 2030 |
| 2033 void visitStatic(HStatic node) { | 2031 void visitStatic(HStatic node) { |
| 2034 Element element = node.element; | 2032 Element element = node.element; |
| 2035 if (element.isFunction()) { | 2033 if (element.isFunction()) { |
| (...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2683 js.PropertyAccess accessHelper(String name) { | 2681 js.PropertyAccess accessHelper(String name) { |
| 2684 Element helper = compiler.findHelper(name); | 2682 Element helper = compiler.findHelper(name); |
| 2685 if (helper == null) { | 2683 if (helper == null) { |
| 2686 // For mocked-up tests. | 2684 // For mocked-up tests. |
| 2687 return js.js('(void 0).$name'); | 2685 return js.js('(void 0).$name'); |
| 2688 } | 2686 } |
| 2689 world.registerStaticUse(helper); | 2687 world.registerStaticUse(helper); |
| 2690 return backend.namer.elementAccess(helper); | 2688 return backend.namer.elementAccess(helper); |
| 2691 } | 2689 } |
| 2692 } | 2690 } |
| OLD | NEW |