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 js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 7 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 8 final Set<HInstruction> boundsChecked; | 8 final Set<HInstruction> boundsChecked; |
| 9 | 9 |
| 10 JavaScriptItemCompilationContext() | 10 JavaScriptItemCompilationContext() |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 List<jsAst.Expression> arguments) { | 115 List<jsAst.Expression> arguments) { |
| 116 DartType type = node.typeExpression; | 116 DartType type = node.typeExpression; |
| 117 assert(type.isMalformed); | 117 assert(type.isMalformed); |
| 118 String reasons = Types.fetchReasonsFromMalformedType(type); | 118 String reasons = Types.fetchReasonsFromMalformedType(type); |
| 119 arguments.add(js.string('$type')); | 119 arguments.add(js.string('$type')); |
| 120 // TODO(johnniwinther): Handle escaping correctly. | 120 // TODO(johnniwinther): Handle escaping correctly. |
| 121 arguments.add(js.string(reasons)); | 121 arguments.add(js.string(reasons)); |
| 122 } | 122 } |
| 123 } | 123 } |
| 124 | 124 |
| 125 /* | |
| 126 * Invariants: | |
| 127 * canInline(function) implies canInline(function, insideLoop:true) | |
| 128 * !canInline(function, insideLoop: true) implies !canInline(function) | |
| 129 */ | |
| 130 class FunctionInlineCache { | |
| 131 final Map<FunctionElement, bool> canBeInlined = | |
| 132 new Map<FunctionElement, bool>(); | |
| 133 | |
| 134 final Map<FunctionElement, bool> canBeInlinedInsideLoop = | |
| 135 new Map<FunctionElement, bool>(); | |
| 136 | |
| 137 // Returns [:true:]/[:false:] if we have a cached decision. | |
| 138 // Returns [:null:] otherwise. | |
| 139 bool canInline(FunctionElement element, {bool insideLoop: false}) { | |
|
ngeoffray
2013/07/16 08:04:45
I'd drop the default value: it reads easier if all
kustermann
2013/07/16 13:27:50
Done.
| |
| 140 if (insideLoop) | |
| 141 return canBeInlinedInsideLoop[element]; | |
| 142 return canBeInlined[element]; | |
|
ngeoffray
2013/07/16 08:04:45
nit: use return insideLoop ? ... : ...;
kustermann
2013/07/16 13:27:50
Done.
| |
| 143 } | |
| 144 | |
| 145 void markAsInlinable(FunctionElement element, {bool insideLoop: false}) { | |
|
ngeoffray
2013/07/16 08:04:45
ditto for insideLoop argument.
kustermann
2013/07/16 13:27:50
Done.
| |
| 146 if (insideLoop) { | |
| 147 canBeInlinedInsideLoop[element] = true; | |
| 148 } else { | |
| 149 // If we can inline a function outside a loop then we should do it inside | |
| 150 // a loop as well. | |
| 151 canBeInlined[element] = true; | |
| 152 canBeInlinedInsideLoop[element] = true; | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 void markAsNonInlinable(FunctionElement element, {bool insideLoop: false}) { | |
|
ngeoffray
2013/07/16 08:04:45
ditto.
kustermann
2013/07/16 13:27:50
Done.
| |
| 157 if (insideLoop) { | |
| 158 // If we can't inline a function inside a loop, then we should not inline | |
| 159 // it outside a loop either. | |
| 160 canBeInlined[element] = false; | |
| 161 canBeInlinedInsideLoop[element] = false; | |
| 162 } else { | |
| 163 canBeInlined[element] = false; | |
| 164 } | |
| 165 } | |
| 166 } | |
| 167 | |
| 125 | 168 |
| 126 class JavaScriptBackend extends Backend { | 169 class JavaScriptBackend extends Backend { |
| 127 SsaBuilderTask builder; | 170 SsaBuilderTask builder; |
| 128 SsaOptimizerTask optimizer; | 171 SsaOptimizerTask optimizer; |
| 129 SsaCodeGeneratorTask generator; | 172 SsaCodeGeneratorTask generator; |
| 130 CodeEmitterTask emitter; | 173 CodeEmitterTask emitter; |
| 131 | 174 |
| 132 /** | 175 /** |
| 133 * The generated code as a js AST for compiled methods. | 176 * The generated code as a js AST for compiled methods. |
| 134 */ | 177 */ |
| 135 Map<Element, jsAst.Expression> get generatedCode { | 178 Map<Element, jsAst.Expression> get generatedCode { |
| 136 return compiler.enqueuer.codegen.generatedCode; | 179 return compiler.enqueuer.codegen.generatedCode; |
| 137 } | 180 } |
| 138 | 181 |
| 139 /** | 182 /** |
| 140 * The generated code as a js AST for compiled bailout methods. | 183 * The generated code as a js AST for compiled bailout methods. |
| 141 */ | 184 */ |
| 142 final Map<Element, jsAst.Expression> generatedBailoutCode = | 185 final Map<Element, jsAst.Expression> generatedBailoutCode = |
| 143 new Map<Element, jsAst.Expression>(); | 186 new Map<Element, jsAst.Expression>(); |
| 144 | 187 |
| 145 /** | 188 FunctionInlineCache inlineCache = new FunctionInlineCache(); |
| 146 * Keep track of which function elements are simple enough to be | |
| 147 * inlined in callers. | |
| 148 */ | |
| 149 final Map<FunctionElement, bool> canBeInlined = | |
| 150 new Map<FunctionElement, bool>(); | |
| 151 | 189 |
| 152 ClassElement jsInterceptorClass; | 190 ClassElement jsInterceptorClass; |
| 153 ClassElement jsStringClass; | 191 ClassElement jsStringClass; |
| 154 ClassElement jsArrayClass; | 192 ClassElement jsArrayClass; |
| 155 ClassElement jsNumberClass; | 193 ClassElement jsNumberClass; |
| 156 ClassElement jsIntClass; | 194 ClassElement jsIntClass; |
| 157 ClassElement jsDoubleClass; | 195 ClassElement jsDoubleClass; |
| 158 ClassElement jsNullClass; | 196 ClassElement jsNullClass; |
| 159 ClassElement jsBoolClass; | 197 ClassElement jsBoolClass; |
| 160 ClassElement jsUnknownClass; | 198 ClassElement jsUnknownClass; |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 429 compiler.findInterceptor(const SourceString('setDispatchProperty')); | 467 compiler.findInterceptor(const SourceString('setDispatchProperty')); |
| 430 getNativeInterceptorMethod = | 468 getNativeInterceptorMethod = |
| 431 compiler.findInterceptor(const SourceString('getNativeInterceptor')); | 469 compiler.findInterceptor(const SourceString('getNativeInterceptor')); |
| 432 initializeDispatchPropertyMethod = | 470 initializeDispatchPropertyMethod = |
| 433 compiler.findInterceptor( | 471 compiler.findInterceptor( |
| 434 new SourceString(emitter.nameOfDispatchPropertyInitializer)); | 472 new SourceString(emitter.nameOfDispatchPropertyInitializer)); |
| 435 defineNativeMethodsFinishMethod = | 473 defineNativeMethodsFinishMethod = |
| 436 compiler.findHelper(const SourceString('defineNativeMethodsFinish')); | 474 compiler.findHelper(const SourceString('defineNativeMethodsFinish')); |
| 437 | 475 |
| 438 // These methods are overwritten with generated versions. | 476 // These methods are overwritten with generated versions. |
| 439 canBeInlined[getInterceptorMethod] = false; | 477 inlineCache.markAsNonInlinable(getInterceptorMethod, insideLoop: true); |
| 440 canBeInlined[getDispatchPropertyMethod] = false; | 478 inlineCache.markAsNonInlinable(getDispatchPropertyMethod, insideLoop: true); |
| 441 canBeInlined[setDispatchPropertyMethod] = false; | 479 inlineCache.markAsNonInlinable(setDispatchPropertyMethod, insideLoop: true); |
| 442 | 480 |
| 443 List<ClassElement> classes = [ | 481 List<ClassElement> classes = [ |
| 444 jsInterceptorClass = | 482 jsInterceptorClass = |
| 445 compiler.findInterceptor(const SourceString('Interceptor')), | 483 compiler.findInterceptor(const SourceString('Interceptor')), |
| 446 jsStringClass = compiler.findInterceptor(const SourceString('JSString')), | 484 jsStringClass = compiler.findInterceptor(const SourceString('JSString')), |
| 447 jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')), | 485 jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')), |
| 448 // The int class must be before the double class, because the | 486 // The int class must be before the double class, because the |
| 449 // emitter relies on this list for the order of type checks. | 487 // emitter relies on this list for the order of type checks. |
| 450 jsIntClass = compiler.findInterceptor(const SourceString('JSInt')), | 488 jsIntClass = compiler.findInterceptor(const SourceString('JSInt')), |
| 451 jsDoubleClass = compiler.findInterceptor(const SourceString('JSDouble')), | 489 jsDoubleClass = compiler.findInterceptor(const SourceString('JSDouble')), |
| (...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1442 } | 1480 } |
| 1443 } | 1481 } |
| 1444 | 1482 |
| 1445 /// Records that [type] is used by [user.element]. | 1483 /// Records that [type] is used by [user.element]. |
| 1446 class Dependency { | 1484 class Dependency { |
| 1447 final DartType type; | 1485 final DartType type; |
| 1448 final TreeElements user; | 1486 final TreeElements user; |
| 1449 | 1487 |
| 1450 const Dependency(this.type, this.user); | 1488 const Dependency(this.type, this.user); |
| 1451 } | 1489 } |
| OLD | NEW |