Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1656)

Unified Diff: frog/leg/compiler.dart

Issue 9873021: Move frog/leg to lib/compiler/implementation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « frog/leg/compile_time_constants.dart ('k') | frog/leg/dart2js.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: frog/leg/compiler.dart
===================================================================
--- frog/leg/compiler.dart (revision 5925)
+++ frog/leg/compiler.dart (working copy)
@@ -1,552 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-class WorkItem {
- final Element element;
- TreeElements resolutionTree;
- Function run;
- bool allowSpeculativeOptimization = true;
- List<HTypeGuard> guards = const <HTypeGuard>[];
-
- WorkItem.toCompile(this.element) : resolutionTree = null {
- run = this.compile;
- }
-
- WorkItem.toCodegen(this.element, this.resolutionTree) {
- run = this.codegen;
- }
-
- bool isAnalyzed() => resolutionTree != null;
-
- int hashCode() => element.hashCode();
-
- String compile(Compiler compiler) {
- return compiler.compile(this);
- }
-
- String codegen(Compiler compiler) {
- return compiler.codegen(this);
- }
-}
-
-class Compiler implements DiagnosticListener {
- Queue<WorkItem> worklist;
- Universe universe;
- String assembledCode;
- Namer namer;
- Types types;
- final String currentDirectory;
-
- final Tracer tracer;
-
- CompilerTask measuredTask;
- Element _currentElement;
- LibraryElement coreLibrary;
- LibraryElement coreImplLibrary;
- LibraryElement isolateLibrary;
- LibraryElement jsHelperLibrary;
- LibraryElement mainApp;
- ClassElement objectClass;
- ClassElement closureClass;
- ClassElement dynamicClass;
- ClassElement boolClass;
- ClassElement numClass;
- ClassElement intClass;
- ClassElement doubleClass;
- ClassElement stringClass;
- ClassElement functionClass;
- ClassElement nullClass;
- ClassElement listClass;
-
- Element get currentElement() => _currentElement;
- withCurrentElement(Element element, f()) {
- Element old = currentElement;
- _currentElement = element;
- try {
- return f();
- } finally {
- _currentElement = old;
- }
- }
-
- List<CompilerTask> tasks;
- ScannerTask scanner;
- DietParserTask dietParser;
- ParserTask parser;
- TreeValidatorTask validator;
- ResolverTask resolver;
- TypeCheckerTask checker;
- SsaBuilderTask builder;
- SsaOptimizerTask optimizer;
- SsaCodeGeneratorTask generator;
- CodeEmitterTask emitter;
- ConstantHandler constantHandler;
- EnqueueTask enqueuer;
-
- static final SourceString MAIN = const SourceString('main');
- static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod');
- static final SourceString NO_SUCH_METHOD_EXCEPTION =
- const SourceString('NoSuchMethodException');
- static final SourceString START_ROOT_ISOLATE =
- const SourceString('startRootIsolate');
- bool enabledNoSuchMethod = false;
-
- bool workListIsClosed = false;
-
- Stopwatch codegenProgress;
-
- Compiler.withCurrentDirectory(String this.currentDirectory,
- [this.tracer = const Tracer()])
- : types = new Types(),
- universe = new Universe(),
- worklist = new Queue<WorkItem>(),
- codegenProgress = new Stopwatch.start() {
- namer = new Namer(this);
- constantHandler = new ConstantHandler(this);
- scanner = new ScannerTask(this);
- dietParser = new DietParserTask(this);
- parser = new ParserTask(this);
- validator = new TreeValidatorTask(this);
- resolver = new ResolverTask(this);
- checker = new TypeCheckerTask(this);
- builder = new SsaBuilderTask(this);
- optimizer = new SsaOptimizerTask(this);
- generator = new SsaCodeGeneratorTask(this);
- emitter = new CodeEmitterTask(this);
- enqueuer = new EnqueueTask(this);
- tasks = [scanner, dietParser, parser, resolver, checker,
- builder, optimizer, generator,
- emitter, constantHandler, enqueuer];
- }
-
- void ensure(bool condition) {
- if (!condition) cancel('failed assertion in leg');
- }
-
- void unimplemented(String methodName,
- [Node node, Token token, HInstruction instruction,
- Element element]) {
- internalError("$methodName not implemented",
- node, token, instruction, element);
- }
-
- void internalError(String message,
- [Node node, Token token, HInstruction instruction,
- Element element]) {
- cancel("${red('internal error:')} $message",
- node, token, instruction, element);
- }
-
- void internalErrorOnElement(Element element, String message) {
- withCurrentElement(element, () {
- internalError(message, element: element);
- });
- }
-
- void cancel([String reason, Node node, Token token,
- HInstruction instruction, Element element]) {
- SourceSpan span = const SourceSpan(null, null, null);
- if (node !== null) {
- span = spanFromNode(node);
- } else if (token !== null) {
- span = spanFromTokens(token, token);
- } else if (instruction !== null) {
- span = spanFromElement(currentElement);
- } else if (element !== null) {
- span = spanFromElement(element);
- }
- reportDiagnostic(span, red(reason), true);
- throw new CompilerCancelledException(reason);
- }
-
- void log(message) {
- reportDiagnostic(null, message, false);
- }
-
- void enqueue(WorkItem work) {
- if (workListIsClosed) {
- internalErrorOnElement(work.element, "work list is closed");
- }
- worklist.add(work);
- }
-
- bool run(Uri uri) {
- try {
- runCompiler(uri);
- } catch (CompilerCancelledException exception) {
- log(exception.toString());
- log('compilation failed');
- return false;
- }
- tracer.close();
- log('compilation succeeded');
- return true;
- }
-
- void enableNoSuchMethod(Element element) {
- if (enabledNoSuchMethod) return;
- if (element.enclosingElement == objectClass) return;
- enabledNoSuchMethod = true;
- enqueuer.registerInvocation(NO_SUCH_METHOD, new Invocation(2));
- }
-
- void enableIsolateSupport(LibraryElement element) {
- isolateLibrary = element;
- addToWorkList(element.find(START_ROOT_ISOLATE));
- }
-
- bool hasIsolateSupport() => isolateLibrary !== null;
-
- void onLibraryLoaded(LibraryElement library, Uri uri) {
- if (uri.toString() == 'dart:isolate') {
- enableIsolateSupport(library);
- }
- if (dynamicClass !== null) {
- // When loading the built-in libraries, dynamicClass is null. We
- // take advantage of this as core and coreimpl import js_helper
- // and see Dynamic this way.
- withCurrentElement(dynamicClass, () {
- library.define(dynamicClass, this);
- });
- }
- }
-
- abstract LibraryElement scanBuiltinLibrary(String filename);
-
- void initializeSpecialClasses() {
- objectClass = coreLibrary.find(const SourceString('Object'));
- boolClass = coreLibrary.find(const SourceString('bool'));
- numClass = coreLibrary.find(const SourceString('num'));
- intClass = coreLibrary.find(const SourceString('int'));
- doubleClass = coreLibrary.find(const SourceString('double'));
- stringClass = coreLibrary.find(const SourceString('String'));
- functionClass = coreLibrary.find(const SourceString('Function'));
- listClass = coreLibrary.find(const SourceString('List'));
- closureClass = jsHelperLibrary.find(const SourceString('Closure'));
- dynamicClass = jsHelperLibrary.find(const SourceString('Dynamic'));
- nullClass = jsHelperLibrary.find(const SourceString('Null'));
- }
-
- void scanBuiltinLibraries() {
- coreImplLibrary = scanBuiltinLibrary('coreimpl.dart');
- jsHelperLibrary = scanBuiltinLibrary('js_helper.dart');
- coreLibrary = scanBuiltinLibrary('core.dart');
-
- // Since coreLibrary import the libraries "coreimpl", and
- // "js_helper", coreLibrary is null when they are being built. So
- // we add the implicit import of coreLibrary now. This can be
- // cleaned up when we have proper support for "dart:core" and
- // don't need to access it through the field "coreLibrary".
- // TODO(ahe): Clean this up as described above.
- scanner.importLibrary(coreImplLibrary, coreLibrary, null);
- scanner.importLibrary(jsHelperLibrary, coreLibrary, null);
- addForeignFunctions(jsHelperLibrary);
-
- universe.libraries['dart:core'] = coreLibrary;
- universe.libraries['dart:coreimpl'] = coreImplLibrary;
-
- initializeSpecialClasses();
- }
-
- /** Define the JS helper functions in the given library. */
- void addForeignFunctions(LibraryElement library) {
- library.define(new ForeignElement(
- const SourceString('JS'), library), this);
- library.define(new ForeignElement(
- const SourceString('UNINTERCEPTED'), library), this);
- library.define(new ForeignElement(
- const SourceString('JS_HAS_EQUALS'), library), this);
- library.define(new ForeignElement(
- const SourceString('JS_CURRENT_ISOLATE'), library), this);
- library.define(new ForeignElement(
- const SourceString('JS_CALL_IN_ISOLATE'), library), this);
- library.define(new ForeignElement(
- const SourceString('DART_CLOSURE_TO_JS'), library), this);
- }
-
- void runCompiler(Uri uri) {
- scanBuiltinLibraries();
- mainApp = scanner.loadLibrary(uri, null);
- final Element mainMethod = mainApp.find(MAIN);
- if (mainMethod === null) {
- withCurrentElement(mainApp, () => cancel('Could not find $MAIN'));
- } else {
- withCurrentElement(mainMethod, () {
- if (!mainMethod.isFunction()) {
- cancel('main is not a function', element: mainMethod);
- }
- FunctionParameters parameters = mainMethod.computeParameters(this);
- if (parameters.parameterCount > 0) {
- cancel('main cannot have parameters', element: mainMethod);
- }
- });
- }
- native.processNativeClasses(this, universe.libraries.getValues());
- enqueue(new WorkItem.toCompile(mainMethod));
- codegenProgress.reset();
- while (!worklist.isEmpty()) {
- WorkItem work = worklist.removeLast();
- withCurrentElement(work.element, () => (work.run)(this));
- }
- workListIsClosed = true;
- assert(enqueuer.checkNoEnqueuedInvokedInstanceMethods());
- enqueuer.registerFieldClosureInvocations();
- emitter.assembleProgram();
- if (!worklist.isEmpty()) {
- internalErrorOnElement(worklist.first().element,
- "work list is not empty");
- }
- }
-
- TreeElements analyzeElement(Element element) {
- assert(parser !== null);
- Node tree = parser.parse(element);
- validator.validate(tree);
- TreeElements elements = resolver.resolve(element);
- checker.check(tree, elements);
- return elements;
- }
-
- TreeElements analyze(WorkItem work) {
- work.resolutionTree = analyzeElement(work.element);
- return work.resolutionTree;
- }
-
- String codegen(WorkItem work) {
- if (codegenProgress.elapsedInMs() > 500) {
- // TODO(ahe): Add structured diagnostics to the compiler API and
- // use it to separate this from the --verbose option.
- log('compiled ${universe.generatedCode.length} methods');
- codegenProgress.reset();
- }
- if (work.element.kind.category == ElementCategory.VARIABLE) {
- constantHandler.compileWorkItem(work);
- return null;
- } else {
- HGraph graph = builder.build(work);
- optimizer.optimize(work, graph);
- if (work.allowSpeculativeOptimization
- && optimizer.trySpeculativeOptimizations(work, graph)) {
- String code = generator.generateBailoutMethod(work, graph);
- universe.addBailoutCode(work, code);
- optimizer.prepareForSpeculativeOptimizations(work, graph);
- optimizer.optimize(work, graph);
- code = generator.generateMethod(work, graph);
- universe.addGeneratedCode(work, code);
- return code;
- } else {
- String code = generator.generateMethod(work, graph);
- universe.addGeneratedCode(work, code);
- return code;
- }
- }
- }
-
- String compile(WorkItem work) {
- String code = universe.generatedCode[work.element];
- if (code !== null) return code;
- analyze(work);
- return codegen(work);
- }
-
- void addToWorkList(Element element) {
- if (workListIsClosed) {
- internalErrorOnElement(element, "work list is closed");
- }
- if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) {
- registerInstantiatedClass(element.enclosingElement);
- }
- worklist.add(new WorkItem.toCompile(element));
- }
-
- void registerStaticUse(Element element) {
- addToWorkList(element);
- }
-
- void registerGetOfStaticFunction(FunctionElement element) {
- registerStaticUse(element);
- universe.staticFunctionsNeedingGetter.add(element);
- }
-
- void registerDynamicInvocation(SourceString methodName, Selector selector) {
- assert(selector !== null);
- enqueuer.registerInvocation(methodName, selector);
- }
-
- void registerDynamicGetter(SourceString methodName) {
- enqueuer.registerGetter(methodName);
- }
-
- void registerDynamicSetter(SourceString methodName) {
- enqueuer.registerSetter(methodName);
- }
-
- void registerInstantiatedClass(ClassElement element) {
- universe.instantiatedClasses.add(element);
- enqueuer.onRegisterInstantiatedClass(element);
- }
-
- // TODO(ngeoffray): This should get a type.
- void registerIsCheck(Element element) {
- universe.isChecks.add(element);
- }
-
- Type resolveType(ClassElement element) {
- return withCurrentElement(element, () => resolver.resolveType(element));
- }
-
- FunctionParameters resolveSignature(FunctionElement element) {
- return withCurrentElement(element,
- () => resolver.resolveSignature(element));
- }
-
- Constant compileVariable(VariableElement element) {
- return withCurrentElement(element, () {
- return constantHandler.compileVariable(element);
- });
- }
-
- reportWarning(Node node, var message) {
- if (message is ResolutionWarning) {
- // TODO(ahe): Don't supress this warning when we support type variables.
- if (message.message.kind === MessageKind.CANNOT_RESOLVE_TYPE) return;
- } else if (message is TypeWarning) {
- // TODO(ahe): Don't supress these warning when the type checker
- // is more complete.
- if (message.message.kind === MessageKind.NOT_ASSIGNABLE) return;
- if (message.message.kind === MessageKind.MISSING_RETURN) return;
- if (message.message.kind === MessageKind.ADDITIONAL_ARGUMENT) return;
- if (message.message.kind === MessageKind.METHOD_NOT_FOUND) return;
- }
- SourceSpan span = spanFromNode(node);
- reportDiagnostic(span, "${magenta('warning:')} $message", false);
- }
-
- reportError(Node node, var message) {
- SourceSpan span = spanFromNode(node);
- reportDiagnostic(span, "${red('error:')} $message", true);
- throw new CompilerCancelledException(message.toString());
- }
-
- abstract void reportDiagnostic(SourceSpan span, String message, bool fatal);
-
- SourceSpan spanFromTokens(Token begin, Token end) {
- if (begin === null || end === null) {
- // TODO(ahe): We can almost always do better. Often it is only
- // end that is null. Otherwise, we probably know the current
- // URI.
- throw 'cannot find tokens to produce error message';
- }
- final startOffset = begin.charOffset;
- // TODO(ahe): Compute proper end offset in token. Right now we use
- // the position of the next token. We want to preserve the
- // invariant that endOffset > startOffset, but for EOF the
- // charoffset of the next token may be [startOffset]. This can
- // also happen for synthetized tokens that are produced during
- // error handling.
- final endOffset =
- Math.max((end.next !== null) ? end.next.charOffset : 0, startOffset + 1);
- assert(endOffset > startOffset);
- Uri uri = currentElement.getCompilationUnit().script.uri;
- return new SourceSpan(uri, startOffset, endOffset);
- }
-
- SourceSpan spanFromNode(Node node) {
- return spanFromTokens(node.getBeginToken(), node.getEndToken());
- }
-
- SourceSpan spanFromElement(Element element) {
- if (element.position() === null) {
- // Sometimes, the backend fakes up elements that have no
- // position. So we use the enclosing element instead. It is
- // not a good error location, but cancel really is "internal
- // error" or "not implemented yet", so the vicinity is good
- // enough for now.
- element = element.enclosingElement;
- // TODO(ahe): I plan to overhaul this infrastructure anyways.
- }
- if (element === null) {
- element = currentElement;
- }
- Token position = element.position();
- if (position === null) {
- // TODO(ahe): Find the enclosing library.
- return const SourceSpan(null, null, null);
- }
- return spanFromTokens(position, position);
- }
-
- Script readScript(Uri uri, [ScriptTag node]) {
- unimplemented('Compiler.readScript');
- }
-
- String get legDirectory() {
- unimplemented('Compiler.legDirectory');
- }
-
- Element findHelper(SourceString name) => jsHelperLibrary.find(name);
-
- bool get isMockCompilation() => false;
-}
-
-class CompilerTask {
- final Compiler compiler;
- final Stopwatch watch;
-
- CompilerTask(this.compiler) : watch = new Stopwatch();
-
- String get name() => 'Unknown task';
- int get timing() => watch.elapsedInMs();
-
- measure(Function action) {
- // TODO(kasperl): Do we have to worry about exceptions here?
- CompilerTask previous = compiler.measuredTask;
- compiler.measuredTask = this;
- if (previous !== null) previous.watch.stop();
- watch.start();
- var result = action();
- watch.stop();
- if (previous !== null) previous.watch.start();
- compiler.measuredTask = previous;
- return result;
- }
-}
-
-class CompilerCancelledException implements Exception {
- final String reason;
- CompilerCancelledException(this.reason);
-
- String toString() {
- String banner = 'compiler cancelled';
- return (reason !== null) ? '$banner: $reason' : '$banner';
- }
-}
-
-interface Tracer default LTracer {
- const Tracer();
- final bool enabled;
- void traceCompilation(String methodName);
- void traceGraph(String name, var graph);
- void close();
-}
-
-// TODO(ahe): Remove when the VM supports implicit interfaces.
-class LTracer implements Tracer {
- const LTracer();
- final bool enabled = false;
- void traceCompilation(String methodName) {
- }
- void traceGraph(String name, var graph) {
- }
- void close() {
- }
-}
-
-class SourceSpan {
- final Uri uri;
- final int begin;
- final int end;
-
- const SourceSpan(this.uri, this.begin, this.end);
-}
« no previous file with comments | « frog/leg/compile_time_constants.dart ('k') | frog/leg/dart2js.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698