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 | 5 |
| 6 /** | 6 /** |
| 7 * If true, print a warning for each method that was resolved, but not | 7 * If true, print a warning for each method that was resolved, but not |
| 8 * compiled. | 8 * compiled. |
| 9 */ | 9 */ |
| 10 final bool REPORT_EXCESS_RESOLUTION = false; | 10 final bool REPORT_EXCESS_RESOLUTION = false; |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 ScannerTask scanner; | 162 ScannerTask scanner; |
| 163 DietParserTask dietParser; | 163 DietParserTask dietParser; |
| 164 ParserTask parser; | 164 ParserTask parser; |
| 165 TreeValidatorTask validator; | 165 TreeValidatorTask validator; |
| 166 UnparseValidator unparseValidator; | 166 UnparseValidator unparseValidator; |
| 167 ResolverTask resolver; | 167 ResolverTask resolver; |
| 168 TypeCheckerTask checker; | 168 TypeCheckerTask checker; |
| 169 Backend backend; | 169 Backend backend; |
| 170 ConstantHandler constantHandler; | 170 ConstantHandler constantHandler; |
| 171 EnqueueTask enqueuer; | 171 EnqueueTask enqueuer; |
| 172 int pass = 1; | |
| 173 | 172 |
| 174 static final SourceString MAIN = const SourceString('main'); | 173 static final SourceString MAIN = const SourceString('main'); |
| 175 static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod'); | 174 static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod'); |
| 176 static final SourceString NO_SUCH_METHOD_EXCEPTION = | 175 static final SourceString NO_SUCH_METHOD_EXCEPTION = |
| 177 const SourceString('NoSuchMethodException'); | 176 const SourceString('NoSuchMethodException'); |
| 178 static final SourceString START_ROOT_ISOLATE = | 177 static final SourceString START_ROOT_ISOLATE = |
| 179 const SourceString('startRootIsolate'); | 178 const SourceString('startRootIsolate'); |
| 180 bool enabledNoSuchMethod = false; | 179 bool enabledNoSuchMethod = false; |
| 181 | 180 |
| 182 Stopwatch codegenProgress; | 181 Stopwatch progress; |
| 182 | |
| 183 static final int PHASE_RESOLVING = 0; | |
| 184 static final int PHASE_COMPILING = 1; | |
| 185 static final int PHASE_RECOMPILING = 2; | |
| 186 int phase; | |
|
ahe
2012/06/15 14:33:16
I agree, this field is a compiler.phase. Perhaps w
Søren Gjesse
2012/06/18 06:40:36
Added scanning.
| |
| 183 | 187 |
| 184 Compiler([this.tracer = const Tracer(), | 188 Compiler([this.tracer = const Tracer(), |
| 185 this.enableTypeAssertions = false, | 189 this.enableTypeAssertions = false, |
| 186 this.enableUserAssertions = false, | 190 this.enableUserAssertions = false, |
| 187 bool emitJavascript = true, | 191 bool emitJavascript = true, |
| 188 validateUnparse = false]) | 192 validateUnparse = false]) |
| 189 : libraries = new Map<String, LibraryElement>(), | 193 : libraries = new Map<String, LibraryElement>(), |
| 190 world = new World(), | 194 world = new World(), |
| 191 codegenProgress = new Stopwatch.start() { | 195 progress = new Stopwatch.start() { |
| 192 namer = new Namer(this); | 196 namer = new Namer(this); |
| 193 constantHandler = new ConstantHandler(this); | 197 constantHandler = new ConstantHandler(this); |
| 194 scanner = new ScannerTask(this); | 198 scanner = new ScannerTask(this); |
| 195 dietParser = new DietParserTask(this); | 199 dietParser = new DietParserTask(this); |
| 196 parser = new ParserTask(this); | 200 parser = new ParserTask(this); |
| 197 validator = new TreeValidatorTask(this); | 201 validator = new TreeValidatorTask(this); |
| 198 unparseValidator = new UnparseValidator(this, validateUnparse); | 202 unparseValidator = new UnparseValidator(this, validateUnparse); |
| 199 resolver = new ResolverTask(this); | 203 resolver = new ResolverTask(this); |
| 200 checker = new TypeCheckerTask(this); | 204 checker = new TypeCheckerTask(this); |
| 201 backend = emitJavascript ? | 205 backend = emitJavascript ? |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 414 parameters.forEachParameter((Element parameter) { | 418 parameters.forEachParameter((Element parameter) { |
| 415 reportFatalError('main cannot have parameters', parameter); | 419 reportFatalError('main cannot have parameters', parameter); |
| 416 }); | 420 }); |
| 417 } | 421 } |
| 418 | 422 |
| 419 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution | 423 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution |
| 420 // should know this. | 424 // should know this. |
| 421 world.populate(this, libraries.getValues()); | 425 world.populate(this, libraries.getValues()); |
| 422 | 426 |
| 423 log('Resolving...'); | 427 log('Resolving...'); |
| 428 phase = PHASE_RESOLVING; | |
| 424 backend.enqueueHelpers(enqueuer.resolution); | 429 backend.enqueueHelpers(enqueuer.resolution); |
| 425 processQueue(enqueuer.resolution, main); | 430 processQueue(enqueuer.resolution, main); |
| 426 log('Resolved ${enqueuer.resolution.resolvedElements.length} elements.'); | 431 log('Resolved ${enqueuer.resolution.resolvedElements.length} elements.'); |
| 427 | 432 |
| 428 log('Compiling...'); | 433 log('Compiling...'); |
| 434 phase = PHASE_COMPILING; | |
| 429 processQueue(enqueuer.codegen, main); | 435 processQueue(enqueuer.codegen, main); |
| 430 log("Recompiling ${enqueuer.codegen.recompilationCandidates.length} " | 436 log("Recompiling ${enqueuer.codegen.recompilationCandidates.length} " |
| 431 "methods..."); | 437 "methods..."); |
| 438 phase = PHASE_RECOMPILING; | |
| 432 processRecompilationQueue(enqueuer.codegen); | 439 processRecompilationQueue(enqueuer.codegen); |
| 433 log('Compiled ${codegenWorld.generatedCode.length} methods.'); | 440 log('Compiled ${codegenWorld.generatedCode.length} methods.'); |
| 434 | 441 |
| 435 backend.assembleProgram(); | 442 backend.assembleProgram(); |
| 436 | 443 |
| 437 checkQueues(); | 444 checkQueues(); |
| 438 } | 445 } |
| 439 | 446 |
| 440 processQueue(Enqueuer world, Element main) { | 447 processQueue(Enqueuer world, Element main) { |
| 441 backend.processNativeClasses(world, libraries.getValues()); | 448 backend.processNativeClasses(world, libraries.getValues()); |
| 442 world.addToWorkList(main); | 449 world.addToWorkList(main); |
| 443 codegenProgress.reset(); | 450 progress.reset(); |
| 444 world.forEach((WorkItem work) { | 451 world.forEach((WorkItem work) { |
| 445 withCurrentElement(work.element, () => work.run(this, world)); | 452 withCurrentElement(work.element, () => work.run(this, world)); |
| 446 }); | 453 }); |
| 447 world.queueIsClosed = true; | 454 world.queueIsClosed = true; |
| 448 assert(world.checkNoEnqueuedInvokedInstanceMethods()); | 455 assert(world.checkNoEnqueuedInvokedInstanceMethods()); |
| 449 world.registerFieldClosureInvocations(); | 456 world.registerFieldClosureInvocations(); |
| 450 } | 457 } |
| 451 | 458 |
| 452 processRecompilationQueue(Enqueuer world) { | 459 processRecompilationQueue(Enqueuer world) { |
| 453 pass = 2; | 460 assert(phase == PHASE_RECOMPILING); |
| 454 while (!world.recompilationCandidates.isEmpty()) { | 461 while (!world.recompilationCandidates.isEmpty()) { |
| 455 WorkItem work = world.recompilationCandidates.next(); | 462 WorkItem work = world.recompilationCandidates.next(); |
| 463 world.universe.generatedCode.remove(work.element); | |
| 456 var oldCode = world.universe.generatedCode[work.element]; | 464 var oldCode = world.universe.generatedCode[work.element]; |
| 457 world.universe.generatedCode.remove(work.element); | |
| 458 withCurrentElement(work.element, () => work.run(this, world)); | 465 withCurrentElement(work.element, () => work.run(this, world)); |
| 459 var newCode = world.universe.generatedCode[work.element]; | 466 var newCode = world.universe.generatedCode[work.element]; |
| 460 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { | 467 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { |
| 461 log("Pass 2 optimization:"); | 468 log("Pass 2 optimization:"); |
| 462 log("Before:\n$oldCode"); | 469 log("Before:\n$oldCode"); |
| 463 log("After:\n$newCode"); | 470 log("After:\n$newCode"); |
| 464 } | 471 } |
| 465 } | 472 } |
| 466 } | 473 } |
| 467 | 474 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 Node tree = parser.parse(element); | 533 Node tree = parser.parse(element); |
| 527 validator.validate(tree); | 534 validator.validate(tree); |
| 528 unparseValidator.check(element); | 535 unparseValidator.check(element); |
| 529 elements = resolver.resolve(element); | 536 elements = resolver.resolve(element); |
| 530 checker.check(tree, elements); | 537 checker.check(tree, elements); |
| 531 return elements; | 538 return elements; |
| 532 } | 539 } |
| 533 | 540 |
| 534 TreeElements analyze(WorkItem work, Enqueuer world) { | 541 TreeElements analyze(WorkItem work, Enqueuer world) { |
| 535 if (work.isAnalyzed()) return work.resolutionTree; | 542 if (work.isAnalyzed()) return work.resolutionTree; |
| 543 if (progress.elapsedInMs() > 500) { | |
| 544 // TODO(ahe): Add structured diagnostics to the compiler API and | |
| 545 // use it to separate this from the --verbose option. | |
| 546 if (phase == PHASE_RESOLVING) { | |
| 547 log('Resolved ${enqueuer.resolution.resolvedElements.length} elements.') ; | |
|
ahe
2012/06/15 14:33:16
Nice, but the line is too long :-)
Søren Gjesse
2012/06/18 06:40:36
Done.
| |
| 548 progress.reset(); | |
| 549 } | |
| 550 } | |
| 536 Element element = work.element; | 551 Element element = work.element; |
| 537 TreeElements result = world.getCachedElements(element); | 552 TreeElements result = world.getCachedElements(element); |
| 538 if (result !== null) return result; | 553 if (result !== null) return result; |
| 539 if (world !== enqueuer.resolution) { | 554 if (world !== enqueuer.resolution) { |
| 540 internalErrorOnElement(element, | 555 internalErrorOnElement(element, |
| 541 'Internal error: unresolved element: $element.'); | 556 'Internal error: unresolved element: $element.'); |
| 542 } | 557 } |
| 543 result = analyzeElement(element); | 558 result = analyzeElement(element); |
| 544 enqueuer.resolution.resolvedElements[element] = result; | 559 enqueuer.resolution.resolvedElements[element] = result; |
| 545 return result; | 560 return result; |
| 546 } | 561 } |
| 547 | 562 |
| 548 String codegen(WorkItem work, Enqueuer world) { | 563 String codegen(WorkItem work, Enqueuer world) { |
| 549 if (world !== enqueuer.codegen) return null; | 564 if (world !== enqueuer.codegen) return null; |
| 550 if (codegenProgress.elapsedInMs() > 500) { | 565 if (progress.elapsedInMs() > 500) { |
| 551 // TODO(ahe): Add structured diagnostics to the compiler API and | 566 // TODO(ahe): Add structured diagnostics to the compiler API and |
| 552 // use it to separate this from the --verbose option. | 567 // use it to separate this from the --verbose option. |
| 553 log('Compiled ${codegenWorld.generatedCode.length} methods.'); | 568 if (phase == PHASE_COMPILING) { |
| 554 codegenProgress.reset(); | 569 log('Compiled ${codegenWorld.generatedCode.length} methods.'); |
| 570 } else { | |
| 571 log('Recompiled ${world.recompilationCandidates.processed} methods.'); | |
| 572 } | |
| 573 progress.reset(); | |
| 555 } | 574 } |
| 556 if (work.element.kind.category == ElementCategory.VARIABLE) { | 575 if (work.element.kind.category == ElementCategory.VARIABLE) { |
| 557 constantHandler.compileWorkItem(work); | 576 constantHandler.compileWorkItem(work); |
| 558 return null; | 577 return null; |
| 559 } else { | 578 } else { |
| 560 String code = backend.codegen(work); | 579 String code = backend.codegen(work); |
| 561 codegenWorld.addGeneratedCode(work, code); | 580 codegenWorld.addGeneratedCode(work, code); |
| 562 return code; | 581 return code; |
| 563 } | 582 } |
| 564 } | 583 } |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 738 // invariant that endOffset > beginOffset, but for EOF the | 757 // invariant that endOffset > beginOffset, but for EOF the |
| 739 // charoffset of the next token may be [beginOffset]. This can | 758 // charoffset of the next token may be [beginOffset]. This can |
| 740 // also happen for synthetized tokens that are produced during | 759 // also happen for synthetized tokens that are produced during |
| 741 // error handling. | 760 // error handling. |
| 742 final endOffset = | 761 final endOffset = |
| 743 Math.max((end.next !== null) ? end.next.charOffset : 0, beginOffset + 1); | 762 Math.max((end.next !== null) ? end.next.charOffset : 0, beginOffset + 1); |
| 744 assert(endOffset > beginOffset); | 763 assert(endOffset > beginOffset); |
| 745 return f(beginOffset, endOffset); | 764 return f(beginOffset, endOffset); |
| 746 } | 765 } |
| 747 } | 766 } |
| OLD | NEW |