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

Side by Side Diff: pkg/compiler/lib/src/compiler.dart

Issue 1284593003: Remove dart2jslib.dart (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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 unified diff | Download patch
OLDNEW
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 part of dart2js; 5 library dart2js.compiler_base;
6 6
7 /** 7 import 'dart:async' show
8 * If true, print a warning for each method that was resolved, but not 8 EventSink,
9 * compiled. 9 Future;
10 */
11 const bool REPORT_EXCESS_RESOLUTION = false;
12 10
13 /** 11 import '../compiler_new.dart' as api;
14 * Contains backend-specific data that is used throughout the compilation of 12 import 'cache_strategy.dart' show
15 * one work item. 13 CacheStrategy;
16 */ 14 import 'closure.dart' as closureMapping show
17 class ItemCompilationContext { 15 ClosureTask;
18 } 16 import 'common/backend_api.dart' show
19 17 Backend;
20 abstract class WorkItem { 18 import 'common/codegen.dart' show
21 final ItemCompilationContext compilationContext; 19 CodegenRegistry,
22 /** 20 CodegenWorkItem;
23 * Documentation wanted -- johnniwinther 21 import 'common/registry.dart' show
24 * 22 Registry;
25 * Invariant: [element] must be a declaration element. 23 import 'common/resolution.dart' show
26 */ 24 ResolutionWorkItem;
27 final AstElement element; 25 import 'common/tasks.dart' show
28 26 CompilerTask,
29 WorkItem(this.element, this.compilationContext) { 27 GenericTask;
30 assert(invariant(element, element.isDeclaration)); 28 import 'common/work.dart' show
31 } 29 WorkItem;
32 30 import 'compile_time_constants.dart';
33 WorldImpact run(Compiler compiler, Enqueuer world); 31 import 'constants/values.dart';
34 } 32 import 'core_types.dart' show
35 33 CoreTypes;
36 /// [WorkItem] used exclusively by the [ResolutionEnqueuer]. 34 import 'cps_ir/cps_ir_builder_task.dart' show
37 class ResolutionWorkItem extends WorkItem { 35 IrBuilderTask;
38 bool _isAnalyzed = false; 36 import 'dart_backend/dart_backend.dart' as dart_backend;
39 37 import 'dart_types.dart' show
40 ResolutionWorkItem(AstElement element, 38 DartType,
41 ItemCompilationContext compilationContext) 39 DynamicType,
42 : super(element, compilationContext); 40 InterfaceType,
43 41 Types;
44 WorldImpact run(Compiler compiler, ResolutionEnqueuer world) { 42 import 'deferred_load.dart' show DeferredLoadTask, OutputUnit;
45 WorldImpact impact = compiler.analyze(this, world); 43 import 'diagnostic_listener.dart';
46 _isAnalyzed = true; 44 import 'diagnostics/code_location.dart';
47 return impact; 45 import 'diagnostics/invariant.dart' show
48 } 46 invariant,
49 47 REPORT_EXCESS_RESOLUTION;
50 bool get isAnalyzed => _isAnalyzed; 48 import 'diagnostics/source_span.dart' show
51 } 49 SourceSpan;
52 50 import 'diagnostics/spannable.dart' show
53 // TODO(johnniwinther): Split this class into interface and implementation. 51 CURRENT_ELEMENT_SPANNABLE,
54 // TODO(johnniwinther): Move this implementation to the JS backend. 52 NO_LOCATION_SPANNABLE,
55 class CodegenRegistry extends Registry { 53 Spannable,
56 final Compiler compiler; 54 SpannableAssertionFailure;
57 final TreeElements treeElements; 55 import 'dump_info.dart' show
58 56 DumpInfoTask;
59 CodegenRegistry(this.compiler, this.treeElements); 57 import 'elements/elements.dart';
60 58 import 'elements/modelx.dart' show
61 bool get isForResolution => false; 59 ErroneousElementX,
62 60 ClassElementX,
63 Element get currentElement => treeElements.analyzedElement; 61 CompilationUnitElementX,
64 62 DeferredLoaderGetterElementX,
65 // TODO(johnniwinther): Remove this getter when [Registry] creates a 63 MethodElementX,
66 // dependency node. 64 LibraryElementX,
67 Setlet<Element> get otherDependencies => treeElements.otherDependencies; 65 PrefixElementX,
68 66 VoidElementX;
69 CodegenEnqueuer get world => compiler.enqueuer.codegen; 67 import 'enqueue.dart' show
70 js_backend.JavaScriptBackend get backend => compiler.backend; 68 CodegenEnqueuer,
71 69 Enqueuer,
72 void registerDependency(Element element) { 70 EnqueueTask,
73 treeElements.registerDependency(element); 71 ResolutionEnqueuer,
74 } 72 QueueFilter,
75 73 WorldImpact;
76 void registerInlining(Element inlinedElement, Element context) { 74 import 'io/source_information.dart' show
77 if (compiler.dumpInfo) { 75 SourceInformation;
78 compiler.dumpInfoTask.registerInlined(inlinedElement, context); 76 import 'js_backend/js_backend.dart' as js_backend show
79 } 77 JavaScriptBackend;
80 } 78 import 'library_loader.dart' show
81 79 LibraryLoader,
82 void registerInstantiatedClass(ClassElement element) { 80 LibraryLoaderTask,
83 world.registerInstantiatedType(element.rawType, this); 81 LoadedLibraries;
84 } 82 import 'messages.dart' show
85 83 Message,
86 void registerInstantiatedType(InterfaceType type) { 84 MessageKind,
87 world.registerInstantiatedType(type, this); 85 MessageTemplate;
88 } 86 import 'mirrors_used.dart' show
89 87 MirrorUsageAnalyzerTask;
90 void registerStaticUse(Element element) { 88 import 'null_compiler_output.dart' show
91 world.registerStaticUse(element); 89 NullCompilerOutput,
92 } 90 NullSink;
93 91 import 'patch_parser.dart' show
94 void registerDynamicInvocation(UniverseSelector selector) { 92 PatchParserTask;
95 world.registerDynamicInvocation(selector); 93 import 'resolution/resolution.dart' show
96 compiler.dumpInfoTask.elementUsesSelector(currentElement, selector); 94 ResolutionRegistry,
97 } 95 ResolverTask,
98 96 TreeElementMapping;
99 void registerDynamicSetter(UniverseSelector selector) { 97 import 'scanner/token_map.dart' show
100 world.registerDynamicSetter(selector); 98 TokenMap;
101 compiler.dumpInfoTask.elementUsesSelector(currentElement, selector); 99 import 'scanner/scannerlib.dart' show
102 } 100 COMMENT_TOKEN,
103 101 DietParserTask,
104 void registerDynamicGetter(UniverseSelector selector) { 102 EOF_TOKEN,
105 world.registerDynamicGetter(selector); 103 ParserTask,
106 compiler.dumpInfoTask.elementUsesSelector(currentElement, selector); 104 ScannerTask,
107 } 105 StringToken,
108 106 Token,
109 void registerGetterForSuperMethod(Element element) { 107 TokenPair;
110 world.registerGetterForSuperMethod(element); 108 import 'serialization/task.dart' show
111 } 109 SerializationTask;
112 110 import 'script.dart' show
113 void registerFieldGetter(Element element) { 111 Script;
114 world.registerFieldGetter(element); 112 import 'ssa/ssa.dart' show
115 } 113 HInstruction;
116 114 import 'tracer.dart' show
117 void registerFieldSetter(Element element) { 115 Tracer;
118 world.registerFieldSetter(element); 116 import 'tree/tree.dart' show
119 } 117 Node;
120 118 import 'typechecker.dart' show
121 void registerIsCheck(DartType type) { 119 TypeCheckerTask;
122 world.registerIsCheck(type); 120 import 'types/types.dart' as ti;
123 backend.registerIsCheckForCodegen(type, world, this); 121 import 'universe/universe.dart' show
124 } 122 Selector,
125 123 Universe;
126 void registerCompileTimeConstant(ConstantValue constant) { 124 import 'util/characters.dart' show $_;
127 backend.registerCompileTimeConstant(constant, this); 125 import 'util/util.dart' show
128 backend.constants.addCompileTimeConstantForEmission(constant); 126 Link;
129 } 127 import 'world.dart' show
130 128 World;
131 void registerTypeVariableBoundsSubtypeCheck(DartType subtype,
132 DartType supertype) {
133 backend.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
134 }
135
136 void registerInstantiatedClosure(LocalFunctionElement element) {
137 backend.registerInstantiatedClosure(element, this);
138 }
139
140 void registerGetOfStaticFunction(FunctionElement element) {
141 world.registerGetOfStaticFunction(element);
142 }
143
144 void registerSelectorUse(Selector selector) {
145 world.registerSelectorUse(new UniverseSelector(selector, null));
146 }
147
148 void registerConstSymbol(String name) {
149 backend.registerConstSymbol(name, this);
150 }
151
152 void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
153 backend.registerSpecializedGetInterceptor(classes);
154 }
155
156 void registerUseInterceptor() {
157 backend.registerUseInterceptor(world);
158 }
159
160 void registerTypeConstant(ClassElement element) {
161 backend.customElementsAnalysis.registerTypeConstant(element, world);
162 }
163
164 void registerStaticInvocation(Element element) {
165 world.registerStaticUse(element);
166 }
167
168 void registerSuperInvocation(Element element) {
169 world.registerStaticUse(element);
170 }
171
172 void registerDirectInvocation(Element element) {
173 world.registerStaticUse(element);
174 }
175
176 void registerInstantiation(InterfaceType type) {
177 world.registerInstantiatedType(type, this);
178 }
179
180 void registerAsyncMarker(FunctionElement element) {
181 backend.registerAsyncMarker(element, world, this);
182 }
183
184 }
185
186 /// [WorkItem] used exclusively by the [CodegenEnqueuer].
187 class CodegenWorkItem extends WorkItem {
188 CodegenRegistry registry;
189
190 factory CodegenWorkItem(
191 Compiler compiler,
192 AstElement element,
193 ItemCompilationContext compilationContext) {
194 // If this assertion fails, the resolution callbacks of the backend may be
195 // missing call of form registry.registerXXX. Alternatively, the code
196 // generation could spuriously be adding dependencies on things we know we
197 // don't need.
198 assert(invariant(element,
199 compiler.enqueuer.resolution.hasBeenResolved(element),
200 message: "$element has not been resolved."));
201 assert(invariant(element, element.resolvedAst.elements != null,
202 message: 'Resolution tree is null for $element in codegen work item'));
203 return new CodegenWorkItem.internal(element, compilationContext);
204 }
205
206 CodegenWorkItem.internal(
207 AstElement element,
208 ItemCompilationContext compilationContext)
209 : super(element, compilationContext);
210
211 TreeElements get resolutionTree => element.resolvedAst.elements;
212
213 WorldImpact run(Compiler compiler, CodegenEnqueuer world) {
214 if (world.isProcessed(element)) return const WorldImpact();
215
216 registry = new CodegenRegistry(compiler, resolutionTree);
217 return compiler.codegen(this, world);
218 }
219 }
220
221 typedef void DeferredAction();
222
223 class DeferredTask {
224 final Element element;
225 final DeferredAction action;
226
227 DeferredTask(this.element, this.action);
228 }
229
230 /// Interface for registration of element dependencies.
231 abstract class Registry {
232 // TODO(johnniwinther): Remove this getter when [Registry] creates a
233 // dependency node.
234 Iterable<Element> get otherDependencies;
235
236 void registerDependency(Element element);
237
238 bool get isForResolution;
239
240 void registerDynamicInvocation(UniverseSelector selector);
241
242 void registerDynamicGetter(UniverseSelector selector);
243
244 void registerDynamicSetter(UniverseSelector selector);
245
246 void registerStaticInvocation(Element element);
247
248 void registerInstantiation(InterfaceType type);
249
250 void registerGetOfStaticFunction(FunctionElement element);
251 }
252
253 abstract class Backend {
254 final Compiler compiler;
255
256 Backend(this.compiler);
257
258 /// Returns true if the backend supports reflection.
259 bool get supportsReflection;
260
261 /// The [ConstantSystem] used to interpret compile-time constants for this
262 /// backend.
263 ConstantSystem get constantSystem;
264
265 /// The constant environment for the backend interpretation of compile-time
266 /// constants.
267 BackendConstantEnvironment get constants;
268
269 /// The compiler task responsible for the compilation of constants for both
270 /// the frontend and the backend.
271 ConstantCompilerTask get constantCompilerTask;
272
273 /// Backend callback methods for the resolution phase.
274 ResolutionCallbacks get resolutionCallbacks;
275
276 /// The strategy used for collecting and emitting source information.
277 SourceInformationStrategy get sourceInformationStrategy {
278 return const SourceInformationStrategy();
279 }
280
281 // TODO(johnniwinther): Move this to the JavaScriptBackend.
282 String get patchVersion => null;
283
284 /// Set of classes that need to be considered for reflection although not
285 /// otherwise visible during resolution.
286 Iterable<ClassElement> classesRequiredForReflection = const [];
287
288 // Given a [FunctionElement], return a buffer with the code generated for it
289 // or null if no code was generated.
290 CodeBuffer codeOf(Element element) => null;
291
292 void initializeHelperClasses() {}
293
294 void enqueueHelpers(ResolutionEnqueuer world, Registry registry);
295 WorldImpact codegen(CodegenWorkItem work);
296
297 // The backend determines the native resolution enqueuer, with a no-op
298 // default, so tools like dart2dart can ignore the native classes.
299 native.NativeEnqueuer nativeResolutionEnqueuer(world) {
300 return new native.NativeEnqueuer();
301 }
302 native.NativeEnqueuer nativeCodegenEnqueuer(world) {
303 return new native.NativeEnqueuer();
304 }
305
306 /// Generates the output and returns the total size of the generated code.
307 int assembleProgram();
308
309 List<CompilerTask> get tasks;
310
311 void onResolutionComplete() {}
312 void onTypeInferenceComplete() {}
313
314 ItemCompilationContext createItemCompilationContext() {
315 return new ItemCompilationContext();
316 }
317
318 bool classNeedsRti(ClassElement cls);
319 bool methodNeedsRti(FunctionElement function);
320
321 /// Enable compilation of code with compile time errors. Returns `true` if
322 /// supported by the backend.
323 bool enableCodegenWithErrorsIfSupported(Spannable node);
324
325 /// Enable deferred loading. Returns `true` if the backend supports deferred
326 /// loading.
327 bool enableDeferredLoadingIfSupported(Spannable node, Registry registry);
328
329 /// Called during codegen when [constant] has been used.
330 void registerCompileTimeConstant(ConstantValue constant, Registry registry) {}
331
332 /// Called during resolution when a constant value for [metadata] on
333 /// [annotatedElement] has been evaluated.
334 void registerMetadataConstant(MetadataAnnotation metadata,
335 Element annotatedElement,
336 Registry registry) {}
337
338 /// Called to notify to the backend that a class is being instantiated.
339 // TODO(johnniwinther): Remove this. It's only called once for each [cls] and
340 // only with [Compiler.globalDependencies] as [registry].
341 void registerInstantiatedClass(ClassElement cls,
342 Enqueuer enqueuer,
343 Registry registry) {}
344
345 /// Called to notify to the backend that an interface type has been
346 /// instantiated.
347 void registerInstantiatedType(InterfaceType type, Registry registry) {}
348
349 /// Register an is check to the backend.
350 void registerIsCheckForCodegen(DartType type,
351 Enqueuer enqueuer,
352 Registry registry) {}
353
354 /// Register a runtime type variable bound tests between [typeArgument] and
355 /// [bound].
356 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument,
357 DartType bound) {}
358
359 /// Returns `true` if [element] represent the assert function.
360 bool isAssertMethod(Element element) => false;
361
362 /**
363 * Call this to register that an instantiated generic class has a call
364 * method.
365 */
366 void registerCallMethodWithFreeTypeVariables(
367 Element callMethod,
368 Enqueuer enqueuer,
369 Registry registry) {}
370
371 /**
372 * Call this to register that a getter exists for a function on an
373 * instantiated generic class.
374 */
375 void registerClosureWithFreeTypeVariables(
376 Element closure,
377 Enqueuer enqueuer,
378 Registry registry) {}
379
380 /// Call this to register that a member has been closurized.
381 void registerBoundClosure(Enqueuer enqueuer) {}
382
383 /// Call this to register that a static function has been closurized.
384 void registerGetOfStaticFunction(Enqueuer enqueuer) {}
385
386 /**
387 * Call this to register that the [:runtimeType:] property has been accessed.
388 */
389 void registerRuntimeType(Enqueuer enqueuer, Registry registry) {}
390
391 /// Call this to register a `noSuchMethod` implementation.
392 void registerNoSuchMethod(FunctionElement noSuchMethodElement) {}
393
394 /// Call this method to enable support for `noSuchMethod`.
395 void enableNoSuchMethod(Enqueuer enqueuer) {}
396
397 /// Returns whether or not `noSuchMethod` support has been enabled.
398 bool get enabledNoSuchMethod => false;
399
400 /// Call this method to enable support for isolates.
401 void enableIsolateSupport(Enqueuer enqueuer) {}
402
403 void registerRequiredType(DartType type, Element enclosingElement) {}
404 void registerClassUsingVariableExpression(ClassElement cls) {}
405
406 void registerConstSymbol(String name, Registry registry) {}
407 void registerNewSymbol(Registry registry) {}
408
409 bool isNullImplementation(ClassElement cls) {
410 return cls == compiler.nullClass;
411 }
412
413 ClassElement get intImplementation => compiler.intClass;
414 ClassElement get doubleImplementation => compiler.doubleClass;
415 ClassElement get numImplementation => compiler.numClass;
416 ClassElement get stringImplementation => compiler.stringClass;
417 ClassElement get listImplementation => compiler.listClass;
418 ClassElement get growableListImplementation => compiler.listClass;
419 ClassElement get fixedListImplementation => compiler.listClass;
420 ClassElement get constListImplementation => compiler.listClass;
421 ClassElement get mapImplementation => compiler.mapClass;
422 ClassElement get constMapImplementation => compiler.mapClass;
423 ClassElement get functionImplementation => compiler.functionClass;
424 ClassElement get typeImplementation => compiler.typeClass;
425 ClassElement get boolImplementation => compiler.boolClass;
426 ClassElement get nullImplementation => compiler.nullClass;
427 ClassElement get uint32Implementation => compiler.intClass;
428 ClassElement get uint31Implementation => compiler.intClass;
429 ClassElement get positiveIntImplementation => compiler.intClass;
430
431 ClassElement defaultSuperclass(ClassElement element) => compiler.objectClass;
432
433 bool isInterceptorClass(ClassElement element) => false;
434
435 /// Returns `true` if [element] is a foreign element, that is, that the
436 /// backend has specialized handling for the element.
437 bool isForeign(Element element) => false;
438
439 /// Processes [element] for resolution and returns the [FunctionElement] that
440 /// defines the implementation of [element].
441 FunctionElement resolveExternalFunction(FunctionElement element) => element;
442
443 /// Returns `true` if [library] is a backend specific library whose members
444 /// have special treatment, such as being allowed to extends blacklisted
445 /// classes or member being eagerly resolved.
446 bool isBackendLibrary(LibraryElement library) {
447 // TODO(johnniwinther): Remove this when patching is only done by the
448 // JavaScript backend.
449 Uri canonicalUri = library.canonicalUri;
450 if (canonicalUri == js_backend.JavaScriptBackend.DART_JS_HELPER ||
451 canonicalUri == js_backend.JavaScriptBackend.DART_INTERCEPTORS) {
452 return true;
453 }
454 return false;
455 }
456
457 void registerStaticUse(Element element, Enqueuer enqueuer) {}
458
459 /// This method is called immediately after the [LibraryElement] [library] has
460 /// been created.
461 void onLibraryCreated(LibraryElement library) {}
462
463 /// This method is called immediately after the [library] and its parts have
464 /// been scanned.
465 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
466 if (library.canUseNative) {
467 library.forEachLocalMember((Element element) {
468 if (element.isClass) {
469 checkNativeAnnotation(compiler, element);
470 }
471 });
472 }
473 return new Future.value();
474 }
475
476 /// This method is called when all new libraries loaded through
477 /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
478 /// have been computed.
479 Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
480 return new Future.value();
481 }
482
483 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
484 /// annotations. The arguments corresponds to the unions of the corresponding
485 /// fields of the annotations.
486 void registerMirrorUsage(Set<String> symbols,
487 Set<Element> targets,
488 Set<Element> metaTargets) {}
489
490 /// Returns true if this element needs reflection information at runtime.
491 bool isAccessibleByReflection(Element element) => true;
492
493 /// Returns true if this element is covered by a mirrorsUsed annotation.
494 ///
495 /// Note that it might still be ok to tree shake the element away if no
496 /// reflection is used in the program (and thus [isTreeShakingDisabled] is
497 /// still false). Therefore _do not_ use this predicate to decide inclusion
498 /// in the tree, use [requiredByMirrorSystem] instead.
499 bool referencedFromMirrorSystem(Element element, [recursive]) => false;
500
501 /// Returns true if this element has to be enqueued due to
502 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
503 /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
504 bool requiredByMirrorSystem(Element element) => false;
505
506 /// Returns true if global optimizations such as type inferencing
507 /// can apply to this element. One category of elements that do not
508 /// apply is runtime helpers that the backend calls, but the
509 /// optimizations don't see those calls.
510 bool canBeUsedForGlobalOptimizations(Element element) => true;
511
512 /// Called when [enqueuer]'s queue is empty, but before it is closed.
513 /// This is used, for example, by the JS backend to enqueue additional
514 /// elements needed for reflection. [recentClasses] is a collection of
515 /// all classes seen for the first time by the [enqueuer] since the last call
516 /// to [onQueueEmpty].
517 ///
518 /// A return value of [:true:] indicates that [recentClasses] has been
519 /// processed and its elements do not need to be seen in the next round. When
520 /// [:false:] is returned, [onQueueEmpty] will be called again once the
521 /// resolution queue has drained and [recentClasses] will be a superset of the
522 /// current value.
523 ///
524 /// There is no guarantee that a class is only present once in
525 /// [recentClasses], but every class seen by the [enqueuer] will be present in
526 /// [recentClasses] at least once.
527 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) {
528 return true;
529 }
530
531 /// Called after [element] has been resolved.
532 // TODO(johnniwinther): Change [TreeElements] to [Registry] or a dependency
533 // node. [elements] is currently unused by the implementation.
534 void onElementResolved(Element element, TreeElements elements) {}
535
536 // Does this element belong in the output
537 bool shouldOutput(Element element) => true;
538
539 FunctionElement helperForBadMain() => null;
540
541 FunctionElement helperForMissingMain() => null;
542
543 FunctionElement helperForMainArity() => null;
544
545 void forgetElement(Element element) {}
546
547 void registerMainHasArguments(Enqueuer enqueuer) {}
548
549 void registerAsyncMarker(FunctionElement element,
550 Enqueuer enqueuer,
551 Registry registry) {}
552 }
553
554 /// Backend callbacks function specific to the resolution phase.
555 class ResolutionCallbacks {
556 /// Register that [node] is a call to `assert`.
557 void onAssert(Send node, Registry registry) {}
558
559 /// Register that an 'await for' has been seen.
560 void onAsyncForIn(AsyncForIn node, Registry registry) {}
561
562 /// Called during resolution to notify to the backend that the
563 /// program uses string interpolation.
564 void onStringInterpolation(Registry registry) {}
565
566 /// Called during resolution to notify to the backend that the
567 /// program has a catch statement.
568 void onCatchStatement(Registry registry) {}
569
570 /// Called during resolution to notify to the backend that the
571 /// program explicitly throws an exception.
572 void onThrowExpression(Registry registry) {}
573
574 /// Called during resolution to notify to the backend that the
575 /// program has a global variable with a lazy initializer.
576 void onLazyField(Registry registry) {}
577
578 /// Called during resolution to notify to the backend that the
579 /// program uses a type variable as an expression.
580 void onTypeVariableExpression(Registry registry) {}
581
582 /// Called during resolution to notify to the backend that the
583 /// program uses a type literal.
584 void onTypeLiteral(DartType type, Registry registry) {}
585
586 /// Called during resolution to notify to the backend that the
587 /// program has a catch statement with a stack trace.
588 void onStackTraceInCatch(Registry registry) {}
589
590 /// Register an is check to the backend.
591 void onIsCheck(DartType type, Registry registry) {}
592
593 /// Called during resolution to notify to the backend that the
594 /// program has a for-in loop.
595 void onSyncForIn(Registry registry) {}
596
597 /// Register an as check to the backend.
598 void onAsCheck(DartType type, Registry registry) {}
599
600 /// Registers that a type variable bounds check might occur at runtime.
601 void onTypeVariableBoundCheck(Registry registry) {}
602
603 /// Register that the application may throw a [NoSuchMethodError].
604 void onThrowNoSuchMethod(Registry registry) {}
605
606 /// Register that the application may throw a [RuntimeError].
607 void onThrowRuntimeError(Registry registry) {}
608
609 /// Register that the application may throw an
610 /// [AbstractClassInstantiationError].
611 void onAbstractClassInstantiation(Registry registry) {}
612
613 /// Register that the application may throw a [FallThroughError].
614 void onFallThroughError(Registry registry) {}
615
616 /// Register that a super call will end up calling
617 /// [: super.noSuchMethod :].
618 void onSuperNoSuchMethod(Registry registry) {}
619
620 /// Register that the application creates a constant map.
621 void onMapLiteral(Registry registry, DartType type, bool isConstant) {}
622
623 /// Called when resolving the `Symbol` constructor.
624 void onSymbolConstructor(Registry registry) {}
625 }
626
627 /**
628 * Key class used in [TokenMap] in which the hash code for a token is based
629 * on the [charOffset].
630 */
631 class TokenKey {
632 final Token token;
633 TokenKey(this.token);
634 int get hashCode => token.charOffset;
635 operator==(other) => other is TokenKey && token == other.token;
636 }
637
638 /// Map of tokens and the first associated comment.
639 /*
640 * This implementation was chosen among several candidates for its space/time
641 * efficiency by empirical tests of running dartdoc on dartdoc itself. Time
642 * measurements for the use of [Compiler.commentMap]:
643 *
644 * 1) Using [TokenKey] as key (this class): ~80 msec
645 * 2) Using [TokenKey] as key + storing a separate map in each script: ~120 msec
646 * 3) Using [Token] as key in a [Map]: ~38000 msec
647 * 4) Storing comments is new field in [Token]: ~20 msec
648 * (Abandoned due to the increased memory usage)
649 * 5) Storing comments in an [Expando]: ~14000 msec
650 * 6) Storing token/comments pairs in a linked list: ~5400 msec
651 */
652 class TokenMap {
653 Map<TokenKey,Token> comments = new Map<TokenKey,Token>();
654
655 Token operator[] (Token key) {
656 if (key == null) return null;
657 return comments[new TokenKey(key)];
658 }
659
660 void operator[]= (Token key, Token value) {
661 if (key == null) return;
662 comments[new TokenKey(key)] = value;
663 }
664 }
665 129
666 abstract class Compiler implements DiagnosticListener { 130 abstract class Compiler implements DiagnosticListener {
667 static final Uri DART_CORE = new Uri(scheme: 'dart', path: 'core'); 131 static final Uri DART_CORE = new Uri(scheme: 'dart', path: 'core');
668 static final Uri DART_MIRRORS = new Uri(scheme: 'dart', path: 'mirrors'); 132 static final Uri DART_MIRRORS = new Uri(scheme: 'dart', path: 'mirrors');
669 static final Uri DART_NATIVE_TYPED_DATA = 133 static final Uri DART_NATIVE_TYPED_DATA =
670 new Uri(scheme: 'dart', path: '_native_typed_data'); 134 new Uri(scheme: 'dart', path: '_native_typed_data');
671 static final Uri DART_INTERNAL = new Uri(scheme: 'dart', path: '_internal'); 135 static final Uri DART_INTERNAL = new Uri(scheme: 'dart', path: '_internal');
672 static final Uri DART_ASYNC = new Uri(scheme: 'dart', path: 'async'); 136 static final Uri DART_ASYNC = new Uri(scheme: 'dart', path: 'async');
673 137
674 final Stopwatch totalCompileTime = new Stopwatch(); 138 final Stopwatch totalCompileTime = new Stopwatch();
(...skipping 1507 matching lines...) Expand 10 before | Expand all | Expand 10 after
2182 // Disable output in test mode: The build bot currently uses the time 1646 // Disable output in test mode: The build bot currently uses the time
2183 // stamp of the generated file to determine whether the output is 1647 // stamp of the generated file to determine whether the output is
2184 // up-to-date. 1648 // up-to-date.
2185 return new NullSink('$name.$extension'); 1649 return new NullSink('$name.$extension');
2186 } 1650 }
2187 } 1651 }
2188 return userOutputProvider.createEventSink(name, extension); 1652 return userOutputProvider.createEventSink(name, extension);
2189 } 1653 }
2190 } 1654 }
2191 1655
2192 class CompilerTask {
2193 final Compiler compiler;
2194 final Stopwatch watch;
2195 UserTag profilerTag;
2196
2197 CompilerTask(Compiler compiler)
2198 : this.compiler = compiler,
2199 watch = (compiler.verbose) ? new Stopwatch() : null;
2200
2201 String get name => "Unknown task '${this.runtimeType}'";
2202 int get timing => (watch != null) ? watch.elapsedMilliseconds : 0;
2203
2204 int get timingMicroseconds => (watch != null) ? watch.elapsedMicroseconds : 0;
2205
2206 UserTag getProfilerTag() {
2207 if (profilerTag == null) profilerTag = new UserTag(name);
2208 return profilerTag;
2209 }
2210
2211 measure(action()) {
2212 // In verbose mode when watch != null.
2213 if (watch == null) return action();
2214 CompilerTask previous = compiler.measuredTask;
2215 if (identical(this, previous)) return action();
2216 compiler.measuredTask = this;
2217 if (previous != null) previous.watch.stop();
2218 watch.start();
2219 UserTag oldTag = getProfilerTag().makeCurrent();
2220 try {
2221 return action();
2222 } finally {
2223 watch.stop();
2224 oldTag.makeCurrent();
2225 if (previous != null) previous.watch.start();
2226 compiler.measuredTask = previous;
2227 }
2228 }
2229
2230 measureElement(Element element, action()) {
2231 compiler.withCurrentElement(element, () => measure(action));
2232 }
2233 }
2234
2235 class SourceSpan implements Spannable {
2236 final Uri uri;
2237 final int begin;
2238 final int end;
2239
2240 const SourceSpan(this.uri, this.begin, this.end);
2241
2242 static withCharacterOffsets(Token begin, Token end,
2243 f(int beginOffset, int endOffset)) {
2244 final beginOffset = begin.charOffset;
2245 final endOffset = end.charOffset + end.charCount;
2246
2247 // [begin] and [end] might be the same for the same empty token. This
2248 // happens for instance when scanning '$$'.
2249 assert(endOffset >= beginOffset);
2250 return f(beginOffset, endOffset);
2251 }
2252
2253 int get hashCode {
2254 return 13 * uri.hashCode +
2255 17 * begin.hashCode +
2256 19 * end.hashCode;
2257 }
2258
2259 bool operator ==(other) {
2260 if (identical(this, other)) return true;
2261 if (other is! SourceSpan) return false;
2262 return uri == other.uri &&
2263 begin == other.begin &&
2264 end == other.end;
2265 }
2266
2267 String toString() => 'SourceSpan($uri, $begin, $end)';
2268 }
2269
2270 /// Flag that can be used in assertions to assert that a code path is only
2271 /// executed as part of development.
2272 ///
2273 /// This flag is automatically set to true if helper methods like, [debugPrint],
2274 /// [debugWrapPrint], [trace], and [reportHere] are called.
2275 bool DEBUG_MODE = false;
2276
2277 /// Assert that [DEBUG_MODE] is `true` and provide [message] as part of the
2278 /// error message.
2279 assertDebugMode(String message) {
2280 assert(invariant(NO_LOCATION_SPANNABLE, DEBUG_MODE,
2281 message: 'Debug mode is not enabled: $message'));
2282 }
2283
2284 /**
2285 * Throws a [SpannableAssertionFailure] if [condition] is
2286 * [:false:]. [condition] must be either a [:bool:] or a no-arg
2287 * function returning a [:bool:].
2288 *
2289 * Use this method to provide better information for assertion by calling
2290 * [invariant] as the argument to an [:assert:] statement:
2291 *
2292 * assert(invariant(position, isValid));
2293 *
2294 * [spannable] must be non-null and will be used to provide positional
2295 * information in the generated error message.
2296 */
2297 bool invariant(Spannable spannable, var condition, {var message: null}) {
2298 // TODO(johnniwinther): Use [spannable] and [message] to provide better
2299 // information on assertion errors.
2300 if (spannable == null) {
2301 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
2302 "Spannable was null for invariant. Use CURRENT_ELEMENT_SPANNABLE.");
2303 }
2304 if (condition is Function){
2305 condition = condition();
2306 }
2307 if (!condition) {
2308 if (message is Function) {
2309 message = message();
2310 }
2311 throw new SpannableAssertionFailure(spannable, message);
2312 }
2313 return true;
2314 }
2315
2316 /// Returns `true` when [s] is private if used as an identifier. 1656 /// Returns `true` when [s] is private if used as an identifier.
2317 bool isPrivateName(String s) => !s.isEmpty && s.codeUnitAt(0) == $_; 1657 bool isPrivateName(String s) => !s.isEmpty && s.codeUnitAt(0) == $_;
2318 1658
2319 /// Returns `true` when [s] is public if used as an identifier. 1659 /// Returns `true` when [s] is public if used as an identifier.
2320 bool isPublicName(String s) => !isPrivateName(s); 1660 bool isPublicName(String s) => !isPrivateName(s);
2321 1661
2322 /// Information about suppressed warnings and hints for a given library. 1662 /// Information about suppressed warnings and hints for a given library.
2323 class SuppressionInfo { 1663 class SuppressionInfo {
2324 int warnings = 0; 1664 int warnings = 0;
2325 int hints = 0; 1665 int hints = 0;
2326 } 1666 }
2327 1667
2328 class GenericTask extends CompilerTask {
2329 final String name;
2330
2331 GenericTask(this.name, Compiler compiler)
2332 : super(compiler);
2333 }
2334
2335 /// [CodeLocation] divides uris into different classes.
2336 ///
2337 /// These are used to group uris from user code, platform libraries and
2338 /// packages.
2339 abstract class CodeLocation {
2340 /// Returns `true` if [uri] is in this code location.
2341 bool inSameLocation(Uri uri);
2342
2343 /// Returns the uri of this location relative to [baseUri].
2344 String relativize(Uri baseUri);
2345
2346 factory CodeLocation(Uri uri) {
2347 if (uri.scheme == 'package') {
2348 int slashPos = uri.path.indexOf('/');
2349 if (slashPos != -1) {
2350 String packageName = uri.path.substring(0, slashPos);
2351 return new PackageLocation(packageName);
2352 } else {
2353 return new UriLocation(uri);
2354 }
2355 } else {
2356 return new SchemeLocation(uri);
2357 }
2358 }
2359 }
2360
2361 /// A code location defined by the scheme of the uri.
2362 ///
2363 /// Used for non-package uris, such as 'dart', 'file', and 'http'.
2364 class SchemeLocation implements CodeLocation {
2365 final Uri uri;
2366
2367 SchemeLocation(this.uri);
2368
2369 bool inSameLocation(Uri uri) {
2370 return this.uri.scheme == uri.scheme;
2371 }
2372
2373 String relativize(Uri baseUri) {
2374 return uri_extras.relativize(baseUri, uri, false);
2375 }
2376 }
2377
2378 /// A code location defined by the package name.
2379 ///
2380 /// Used for package uris, separated by their `package names`, that is, the
2381 /// 'foo' of 'package:foo/bar.dart'.
2382 class PackageLocation implements CodeLocation {
2383 final String packageName;
2384
2385 PackageLocation(this.packageName);
2386
2387 bool inSameLocation(Uri uri) {
2388 return uri.scheme == 'package' && uri.path.startsWith('$packageName/');
2389 }
2390
2391 String relativize(Uri baseUri) => 'package:$packageName';
2392 }
2393
2394 /// A code location defined by the whole uri.
2395 ///
2396 /// Used for package uris with no package name. For instance 'package:foo.dart'.
2397 class UriLocation implements CodeLocation {
2398 final Uri uri;
2399
2400 UriLocation(this.uri);
2401
2402 bool inSameLocation(Uri uri) => this.uri == uri;
2403
2404 String relativize(Uri baseUri) {
2405 return uri_extras.relativize(baseUri, uri, false);
2406 }
2407 }
2408
2409 /// A code location that contains any uri.
2410 class AnyLocation implements CodeLocation {
2411 const AnyLocation();
2412
2413 bool inSameLocation(Uri uri) => true;
2414
2415 String relativize(Uri baseUri) => '$baseUri';
2416 }
2417
2418 class _CompilerCoreTypes implements CoreTypes { 1668 class _CompilerCoreTypes implements CoreTypes {
2419 final Compiler compiler; 1669 final Compiler compiler;
2420 1670
2421 ClassElement objectClass; 1671 ClassElement objectClass;
2422 ClassElement boolClass; 1672 ClassElement boolClass;
2423 ClassElement numClass; 1673 ClassElement numClass;
2424 ClassElement intClass; 1674 ClassElement intClass;
2425 ClassElement doubleClass; 1675 ClassElement doubleClass;
2426 ClassElement stringClass; 1676 ClassElement stringClass;
2427 ClassElement functionClass; 1677 ClassElement functionClass;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2510 1760
2511 @override 1761 @override
2512 InterfaceType streamType([DartType elementType]) { 1762 InterfaceType streamType([DartType elementType]) {
2513 InterfaceType type = streamClass.computeType(compiler); 1763 InterfaceType type = streamClass.computeType(compiler);
2514 if (elementType == null) { 1764 if (elementType == null) {
2515 return streamClass.rawType; 1765 return streamClass.rawType;
2516 } 1766 }
2517 return type.createInstantiation([elementType]); 1767 return type.createInstantiation([elementType]);
2518 } 1768 }
2519 } 1769 }
2520
2521 typedef void InternalErrorFunction(Spannable location, String message);
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/compile_time_constants.dart ('k') | pkg/compiler/lib/src/constant_system_dart.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698