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