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