Linter Demo Errors: 3Warnings: 20File: /home/fstrocco/Dart/dart/benchmark/compiler/lib/src/dart_backend/backend.dart // 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. part of dart_backend; // TODO(ahe): This class is simply wrong. This backend should use // elements when it can, not AST nodes. Perhaps a [Map] is what is needed. class ElementAst { final Node ast; final TreeElements treeElements; ElementAst(this.ast, this.treeElements); } class DartBackend extends Backend { final List tasks; final bool stripAsserts; // TODO(zarah) Maybe change this to a command-line option. // Right now, it is set by the tests. bool useMirrorHelperLibrary = false; /// Updated to a [MirrorRenamerImpl] instance if the [useMirrorHelperLibrary] /// field is set and mirror are needed. MirrorRenamer mirrorRenamer = const MirrorRenamer(); final DartOutputter outputter; // Used in test. PlaceholderRenamer get placeholderRenamer => outputter.renamer; Map> get memberNodes => outputter.output.memberNodes; ConstantSystem get constantSystem { return constantCompilerTask.constantCompiler.constantSystem; } BackendConstantEnvironment get constants => constantCompilerTask; DartConstantTask constantCompilerTask; DartResolutionCallbacks resolutionCallbacks; final Set usedTypeLiterals = new Set(); /// The set of visible platform classes that are implemented by instantiated /// user classes. final Set _userImplementedPlatformClasses = new Set(); bool get canHandleCompilationFailed => false; /** * Tells whether it is safe to remove type declarations from variables, * functions parameters. It becomes not safe if: * 1) TypeError is used somewhere in the code, * 2) The code has typedefs in right hand side of IS checks, * 3) The code has classes which extend typedefs, have type arguments typedefs * or type variable bounds typedefs. * These restrictions can be less strict. */ bool isSafeToRemoveTypeDeclarations( Map> classMembers) { ClassElement typeErrorElement = compiler.coreLibrary.find('TypeError'); if (classMembers.containsKey(typeErrorElement) || compiler.resolverWorld.isChecks.any( (DartType type) => type.element == typeErrorElement)) { return false; } Set processedTypes = new Set(); List workQueue = new List(); workQueue.addAll( classMembers.keys.map((classElement) => classElement.thisType)); workQueue.addAll(compiler.resolverWorld.isChecks); while (!workQueue.isEmpty) { DartType type = workQueue.removeLast(); if (processedTypes.contains(type)) continue; processedTypes.add(type); if (type is FunctionType) return false; if (type is TypedefType) return false; if (type is InterfaceType) { InterfaceType interfaceType = type; // Check all type arguments. interfaceType.typeArguments.forEach(workQueue.add); ClassElement element = type.element; // Check all supertypes. if (element.allSupertypes != null) { element.allSupertypes.forEach(workQueue.add); } } } return true; } DartBackend(Compiler compiler, List strips, {bool multiFile}) : tasks = [], stripAsserts = strips.indexOf('asserts') != -1, constantCompilerTask = new DartConstantTask(compiler), outputter = new DartOutputter( compiler, compiler.outputProvider, forceStripTypes: strips.indexOf('types') != -1, multiFile: multiFile, enableMinification: compiler.enableMinification), super(compiler) { resolutionCallbacks = new DartResolutionCallbacks(this); } bool classNeedsRti(ClassElement cls) => false; bool methodNeedsRti(FunctionElement function) => false; void enqueueHelpers(ResolutionEnqueuer world, Registry registry) { // Right now resolver doesn't always resolve interfaces needed // for literals, so force them. TODO(antonm): fix in the resolver. final LITERAL_TYPE_NAMES = const [ 'Map', 'List', 'num', 'int', 'double', 'bool' ]; final coreLibrary = compiler.coreLibrary; for (final name in LITERAL_TYPE_NAMES) { ClassElement classElement = coreLibrary.findLocal(name); classElement.ensureResolved(compiler); } // Enqueue the methods that the VM might invoke on user objects because // we don't trust the resolution to always get these included. world.registerInvocation(new Selector.call("toString", null, 0)); world.registerInvokedGetter(new Selector.getter("hashCode", null)); world.registerInvocation(new Selector.binaryOperator("==")); world.registerInvocation(new Selector.call("compareTo", null, 1)); } void codegen(CodegenWorkItem work) { } static bool checkTreeIntegrity(tree_ir.RootNode node) { new CheckTreeIntegrity().check(node); return true; // So this can be used from assert(). } static bool checkCpsIntegrity(cps_ir.RootNode node) { new CheckCpsIntegrity().check(node); return true; // So this can be used from assert(). } /// Create an [ElementAst] from the CPS IR. static ElementAst createElementAst( ElementAstCreationContext context, Element element, cps_ir.RootNode cpsRoot) { context.traceCompilation(element.name); context.traceGraph('CPS builder', cpsRoot); assert(checkCpsIntegrity(cpsRoot)); // Transformations on the CPS IR. void applyCpsPass(cps_opt.Pass pass) { pass.rewrite(cpsRoot); context.traceGraph(pass.passName, cpsRoot); assert(checkCpsIntegrity(cpsRoot)); } // TODO(karlklose): enable type propagation for dart2dart when constant // types are correctly marked as instantiated (Issue 21880). TypePropagator typePropagator = new TypePropagator( context.dartTypes, context.constantSystem, new UnitTypeSystem(), context.internalError); applyCpsPass(typePropagator); applyCpsPass(new RedundantPhiEliminator()); applyCpsPass(new ShrinkingReducer()); tree_builder.Builder builder = new tree_builder.Builder(context.internalError); tree_ir.RootNode treeRoot = builder.build(cpsRoot); assert(treeRoot != null); context.traceGraph('Tree builder', treeRoot); assert(checkTreeIntegrity(treeRoot)); // Transformations on the Tree IR. void applyTreePass(tree_opt.Pass pass) { pass.rewrite(treeRoot); context.traceGraph(pass.passName, treeRoot); assert(checkTreeIntegrity(treeRoot)); } applyTreePass(new StatementRewriter()); applyTreePass(new VariableMerger()); applyTreePass(new LoopRewriter()); applyTreePass(new LogicalRewriter()); // Backend-specific transformations. new backend_ast_emitter.UnshadowParameters().unshadow(treeRoot); context.traceGraph('Unshadow parameters', treeRoot); TreeElementMapping treeElements = new TreeElementMapping(element); backend_ast.RootNode backendAst = backend_ast_emitter.emit(treeRoot); Node frontend_ast = backend2frontend.emit(treeElements, backendAst); return new ElementAst(frontend_ast, treeElements); } /** * Tells whether we should output given element. Corelib classes like * Object should not be in the resulting code. */ @override bool shouldOutput(Element element) { return (!element.library.isPlatformLibrary && !element.isSynthesized && element is! AbstractFieldElement) || mirrorRenamer.isMirrorHelperLibrary(element.library); } int assembleProgram() { ElementAstCreationContext context = new _ElementAstCreationContext(compiler, constantSystem); ElementAst computeElementAst(AstElement element) { if (!compiler.irBuilder.hasIr(element)) { return new ElementAst(element.resolvedAst.node, element.resolvedAst.elements); } else { cps_ir.RootNode irNode = compiler.irBuilder.getIr(element); return createElementAst(context, element, irNode); } } // TODO(johnniwinther): Remove the need for this method. void postProcessElementAst( AstElement element, ElementAst elementAst, newTypedefElementCallback, newClassElementCallback) { ReferencedElementCollector collector = new ReferencedElementCollector(compiler, element, elementAst, newTypedefElementCallback, newClassElementCallback); collector.collect(); } int totalSize = outputter.assembleProgram( libraries: compiler.libraryLoader.libraries, instantiatedClasses: compiler.resolverWorld.directlyInstantiatedClasses, resolvedElements: compiler.enqueuer.resolution.resolvedElements, usedTypeLiterals: usedTypeLiterals, postProcessElementAst: postProcessElementAst, computeElementAst: computeElementAst, shouldOutput: shouldOutput, isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations, sortElements: Elements.sortedByPosition, mirrorRenamer: mirrorRenamer, mainFunction: compiler.mainFunction, outputUri: compiler.outputUri); // Output verbose info about size ratio of resulting bundle to all // referenced non-platform sources. logResultBundleSizeInfo( outputter.libraryInfo.userLibraries, outputter.elementInfo.topLevelElements, totalSize); return totalSize; } void logResultBundleSizeInfo(Iterable userLibraries, Iterable topLevelElements, int totalOutputSize) { // Sum total size of scripts in each referenced library. int nonPlatformSize = 0; for (LibraryElement lib in userLibraries) { for (CompilationUnitElement compilationUnit in lib.compilationUnits) { nonPlatformSize += compilationUnit.script.file.length; } } int percentage = totalOutputSize * 100 ~/ nonPlatformSize; log('Total used non-platform files size: ${nonPlatformSize} bytes, ' 'Output total size: $totalOutputSize bytes (${percentage}%)'); } log(String message) => compiler.log('[DartBackend] $message'); @override Future onLibrariesLoaded(LoadedLibraries loadedLibraries) { // All platform classes must be resolved to ensure that their member names // are preserved. loadedLibraries.forEachLibrary((LibraryElement library) { if (library.isPlatformLibrary) { library.forEachLocalMember((Element element) { if (element.isClass) { ClassElement classElement = element; classElement.ensureResolved(compiler); } }); } }); if (useMirrorHelperLibrary && loadedLibraries.containsLibrary(Compiler.DART_MIRRORS)) { return compiler.libraryLoader.loadLibrary( compiler.translateResolvedUri( loadedLibraries.getLibrary(Compiler.DART_MIRRORS), MirrorRenamerImpl.DART_MIRROR_HELPER, null)). then((LibraryElement library) { mirrorRenamer = new MirrorRenamerImpl(compiler, this, library); }); } return new Future.value(); } @override void registerStaticUse(Element element, Enqueuer enqueuer) { if (element == compiler.mirrorSystemGetNameFunction) { FunctionElement getNameFunction = mirrorRenamer.getNameFunction; if (getNameFunction != null) { enqueuer.addToWorkList(getNameFunction); } } } @override void registerInstantiatedType(InterfaceType type, Registry registry) { // Without patching, dart2dart has no way of performing sound tree-shaking // in face external functions. Therefore we employ another scheme: // // Based on the assumption that the platform code only relies on the // interfaces of it's own classes, we can approximate the semantics of // external functions by eagerly registering dynamic invocation of instance // members defined the platform interfaces. // // Since we only need to generate code for non-platform classes we can // restrict this registration to platform interfaces implemented by // instantiated non-platform classes. // // Consider for instance this program: // // import 'dart:math' show Random; // // class MyRandom implements Random { // int nextInt() => 0; // } // // main() { // print([0, 1, 2].shuffle(new MyRandom())); // } // // Here `MyRandom` is a subtype if `Random` defined in 'dart:math'. By the // assumption, all methods defined `Random` are potentially called, and // therefore, though there are no visible call sites from the user node, // dynamic invocation of for instance `nextInt` should be registered. In // this case, `nextInt` is actually called by the standard implementation of // `shuffle`. ClassElement cls = type.element; if (!cls.library.isPlatformLibrary) { for (Link link = cls.allSupertypes; !link.isEmpty; link = link.tail) { InterfaceType supertype = link.head; ClassElement superclass = supertype.element; LibraryElement library = superclass.library; if (library.isPlatformLibrary) { if (_userImplementedPlatformClasses.add(superclass)) { // Register selectors for all instance methods since these might // be called on user classes from within the platform // implementation. superclass.forEachLocalMember((Element element) { if (element.isConstructor || element.isStatic) return; FunctionElement function = element.asFunctionElement(); if (function != null) { function.computeSignature(compiler); } Selector selector = new Selector.fromElement(element); if (selector.isGetter) { registry.registerDynamicGetter(selector); } else if (selector.isSetter) { registry.registerDynamicSetter(selector); } else { registry.registerDynamicInvocation(selector); } }); } } } } } } class DartResolutionCallbacks extends ResolutionCallbacks { final DartBackend backend; DartResolutionCallbacks(this.backend); void onTypeLiteral(DartType type, Registry registry) { if (type.isInterfaceType) { backend.usedTypeLiterals.add(type.element); } } } class EmitterUnparser extends Unparser { final Map renames; EmitterUnparser(this.renames, {bool minify, bool stripTypes}) : super(minify: minify, stripTypes: stripTypes); visit(Node node) { if (node != null && renames.containsKey(node)) { write(renames[node]); } else { super.visit(node); } } unparseSendReceiver(Send node, {bool spacesNeeded: false}) { // TODO(smok): Remove ugly hack for library prefices. if (node.receiver != null && renames[node.receiver] == '') return; super.unparseSendReceiver(node, spacesNeeded: spacesNeeded); } unparseFunctionName(Node name) { if (name != null && renames.containsKey(name)) { write(renames[name]); } else { super.unparseFunctionName(name); } } } /** * Some elements are not recorded by resolver now, * for example, typedefs or classes which are only * used in signatures, as/is operators or in super clauses * (just to name a few). Retraverse AST to pick those up. */ class ReferencedElementCollector extends Visitor { final Compiler compiler; final Element element; final ElementAst elementAst; final newTypedefElementCallback; final newClassElementCallback; ReferencedElementCollector(this.compiler, this.element, this.elementAst, this.newTypedefElementCallback, this.newClassElementCallback); visitNode(Node node) { node.visitChildren(this); } visitTypeAnnotation(TypeAnnotation typeAnnotation) { TreeElements treeElements = elementAst.treeElements; final DartType type = treeElements.getType(typeAnnotation); assert(invariant(typeAnnotation, type != null, message: "Missing type for type annotation: $treeElements.")); if (type.isTypedef) newTypedefElementCallback(type.element); if (type.isInterfaceType) newClassElementCallback(type.element); typeAnnotation.visitChildren(this); } void collect() { compiler.withCurrentElement(element, () { elementAst.ast.accept(this); }); } } Comparator compareBy(f) => (x, y) => f(x).compareTo(f(y)); List sorted(Iterable l, comparison) { final result = new List.from(l); result.sort(comparison); return result; } compareElements(e0, e1) { int result = compareBy((e) => e.library.canonicalUri.toString())(e0, e1); if (result != 0) return result; return compareBy((e) => e.position.charOffset)(e0, e1); } /// [ConstantCompilerTask] for compilation of constants for the Dart backend. /// /// Since this task needs no distinction between frontend and backend constants /// it also serves as the [BackendConstantEnvironment]. class DartConstantTask extends ConstantCompilerTask implements BackendConstantEnvironment { final DartConstantCompiler constantCompiler; DartConstantTask(Compiler compiler) : this.constantCompiler = new DartConstantCompiler(compiler), super(compiler); String get name => 'ConstantHandler'; ConstantExpression getConstantForVariable(VariableElement element) { return constantCompiler.getConstantForVariable(element); } ConstantExpression getConstantForNode(Node node, TreeElements elements) { return constantCompiler.getConstantForNode(node, elements); } ConstantExpression getConstantForMetadata(MetadataAnnotation metadata) { return metadata.constant; } ConstantExpression compileConstant(VariableElement element) { return measure(() { return constantCompiler.compileConstant(element); }); } void compileVariable(VariableElement element) { measure(() { constantCompiler.compileVariable(element); }); } ConstantExpression compileNode(Node node, TreeElements elements) { return measure(() { return constantCompiler.compileNodeWithDefinitions(node, elements); }); } ConstantExpression compileMetadata(MetadataAnnotation metadata, Node node, TreeElements elements) { return measure(() { return constantCompiler.compileMetadata(metadata, node, elements); }); } } abstract class ElementAstCreationContext { DartTypes get dartTypes; ConstantSystem get constantSystem; InternalErrorFunction get internalError; void traceCompilation(String name); void traceGraph(String title, var irObject); } class _ElementAstCreationContext implements ElementAstCreationContext { final Compiler compiler; final ConstantSystem constantSystem; _ElementAstCreationContext(this.compiler, this.constantSystem); void traceCompilation(String name) { compiler.tracer.traceCompilation(name, null); } void traceGraph(String title, var irObject) { compiler.tracer.traceGraph(title, irObject); } DartTypes get dartTypes => compiler.types; InternalErrorFunction get internalError => compiler.internalError; }