| Index: pkg/compiler/lib/src/compiler.dart
|
| diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
|
| index f6353790b591b93f3bebbb4a9327f03e6910937b..2fdbf2e2a2b263f6474708211e510247da748787 100644
|
| --- a/pkg/compiler/lib/src/compiler.dart
|
| +++ b/pkg/compiler/lib/src/compiler.dart
|
| @@ -2,666 +2,130 @@
|
| // 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.
|
|
|
| -part of dart2js;
|
| -
|
| -/**
|
| - * If true, print a warning for each method that was resolved, but not
|
| - * compiled.
|
| - */
|
| -const bool REPORT_EXCESS_RESOLUTION = false;
|
| -
|
| -/**
|
| - * Contains backend-specific data that is used throughout the compilation of
|
| - * one work item.
|
| - */
|
| -class ItemCompilationContext {
|
| -}
|
| -
|
| -abstract class WorkItem {
|
| - final ItemCompilationContext compilationContext;
|
| - /**
|
| - * Documentation wanted -- johnniwinther
|
| - *
|
| - * Invariant: [element] must be a declaration element.
|
| - */
|
| - final AstElement element;
|
| -
|
| - WorkItem(this.element, this.compilationContext) {
|
| - assert(invariant(element, element.isDeclaration));
|
| - }
|
| -
|
| - WorldImpact run(Compiler compiler, Enqueuer world);
|
| -}
|
| -
|
| -/// [WorkItem] used exclusively by the [ResolutionEnqueuer].
|
| -class ResolutionWorkItem extends WorkItem {
|
| - bool _isAnalyzed = false;
|
| -
|
| - ResolutionWorkItem(AstElement element,
|
| - ItemCompilationContext compilationContext)
|
| - : super(element, compilationContext);
|
| -
|
| - WorldImpact run(Compiler compiler, ResolutionEnqueuer world) {
|
| - WorldImpact impact = compiler.analyze(this, world);
|
| - _isAnalyzed = true;
|
| - return impact;
|
| - }
|
| -
|
| - bool get isAnalyzed => _isAnalyzed;
|
| -}
|
| -
|
| -// TODO(johnniwinther): Split this class into interface and implementation.
|
| -// TODO(johnniwinther): Move this implementation to the JS backend.
|
| -class CodegenRegistry extends Registry {
|
| - final Compiler compiler;
|
| - final TreeElements treeElements;
|
| -
|
| - CodegenRegistry(this.compiler, this.treeElements);
|
| -
|
| - bool get isForResolution => false;
|
| -
|
| - Element get currentElement => treeElements.analyzedElement;
|
| -
|
| - // TODO(johnniwinther): Remove this getter when [Registry] creates a
|
| - // dependency node.
|
| - Setlet<Element> get otherDependencies => treeElements.otherDependencies;
|
| -
|
| - CodegenEnqueuer get world => compiler.enqueuer.codegen;
|
| - js_backend.JavaScriptBackend get backend => compiler.backend;
|
| -
|
| - void registerDependency(Element element) {
|
| - treeElements.registerDependency(element);
|
| - }
|
| -
|
| - void registerInlining(Element inlinedElement, Element context) {
|
| - if (compiler.dumpInfo) {
|
| - compiler.dumpInfoTask.registerInlined(inlinedElement, context);
|
| - }
|
| - }
|
| -
|
| - void registerInstantiatedClass(ClassElement element) {
|
| - world.registerInstantiatedType(element.rawType, this);
|
| - }
|
| -
|
| - void registerInstantiatedType(InterfaceType type) {
|
| - world.registerInstantiatedType(type, this);
|
| - }
|
| -
|
| - void registerStaticUse(Element element) {
|
| - world.registerStaticUse(element);
|
| - }
|
| -
|
| - void registerDynamicInvocation(UniverseSelector selector) {
|
| - world.registerDynamicInvocation(selector);
|
| - compiler.dumpInfoTask.elementUsesSelector(currentElement, selector);
|
| - }
|
| -
|
| - void registerDynamicSetter(UniverseSelector selector) {
|
| - world.registerDynamicSetter(selector);
|
| - compiler.dumpInfoTask.elementUsesSelector(currentElement, selector);
|
| - }
|
| -
|
| - void registerDynamicGetter(UniverseSelector selector) {
|
| - world.registerDynamicGetter(selector);
|
| - compiler.dumpInfoTask.elementUsesSelector(currentElement, selector);
|
| - }
|
| -
|
| - void registerGetterForSuperMethod(Element element) {
|
| - world.registerGetterForSuperMethod(element);
|
| - }
|
| -
|
| - void registerFieldGetter(Element element) {
|
| - world.registerFieldGetter(element);
|
| - }
|
| -
|
| - void registerFieldSetter(Element element) {
|
| - world.registerFieldSetter(element);
|
| - }
|
| -
|
| - void registerIsCheck(DartType type) {
|
| - world.registerIsCheck(type);
|
| - backend.registerIsCheckForCodegen(type, world, this);
|
| - }
|
| -
|
| - void registerCompileTimeConstant(ConstantValue constant) {
|
| - backend.registerCompileTimeConstant(constant, this);
|
| - backend.constants.addCompileTimeConstantForEmission(constant);
|
| - }
|
| -
|
| - void registerTypeVariableBoundsSubtypeCheck(DartType subtype,
|
| - DartType supertype) {
|
| - backend.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
|
| - }
|
| -
|
| - void registerInstantiatedClosure(LocalFunctionElement element) {
|
| - backend.registerInstantiatedClosure(element, this);
|
| - }
|
| -
|
| - void registerGetOfStaticFunction(FunctionElement element) {
|
| - world.registerGetOfStaticFunction(element);
|
| - }
|
| -
|
| - void registerSelectorUse(Selector selector) {
|
| - world.registerSelectorUse(new UniverseSelector(selector, null));
|
| - }
|
| -
|
| - void registerConstSymbol(String name) {
|
| - backend.registerConstSymbol(name, this);
|
| - }
|
| -
|
| - void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
|
| - backend.registerSpecializedGetInterceptor(classes);
|
| - }
|
| -
|
| - void registerUseInterceptor() {
|
| - backend.registerUseInterceptor(world);
|
| - }
|
| -
|
| - void registerTypeConstant(ClassElement element) {
|
| - backend.customElementsAnalysis.registerTypeConstant(element, world);
|
| - }
|
| -
|
| - void registerStaticInvocation(Element element) {
|
| - world.registerStaticUse(element);
|
| - }
|
| -
|
| - void registerSuperInvocation(Element element) {
|
| - world.registerStaticUse(element);
|
| - }
|
| -
|
| - void registerDirectInvocation(Element element) {
|
| - world.registerStaticUse(element);
|
| - }
|
| -
|
| - void registerInstantiation(InterfaceType type) {
|
| - world.registerInstantiatedType(type, this);
|
| - }
|
| -
|
| - void registerAsyncMarker(FunctionElement element) {
|
| - backend.registerAsyncMarker(element, world, this);
|
| - }
|
| -
|
| -}
|
| -
|
| -/// [WorkItem] used exclusively by the [CodegenEnqueuer].
|
| -class CodegenWorkItem extends WorkItem {
|
| - CodegenRegistry registry;
|
| -
|
| - factory CodegenWorkItem(
|
| - Compiler compiler,
|
| - AstElement element,
|
| - ItemCompilationContext compilationContext) {
|
| - // If this assertion fails, the resolution callbacks of the backend may be
|
| - // missing call of form registry.registerXXX. Alternatively, the code
|
| - // generation could spuriously be adding dependencies on things we know we
|
| - // don't need.
|
| - assert(invariant(element,
|
| - compiler.enqueuer.resolution.hasBeenResolved(element),
|
| - message: "$element has not been resolved."));
|
| - assert(invariant(element, element.resolvedAst.elements != null,
|
| - message: 'Resolution tree is null for $element in codegen work item'));
|
| - return new CodegenWorkItem.internal(element, compilationContext);
|
| - }
|
| -
|
| - CodegenWorkItem.internal(
|
| - AstElement element,
|
| - ItemCompilationContext compilationContext)
|
| - : super(element, compilationContext);
|
| -
|
| - TreeElements get resolutionTree => element.resolvedAst.elements;
|
| -
|
| - WorldImpact run(Compiler compiler, CodegenEnqueuer world) {
|
| - if (world.isProcessed(element)) return const WorldImpact();
|
| -
|
| - registry = new CodegenRegistry(compiler, resolutionTree);
|
| - return compiler.codegen(this, world);
|
| - }
|
| -}
|
| -
|
| -typedef void DeferredAction();
|
| -
|
| -class DeferredTask {
|
| - final Element element;
|
| - final DeferredAction action;
|
| -
|
| - DeferredTask(this.element, this.action);
|
| -}
|
| -
|
| -/// Interface for registration of element dependencies.
|
| -abstract class Registry {
|
| - // TODO(johnniwinther): Remove this getter when [Registry] creates a
|
| - // dependency node.
|
| - Iterable<Element> get otherDependencies;
|
| -
|
| - void registerDependency(Element element);
|
| -
|
| - bool get isForResolution;
|
| -
|
| - void registerDynamicInvocation(UniverseSelector selector);
|
| -
|
| - void registerDynamicGetter(UniverseSelector selector);
|
| -
|
| - void registerDynamicSetter(UniverseSelector selector);
|
| -
|
| - void registerStaticInvocation(Element element);
|
| -
|
| - void registerInstantiation(InterfaceType type);
|
| -
|
| - void registerGetOfStaticFunction(FunctionElement element);
|
| -}
|
| -
|
| -abstract class Backend {
|
| - final Compiler compiler;
|
| -
|
| - Backend(this.compiler);
|
| -
|
| - /// Returns true if the backend supports reflection.
|
| - bool get supportsReflection;
|
| -
|
| - /// The [ConstantSystem] used to interpret compile-time constants for this
|
| - /// backend.
|
| - ConstantSystem get constantSystem;
|
| -
|
| - /// The constant environment for the backend interpretation of compile-time
|
| - /// constants.
|
| - BackendConstantEnvironment get constants;
|
| -
|
| - /// The compiler task responsible for the compilation of constants for both
|
| - /// the frontend and the backend.
|
| - ConstantCompilerTask get constantCompilerTask;
|
| -
|
| - /// Backend callback methods for the resolution phase.
|
| - ResolutionCallbacks get resolutionCallbacks;
|
| -
|
| - /// The strategy used for collecting and emitting source information.
|
| - SourceInformationStrategy get sourceInformationStrategy {
|
| - return const SourceInformationStrategy();
|
| - }
|
| -
|
| - // TODO(johnniwinther): Move this to the JavaScriptBackend.
|
| - String get patchVersion => null;
|
| -
|
| - /// Set of classes that need to be considered for reflection although not
|
| - /// otherwise visible during resolution.
|
| - Iterable<ClassElement> classesRequiredForReflection = const [];
|
| -
|
| - // Given a [FunctionElement], return a buffer with the code generated for it
|
| - // or null if no code was generated.
|
| - CodeBuffer codeOf(Element element) => null;
|
| -
|
| - void initializeHelperClasses() {}
|
| -
|
| - void enqueueHelpers(ResolutionEnqueuer world, Registry registry);
|
| - WorldImpact codegen(CodegenWorkItem work);
|
| -
|
| - // The backend determines the native resolution enqueuer, with a no-op
|
| - // default, so tools like dart2dart can ignore the native classes.
|
| - native.NativeEnqueuer nativeResolutionEnqueuer(world) {
|
| - return new native.NativeEnqueuer();
|
| - }
|
| - native.NativeEnqueuer nativeCodegenEnqueuer(world) {
|
| - return new native.NativeEnqueuer();
|
| - }
|
| -
|
| - /// Generates the output and returns the total size of the generated code.
|
| - int assembleProgram();
|
| -
|
| - List<CompilerTask> get tasks;
|
| -
|
| - void onResolutionComplete() {}
|
| - void onTypeInferenceComplete() {}
|
| -
|
| - ItemCompilationContext createItemCompilationContext() {
|
| - return new ItemCompilationContext();
|
| - }
|
| -
|
| - bool classNeedsRti(ClassElement cls);
|
| - bool methodNeedsRti(FunctionElement function);
|
| -
|
| - /// Enable compilation of code with compile time errors. Returns `true` if
|
| - /// supported by the backend.
|
| - bool enableCodegenWithErrorsIfSupported(Spannable node);
|
| -
|
| - /// Enable deferred loading. Returns `true` if the backend supports deferred
|
| - /// loading.
|
| - bool enableDeferredLoadingIfSupported(Spannable node, Registry registry);
|
| -
|
| - /// Called during codegen when [constant] has been used.
|
| - void registerCompileTimeConstant(ConstantValue constant, Registry registry) {}
|
| -
|
| - /// Called during resolution when a constant value for [metadata] on
|
| - /// [annotatedElement] has been evaluated.
|
| - void registerMetadataConstant(MetadataAnnotation metadata,
|
| - Element annotatedElement,
|
| - Registry registry) {}
|
| -
|
| - /// Called to notify to the backend that a class is being instantiated.
|
| - // TODO(johnniwinther): Remove this. It's only called once for each [cls] and
|
| - // only with [Compiler.globalDependencies] as [registry].
|
| - void registerInstantiatedClass(ClassElement cls,
|
| - Enqueuer enqueuer,
|
| - Registry registry) {}
|
| -
|
| - /// Called to notify to the backend that an interface type has been
|
| - /// instantiated.
|
| - void registerInstantiatedType(InterfaceType type, Registry registry) {}
|
| -
|
| - /// Register an is check to the backend.
|
| - void registerIsCheckForCodegen(DartType type,
|
| - Enqueuer enqueuer,
|
| - Registry registry) {}
|
| -
|
| - /// Register a runtime type variable bound tests between [typeArgument] and
|
| - /// [bound].
|
| - void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument,
|
| - DartType bound) {}
|
| -
|
| - /// Returns `true` if [element] represent the assert function.
|
| - bool isAssertMethod(Element element) => false;
|
| -
|
| - /**
|
| - * Call this to register that an instantiated generic class has a call
|
| - * method.
|
| - */
|
| - void registerCallMethodWithFreeTypeVariables(
|
| - Element callMethod,
|
| - Enqueuer enqueuer,
|
| - Registry registry) {}
|
| -
|
| - /**
|
| - * Call this to register that a getter exists for a function on an
|
| - * instantiated generic class.
|
| - */
|
| - void registerClosureWithFreeTypeVariables(
|
| - Element closure,
|
| - Enqueuer enqueuer,
|
| - Registry registry) {}
|
| -
|
| - /// Call this to register that a member has been closurized.
|
| - void registerBoundClosure(Enqueuer enqueuer) {}
|
| -
|
| - /// Call this to register that a static function has been closurized.
|
| - void registerGetOfStaticFunction(Enqueuer enqueuer) {}
|
| -
|
| - /**
|
| - * Call this to register that the [:runtimeType:] property has been accessed.
|
| - */
|
| - void registerRuntimeType(Enqueuer enqueuer, Registry registry) {}
|
| -
|
| - /// Call this to register a `noSuchMethod` implementation.
|
| - void registerNoSuchMethod(FunctionElement noSuchMethodElement) {}
|
| -
|
| - /// Call this method to enable support for `noSuchMethod`.
|
| - void enableNoSuchMethod(Enqueuer enqueuer) {}
|
| -
|
| - /// Returns whether or not `noSuchMethod` support has been enabled.
|
| - bool get enabledNoSuchMethod => false;
|
| -
|
| - /// Call this method to enable support for isolates.
|
| - void enableIsolateSupport(Enqueuer enqueuer) {}
|
| -
|
| - void registerRequiredType(DartType type, Element enclosingElement) {}
|
| - void registerClassUsingVariableExpression(ClassElement cls) {}
|
| -
|
| - void registerConstSymbol(String name, Registry registry) {}
|
| - void registerNewSymbol(Registry registry) {}
|
| -
|
| - bool isNullImplementation(ClassElement cls) {
|
| - return cls == compiler.nullClass;
|
| - }
|
| -
|
| - ClassElement get intImplementation => compiler.intClass;
|
| - ClassElement get doubleImplementation => compiler.doubleClass;
|
| - ClassElement get numImplementation => compiler.numClass;
|
| - ClassElement get stringImplementation => compiler.stringClass;
|
| - ClassElement get listImplementation => compiler.listClass;
|
| - ClassElement get growableListImplementation => compiler.listClass;
|
| - ClassElement get fixedListImplementation => compiler.listClass;
|
| - ClassElement get constListImplementation => compiler.listClass;
|
| - ClassElement get mapImplementation => compiler.mapClass;
|
| - ClassElement get constMapImplementation => compiler.mapClass;
|
| - ClassElement get functionImplementation => compiler.functionClass;
|
| - ClassElement get typeImplementation => compiler.typeClass;
|
| - ClassElement get boolImplementation => compiler.boolClass;
|
| - ClassElement get nullImplementation => compiler.nullClass;
|
| - ClassElement get uint32Implementation => compiler.intClass;
|
| - ClassElement get uint31Implementation => compiler.intClass;
|
| - ClassElement get positiveIntImplementation => compiler.intClass;
|
| -
|
| - ClassElement defaultSuperclass(ClassElement element) => compiler.objectClass;
|
| -
|
| - bool isInterceptorClass(ClassElement element) => false;
|
| -
|
| - /// Returns `true` if [element] is a foreign element, that is, that the
|
| - /// backend has specialized handling for the element.
|
| - bool isForeign(Element element) => false;
|
| -
|
| - /// Processes [element] for resolution and returns the [FunctionElement] that
|
| - /// defines the implementation of [element].
|
| - FunctionElement resolveExternalFunction(FunctionElement element) => element;
|
| -
|
| - /// Returns `true` if [library] is a backend specific library whose members
|
| - /// have special treatment, such as being allowed to extends blacklisted
|
| - /// classes or member being eagerly resolved.
|
| - bool isBackendLibrary(LibraryElement library) {
|
| - // TODO(johnniwinther): Remove this when patching is only done by the
|
| - // JavaScript backend.
|
| - Uri canonicalUri = library.canonicalUri;
|
| - if (canonicalUri == js_backend.JavaScriptBackend.DART_JS_HELPER ||
|
| - canonicalUri == js_backend.JavaScriptBackend.DART_INTERCEPTORS) {
|
| - return true;
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - void registerStaticUse(Element element, Enqueuer enqueuer) {}
|
| -
|
| - /// This method is called immediately after the [LibraryElement] [library] has
|
| - /// been created.
|
| - void onLibraryCreated(LibraryElement library) {}
|
| -
|
| - /// This method is called immediately after the [library] and its parts have
|
| - /// been scanned.
|
| - Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
|
| - if (library.canUseNative) {
|
| - library.forEachLocalMember((Element element) {
|
| - if (element.isClass) {
|
| - checkNativeAnnotation(compiler, element);
|
| - }
|
| - });
|
| - }
|
| - return new Future.value();
|
| - }
|
| -
|
| - /// This method is called when all new libraries loaded through
|
| - /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
|
| - /// have been computed.
|
| - Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
|
| - return new Future.value();
|
| - }
|
| -
|
| - /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
|
| - /// annotations. The arguments corresponds to the unions of the corresponding
|
| - /// fields of the annotations.
|
| - void registerMirrorUsage(Set<String> symbols,
|
| - Set<Element> targets,
|
| - Set<Element> metaTargets) {}
|
| -
|
| - /// Returns true if this element needs reflection information at runtime.
|
| - bool isAccessibleByReflection(Element element) => true;
|
| -
|
| - /// Returns true if this element is covered by a mirrorsUsed annotation.
|
| - ///
|
| - /// Note that it might still be ok to tree shake the element away if no
|
| - /// reflection is used in the program (and thus [isTreeShakingDisabled] is
|
| - /// still false). Therefore _do not_ use this predicate to decide inclusion
|
| - /// in the tree, use [requiredByMirrorSystem] instead.
|
| - bool referencedFromMirrorSystem(Element element, [recursive]) => false;
|
| -
|
| - /// Returns true if this element has to be enqueued due to
|
| - /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
|
| - /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
|
| - bool requiredByMirrorSystem(Element element) => false;
|
| -
|
| - /// Returns true if global optimizations such as type inferencing
|
| - /// can apply to this element. One category of elements that do not
|
| - /// apply is runtime helpers that the backend calls, but the
|
| - /// optimizations don't see those calls.
|
| - bool canBeUsedForGlobalOptimizations(Element element) => true;
|
| -
|
| - /// Called when [enqueuer]'s queue is empty, but before it is closed.
|
| - /// This is used, for example, by the JS backend to enqueue additional
|
| - /// elements needed for reflection. [recentClasses] is a collection of
|
| - /// all classes seen for the first time by the [enqueuer] since the last call
|
| - /// to [onQueueEmpty].
|
| - ///
|
| - /// A return value of [:true:] indicates that [recentClasses] has been
|
| - /// processed and its elements do not need to be seen in the next round. When
|
| - /// [:false:] is returned, [onQueueEmpty] will be called again once the
|
| - /// resolution queue has drained and [recentClasses] will be a superset of the
|
| - /// current value.
|
| - ///
|
| - /// There is no guarantee that a class is only present once in
|
| - /// [recentClasses], but every class seen by the [enqueuer] will be present in
|
| - /// [recentClasses] at least once.
|
| - bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) {
|
| - return true;
|
| - }
|
| -
|
| - /// Called after [element] has been resolved.
|
| - // TODO(johnniwinther): Change [TreeElements] to [Registry] or a dependency
|
| - // node. [elements] is currently unused by the implementation.
|
| - void onElementResolved(Element element, TreeElements elements) {}
|
| -
|
| - // Does this element belong in the output
|
| - bool shouldOutput(Element element) => true;
|
| -
|
| - FunctionElement helperForBadMain() => null;
|
| -
|
| - FunctionElement helperForMissingMain() => null;
|
| -
|
| - FunctionElement helperForMainArity() => null;
|
| -
|
| - void forgetElement(Element element) {}
|
| -
|
| - void registerMainHasArguments(Enqueuer enqueuer) {}
|
| -
|
| - void registerAsyncMarker(FunctionElement element,
|
| - Enqueuer enqueuer,
|
| - Registry registry) {}
|
| -}
|
| -
|
| -/// Backend callbacks function specific to the resolution phase.
|
| -class ResolutionCallbacks {
|
| - /// Register that [node] is a call to `assert`.
|
| - void onAssert(Send node, Registry registry) {}
|
| -
|
| - /// Register that an 'await for' has been seen.
|
| - void onAsyncForIn(AsyncForIn node, Registry registry) {}
|
| -
|
| - /// Called during resolution to notify to the backend that the
|
| - /// program uses string interpolation.
|
| - void onStringInterpolation(Registry registry) {}
|
| -
|
| - /// Called during resolution to notify to the backend that the
|
| - /// program has a catch statement.
|
| - void onCatchStatement(Registry registry) {}
|
| -
|
| - /// Called during resolution to notify to the backend that the
|
| - /// program explicitly throws an exception.
|
| - void onThrowExpression(Registry registry) {}
|
| -
|
| - /// Called during resolution to notify to the backend that the
|
| - /// program has a global variable with a lazy initializer.
|
| - void onLazyField(Registry registry) {}
|
| -
|
| - /// Called during resolution to notify to the backend that the
|
| - /// program uses a type variable as an expression.
|
| - void onTypeVariableExpression(Registry registry) {}
|
| -
|
| - /// Called during resolution to notify to the backend that the
|
| - /// program uses a type literal.
|
| - void onTypeLiteral(DartType type, Registry registry) {}
|
| -
|
| - /// Called during resolution to notify to the backend that the
|
| - /// program has a catch statement with a stack trace.
|
| - void onStackTraceInCatch(Registry registry) {}
|
| -
|
| - /// Register an is check to the backend.
|
| - void onIsCheck(DartType type, Registry registry) {}
|
| -
|
| - /// Called during resolution to notify to the backend that the
|
| - /// program has a for-in loop.
|
| - void onSyncForIn(Registry registry) {}
|
| -
|
| - /// Register an as check to the backend.
|
| - void onAsCheck(DartType type, Registry registry) {}
|
| -
|
| - /// Registers that a type variable bounds check might occur at runtime.
|
| - void onTypeVariableBoundCheck(Registry registry) {}
|
| -
|
| - /// Register that the application may throw a [NoSuchMethodError].
|
| - void onThrowNoSuchMethod(Registry registry) {}
|
| -
|
| - /// Register that the application may throw a [RuntimeError].
|
| - void onThrowRuntimeError(Registry registry) {}
|
| -
|
| - /// Register that the application may throw an
|
| - /// [AbstractClassInstantiationError].
|
| - void onAbstractClassInstantiation(Registry registry) {}
|
| -
|
| - /// Register that the application may throw a [FallThroughError].
|
| - void onFallThroughError(Registry registry) {}
|
| -
|
| - /// Register that a super call will end up calling
|
| - /// [: super.noSuchMethod :].
|
| - void onSuperNoSuchMethod(Registry registry) {}
|
| -
|
| - /// Register that the application creates a constant map.
|
| - void onMapLiteral(Registry registry, DartType type, bool isConstant) {}
|
| -
|
| - /// Called when resolving the `Symbol` constructor.
|
| - void onSymbolConstructor(Registry registry) {}
|
| -}
|
| -
|
| -/**
|
| - * Key class used in [TokenMap] in which the hash code for a token is based
|
| - * on the [charOffset].
|
| - */
|
| -class TokenKey {
|
| - final Token token;
|
| - TokenKey(this.token);
|
| - int get hashCode => token.charOffset;
|
| - operator==(other) => other is TokenKey && token == other.token;
|
| -}
|
| -
|
| -/// Map of tokens and the first associated comment.
|
| -/*
|
| - * This implementation was chosen among several candidates for its space/time
|
| - * efficiency by empirical tests of running dartdoc on dartdoc itself. Time
|
| - * measurements for the use of [Compiler.commentMap]:
|
| - *
|
| - * 1) Using [TokenKey] as key (this class): ~80 msec
|
| - * 2) Using [TokenKey] as key + storing a separate map in each script: ~120 msec
|
| - * 3) Using [Token] as key in a [Map]: ~38000 msec
|
| - * 4) Storing comments is new field in [Token]: ~20 msec
|
| - * (Abandoned due to the increased memory usage)
|
| - * 5) Storing comments in an [Expando]: ~14000 msec
|
| - * 6) Storing token/comments pairs in a linked list: ~5400 msec
|
| - */
|
| -class TokenMap {
|
| - Map<TokenKey,Token> comments = new Map<TokenKey,Token>();
|
| -
|
| - Token operator[] (Token key) {
|
| - if (key == null) return null;
|
| - return comments[new TokenKey(key)];
|
| - }
|
| -
|
| - void operator[]= (Token key, Token value) {
|
| - if (key == null) return;
|
| - comments[new TokenKey(key)] = value;
|
| - }
|
| -}
|
| +library dart2js.compiler_base;
|
| +
|
| +import 'dart:async' show
|
| + EventSink,
|
| + Future;
|
| +
|
| +import '../compiler_new.dart' as api;
|
| +import 'cache_strategy.dart' show
|
| + CacheStrategy;
|
| +import 'closure.dart' as closureMapping show
|
| + ClosureTask;
|
| +import 'common/backend_api.dart' show
|
| + Backend;
|
| +import 'common/codegen.dart' show
|
| + CodegenRegistry,
|
| + CodegenWorkItem;
|
| +import 'common/registry.dart' show
|
| + Registry;
|
| +import 'common/resolution.dart' show
|
| + ResolutionWorkItem;
|
| +import 'common/tasks.dart' show
|
| + CompilerTask,
|
| + GenericTask;
|
| +import 'common/work.dart' show
|
| + WorkItem;
|
| +import 'compile_time_constants.dart';
|
| +import 'constants/values.dart';
|
| +import 'core_types.dart' show
|
| + CoreTypes;
|
| +import 'cps_ir/cps_ir_builder_task.dart' show
|
| + IrBuilderTask;
|
| +import 'dart_backend/dart_backend.dart' as dart_backend;
|
| +import 'dart_types.dart' show
|
| + DartType,
|
| + DynamicType,
|
| + InterfaceType,
|
| + Types;
|
| +import 'deferred_load.dart' show DeferredLoadTask, OutputUnit;
|
| +import 'diagnostic_listener.dart';
|
| +import 'diagnostics/code_location.dart';
|
| +import 'diagnostics/invariant.dart' show
|
| + invariant,
|
| + REPORT_EXCESS_RESOLUTION;
|
| +import 'diagnostics/source_span.dart' show
|
| + SourceSpan;
|
| +import 'diagnostics/spannable.dart' show
|
| + CURRENT_ELEMENT_SPANNABLE,
|
| + NO_LOCATION_SPANNABLE,
|
| + Spannable,
|
| + SpannableAssertionFailure;
|
| +import 'dump_info.dart' show
|
| + DumpInfoTask;
|
| +import 'elements/elements.dart';
|
| +import 'elements/modelx.dart' show
|
| + ErroneousElementX,
|
| + ClassElementX,
|
| + CompilationUnitElementX,
|
| + DeferredLoaderGetterElementX,
|
| + MethodElementX,
|
| + LibraryElementX,
|
| + PrefixElementX,
|
| + VoidElementX;
|
| +import 'enqueue.dart' show
|
| + CodegenEnqueuer,
|
| + Enqueuer,
|
| + EnqueueTask,
|
| + ResolutionEnqueuer,
|
| + QueueFilter,
|
| + WorldImpact;
|
| +import 'io/source_information.dart' show
|
| + SourceInformation;
|
| +import 'js_backend/js_backend.dart' as js_backend show
|
| + JavaScriptBackend;
|
| +import 'library_loader.dart' show
|
| + LibraryLoader,
|
| + LibraryLoaderTask,
|
| + LoadedLibraries;
|
| +import 'messages.dart' show
|
| + Message,
|
| + MessageKind,
|
| + MessageTemplate;
|
| +import 'mirrors_used.dart' show
|
| + MirrorUsageAnalyzerTask;
|
| +import 'null_compiler_output.dart' show
|
| + NullCompilerOutput,
|
| + NullSink;
|
| +import 'patch_parser.dart' show
|
| + PatchParserTask;
|
| +import 'resolution/resolution.dart' show
|
| + ResolutionRegistry,
|
| + ResolverTask,
|
| + TreeElementMapping;
|
| +import 'scanner/token_map.dart' show
|
| + TokenMap;
|
| +import 'scanner/scannerlib.dart' show
|
| + COMMENT_TOKEN,
|
| + DietParserTask,
|
| + EOF_TOKEN,
|
| + ParserTask,
|
| + ScannerTask,
|
| + StringToken,
|
| + Token,
|
| + TokenPair;
|
| +import 'serialization/task.dart' show
|
| + SerializationTask;
|
| +import 'script.dart' show
|
| + Script;
|
| +import 'ssa/ssa.dart' show
|
| + HInstruction;
|
| +import 'tracer.dart' show
|
| + Tracer;
|
| +import 'tree/tree.dart' show
|
| + Node;
|
| +import 'typechecker.dart' show
|
| + TypeCheckerTask;
|
| +import 'types/types.dart' as ti;
|
| +import 'universe/universe.dart' show
|
| + Selector,
|
| + Universe;
|
| +import 'util/characters.dart' show $_;
|
| +import 'util/util.dart' show
|
| + Link;
|
| +import 'world.dart' show
|
| + World;
|
|
|
| abstract class Compiler implements DiagnosticListener {
|
| static final Uri DART_CORE = new Uri(scheme: 'dart', path: 'core');
|
| @@ -2189,130 +1653,6 @@ abstract class Compiler implements DiagnosticListener {
|
| }
|
| }
|
|
|
| -class CompilerTask {
|
| - final Compiler compiler;
|
| - final Stopwatch watch;
|
| - UserTag profilerTag;
|
| -
|
| - CompilerTask(Compiler compiler)
|
| - : this.compiler = compiler,
|
| - watch = (compiler.verbose) ? new Stopwatch() : null;
|
| -
|
| - String get name => "Unknown task '${this.runtimeType}'";
|
| - int get timing => (watch != null) ? watch.elapsedMilliseconds : 0;
|
| -
|
| - int get timingMicroseconds => (watch != null) ? watch.elapsedMicroseconds : 0;
|
| -
|
| - UserTag getProfilerTag() {
|
| - if (profilerTag == null) profilerTag = new UserTag(name);
|
| - return profilerTag;
|
| - }
|
| -
|
| - measure(action()) {
|
| - // In verbose mode when watch != null.
|
| - if (watch == null) return action();
|
| - CompilerTask previous = compiler.measuredTask;
|
| - if (identical(this, previous)) return action();
|
| - compiler.measuredTask = this;
|
| - if (previous != null) previous.watch.stop();
|
| - watch.start();
|
| - UserTag oldTag = getProfilerTag().makeCurrent();
|
| - try {
|
| - return action();
|
| - } finally {
|
| - watch.stop();
|
| - oldTag.makeCurrent();
|
| - if (previous != null) previous.watch.start();
|
| - compiler.measuredTask = previous;
|
| - }
|
| - }
|
| -
|
| - measureElement(Element element, action()) {
|
| - compiler.withCurrentElement(element, () => measure(action));
|
| - }
|
| -}
|
| -
|
| -class SourceSpan implements Spannable {
|
| - final Uri uri;
|
| - final int begin;
|
| - final int end;
|
| -
|
| - const SourceSpan(this.uri, this.begin, this.end);
|
| -
|
| - static withCharacterOffsets(Token begin, Token end,
|
| - f(int beginOffset, int endOffset)) {
|
| - final beginOffset = begin.charOffset;
|
| - final endOffset = end.charOffset + end.charCount;
|
| -
|
| - // [begin] and [end] might be the same for the same empty token. This
|
| - // happens for instance when scanning '$$'.
|
| - assert(endOffset >= beginOffset);
|
| - return f(beginOffset, endOffset);
|
| - }
|
| -
|
| - int get hashCode {
|
| - return 13 * uri.hashCode +
|
| - 17 * begin.hashCode +
|
| - 19 * end.hashCode;
|
| - }
|
| -
|
| - bool operator ==(other) {
|
| - if (identical(this, other)) return true;
|
| - if (other is! SourceSpan) return false;
|
| - return uri == other.uri &&
|
| - begin == other.begin &&
|
| - end == other.end;
|
| - }
|
| -
|
| - String toString() => 'SourceSpan($uri, $begin, $end)';
|
| -}
|
| -
|
| -/// Flag that can be used in assertions to assert that a code path is only
|
| -/// executed as part of development.
|
| -///
|
| -/// This flag is automatically set to true if helper methods like, [debugPrint],
|
| -/// [debugWrapPrint], [trace], and [reportHere] are called.
|
| -bool DEBUG_MODE = false;
|
| -
|
| -/// Assert that [DEBUG_MODE] is `true` and provide [message] as part of the
|
| -/// error message.
|
| -assertDebugMode(String message) {
|
| - assert(invariant(NO_LOCATION_SPANNABLE, DEBUG_MODE,
|
| - message: 'Debug mode is not enabled: $message'));
|
| -}
|
| -
|
| -/**
|
| - * Throws a [SpannableAssertionFailure] if [condition] is
|
| - * [:false:]. [condition] must be either a [:bool:] or a no-arg
|
| - * function returning a [:bool:].
|
| - *
|
| - * Use this method to provide better information for assertion by calling
|
| - * [invariant] as the argument to an [:assert:] statement:
|
| - *
|
| - * assert(invariant(position, isValid));
|
| - *
|
| - * [spannable] must be non-null and will be used to provide positional
|
| - * information in the generated error message.
|
| - */
|
| -bool invariant(Spannable spannable, var condition, {var message: null}) {
|
| - // TODO(johnniwinther): Use [spannable] and [message] to provide better
|
| - // information on assertion errors.
|
| - if (spannable == null) {
|
| - throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
|
| - "Spannable was null for invariant. Use CURRENT_ELEMENT_SPANNABLE.");
|
| - }
|
| - if (condition is Function){
|
| - condition = condition();
|
| - }
|
| - if (!condition) {
|
| - if (message is Function) {
|
| - message = message();
|
| - }
|
| - throw new SpannableAssertionFailure(spannable, message);
|
| - }
|
| - return true;
|
| -}
|
| -
|
| /// Returns `true` when [s] is private if used as an identifier.
|
| bool isPrivateName(String s) => !s.isEmpty && s.codeUnitAt(0) == $_;
|
|
|
| @@ -2325,96 +1665,6 @@ class SuppressionInfo {
|
| int hints = 0;
|
| }
|
|
|
| -class GenericTask extends CompilerTask {
|
| - final String name;
|
| -
|
| - GenericTask(this.name, Compiler compiler)
|
| - : super(compiler);
|
| -}
|
| -
|
| -/// [CodeLocation] divides uris into different classes.
|
| -///
|
| -/// These are used to group uris from user code, platform libraries and
|
| -/// packages.
|
| -abstract class CodeLocation {
|
| - /// Returns `true` if [uri] is in this code location.
|
| - bool inSameLocation(Uri uri);
|
| -
|
| - /// Returns the uri of this location relative to [baseUri].
|
| - String relativize(Uri baseUri);
|
| -
|
| - factory CodeLocation(Uri uri) {
|
| - if (uri.scheme == 'package') {
|
| - int slashPos = uri.path.indexOf('/');
|
| - if (slashPos != -1) {
|
| - String packageName = uri.path.substring(0, slashPos);
|
| - return new PackageLocation(packageName);
|
| - } else {
|
| - return new UriLocation(uri);
|
| - }
|
| - } else {
|
| - return new SchemeLocation(uri);
|
| - }
|
| - }
|
| -}
|
| -
|
| -/// A code location defined by the scheme of the uri.
|
| -///
|
| -/// Used for non-package uris, such as 'dart', 'file', and 'http'.
|
| -class SchemeLocation implements CodeLocation {
|
| - final Uri uri;
|
| -
|
| - SchemeLocation(this.uri);
|
| -
|
| - bool inSameLocation(Uri uri) {
|
| - return this.uri.scheme == uri.scheme;
|
| - }
|
| -
|
| - String relativize(Uri baseUri) {
|
| - return uri_extras.relativize(baseUri, uri, false);
|
| - }
|
| -}
|
| -
|
| -/// A code location defined by the package name.
|
| -///
|
| -/// Used for package uris, separated by their `package names`, that is, the
|
| -/// 'foo' of 'package:foo/bar.dart'.
|
| -class PackageLocation implements CodeLocation {
|
| - final String packageName;
|
| -
|
| - PackageLocation(this.packageName);
|
| -
|
| - bool inSameLocation(Uri uri) {
|
| - return uri.scheme == 'package' && uri.path.startsWith('$packageName/');
|
| - }
|
| -
|
| - String relativize(Uri baseUri) => 'package:$packageName';
|
| -}
|
| -
|
| -/// A code location defined by the whole uri.
|
| -///
|
| -/// Used for package uris with no package name. For instance 'package:foo.dart'.
|
| -class UriLocation implements CodeLocation {
|
| - final Uri uri;
|
| -
|
| - UriLocation(this.uri);
|
| -
|
| - bool inSameLocation(Uri uri) => this.uri == uri;
|
| -
|
| - String relativize(Uri baseUri) {
|
| - return uri_extras.relativize(baseUri, uri, false);
|
| - }
|
| -}
|
| -
|
| -/// A code location that contains any uri.
|
| -class AnyLocation implements CodeLocation {
|
| - const AnyLocation();
|
| -
|
| - bool inSameLocation(Uri uri) => true;
|
| -
|
| - String relativize(Uri baseUri) => '$baseUri';
|
| -}
|
| -
|
| class _CompilerCoreTypes implements CoreTypes {
|
| final Compiler compiler;
|
|
|
| @@ -2517,5 +1767,3 @@ class _CompilerCoreTypes implements CoreTypes {
|
| return type.createInstantiation([elementType]);
|
| }
|
| }
|
| -
|
| -typedef void InternalErrorFunction(Spannable location, String message);
|
|
|