| 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 library dart2js.backend_api; | 5 library dart2js.backend_api; |
| 6 | 6 |
| 7 import 'dart:async' show Future; | 7 import 'dart:async' show Future; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../common/codegen.dart' show CodegenImpact; | 10 import '../common/codegen.dart' show CodegenImpact; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 show checkNativeAnnotation, checkJsInteropAnnotation; | 38 show checkNativeAnnotation, checkJsInteropAnnotation; |
| 39 import '../serialization/serialization.dart' | 39 import '../serialization/serialization.dart' |
| 40 show DeserializerPlugin, SerializerPlugin; | 40 show DeserializerPlugin, SerializerPlugin; |
| 41 import '../tree/tree.dart' show Node; | 41 import '../tree/tree.dart' show Node; |
| 42 import '../universe/world_impact.dart' | 42 import '../universe/world_impact.dart' |
| 43 show ImpactStrategy, WorldImpact, WorldImpactBuilder; | 43 show ImpactStrategy, WorldImpact, WorldImpactBuilder; |
| 44 import '../world.dart' show ClosedWorld, ClosedWorldRefiner; | 44 import '../world.dart' show ClosedWorld, ClosedWorldRefiner; |
| 45 import 'codegen.dart' show CodegenWorkItem; | 45 import 'codegen.dart' show CodegenWorkItem; |
| 46 import 'tasks.dart' show CompilerTask; | 46 import 'tasks.dart' show CompilerTask; |
| 47 | 47 |
| 48 abstract class Backend extends Target { | |
| 49 final Compiler compiler; | |
| 50 | |
| 51 Backend(this.compiler); | |
| 52 | |
| 53 /// Returns true if the backend supports reflection. | |
| 54 bool get supportsReflection; | |
| 55 | |
| 56 /// The [ConstantSystem] used to interpret compile-time constants for this | |
| 57 /// backend. | |
| 58 ConstantSystem get constantSystem; | |
| 59 | |
| 60 /// The constant environment for the backend interpretation of compile-time | |
| 61 /// constants. | |
| 62 BackendConstantEnvironment get constants; | |
| 63 | |
| 64 /// The compiler task responsible for the compilation of constants for both | |
| 65 /// the frontend and the backend. | |
| 66 ConstantCompilerTask get constantCompilerTask; | |
| 67 | |
| 68 /// Backend transformation methods for the world impacts. | |
| 69 ImpactTransformer get impactTransformer; | |
| 70 | |
| 71 /// The strategy used for collecting and emitting source information. | |
| 72 SourceInformationStrategy get sourceInformationStrategy { | |
| 73 return const SourceInformationStrategy(); | |
| 74 } | |
| 75 | |
| 76 /// Common classes used by the backend. | |
| 77 BackendClasses get backendClasses; | |
| 78 | |
| 79 /// Interface for serialization of backend specific data. | |
| 80 BackendSerialization get serialization => const BackendSerialization(); | |
| 81 | |
| 82 // TODO(johnniwinther): Move this to the JavaScriptBackend. | |
| 83 String get patchVersion => null; | |
| 84 | |
| 85 /// Set of classes that need to be considered for reflection although not | |
| 86 /// otherwise visible during resolution. | |
| 87 Iterable<ClassElement> classesRequiredForReflection = const []; | |
| 88 | |
| 89 // Given a [FunctionElement], return a buffer with the code generated for it | |
| 90 // or null if no code was generated. | |
| 91 CodeBuffer codeOf(Element element) => null; | |
| 92 | |
| 93 void initializeHelperClasses() {} | |
| 94 | |
| 95 /// Compute the [WorldImpact] for backend helper methods. | |
| 96 WorldImpact computeHelpersImpact(); | |
| 97 | |
| 98 /// Creates an [Enqueuer] for code generation specific to this backend. | |
| 99 Enqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler); | |
| 100 | |
| 101 WorldImpact codegen(CodegenWorkItem work); | |
| 102 | |
| 103 // The backend determines the native resolution enqueuer, with a no-op | |
| 104 // default, so tools like dart2dart can ignore the native classes. | |
| 105 native.NativeEnqueuer nativeResolutionEnqueuer() { | |
| 106 return new native.NativeEnqueuer(); | |
| 107 } | |
| 108 | |
| 109 native.NativeEnqueuer nativeCodegenEnqueuer() { | |
| 110 return new native.NativeEnqueuer(); | |
| 111 } | |
| 112 | |
| 113 /// Generates the output and returns the total size of the generated code. | |
| 114 int assembleProgram(ClosedWorld closedWorld); | |
| 115 | |
| 116 List<CompilerTask> get tasks; | |
| 117 | |
| 118 void onResolutionComplete( | |
| 119 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) {} | |
| 120 void onTypeInferenceComplete() {} | |
| 121 | |
| 122 bool classNeedsRti(ClassElement cls); | |
| 123 bool methodNeedsRti(FunctionElement function); | |
| 124 | |
| 125 /// Enable compilation of code with compile time errors. Returns `true` if | |
| 126 /// supported by the backend. | |
| 127 bool enableCodegenWithErrorsIfSupported(Spannable node); | |
| 128 | |
| 129 /// Enable deferred loading. Returns `true` if the backend supports deferred | |
| 130 /// loading. | |
| 131 bool enableDeferredLoadingIfSupported(Spannable node); | |
| 132 | |
| 133 /// Returns the [WorldImpact] of enabling deferred loading. | |
| 134 WorldImpact computeDeferredLoadingImpact() => const WorldImpact(); | |
| 135 | |
| 136 /// Called during codegen when [constant] has been used. | |
| 137 void computeImpactForCompileTimeConstant(ConstantValue constant, | |
| 138 WorldImpactBuilder impactBuilder, bool isForResolution) {} | |
| 139 | |
| 140 /// Called to notify to the backend that a class is being instantiated. Any | |
| 141 /// backend specific [WorldImpact] of this is returned. | |
| 142 WorldImpact registerInstantiatedClass(ClassElement cls, | |
| 143 {bool forResolution}) => | |
| 144 const WorldImpact(); | |
| 145 | |
| 146 /// Called to notify to the backend that a class is implemented by an | |
| 147 /// instantiated class. Any backend specific [WorldImpact] of this is | |
| 148 /// returned. | |
| 149 WorldImpact registerImplementedClass(ClassElement cls, | |
| 150 {bool forResolution}) => | |
| 151 const WorldImpact(); | |
| 152 | |
| 153 /// Called to instruct to the backend register [type] as instantiated on | |
| 154 /// [enqueuer]. | |
| 155 void registerInstantiatedType(ResolutionInterfaceType type) {} | |
| 156 | |
| 157 /// Register a runtime type variable bound tests between [typeArgument] and | |
| 158 /// [bound]. | |
| 159 void registerTypeVariableBoundsSubtypeCheck( | |
| 160 ResolutionDartType typeArgument, ResolutionDartType bound) {} | |
| 161 | |
| 162 /// Called to instruct the backend to register that a closure exists for a | |
| 163 /// function on an instantiated generic class. Any backend specific | |
| 164 /// [WorldImpact] of this is returned. | |
| 165 WorldImpact registerClosureWithFreeTypeVariables(Element closure, | |
| 166 {bool forResolution}) => | |
| 167 const WorldImpact(); | |
| 168 | |
| 169 /// Called to register that a member has been closurized. Any backend specific | |
| 170 /// [WorldImpact] of this is returned. | |
| 171 WorldImpact registerBoundClosure() => const WorldImpact(); | |
| 172 | |
| 173 /// Called to register that a static function has been closurized. Any backend | |
| 174 /// specific [WorldImpact] of this is returned. | |
| 175 WorldImpact registerGetOfStaticFunction() => const WorldImpact(); | |
| 176 | |
| 177 /// Returns whether or not `noSuchMethod` support has been enabled. | |
| 178 bool get enabledNoSuchMethod => false; | |
| 179 | |
| 180 /// Called to enable support for isolates. Any backend specific [WorldImpact] | |
| 181 /// of this is returned. | |
| 182 WorldImpact enableIsolateSupport({bool forResolution}); | |
| 183 | |
| 184 void registerConstSymbol(String name) {} | |
| 185 | |
| 186 ClassElement defaultSuperclass(ClassElement element) { | |
| 187 return compiler.commonElements.objectClass; | |
| 188 } | |
| 189 | |
| 190 bool isInterceptorClass(ClassElement element) => false; | |
| 191 | |
| 192 /// Returns `true` if [element] is implemented via typed JavaScript interop. | |
| 193 // TODO(johnniwinther): Move this to [JavaScriptBackend]. | |
| 194 bool isJsInterop(Element element) => false; | |
| 195 | |
| 196 /// Returns `true` if the `native` pseudo keyword is supported for [library]. | |
| 197 bool canLibraryUseNative(LibraryElement library) { | |
| 198 // TODO(johnniwinther): Move this to [JavaScriptBackend]. | |
| 199 return native.maybeEnableNative(compiler, library); | |
| 200 } | |
| 201 | |
| 202 @override | |
| 203 bool isTargetSpecificLibrary(LibraryElement library) { | |
| 204 // TODO(johnniwinther): Remove this when patching is only done by the | |
| 205 // JavaScript backend. | |
| 206 Uri canonicalUri = library.canonicalUri; | |
| 207 if (canonicalUri == js_backend.BackendHelpers.DART_JS_HELPER || | |
| 208 canonicalUri == js_backend.BackendHelpers.DART_INTERCEPTORS) { | |
| 209 return true; | |
| 210 } | |
| 211 return false; | |
| 212 } | |
| 213 | |
| 214 /// Called to register that [element] is statically known to be used. Any | |
| 215 /// backend specific [WorldImpact] of this is returned. | |
| 216 WorldImpact registerUsedElement(MemberElement element, | |
| 217 {bool forResolution}) => | |
| 218 const WorldImpact(); | |
| 219 | |
| 220 /// This method is called immediately after the [library] and its parts have | |
| 221 /// been scanned. | |
| 222 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { | |
| 223 // TODO(johnniwinther): Move this to [JavaScriptBackend]. | |
| 224 if (!compiler.serialization.isDeserialized(library)) { | |
| 225 if (canLibraryUseNative(library)) { | |
| 226 library.forEachLocalMember((Element element) { | |
| 227 if (element.isClass) { | |
| 228 checkNativeAnnotation(compiler, element); | |
| 229 } | |
| 230 }); | |
| 231 } | |
| 232 checkJsInteropAnnotation(compiler, library); | |
| 233 library.forEachLocalMember((Element element) { | |
| 234 checkJsInteropAnnotation(compiler, element); | |
| 235 if (element.isClass && isJsInterop(element)) { | |
| 236 ClassElement classElement = element; | |
| 237 classElement.forEachMember((_, memberElement) { | |
| 238 checkJsInteropAnnotation(compiler, memberElement); | |
| 239 }); | |
| 240 } | |
| 241 }); | |
| 242 } | |
| 243 return new Future.value(); | |
| 244 } | |
| 245 | |
| 246 /// This method is called when all new libraries loaded through | |
| 247 /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports | |
| 248 /// have been computed. | |
| 249 Future onLibrariesLoaded(LoadedLibraries loadedLibraries) { | |
| 250 return new Future.value(); | |
| 251 } | |
| 252 | |
| 253 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed | |
| 254 /// annotations. The arguments corresponds to the unions of the corresponding | |
| 255 /// fields of the annotations. | |
| 256 void registerMirrorUsage( | |
| 257 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) {} | |
| 258 | |
| 259 /// Returns true if this element needs reflection information at runtime. | |
| 260 bool isAccessibleByReflection(Element element) => true; | |
| 261 | |
| 262 /// Returns true if this member element needs reflection information at | |
| 263 /// runtime. | |
| 264 bool isMemberAccessibleByReflection(MemberElement element) => true; | |
| 265 | |
| 266 /// Returns true if this element is covered by a mirrorsUsed annotation. | |
| 267 /// | |
| 268 /// Note that it might still be ok to tree shake the element away if no | |
| 269 /// reflection is used in the program (and thus [isTreeShakingDisabled] is | |
| 270 /// still false). Therefore _do not_ use this predicate to decide inclusion | |
| 271 /// in the tree, use [requiredByMirrorSystem] instead. | |
| 272 bool referencedFromMirrorSystem(Element element, [recursive]) => false; | |
| 273 | |
| 274 /// Returns true if this element has to be enqueued due to | |
| 275 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if | |
| 276 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). | |
| 277 bool requiredByMirrorSystem(Element element) => false; | |
| 278 | |
| 279 /// Returns true if global optimizations such as type inferencing | |
| 280 /// can apply to this element. One category of elements that do not | |
| 281 /// apply is runtime helpers that the backend calls, but the | |
| 282 /// optimizations don't see those calls. | |
| 283 bool canBeUsedForGlobalOptimizations(Element element) => true; | |
| 284 | |
| 285 /// Called when [enqueuer]'s queue is empty, but before it is closed. | |
| 286 /// This is used, for example, by the JS backend to enqueue additional | |
| 287 /// elements needed for reflection. [recentClasses] is a collection of | |
| 288 /// all classes seen for the first time by the [enqueuer] since the last call | |
| 289 /// to [onQueueEmpty]. | |
| 290 /// | |
| 291 /// A return value of [:true:] indicates that [recentClasses] has been | |
| 292 /// processed and its elements do not need to be seen in the next round. When | |
| 293 /// [:false:] is returned, [onQueueEmpty] will be called again once the | |
| 294 /// resolution queue has drained and [recentClasses] will be a superset of the | |
| 295 /// current value. | |
| 296 /// | |
| 297 /// There is no guarantee that a class is only present once in | |
| 298 /// [recentClasses], but every class seen by the [enqueuer] will be present in | |
| 299 /// [recentClasses] at least once. | |
| 300 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) { | |
| 301 return true; | |
| 302 } | |
| 303 | |
| 304 /// Called after the queue is closed. [onQueueEmpty] may be called multiple | |
| 305 /// times, but [onQueueClosed] is only called once. | |
| 306 void onQueueClosed() {} | |
| 307 | |
| 308 /// Called when the compiler starts running the codegen enqueuer. The | |
| 309 /// [WorldImpact] of enabled backend features is returned. | |
| 310 WorldImpact onCodegenStart(ClosedWorld closedWorld) => const WorldImpact(); | |
| 311 | |
| 312 /// Called when code generation has been completed. | |
| 313 void onCodegenEnd() {} | |
| 314 | |
| 315 // Does this element belong in the output | |
| 316 bool shouldOutput(Element element) => true; | |
| 317 | |
| 318 MethodElement helperForBadMain() => null; | |
| 319 | |
| 320 MethodElement helperForMissingMain() => null; | |
| 321 | |
| 322 MethodElement helperForMainArity() => null; | |
| 323 | |
| 324 /// Computes the [WorldImpact] of calling [mainMethod] as the entry point. | |
| 325 WorldImpact computeMainImpact(MethodElement mainMethod, | |
| 326 {bool forResolution}) => | |
| 327 const WorldImpact(); | |
| 328 | |
| 329 /// Returns the location of the patch-file associated with [libraryName] | |
| 330 /// resolved from [plaformConfigUri]. | |
| 331 /// | |
| 332 /// Returns null if there is none. | |
| 333 Uri resolvePatchUri(String libraryName, Uri plaformConfigUri); | |
| 334 | |
| 335 /// Creates an impact strategy to use for compilation. | |
| 336 ImpactStrategy createImpactStrategy( | |
| 337 {bool supportDeferredLoad: true, | |
| 338 bool supportDumpInfo: true, | |
| 339 bool supportSerialization: true}) { | |
| 340 return const ImpactStrategy(); | |
| 341 } | |
| 342 | |
| 343 /// Backend access to the front-end. | |
| 344 Frontend get frontend => compiler.resolution; | |
| 345 | |
| 346 EnqueueTask makeEnqueuer() => new EnqueueTask(compiler); | |
| 347 } | |
| 348 | |
| 349 /// Interface for resolving native data for a target specific element. | 48 /// Interface for resolving native data for a target specific element. |
| 350 abstract class NativeRegistry { | 49 abstract class NativeRegistry { |
| 351 /// Registers [nativeData] as part of the resolution impact. | 50 /// Registers [nativeData] as part of the resolution impact. |
| 352 void registerNativeData(dynamic nativeData); | 51 void registerNativeData(dynamic nativeData); |
| 353 } | 52 } |
| 354 | 53 |
| 355 /// Interface for resolving calls to foreign functions. | 54 /// Interface for resolving calls to foreign functions. |
| 356 abstract class ForeignResolver { | 55 abstract class ForeignResolver { |
| 357 /// Returns the constant expression of [node], or `null` if [node] is not | 56 /// Returns the constant expression of [node], or `null` if [node] is not |
| 358 /// a constant expression. | 57 /// a constant expression. |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 /// Returns `true` if [cls] is an intercepted class. | 203 /// Returns `true` if [cls] is an intercepted class. |
| 505 // TODO(johnniwinther): Rename this to `isInterceptedClass`. | 204 // TODO(johnniwinther): Rename this to `isInterceptedClass`. |
| 506 bool isInterceptorClass(ClassEntity cls); | 205 bool isInterceptorClass(ClassEntity cls); |
| 507 | 206 |
| 508 /// Returns `true` if [cls] is a native class. | 207 /// Returns `true` if [cls] is a native class. |
| 509 bool isNativeClass(ClassEntity element); | 208 bool isNativeClass(ClassEntity element); |
| 510 | 209 |
| 511 /// Returns `true` if [element] is a native member of a native class. | 210 /// Returns `true` if [element] is a native member of a native class. |
| 512 bool isNativeMember(MemberEntity element); | 211 bool isNativeMember(MemberEntity element); |
| 513 } | 212 } |
| OLD | NEW |