| 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 bool allowSpeculativeOptimization = true; | 8 bool allowSpeculativeOptimization = true; |
| 9 List<HTypeGuard> guards = const <HTypeGuard>[]; | 9 List<HTypeGuard> guards = const <HTypeGuard>[]; |
| 10 | 10 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 return compiler.codegen(this); | 22 return compiler.codegen(this); |
| 23 } catch (CompilerCancelledException ex) { | 23 } catch (CompilerCancelledException ex) { |
| 24 throw; | 24 throw; |
| 25 } catch (var ex) { | 25 } catch (var ex) { |
| 26 compiler.unhandledExceptionOnElement(element); | 26 compiler.unhandledExceptionOnElement(element); |
| 27 throw; | 27 throw; |
| 28 } | 28 } |
| 29 } | 29 } |
| 30 } | 30 } |
| 31 | 31 |
| 32 class Backend { |
| 33 final Compiler compiler; |
| 34 |
| 35 Backend(this.compiler); |
| 36 |
| 37 abstract String codegen(WorkItem work); |
| 38 abstract void processNativeClasses(libraries); |
| 39 abstract void assembleProgram(); |
| 40 } |
| 41 |
| 42 class JavaScriptBackend extends Backend { |
| 43 SsaBuilderTask builder; |
| 44 SsaOptimizerTask optimizer; |
| 45 SsaCodeGeneratorTask generator; |
| 46 CodeEmitterTask emitter; |
| 47 |
| 48 JavaScriptBackend(Compiler compiler) |
| 49 : emitter = new CodeEmitterTask(compiler), |
| 50 super(compiler) { |
| 51 builder = new SsaBuilderTask(this); |
| 52 optimizer = new SsaOptimizerTask(this); |
| 53 generator = new SsaCodeGeneratorTask(this); |
| 54 } |
| 55 |
| 56 String codegen(WorkItem work) { |
| 57 HGraph graph = builder.build(work); |
| 58 optimizer.optimize(work, graph); |
| 59 if (work.allowSpeculativeOptimization |
| 60 && optimizer.trySpeculativeOptimizations(work, graph)) { |
| 61 String code = generator.generateBailoutMethod(work, graph); |
| 62 compiler.universe.addBailoutCode(work, code); |
| 63 optimizer.prepareForSpeculativeOptimizations(work, graph); |
| 64 optimizer.optimize(work, graph); |
| 65 } |
| 66 return generator.generateMethod(work, graph); |
| 67 } |
| 68 |
| 69 void processNativeClasses(libraries) { |
| 70 native.processNativeClasses(emitter, libraries); |
| 71 } |
| 72 |
| 73 void assembleProgram() => emitter.assembleProgram(); |
| 74 } |
| 75 |
| 32 class Compiler implements DiagnosticListener { | 76 class Compiler implements DiagnosticListener { |
| 33 Queue<WorkItem> codegenQueue; | 77 Queue<WorkItem> codegenQueue; |
| 34 Universe universe; | 78 Universe universe; |
| 35 World world; | 79 World world; |
| 36 String assembledCode; | 80 String assembledCode; |
| 37 Namer namer; | 81 Namer namer; |
| 38 Types types; | 82 Types types; |
| 39 bool enableTypeAssertions = false; | 83 bool enableTypeAssertions = false; |
| 40 | 84 |
| 41 final Tracer tracer; | 85 final Tracer tracer; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 72 } | 116 } |
| 73 } | 117 } |
| 74 | 118 |
| 75 List<CompilerTask> tasks; | 119 List<CompilerTask> tasks; |
| 76 ScannerTask scanner; | 120 ScannerTask scanner; |
| 77 DietParserTask dietParser; | 121 DietParserTask dietParser; |
| 78 ParserTask parser; | 122 ParserTask parser; |
| 79 TreeValidatorTask validator; | 123 TreeValidatorTask validator; |
| 80 ResolverTask resolver; | 124 ResolverTask resolver; |
| 81 TypeCheckerTask checker; | 125 TypeCheckerTask checker; |
| 82 SsaBuilderTask builder; | 126 Backend backend; |
| 83 SsaOptimizerTask optimizer; | |
| 84 SsaCodeGeneratorTask generator; | |
| 85 CodeEmitterTask emitter; | |
| 86 ConstantHandler constantHandler; | 127 ConstantHandler constantHandler; |
| 87 EnqueueTask enqueuer; | 128 EnqueueTask enqueuer; |
| 88 | 129 |
| 89 static final SourceString MAIN = const SourceString('main'); | 130 static final SourceString MAIN = const SourceString('main'); |
| 90 static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod'); | 131 static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod'); |
| 91 static final SourceString NO_SUCH_METHOD_EXCEPTION = | 132 static final SourceString NO_SUCH_METHOD_EXCEPTION = |
| 92 const SourceString('NoSuchMethodException'); | 133 const SourceString('NoSuchMethodException'); |
| 93 static final SourceString START_ROOT_ISOLATE = | 134 static final SourceString START_ROOT_ISOLATE = |
| 94 const SourceString('startRootIsolate'); | 135 const SourceString('startRootIsolate'); |
| 95 bool enabledNoSuchMethod = false; | 136 bool enabledNoSuchMethod = false; |
| 96 | 137 |
| 97 bool codegenQueueIsClosed = false; | 138 bool codegenQueueIsClosed = false; |
| 98 | 139 |
| 99 Stopwatch codegenProgress; | 140 Stopwatch codegenProgress; |
| 100 | 141 |
| 101 Compiler([this.tracer = const Tracer()]) | 142 Compiler([this.tracer = const Tracer()]) |
| 102 : universe = new Universe(), | 143 : universe = new Universe(), |
| 103 world = new World(), | 144 world = new World(), |
| 104 codegenQueue = new Queue<WorkItem>(), | 145 codegenQueue = new Queue<WorkItem>(), |
| 105 codegenProgress = new Stopwatch.start() { | 146 codegenProgress = new Stopwatch.start() { |
| 106 namer = new Namer(this); | 147 namer = new Namer(this); |
| 107 constantHandler = new ConstantHandler(this); | 148 constantHandler = new ConstantHandler(this); |
| 108 scanner = new ScannerTask(this); | 149 scanner = new ScannerTask(this); |
| 109 dietParser = new DietParserTask(this); | 150 dietParser = new DietParserTask(this); |
| 110 parser = new ParserTask(this); | 151 parser = new ParserTask(this); |
| 111 validator = new TreeValidatorTask(this); | 152 validator = new TreeValidatorTask(this); |
| 112 resolver = new ResolverTask(this); | 153 resolver = new ResolverTask(this); |
| 113 checker = new TypeCheckerTask(this); | 154 checker = new TypeCheckerTask(this); |
| 114 builder = new SsaBuilderTask(this); | 155 backend = new JavaScriptBackend(this); |
| 115 optimizer = new SsaOptimizerTask(this); | |
| 116 generator = new SsaCodeGeneratorTask(this); | |
| 117 emitter = new CodeEmitterTask(this); | |
| 118 enqueuer = new EnqueueTask(this); | 156 enqueuer = new EnqueueTask(this); |
| 119 tasks = [scanner, dietParser, parser, resolver, checker, | 157 tasks = [scanner, dietParser, parser, resolver, checker, |
| 120 builder, optimizer, generator, | 158 constantHandler, enqueuer]; |
| 121 emitter, constantHandler, enqueuer]; | |
| 122 } | 159 } |
| 123 | 160 |
| 124 void ensure(bool condition) { | 161 void ensure(bool condition) { |
| 125 if (!condition) cancel('failed assertion in leg'); | 162 if (!condition) cancel('failed assertion in leg'); |
| 126 } | 163 } |
| 127 | 164 |
| 128 void unimplemented(String methodName, | 165 void unimplemented(String methodName, |
| 129 [Node node, Token token, HInstruction instruction, | 166 [Node node, Token token, HInstruction instruction, |
| 130 Element element]) { | 167 Element element]) { |
| 131 internalError("$methodName not implemented", | 168 internalError("$methodName not implemented", |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 reportFatalError('Could not find $MAIN', mainApp); | 335 reportFatalError('Could not find $MAIN', mainApp); |
| 299 } else { | 336 } else { |
| 300 if (!main.isFunction()) reportFatalError('main is not a function', main); | 337 if (!main.isFunction()) reportFatalError('main is not a function', main); |
| 301 FunctionElement mainMethod = main; | 338 FunctionElement mainMethod = main; |
| 302 FunctionSignature parameters = mainMethod.computeSignature(this); | 339 FunctionSignature parameters = mainMethod.computeSignature(this); |
| 303 parameters.forEachParameter((Element parameter) { | 340 parameters.forEachParameter((Element parameter) { |
| 304 reportFatalError('main cannot have parameters', parameter); | 341 reportFatalError('main cannot have parameters', parameter); |
| 305 }); | 342 }); |
| 306 } | 343 } |
| 307 Collection<LibraryElement> libraries = universe.libraries.getValues(); | 344 Collection<LibraryElement> libraries = universe.libraries.getValues(); |
| 308 native.processNativeClasses(this, libraries); | 345 backend.processNativeClasses(libraries); |
| 309 world.populate(this, libraries); | 346 world.populate(this, libraries); |
| 310 addToWorkList(main); | 347 addToWorkList(main); |
| 311 codegenProgress.reset(); | 348 codegenProgress.reset(); |
| 312 while (!codegenQueue.isEmpty()) { | 349 while (!codegenQueue.isEmpty()) { |
| 313 WorkItem work = codegenQueue.removeLast(); | 350 WorkItem work = codegenQueue.removeLast(); |
| 314 withCurrentElement(work.element, () => work.run(this)); | 351 withCurrentElement(work.element, () => work.run(this)); |
| 315 } | 352 } |
| 316 codegenQueueIsClosed = true; | 353 codegenQueueIsClosed = true; |
| 317 assert(enqueuer.checkNoEnqueuedInvokedInstanceMethods()); | 354 assert(enqueuer.checkNoEnqueuedInvokedInstanceMethods()); |
| 318 enqueuer.registerFieldClosureInvocations(); | 355 enqueuer.registerFieldClosureInvocations(); |
| 319 emitter.assembleProgram(); | 356 backend.assembleProgram(); |
| 320 if (!codegenQueue.isEmpty()) { | 357 if (!codegenQueue.isEmpty()) { |
| 321 internalErrorOnElement(codegenQueue.first().element, | 358 internalErrorOnElement(codegenQueue.first().element, |
| 322 "work list is not empty"); | 359 "work list is not empty"); |
| 323 } | 360 } |
| 324 } | 361 } |
| 325 | 362 |
| 326 TreeElements analyzeElement(Element element) { | 363 TreeElements analyzeElement(Element element) { |
| 327 assert(parser !== null); | 364 assert(parser !== null); |
| 328 Node tree = parser.parse(element); | 365 Node tree = parser.parse(element); |
| 329 validator.validate(tree); | 366 validator.validate(tree); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 341 if (codegenProgress.elapsedInMs() > 500) { | 378 if (codegenProgress.elapsedInMs() > 500) { |
| 342 // TODO(ahe): Add structured diagnostics to the compiler API and | 379 // TODO(ahe): Add structured diagnostics to the compiler API and |
| 343 // use it to separate this from the --verbose option. | 380 // use it to separate this from the --verbose option. |
| 344 log('compiled ${universe.generatedCode.length} methods'); | 381 log('compiled ${universe.generatedCode.length} methods'); |
| 345 codegenProgress.reset(); | 382 codegenProgress.reset(); |
| 346 } | 383 } |
| 347 if (work.element.kind.category == ElementCategory.VARIABLE) { | 384 if (work.element.kind.category == ElementCategory.VARIABLE) { |
| 348 constantHandler.compileWorkItem(work); | 385 constantHandler.compileWorkItem(work); |
| 349 return null; | 386 return null; |
| 350 } else { | 387 } else { |
| 351 HGraph graph = builder.build(work); | 388 String code = backend.codegen(work); |
| 352 optimizer.optimize(work, graph); | 389 universe.addGeneratedCode(work, code); |
| 353 if (work.allowSpeculativeOptimization | 390 return code; |
| 354 && optimizer.trySpeculativeOptimizations(work, graph)) { | |
| 355 String code = generator.generateBailoutMethod(work, graph); | |
| 356 universe.addBailoutCode(work, code); | |
| 357 optimizer.prepareForSpeculativeOptimizations(work, graph); | |
| 358 optimizer.optimize(work, graph); | |
| 359 code = generator.generateMethod(work, graph); | |
| 360 universe.addGeneratedCode(work, code); | |
| 361 return code; | |
| 362 } else { | |
| 363 String code = generator.generateMethod(work, graph); | |
| 364 universe.addGeneratedCode(work, code); | |
| 365 return code; | |
| 366 } | |
| 367 } | 391 } |
| 368 } | 392 } |
| 369 | 393 |
| 370 void addToWorkList(Element element, [TreeElements elements]) { | 394 void addToWorkList(Element element, [TreeElements elements]) { |
| 371 if (codegenQueueIsClosed) { | 395 if (codegenQueueIsClosed) { |
| 372 internalErrorOnElement(element, "work list is closed"); | 396 internalErrorOnElement(element, "work list is closed"); |
| 373 } | 397 } |
| 374 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { | 398 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 375 registerInstantiatedClass(element.enclosingElement); | 399 registerInstantiatedClass(element.enclosingElement); |
| 376 } | 400 } |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 } | 587 } |
| 564 } | 588 } |
| 565 | 589 |
| 566 class SourceSpan { | 590 class SourceSpan { |
| 567 final Uri uri; | 591 final Uri uri; |
| 568 final int begin; | 592 final int begin; |
| 569 final int end; | 593 final int end; |
| 570 | 594 |
| 571 const SourceSpan(this.uri, this.begin, this.end); | 595 const SourceSpan(this.uri, this.begin, this.end); |
| 572 } | 596 } |
| OLD | NEW |