| 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 final JavaScriptBackend backend; | 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); |
| 7 SsaCodeGeneratorTask(JavaScriptBackend backend) | |
| 8 : this.backend = backend, | |
| 9 super(backend.compiler); | |
| 10 String get name() => 'SSA code generator'; | 7 String get name() => 'SSA code generator'; |
| 11 NativeEmitter get nativeEmitter() => backend.emitter.nativeEmitter; | |
| 12 | 8 |
| 13 | 9 |
| 14 String buildJavaScriptFunction(FunctionElement element, | 10 String buildJavaScriptFunction(FunctionElement element, |
| 15 String parameters, | 11 String parameters, |
| 16 String body) { | 12 String body) { |
| 17 String extraSpace = ""; | 13 String extraSpace = ""; |
| 18 // Members are emitted inside a JavaScript object literal. To line up the | 14 // Members are emitted inside a JavaScript object literal. To line up the |
| 19 // indentation we want the closing curly brace to be indented by one space. | 15 // indentation we want the closing curly brace to be indented by one space. |
| 20 // Example: | 16 // Example: |
| 21 // defineClass("A", "B", ... , { | 17 // defineClass("A", "B", ... , { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 34 } | 30 } |
| 35 return 'function($parameters) {\n$body$extraSpace}'; | 31 return 'function($parameters) {\n$body$extraSpace}'; |
| 36 } | 32 } |
| 37 | 33 |
| 38 String generateMethod(WorkItem work, HGraph graph) { | 34 String generateMethod(WorkItem work, HGraph graph) { |
| 39 return measure(() { | 35 return measure(() { |
| 40 compiler.tracer.traceGraph("codegen", graph); | 36 compiler.tracer.traceGraph("codegen", graph); |
| 41 Map<Element, String> parameterNames = getParameterNames(work); | 37 Map<Element, String> parameterNames = getParameterNames(work); |
| 42 String parameters = Strings.join(parameterNames.getValues(), ', '); | 38 String parameters = Strings.join(parameterNames.getValues(), ', '); |
| 43 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( | 39 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( |
| 44 backend, work, parameters, parameterNames); | 40 compiler, work, parameters, parameterNames); |
| 45 codegen.visitGraph(graph); | 41 codegen.visitGraph(graph); |
| 46 | 42 |
| 47 FunctionElement element = work.element; | 43 FunctionElement element = work.element; |
| 48 String code; | 44 String code; |
| 49 if (element.isInstanceMember() | 45 if (element.isInstanceMember() |
| 50 && element.enclosingElement.isClass() | 46 && element.enclosingElement.isClass() |
| 51 && element.enclosingElement.isNative() | 47 && element.enclosingElement.isNative() |
| 52 && native.isOverriddenMethod( | 48 && native.isOverriddenMethod(element, |
| 53 element, element.enclosingElement, nativeEmitter)) { | 49 element.enclosingElement, |
| 50 compiler.emitter.nativeEmitter)) { |
| 54 // Record that this method is overridden. In case of optional | 51 // Record that this method is overridden. In case of optional |
| 55 // arguments, the emitter will generate stubs to handle them, | 52 // arguments, the emitter will generate stubs to handle them, |
| 56 // and needs to know if the method is overridden. | 53 // and needs to know if the method is overridden. |
| 57 nativeEmitter.overriddenMethods.add(element); | 54 compiler.emitter.nativeEmitter.overriddenMethods.add(element); |
| 58 StringBuffer buffer = new StringBuffer(); | 55 StringBuffer buffer = new StringBuffer(); |
| 59 native.generateMethodWithPrototypeCheckForElement( | 56 native.generateMethodWithPrototypeCheckForElement( |
| 60 compiler, buffer, element, '${codegen.buffer}', parameters); | 57 compiler, buffer, element, '${codegen.buffer}', parameters); |
| 61 code = buffer.toString(); | 58 code = buffer.toString(); |
| 62 } else { | 59 } else { |
| 63 code = codegen.buffer.toString(); | 60 code = codegen.buffer.toString(); |
| 64 } | 61 } |
| 65 return buildJavaScriptFunction(element, parameters, code); | 62 return buildJavaScriptFunction(element, parameters, code); |
| 66 }); | 63 }); |
| 67 } | 64 } |
| 68 | 65 |
| 69 String generateBailoutMethod(WorkItem work, HGraph graph) { | 66 String generateBailoutMethod(WorkItem work, HGraph graph) { |
| 70 return measure(() { | 67 return measure(() { |
| 71 compiler.tracer.traceGraph("codegen-bailout", graph); | 68 compiler.tracer.traceGraph("codegen-bailout", graph); |
| 72 new SsaBailoutPropagator(compiler).visitGraph(graph); | 69 new SsaBailoutPropagator(compiler).visitGraph(graph); |
| 73 | 70 |
| 74 Map<Element, String> parameterNames = getParameterNames(work); | 71 Map<Element, String> parameterNames = getParameterNames(work); |
| 75 String parameters = Strings.join(parameterNames.getValues(), ', '); | 72 String parameters = Strings.join(parameterNames.getValues(), ', '); |
| 76 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator( | 73 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator( |
| 77 backend, work, parameters, parameterNames); | 74 compiler, work, parameters, parameterNames); |
| 78 codegen.visitGraph(graph); | 75 codegen.visitGraph(graph); |
| 79 | 76 |
| 80 StringBuffer newParameters = new StringBuffer(); | 77 StringBuffer newParameters = new StringBuffer(); |
| 81 if (!parameterNames.isEmpty()) newParameters.add('$parameters, '); | 78 if (!parameterNames.isEmpty()) newParameters.add('$parameters, '); |
| 82 newParameters.add('state'); | 79 newParameters.add('state'); |
| 83 | 80 |
| 84 for (int i = 0; i < codegen.maxBailoutParameters; i++) { | 81 for (int i = 0; i < codegen.maxBailoutParameters; i++) { |
| 85 newParameters.add(', env$i'); | 82 newParameters.add(', env$i'); |
| 86 } | 83 } |
| 87 | 84 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 * expression, and that it only generates expressions of the form | 130 * expression, and that it only generates expressions of the form |
| 134 * variable = expression | 131 * variable = expression |
| 135 * which are also valid as parts of a "var" declaration. | 132 * which are also valid as parts of a "var" declaration. |
| 136 */ | 133 */ |
| 137 static final int TYPE_STATEMENT = 0; | 134 static final int TYPE_STATEMENT = 0; |
| 138 static final int TYPE_EXPRESSION = 1; | 135 static final int TYPE_EXPRESSION = 1; |
| 139 static final int TYPE_DECLARATION = 2; | 136 static final int TYPE_DECLARATION = 2; |
| 140 | 137 |
| 141 static final String TEMPORARY_PREFIX = 't'; | 138 static final String TEMPORARY_PREFIX = 't'; |
| 142 | 139 |
| 143 final JavaScriptBackend backend; | 140 final Compiler compiler; |
| 144 final WorkItem work; | 141 final WorkItem work; |
| 145 final StringBuffer buffer; | 142 final StringBuffer buffer; |
| 146 final String parameters; | 143 final String parameters; |
| 147 | 144 |
| 148 final Map<Element, String> parameterNames; | 145 final Map<Element, String> parameterNames; |
| 149 final Map<int, String> names; | 146 final Map<int, String> names; |
| 150 final Set<String> usedNames; | 147 final Set<String> usedNames; |
| 151 final Set<HInstruction> declaredInstructions; | 148 final Set<HInstruction> declaredInstructions; |
| 152 final Map<String, int> prefixes; | 149 final Map<String, int> prefixes; |
| 153 final Set<HInstruction> generateAtUseSite; | 150 final Set<HInstruction> generateAtUseSite; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 175 HBasicBlock currentBlock; | 172 HBasicBlock currentBlock; |
| 176 | 173 |
| 177 // Records a block-information that is being handled specially. | 174 // Records a block-information that is being handled specially. |
| 178 // Used to break bad recursion. | 175 // Used to break bad recursion. |
| 179 HBlockInformation currentBlockInformation; | 176 HBlockInformation currentBlockInformation; |
| 180 // The subgraph is used to delimit traversal for some constructions, e.g., | 177 // The subgraph is used to delimit traversal for some constructions, e.g., |
| 181 // if branches. | 178 // if branches. |
| 182 SubGraph subGraph; | 179 SubGraph subGraph; |
| 183 | 180 |
| 184 LibraryElement get currentLibrary() => work.element.getLibrary(); | 181 LibraryElement get currentLibrary() => work.element.getLibrary(); |
| 185 Compiler get compiler() => backend.compiler; | |
| 186 | 182 |
| 187 bool isGenerateAtUseSite(HInstruction instruction) { | 183 bool isGenerateAtUseSite(HInstruction instruction) { |
| 188 return generateAtUseSite.contains(instruction); | 184 return generateAtUseSite.contains(instruction); |
| 189 } | 185 } |
| 190 | 186 |
| 191 SsaCodeGenerator(this.backend, | 187 SsaCodeGenerator(this.compiler, |
| 192 this.work, | 188 this.work, |
| 193 this.parameters, | 189 this.parameters, |
| 194 this.parameterNames) | 190 this.parameterNames) |
| 195 : names = new Map<int, String>(), | 191 : names = new Map<int, String>(), |
| 196 prefixes = new Map<String, int>(), | 192 prefixes = new Map<String, int>(), |
| 197 usedNames = new Set<String>(), | 193 usedNames = new Set<String>(), |
| 198 declaredInstructions = new Set<HInstruction>(), | 194 declaredInstructions = new Set<HInstruction>(), |
| 199 buffer = new StringBuffer(), | 195 buffer = new StringBuffer(), |
| 200 generateAtUseSite = new Set<HInstruction>(), | 196 generateAtUseSite = new Set<HInstruction>(), |
| 201 logicalOperations = new Map<HPhi, String>(), | 197 logicalOperations = new Map<HPhi, String>(), |
| 202 breakAction = new Map<Element, ElementAction>(), | 198 breakAction = new Map<Element, ElementAction>(), |
| 203 continueAction = new Map<Element, ElementAction>(), | 199 continueAction = new Map<Element, ElementAction>(), |
| 204 phiEquivalence = new Equivalence<HPhi>(), | 200 phiEquivalence = new Equivalence<HPhi>(), |
| 205 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { | 201 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { |
| 206 | 202 |
| 207 for (final name in parameterNames.getValues()) { | 203 for (final name in parameterNames.getValues()) { |
| 208 prefixes[name] = 0; | 204 prefixes[name] = 0; |
| 209 } | 205 } |
| 210 | 206 |
| 211 // Create a namespace for temporaries. | 207 // Create a namespace for temporaries. |
| 212 prefixes[TEMPORARY_PREFIX] = 0; | 208 prefixes[TEMPORARY_PREFIX] = 0; |
| 213 | 209 |
| 214 Interceptors interceptors = backend.builder.interceptors; | 210 Interceptors interceptors = compiler.builder.interceptors; |
| 215 equalsNullElement = interceptors.getEqualsNullInterceptor(); | 211 equalsNullElement = interceptors.getEqualsNullInterceptor(); |
| 216 boolifiedEqualsNullElement = | 212 boolifiedEqualsNullElement = |
| 217 interceptors.getBoolifiedVersionOf(equalsNullElement); | 213 interceptors.getBoolifiedVersionOf(equalsNullElement); |
| 218 } | 214 } |
| 219 | 215 |
| 220 abstract visitTypeGuard(HTypeGuard node); | 216 abstract visitTypeGuard(HTypeGuard node); |
| 221 | 217 |
| 222 abstract beginGraph(HGraph graph); | 218 abstract beginGraph(HGraph graph); |
| 223 abstract endGraph(HGraph graph); | 219 abstract endGraph(HGraph graph); |
| 224 | 220 |
| (...skipping 1822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2047 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2043 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| 2048 checkObject(input, '==='); | 2044 checkObject(input, '==='); |
| 2049 buffer.add(" && "); | 2045 buffer.add(" && "); |
| 2050 checkType(input, element); | 2046 checkType(input, element); |
| 2051 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2047 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| 2052 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2048 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); |
| 2053 } | 2049 } |
| 2054 | 2050 |
| 2055 void checkType(HInstruction input, Element element) { | 2051 void checkType(HInstruction input, Element element) { |
| 2056 bool requiresNativeIsCheck = | 2052 bool requiresNativeIsCheck = |
| 2057 backend.emitter.nativeEmitter.requiresNativeIsCheck(element); | 2053 compiler.emitter.nativeEmitter.requiresNativeIsCheck(element); |
| 2058 if (!requiresNativeIsCheck) buffer.add('!!'); | 2054 if (!requiresNativeIsCheck) buffer.add('!!'); |
| 2059 use(input, JSPrecedence.MEMBER_PRECEDENCE); | 2055 use(input, JSPrecedence.MEMBER_PRECEDENCE); |
| 2060 buffer.add('.'); | 2056 buffer.add('.'); |
| 2061 buffer.add(compiler.namer.operatorIs(element)); | 2057 buffer.add(compiler.namer.operatorIs(element)); |
| 2062 if (requiresNativeIsCheck) buffer.add('()'); | 2058 if (requiresNativeIsCheck) buffer.add('()'); |
| 2063 } | 2059 } |
| 2064 | 2060 |
| 2065 void handleStringSupertypeCheck(HInstruction input, Element element) { | 2061 void handleStringSupertypeCheck(HInstruction input, Element element) { |
| 2066 // Make sure List and String don't share supertypes, otherwise we | 2062 // Make sure List and String don't share supertypes, otherwise we |
| 2067 // would need to check for List too. | 2063 // would need to check for List too. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2166 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2162 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); |
| 2167 } | 2163 } |
| 2168 } | 2164 } |
| 2169 | 2165 |
| 2170 void visitTypeConversion(HTypeConversion node) { | 2166 void visitTypeConversion(HTypeConversion node) { |
| 2171 if (node.checked) { | 2167 if (node.checked) { |
| 2172 Element element = node.type.computeType(compiler).element; | 2168 Element element = node.type.computeType(compiler).element; |
| 2173 compiler.registerIsCheck(element); | 2169 compiler.registerIsCheck(element); |
| 2174 SourceString helper; | 2170 SourceString helper; |
| 2175 String additionalArgument; | 2171 String additionalArgument; |
| 2176 bool nativeCheck = nativeEmitter.requiresNativeIsCheck(element); | 2172 bool nativeCheck = |
| 2173 compiler.emitter.nativeEmitter.requiresNativeIsCheck(element); |
| 2177 beginExpression(JSPrecedence.CALL_PRECEDENCE); | 2174 beginExpression(JSPrecedence.CALL_PRECEDENCE); |
| 2178 | 2175 |
| 2179 if (element == compiler.stringClass) { | 2176 if (element == compiler.stringClass) { |
| 2180 helper = const SourceString('stringTypeCheck'); | 2177 helper = const SourceString('stringTypeCheck'); |
| 2181 } else if (element == compiler.doubleClass) { | 2178 } else if (element == compiler.doubleClass) { |
| 2182 helper = const SourceString('doubleTypeCheck'); | 2179 helper = const SourceString('doubleTypeCheck'); |
| 2183 } else if (element == compiler.numClass) { | 2180 } else if (element == compiler.numClass) { |
| 2184 helper = const SourceString('numTypeCheck'); | 2181 helper = const SourceString('numTypeCheck'); |
| 2185 } else if (element == compiler.boolClass) { | 2182 } else if (element == compiler.boolClass) { |
| 2186 helper = const SourceString('boolTypeCheck'); | 2183 helper = const SourceString('boolTypeCheck'); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2218 if (additionalArgument !== null) buffer.add(", '$additionalArgument'"); | 2215 if (additionalArgument !== null) buffer.add(", '$additionalArgument'"); |
| 2219 buffer.add(')'); | 2216 buffer.add(')'); |
| 2220 endExpression(JSPrecedence.CALL_PRECEDENCE); | 2217 endExpression(JSPrecedence.CALL_PRECEDENCE); |
| 2221 } else { | 2218 } else { |
| 2222 use(node.checkedInput, expectedPrecedence); | 2219 use(node.checkedInput, expectedPrecedence); |
| 2223 } | 2220 } |
| 2224 } | 2221 } |
| 2225 } | 2222 } |
| 2226 | 2223 |
| 2227 class SsaOptimizedCodeGenerator extends SsaCodeGenerator { | 2224 class SsaOptimizedCodeGenerator extends SsaCodeGenerator { |
| 2228 SsaOptimizedCodeGenerator(backend, work, parameters, parameterNames) | 2225 SsaOptimizedCodeGenerator(compiler, work, parameters, parameterNames) |
| 2229 : super(backend, work, parameters, parameterNames); | 2226 : super(compiler, work, parameters, parameterNames); |
| 2230 | 2227 |
| 2231 void beginGraph(HGraph graph) {} | 2228 void beginGraph(HGraph graph) {} |
| 2232 void endGraph(HGraph graph) {} | 2229 void endGraph(HGraph graph) {} |
| 2233 | 2230 |
| 2234 void bailout(HTypeGuard guard, String reason) { | 2231 void bailout(HTypeGuard guard, String reason) { |
| 2235 HInstruction input = guard.guarded; | 2232 HInstruction input = guard.guarded; |
| 2236 Namer namer = compiler.namer; | 2233 Namer namer = compiler.namer; |
| 2237 Element element = work.element; | 2234 Element element = work.element; |
| 2238 buffer.add('return '); | 2235 buffer.add('return '); |
| 2239 if (element.isInstanceMember()) { | 2236 if (element.isInstanceMember()) { |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2387 } | 2384 } |
| 2388 } | 2385 } |
| 2389 | 2386 |
| 2390 class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { | 2387 class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { |
| 2391 | 2388 |
| 2392 final StringBuffer setup; | 2389 final StringBuffer setup; |
| 2393 final List<String> labels; | 2390 final List<String> labels; |
| 2394 int labelId = 0; | 2391 int labelId = 0; |
| 2395 int maxBailoutParameters = 0; | 2392 int maxBailoutParameters = 0; |
| 2396 | 2393 |
| 2397 SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames) | 2394 SsaUnoptimizedCodeGenerator(compiler, work, parameters, parameterNames) |
| 2398 : super(backend, work, parameters, parameterNames), | 2395 : super(compiler, work, parameters, parameterNames), |
| 2399 setup = new StringBuffer(), | 2396 setup = new StringBuffer(), |
| 2400 labels = <String>[]; | 2397 labels = <String>[]; |
| 2401 | 2398 |
| 2402 String pushLabel() { | 2399 String pushLabel() { |
| 2403 String label = 'L${labelId++}'; | 2400 String label = 'L${labelId++}'; |
| 2404 labels.addLast(label); | 2401 labels.addLast(label); |
| 2405 return label; | 2402 return label; |
| 2406 } | 2403 } |
| 2407 | 2404 |
| 2408 String popLabel() { | 2405 String popLabel() { |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2620 startBailoutSwitch(); | 2617 startBailoutSwitch(); |
| 2621 } | 2618 } |
| 2622 } | 2619 } |
| 2623 | 2620 |
| 2624 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2621 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2625 if (labeledBlockInfo.body.start.hasGuards()) { | 2622 if (labeledBlockInfo.body.start.hasGuards()) { |
| 2626 endBailoutSwitch(); | 2623 endBailoutSwitch(); |
| 2627 } | 2624 } |
| 2628 } | 2625 } |
| 2629 } | 2626 } |
| OLD | NEW |