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 WorkItem { | 5 class WorkItem { |
| 6 final Element element; | 6 final Element element; |
| 7 TreeElements resolutionTree; | 7 TreeElements resolutionTree; |
| 8 Function run; | 8 Function run; |
| 9 bool allowSpeculativeOptimization = true; | 9 bool allowSpeculativeOptimization = true; |
| 10 List<HTypeGuard> guards = const <HTypeGuard>[]; | 10 List<HTypeGuard> guards = const <HTypeGuard>[]; |
| 11 | 11 |
| 12 WorkItem.toCompile(this.element) : resolutionTree = null { | 12 WorkItem.toCompile(this.element) : resolutionTree = null { |
| 13 run = (Compiler compiler) => compiler.compile(this); | 13 run = (Compiler compiler) => compiler.compile(this); |
| 14 } | 14 } |
| 15 | 15 |
| 16 WorkItem.toCodegen(this.element, this.resolutionTree) { | 16 WorkItem.toCodegen(this.element, this.resolutionTree) { |
| 17 run = (Compiler compiler) => compiler.codegen(this); | 17 run = (Compiler compiler) => compiler.codegen(this); |
| 18 } | 18 } |
| 19 | 19 |
| 20 bool isAnalyzed() => resolutionTree != null; | 20 bool isAnalyzed() => resolutionTree != null; |
| 21 | 21 |
| 22 int hashCode() => element.hashCode(); | 22 int hashCode() => element.hashCode(); |
| 23 } | 23 } |
| 24 | 24 |
| 25 interface Backend { | |
| 26 String codegen(WorkItem work); | |
| 27 void assembleProgram(); | |
| 28 } | |
| 29 | |
| 30 class JavaScriptBackend implements Backend { | |
|
ahe
2012/05/14 08:14:30
Consider creating a separate library for this clas
Anton Muhin
2012/05/14 14:36:45
What would be your recommendation where to place i
| |
| 31 Compiler compiler; | |
| 32 SsaBuilderTask builder; | |
| 33 SsaOptimizerTask optimizer; | |
| 34 SsaCodeGeneratorTask generator; | |
| 35 CodeEmitterTask emitter; | |
| 36 | |
| 37 JavaScriptBackend(Compiler compiler) | |
| 38 : this.compiler = compiler, | |
| 39 builder = new SsaBuilderTask(compiler), | |
| 40 optimizer = new SsaOptimizerTask(compiler), | |
| 41 generator = new SsaCodeGeneratorTask(compiler), | |
| 42 emitter = new CodeEmitterTask(compiler); | |
| 43 | |
| 44 String codegen(WorkItem work) { | |
| 45 HGraph graph = builder.build(work); | |
| 46 optimizer.optimize(work, graph); | |
| 47 if (work.allowSpeculativeOptimization | |
| 48 && optimizer.trySpeculativeOptimizations(work, graph)) { | |
| 49 String code = generator.generateBailoutMethod(work, graph); | |
| 50 compiler.universe.addBailoutCode(work, code); | |
| 51 optimizer.prepareForSpeculativeOptimizations(work, graph); | |
| 52 optimizer.optimize(work, graph); | |
| 53 } | |
| 54 return generator.generateMethod(work, graph); | |
| 55 } | |
| 56 | |
| 57 void assembleProgram() => emitter.assembleProgram(); | |
| 58 } | |
| 59 | |
| 25 class Compiler implements DiagnosticListener { | 60 class Compiler implements DiagnosticListener { |
| 26 Queue<WorkItem> worklist; | 61 Queue<WorkItem> worklist; |
| 27 Universe universe; | 62 Universe universe; |
| 28 World world; | 63 World world; |
| 29 String assembledCode; | 64 String assembledCode; |
| 30 Namer namer; | 65 Namer namer; |
| 31 Types types; | 66 Types types; |
| 32 bool enableTypeAssertions = false; | 67 bool enableTypeAssertions = false; |
| 33 | 68 |
| 34 final Tracer tracer; | 69 final Tracer tracer; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 65 } | 100 } |
| 66 } | 101 } |
| 67 | 102 |
| 68 List<CompilerTask> tasks; | 103 List<CompilerTask> tasks; |
| 69 ScannerTask scanner; | 104 ScannerTask scanner; |
| 70 DietParserTask dietParser; | 105 DietParserTask dietParser; |
| 71 ParserTask parser; | 106 ParserTask parser; |
| 72 TreeValidatorTask validator; | 107 TreeValidatorTask validator; |
| 73 ResolverTask resolver; | 108 ResolverTask resolver; |
| 74 TypeCheckerTask checker; | 109 TypeCheckerTask checker; |
| 75 SsaBuilderTask builder; | 110 Backend backend; |
| 76 SsaOptimizerTask optimizer; | |
| 77 SsaCodeGeneratorTask generator; | |
| 78 CodeEmitterTask emitter; | |
| 79 ConstantHandler constantHandler; | 111 ConstantHandler constantHandler; |
| 80 EnqueueTask enqueuer; | 112 EnqueueTask enqueuer; |
| 81 | 113 |
| 82 static final SourceString MAIN = const SourceString('main'); | 114 static final SourceString MAIN = const SourceString('main'); |
| 83 static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod'); | 115 static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod'); |
| 84 static final SourceString NO_SUCH_METHOD_EXCEPTION = | 116 static final SourceString NO_SUCH_METHOD_EXCEPTION = |
| 85 const SourceString('NoSuchMethodException'); | 117 const SourceString('NoSuchMethodException'); |
| 86 static final SourceString START_ROOT_ISOLATE = | 118 static final SourceString START_ROOT_ISOLATE = |
| 87 const SourceString('startRootIsolate'); | 119 const SourceString('startRootIsolate'); |
| 88 bool enabledNoSuchMethod = false; | 120 bool enabledNoSuchMethod = false; |
| 89 | 121 |
| 90 bool workListIsClosed = false; | 122 bool workListIsClosed = false; |
| 91 | 123 |
| 92 Stopwatch codegenProgress; | 124 Stopwatch codegenProgress; |
| 93 | 125 |
| 94 Compiler([this.tracer = const Tracer()]) | 126 Compiler([this.tracer = const Tracer()]) |
| 95 : universe = new Universe(), | 127 : universe = new Universe(), |
| 96 world = new World(), | 128 world = new World(), |
| 97 worklist = new Queue<WorkItem>(), | 129 worklist = new Queue<WorkItem>(), |
| 98 codegenProgress = new Stopwatch.start() { | 130 codegenProgress = new Stopwatch.start() { |
| 99 namer = new Namer(this); | 131 namer = new Namer(this); |
| 100 constantHandler = new ConstantHandler(this); | 132 constantHandler = new ConstantHandler(this); |
| 101 scanner = new ScannerTask(this); | 133 scanner = new ScannerTask(this); |
| 102 dietParser = new DietParserTask(this); | 134 dietParser = new DietParserTask(this); |
| 103 parser = new ParserTask(this); | 135 parser = new ParserTask(this); |
| 104 validator = new TreeValidatorTask(this); | 136 validator = new TreeValidatorTask(this); |
| 105 resolver = new ResolverTask(this); | 137 resolver = new ResolverTask(this); |
| 106 checker = new TypeCheckerTask(this); | 138 checker = new TypeCheckerTask(this); |
| 107 builder = new SsaBuilderTask(this); | 139 backend = new JavaScriptBackend(this); |
| 108 optimizer = new SsaOptimizerTask(this); | |
| 109 generator = new SsaCodeGeneratorTask(this); | |
| 110 emitter = new CodeEmitterTask(this); | |
| 111 enqueuer = new EnqueueTask(this); | 140 enqueuer = new EnqueueTask(this); |
| 112 tasks = [scanner, dietParser, parser, resolver, checker, | 141 tasks = [scanner, dietParser, parser, resolver, checker, |
| 113 builder, optimizer, generator, | 142 constantHandler, enqueuer]; |
| 114 emitter, constantHandler, enqueuer]; | |
| 115 } | 143 } |
| 116 | 144 |
| 117 void ensure(bool condition) { | 145 void ensure(bool condition) { |
| 118 if (!condition) cancel('failed assertion in leg'); | 146 if (!condition) cancel('failed assertion in leg'); |
| 119 } | 147 } |
| 120 | 148 |
| 121 void unimplemented(String methodName, | 149 void unimplemented(String methodName, |
| 122 [Node node, Token token, HInstruction instruction, | 150 [Node node, Token token, HInstruction instruction, |
| 123 Element element]) { | 151 Element element]) { |
| 124 internalError("$methodName not implemented", | 152 internalError("$methodName not implemented", |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 298 world.populate(this, libraries); | 326 world.populate(this, libraries); |
| 299 enqueue(new WorkItem.toCompile(main)); | 327 enqueue(new WorkItem.toCompile(main)); |
| 300 codegenProgress.reset(); | 328 codegenProgress.reset(); |
| 301 while (!worklist.isEmpty()) { | 329 while (!worklist.isEmpty()) { |
| 302 WorkItem work = worklist.removeLast(); | 330 WorkItem work = worklist.removeLast(); |
| 303 withCurrentElement(work.element, () => (work.run)(this)); | 331 withCurrentElement(work.element, () => (work.run)(this)); |
| 304 } | 332 } |
| 305 workListIsClosed = true; | 333 workListIsClosed = true; |
| 306 assert(enqueuer.checkNoEnqueuedInvokedInstanceMethods()); | 334 assert(enqueuer.checkNoEnqueuedInvokedInstanceMethods()); |
| 307 enqueuer.registerFieldClosureInvocations(); | 335 enqueuer.registerFieldClosureInvocations(); |
| 308 emitter.assembleProgram(); | 336 backend.assembleProgram(); |
| 309 if (!worklist.isEmpty()) { | 337 if (!worklist.isEmpty()) { |
| 310 internalErrorOnElement(worklist.first().element, | 338 internalErrorOnElement(worklist.first().element, |
| 311 "work list is not empty"); | 339 "work list is not empty"); |
| 312 } | 340 } |
| 313 } | 341 } |
| 314 | 342 |
| 315 TreeElements analyzeElement(Element element) { | 343 TreeElements analyzeElement(Element element) { |
| 316 assert(parser !== null); | 344 assert(parser !== null); |
| 317 Node tree = parser.parse(element); | 345 Node tree = parser.parse(element); |
| 318 validator.validate(tree); | 346 validator.validate(tree); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 330 if (codegenProgress.elapsedInMs() > 500) { | 358 if (codegenProgress.elapsedInMs() > 500) { |
| 331 // TODO(ahe): Add structured diagnostics to the compiler API and | 359 // TODO(ahe): Add structured diagnostics to the compiler API and |
| 332 // use it to separate this from the --verbose option. | 360 // use it to separate this from the --verbose option. |
| 333 log('compiled ${universe.generatedCode.length} methods'); | 361 log('compiled ${universe.generatedCode.length} methods'); |
| 334 codegenProgress.reset(); | 362 codegenProgress.reset(); |
| 335 } | 363 } |
| 336 if (work.element.kind.category == ElementCategory.VARIABLE) { | 364 if (work.element.kind.category == ElementCategory.VARIABLE) { |
| 337 constantHandler.compileWorkItem(work); | 365 constantHandler.compileWorkItem(work); |
| 338 return null; | 366 return null; |
| 339 } else { | 367 } else { |
| 340 HGraph graph = builder.build(work); | 368 String code = backend.codegen(work); |
| 341 optimizer.optimize(work, graph); | 369 universe.addGeneratedCode(work, code); |
| 342 if (work.allowSpeculativeOptimization | 370 return code; |
| 343 && optimizer.trySpeculativeOptimizations(work, graph)) { | |
| 344 String code = generator.generateBailoutMethod(work, graph); | |
| 345 universe.addBailoutCode(work, code); | |
| 346 optimizer.prepareForSpeculativeOptimizations(work, graph); | |
| 347 optimizer.optimize(work, graph); | |
| 348 code = generator.generateMethod(work, graph); | |
| 349 universe.addGeneratedCode(work, code); | |
| 350 return code; | |
| 351 } else { | |
| 352 String code = generator.generateMethod(work, graph); | |
| 353 universe.addGeneratedCode(work, code); | |
| 354 return code; | |
| 355 } | |
| 356 } | 371 } |
| 357 } | 372 } |
| 358 | 373 |
| 359 String compile(WorkItem work) { | 374 String compile(WorkItem work) { |
| 360 String code = universe.generatedCode[work.element]; | 375 String code = universe.generatedCode[work.element]; |
| 361 if (code !== null) return code; | 376 if (code !== null) return code; |
| 362 analyze(work); | 377 analyze(work); |
| 363 return codegen(work); | 378 return codegen(work); |
| 364 } | 379 } |
| 365 | 380 |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 } | 574 } |
| 560 } | 575 } |
| 561 | 576 |
| 562 class SourceSpan { | 577 class SourceSpan { |
| 563 final Uri uri; | 578 final Uri uri; |
| 564 final int begin; | 579 final int begin; |
| 565 final int end; | 580 final int end; |
| 566 | 581 |
| 567 const SourceSpan(this.uri, this.begin, this.end); | 582 const SourceSpan(this.uri, this.begin, this.end); |
| 568 } | 583 } |
| OLD | NEW |