OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 | 7 |
8 class OldEmitter implements Emitter { | 8 class OldEmitter implements Emitter { |
9 final Compiler compiler; | 9 final Compiler compiler; |
10 final CodeEmitterTask task; | 10 final CodeEmitterTask task; |
11 | 11 |
12 final ContainerBuilder containerBuilder = new ContainerBuilder(); | 12 final ContainerBuilder containerBuilder = new ContainerBuilder(); |
13 final ClassEmitter classEmitter = new ClassEmitter(); | 13 final ClassEmitter classEmitter = new ClassEmitter(); |
14 final NsmEmitter nsmEmitter = new NsmEmitter(); | 14 final NsmEmitter nsmEmitter = new NsmEmitter(); |
15 final InterceptorEmitter interceptorEmitter = new InterceptorEmitter(); | 15 final InterceptorEmitter interceptorEmitter = new InterceptorEmitter(); |
16 | 16 |
17 // TODO(johnniwinther): Wrap these fields in a caching strategy. | 17 // TODO(johnniwinther): Wrap these fields in a caching strategy. |
18 final Set<ConstantValue> cachedEmittedConstants; | 18 final Set<ConstantValue> cachedEmittedConstants; |
19 final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer(); | 19 final List<jsAst.Statement> cachedEmittedConstantsAst = <jsAst.Statement>[]; |
20 final Map<Element, ClassBuilder> cachedClassBuilders; | 20 final Map<Element, ClassBuilder> cachedClassBuilders; |
21 final Set<Element> cachedElements; | 21 final Set<Element> cachedElements; |
22 | 22 |
23 bool needsClassSupport = false; | 23 bool needsClassSupport = false; |
24 bool needsMixinSupport = false; | 24 bool needsMixinSupport = false; |
25 bool needsLazyInitializer = false; | 25 bool needsLazyInitializer = false; |
26 | 26 |
27 /// True if [ContainerBuilder.addMemberMethodFromInfo] used "structured info", | 27 /// True if [ContainerBuilder.addMemberMethodFromInfo] used "structured info", |
28 /// that is, some function was needed for reflection, had stubs, or had a | 28 /// that is, some function was needed for reflection, had stubs, or had a |
29 /// super alias. | 29 /// super alias. |
30 bool needsStructuredMemberInfo = false; | 30 bool needsStructuredMemberInfo = false; |
31 | 31 |
32 final Namer namer; | 32 final Namer namer; |
33 ConstantEmitter constantEmitter; | 33 ConstantEmitter constantEmitter; |
34 NativeEmitter get nativeEmitter => task.nativeEmitter; | 34 NativeEmitter get nativeEmitter => task.nativeEmitter; |
35 TypeTestRegistry get typeTestRegistry => task.typeTestRegistry; | 35 TypeTestRegistry get typeTestRegistry => task.typeTestRegistry; |
36 | 36 |
37 // The full code that is written to each hunk part-file. | 37 // The full code that is written to each hunk part-file. |
38 Map<OutputUnit, CodeOutput> outputBuffers = new Map<OutputUnit, CodeOutput>(); | 38 Map<OutputUnit, CodeOutput> outputBuffers = new Map<OutputUnit, CodeOutput>(); |
39 | 39 |
40 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | |
41 well as in the generated code. */ | |
42 String isolateProperties; | |
43 String classesCollector; | 40 String classesCollector; |
44 Set<ClassElement> get neededClasses => task.neededClasses; | 41 Set<ClassElement> get neededClasses => task.neededClasses; |
45 Map<OutputUnit, List<ClassElement>> get outputClassLists | 42 Map<OutputUnit, List<ClassElement>> get outputClassLists |
46 => task.outputClassLists; | 43 => task.outputClassLists; |
47 Map<OutputUnit, List<ConstantValue>> get outputConstantLists | 44 Map<OutputUnit, List<ConstantValue>> get outputConstantLists |
48 => task.outputConstantLists; | 45 => task.outputConstantLists; |
49 final Map<String, String> mangledFieldNames = <String, String>{}; | 46 final Map<String, String> mangledFieldNames = <String, String>{}; |
50 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; | 47 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; |
51 final Set<String> recordedMangledNames = new Set<String>(); | 48 final Set<String> recordedMangledNames = new Set<String>(); |
52 | 49 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 () => new List<jsAst.Expression>()); | 113 () => new List<jsAst.Expression>()); |
117 } | 114 } |
118 | 115 |
119 /// Erases the precompiled information for csp mode for all output units. | 116 /// Erases the precompiled information for csp mode for all output units. |
120 /// Used by the incremental compiler. | 117 /// Used by the incremental compiler. |
121 void clearCspPrecompiledNodes() { | 118 void clearCspPrecompiledNodes() { |
122 _cspPrecompiledFunctions.clear(); | 119 _cspPrecompiledFunctions.clear(); |
123 _cspPrecompiledConstructorNames.clear(); | 120 _cspPrecompiledConstructorNames.clear(); |
124 } | 121 } |
125 | 122 |
126 void addComment(String comment, CodeOutput output) { | |
127 output.addBuffer(jsAst.prettyPrint(js.comment(comment), compiler)); | |
128 } | |
129 | |
130 @override | 123 @override |
131 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { | 124 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { |
132 if (constant.isFunction) return true; // Already emitted. | 125 if (constant.isFunction) return true; // Already emitted. |
133 if (constant.isPrimitive) return true; // Inlined. | 126 if (constant.isPrimitive) return true; // Inlined. |
134 if (constant.isDummy) return true; // Inlined. | 127 if (constant.isDummy) return true; // Inlined. |
135 // The name is null when the constant is already a JS constant. | 128 // The name is null when the constant is already a JS constant. |
136 // TODO(floitsch): every constant should be registered, so that we can | 129 // TODO(floitsch): every constant should be registered, so that we can |
137 // share the ones that take up too much space (like some strings). | 130 // share the ones that take up too much space (like some strings). |
138 if (namer.constantName(constant) == null) return true; | 131 if (namer.constantName(constant) == null) return true; |
139 return false; | 132 return false; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
195 String get initName => 'init'; | 188 String get initName => 'init'; |
196 | 189 |
197 String get makeConstListProperty => namer.internalGlobal('makeConstantList'); | 190 String get makeConstListProperty => namer.internalGlobal('makeConstantList'); |
198 | 191 |
199 /// The name of the property that contains all field names. | 192 /// The name of the property that contains all field names. |
200 /// | 193 /// |
201 /// This property is added to constructors when isolate support is enabled. | 194 /// This property is added to constructors when isolate support is enabled. |
202 static const String FIELD_NAMES_PROPERTY_NAME = r"$__fields__"; | 195 static const String FIELD_NAMES_PROPERTY_NAME = r"$__fields__"; |
203 | 196 |
204 /// For deferred loading we communicate the initializers via this global var. | 197 /// For deferred loading we communicate the initializers via this global var. |
205 final String deferredInitializers = r"$dart_deferred_initializers"; | 198 final String deferredInitializers = r"$dart_deferred_initializers$"; |
206 | 199 |
207 /// Contains the global state that is needed to initialize and load a | 200 /// Contains the global state that is needed to initialize and load a |
208 /// deferred library. | 201 /// deferred library. |
209 String get globalsHolder => namer.internalGlobal("globalsHolder"); | 202 String get globalsHolder => namer.internalGlobal("globalsHolder"); |
210 | 203 |
211 @override | 204 @override |
212 jsAst.Expression generateEmbeddedGlobalAccess(String global) { | 205 jsAst.Expression generateEmbeddedGlobalAccess(String global) { |
213 return js(generateEmbeddedGlobalAccessString(global)); | 206 return js(generateEmbeddedGlobalAccessString(global)); |
214 } | 207 } |
215 | 208 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
336 return nativeEmitter.buildNativeInfoHandler(infoAccess, constructorAccess, | 329 return nativeEmitter.buildNativeInfoHandler(infoAccess, constructorAccess, |
337 subclassReadGenerator, | 330 subclassReadGenerator, |
338 interceptorsByTagAccess, | 331 interceptorsByTagAccess, |
339 leafTagsAccess); | 332 leafTagsAccess); |
340 } | 333 } |
341 | 334 |
342 jsAst.ObjectInitializer generateInterceptedNamesSet() { | 335 jsAst.ObjectInitializer generateInterceptedNamesSet() { |
343 return interceptorEmitter.generateInterceptedNamesSet(); | 336 return interceptorEmitter.generateInterceptedNamesSet(); |
344 } | 337 } |
345 | 338 |
346 void emitFinishIsolateConstructorInvocation(CodeOutput output) { | |
347 String isolate = namer.isolateName; | |
348 output.add("$isolate = $finishIsolateConstructorName($isolate)$N"); | |
349 } | |
350 | |
351 /// In minified mode we want to keep the name for the most common core types. | 339 /// In minified mode we want to keep the name for the most common core types. |
352 bool _isNativeTypeNeedingReflectionName(Element element) { | 340 bool _isNativeTypeNeedingReflectionName(Element element) { |
353 if (!element.isClass) return false; | 341 if (!element.isClass) return false; |
354 return (element == compiler.intClass || | 342 return (element == compiler.intClass || |
355 element == compiler.doubleClass || | 343 element == compiler.doubleClass || |
356 element == compiler.numClass || | 344 element == compiler.numClass || |
357 element == compiler.stringClass || | 345 element == compiler.stringClass || |
358 element == compiler.boolClass || | 346 element == compiler.boolClass || |
359 element == compiler.nullClass || | 347 element == compiler.nullClass || |
360 element == compiler.listClass); | 348 element == compiler.listClass); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
464 } | 452 } |
465 | 453 |
466 String namedParametersAsReflectionNames(CallStructure structure) { | 454 String namedParametersAsReflectionNames(CallStructure structure) { |
467 if (structure.isUnnamed) return ''; | 455 if (structure.isUnnamed) return ''; |
468 String names = structure.getOrderedNamedArguments().join(':'); | 456 String names = structure.getOrderedNamedArguments().join(':'); |
469 return ':$names'; | 457 return ':$names'; |
470 } | 458 } |
471 | 459 |
472 jsAst.Statement buildCspPrecompiledFunctionFor( | 460 jsAst.Statement buildCspPrecompiledFunctionFor( |
473 OutputUnit outputUnit) { | 461 OutputUnit outputUnit) { |
474 // TODO(ahe): Compute a hash code. | 462 if (compiler.useContentSecurityPolicy) { |
475 // TODO(sigurdm): Avoid this precompiled function. Generated | 463 // TODO(ahe): Compute a hash code. |
476 // constructor-functions and getter/setter functions can be stored in the | 464 // TODO(sigurdm): Avoid this precompiled function. Generated |
477 // library-description table. Setting properties on these can be moved to | 465 // constructor-functions and getter/setter functions can be stored in the |
478 // finishClasses. | 466 // library-description table. Setting properties on these can be moved to |
479 return js.statement(''' | 467 // finishClasses. |
480 # = function (\$collectedClasses) { | 468 return js.statement(''' |
481 var \$desc; | 469 # = function (\$collectedClasses) { |
482 #; | 470 var \$desc; |
483 return #; | 471 #; |
484 };''', | 472 return #; |
485 [generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED), | 473 };''', |
486 cspPrecompiledFunctionFor(outputUnit), | 474 [generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED), |
487 new jsAst.ArrayInitializer( | 475 cspPrecompiledFunctionFor(outputUnit), |
488 cspPrecompiledConstructorNamesFor(outputUnit))]); | 476 new jsAst.ArrayInitializer( |
477 cspPrecompiledConstructorNamesFor(outputUnit))]); | |
478 } else { | |
479 return js.comment("Constructors are generated at runtime."); | |
480 } | |
489 } | 481 } |
490 | 482 |
491 void assembleClass(Class cls, ClassBuilder enclosingBuilder, | 483 void assembleClass(Class cls, ClassBuilder enclosingBuilder, |
492 Fragment fragment) { | 484 Fragment fragment) { |
493 ClassElement classElement = cls.element; | 485 ClassElement classElement = cls.element; |
494 compiler.withCurrentElement(classElement, () { | 486 compiler.withCurrentElement(classElement, () { |
495 if (compiler.hasIncrementalSupport) { | 487 if (compiler.hasIncrementalSupport) { |
496 ClassBuilder cachedBuilder = | 488 ClassBuilder cachedBuilder = |
497 cachedClassBuilders.putIfAbsent(classElement, () { | 489 cachedClassBuilders.putIfAbsent(classElement, () { |
498 ClassBuilder builder = new ClassBuilder(classElement, namer); | 490 ClassBuilder builder = new ClassBuilder(classElement, namer); |
(...skipping 20 matching lines...) Expand all Loading... | |
519 // We need to filter out null-elements for the interceptors. | 511 // We need to filter out null-elements for the interceptors. |
520 // TODO(floitsch): use the precomputed interceptors here. | 512 // TODO(floitsch): use the precomputed interceptors here. |
521 if (element == null) continue; | 513 if (element == null) continue; |
522 ClassBuilder builder = new ClassBuilder(element, namer); | 514 ClassBuilder builder = new ClassBuilder(element, namer); |
523 containerBuilder.addMemberMethod(method, builder); | 515 containerBuilder.addMemberMethod(method, builder); |
524 getElementDescriptor(element, fragment).properties | 516 getElementDescriptor(element, fragment).properties |
525 .addAll(builder.properties); | 517 .addAll(builder.properties); |
526 } | 518 } |
527 } | 519 } |
528 | 520 |
529 void emitStaticNonFinalFieldInitializations(CodeOutput output, | 521 jsAst.Statement buildStaticNonFinalFieldInitializations( |
530 OutputUnit outputUnit) { | 522 OutputUnit outputUnit) { |
531 void emitInitialization(Element element, jsAst.Expression initialValue) { | 523 jsAst.Statement buildInitialization(Element element, |
532 jsAst.Expression init = | 524 jsAst.Expression initialValue) { |
533 js('$isolateProperties.# = #', | 525 return js.statement('${namer.currentIsolate}.# = #', |
floitsch
2015/05/19 13:43:35
I don't like this.
It is true, that the isolatePro
herhut
2015/05/19 14:08:09
But I can no longer do the magic "from here on we
floitsch
2015/05/19 14:15:28
No it's not clear. This code says: "store the init
floitsch
2015/05/19 14:16:50
Also: it doesn't matter when things are instantiat
| |
534 [namer.globalPropertyName(element), initialValue]); | 526 [namer.globalPropertyName(element), initialValue]); |
535 output.addBuffer(jsAst.prettyPrint(init, compiler, | |
536 monitor: compiler.dumpInfoTask)); | |
537 output.add('$N'); | |
538 } | 527 } |
539 | 528 |
540 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); | 529 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); |
541 JavaScriptConstantCompiler handler = backend.constants; | 530 JavaScriptConstantCompiler handler = backend.constants; |
531 List<jsAst.Statement> parts = <jsAst.Statement>[]; | |
542 | 532 |
543 Iterable<Element> fields = task.outputStaticNonFinalFieldLists[outputUnit]; | 533 Iterable<Element> fields = task.outputStaticNonFinalFieldLists[outputUnit]; |
544 // If the outputUnit does not contain any static non-final fields, then | 534 // If the outputUnit does not contain any static non-final fields, then |
545 // [fields] is `null`. | 535 // [fields] is `null`. |
546 if (fields != null) { | 536 if (fields != null) { |
547 for (Element element in fields) { | 537 for (Element element in fields) { |
548 compiler.withCurrentElement(element, () { | 538 compiler.withCurrentElement(element, () { |
549 ConstantValue constant = handler.getInitialValueFor(element).value; | 539 ConstantValue constant = handler.getInitialValueFor(element).value; |
550 emitInitialization(element, constantReference(constant)); | 540 parts.add(buildInitialization(element, constantReference(constant))); |
551 }); | 541 }); |
552 } | 542 } |
553 } | 543 } |
554 | 544 |
555 if (inMainUnit && task.outputStaticNonFinalFieldLists.length > 1) { | 545 if (inMainUnit && task.outputStaticNonFinalFieldLists.length > 1) { |
556 // In the main output-unit we output a stub initializer for deferred | 546 // In the main output-unit we output a stub initializer for deferred |
557 // variables, so that `isolateProperties` stays a fast object. | 547 // variables, so that `isolateProperties` stays a fast object. |
558 task.outputStaticNonFinalFieldLists.forEach( | 548 task.outputStaticNonFinalFieldLists.forEach( |
559 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { | 549 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { |
560 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. | 550 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. |
561 for (Element element in fields) { | 551 for (Element element in fields) { |
562 compiler.withCurrentElement(element, () { | 552 compiler.withCurrentElement(element, () { |
563 emitInitialization(element, jsAst.number(0)); | 553 parts.add(buildInitialization(element, jsAst.number(0))); |
564 }); | 554 }); |
565 } | 555 } |
566 }); | 556 }); |
567 } | 557 } |
558 | |
559 return new jsAst.Block(parts); | |
568 } | 560 } |
569 | 561 |
570 void emitLazilyInitializedStaticFields(CodeOutput output) { | 562 jsAst.Statement buildLazilyInitializedStaticFields() { |
571 JavaScriptConstantCompiler handler = backend.constants; | 563 JavaScriptConstantCompiler handler = backend.constants; |
572 List<VariableElement> lazyFields = | 564 List<VariableElement> lazyFields = |
573 handler.getLazilyInitializedFieldsForEmission(); | 565 handler.getLazilyInitializedFieldsForEmission(); |
574 if (!lazyFields.isEmpty) { | 566 if (lazyFields.isNotEmpty) { |
575 needsLazyInitializer = true; | 567 needsLazyInitializer = true; |
576 List<jsAst.Expression> laziesInfo = buildLaziesInfo(lazyFields); | 568 List<jsAst.Expression> laziesInfo = buildLaziesInfo(lazyFields); |
577 jsAst.Statement code = js.statement(''' | 569 return js.statement(''' |
578 (function(lazies) { | 570 (function(lazies) { |
579 if (#notInMinifiedMode) { | 571 if (#notInMinifiedMode) { |
580 var descriptorLength = 4; | 572 var descriptorLength = 4; |
581 } else { | 573 } else { |
582 var descriptorLength = 3; | 574 var descriptorLength = 3; |
583 } | 575 } |
584 | 576 |
585 for (var i = 0; i < lazies.length; i += descriptorLength) { | 577 for (var i = 0; i < lazies.length; i += descriptorLength) { |
586 var fieldName = lazies [i]; | 578 var fieldName = lazies [i]; |
587 var getterName = lazies[i + 1]; | 579 var getterName = lazies[i + 1]; |
588 var lazyValue = lazies[i + 2]; | 580 var lazyValue = lazies[i + 2]; |
589 if (#notInMinifiedMode) { | 581 if (#notInMinifiedMode) { |
590 var staticName = lazies[i + 3]; | 582 var staticName = lazies[i + 3]; |
591 } | 583 } |
592 | 584 |
593 // We build the lazy-check here: | 585 // We build the lazy-check here: |
594 // lazyInitializer(fieldName, getterName, lazyValue, staticName); | 586 // lazyInitializer(fieldName, getterName, lazyValue, staticName); |
595 // 'staticName' is used for error reporting in non-minified mode. | 587 // 'staticName' is used for error reporting in non-minified mode. |
596 // 'lazyValue' must be a closure that constructs the initial value. | 588 // 'lazyValue' must be a closure that constructs the initial value. |
597 if (#notInMinifiedMode) { | 589 if (#notInMinifiedMode) { |
598 #lazy(fieldName, getterName, lazyValue, staticName); | 590 #lazy(fieldName, getterName, lazyValue, staticName); |
599 } else { | 591 } else { |
600 #lazy(fieldName, getterName, lazyValue); | 592 #lazy(fieldName, getterName, lazyValue); |
601 } | 593 } |
602 } | 594 } |
603 })(#laziesInfo) | 595 })(#laziesInfo) |
604 ''', {'notInMinifiedMode': !compiler.enableMinification, | 596 ''', {'notInMinifiedMode': !compiler.enableMinification, |
605 'laziesInfo': new jsAst.ArrayInitializer(laziesInfo), | 597 'laziesInfo': new jsAst.ArrayInitializer(laziesInfo), |
606 'lazy': js(lazyInitializerName)}); | 598 'lazy': js(lazyInitializerName)}); |
607 | 599 } else { |
608 output.addBuffer( | 600 return js.comment("No lazy statics."); |
609 jsAst.prettyPrint(code, compiler, monitor: compiler.dumpInfoTask)); | |
610 output.add("$N"); | |
611 } | 601 } |
612 } | 602 } |
613 | 603 |
614 List<jsAst.Expression> buildLaziesInfo(List<VariableElement> lazies) { | 604 List<jsAst.Expression> buildLaziesInfo(List<VariableElement> lazies) { |
615 List<jsAst.Expression> laziesInfo = <jsAst.Expression>[]; | 605 List<jsAst.Expression> laziesInfo = <jsAst.Expression>[]; |
616 for (VariableElement element in Elements.sortedByPosition(lazies)) { | 606 for (VariableElement element in Elements.sortedByPosition(lazies)) { |
617 jsAst.Expression code = backend.generatedCode[element]; | 607 jsAst.Expression code = backend.generatedCode[element]; |
618 // The code is null if we ended up not needing the lazily | 608 // The code is null if we ended up not needing the lazily |
619 // initialized field after all because of constant folding | 609 // initialized field after all because of constant folding |
620 // before code generation. | 610 // before code generation. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
666 } else { | 656 } else { |
667 return js('#(#,#,#,#)', | 657 return js('#(#,#,#,#)', |
668 [js(lazyInitializerName), | 658 [js(lazyInitializerName), |
669 js.string(namer.globalPropertyName(element)), | 659 js.string(namer.globalPropertyName(element)), |
670 js.string(namer.lazyInitializerName(element)), | 660 js.string(namer.lazyInitializerName(element)), |
671 code, | 661 code, |
672 js.string(element.name)]); | 662 js.string(element.name)]); |
673 } | 663 } |
674 } | 664 } |
675 | 665 |
676 void emitMetadata(Program program, CodeOutput output, OutputUnit outputUnit) { | 666 jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) { |
667 List<jsAst.Statement> parts = <jsAst.Statement>[]; | |
677 | 668 |
678 jsAst.Expression constructList(List<jsAst.Expression> list) { | 669 jsAst.Expression constructList(List<jsAst.Expression> list) { |
679 return new jsAst.ArrayInitializer(list == null ? [] : list); | 670 return new jsAst.ArrayInitializer(list == null ? [] : list); |
680 } | 671 } |
681 | 672 |
682 List<jsAst.Expression> types = program.metadataTypes[outputUnit]; | 673 List<jsAst.Expression> types = program.metadataTypes[outputUnit]; |
683 | 674 |
684 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { | 675 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { |
685 jsAst.Expression metadataAccess = | 676 jsAst.Expression metadataAccess = |
686 generateEmbeddedGlobalAccess(embeddedNames.METADATA); | 677 generateEmbeddedGlobalAccess(embeddedNames.METADATA); |
687 jsAst.Expression typesAccess = | 678 jsAst.Expression typesAccess = |
688 generateEmbeddedGlobalAccess(embeddedNames.TYPES); | 679 generateEmbeddedGlobalAccess(embeddedNames.TYPES); |
689 | 680 |
690 output.addBuffer( | 681 parts..add(js.statement('# = #;', [metadataAccess, |
691 jsAst.prettyPrint(new jsAst.Block([ | 682 constructList(program.metadata)])) |
692 js.statement('# = #;', [metadataAccess, | 683 ..add(js.statement('# = #;', [typesAccess, constructList(types)])); |
693 constructList(program.metadata)]), | |
694 js.statement('# = #;', [typesAccess, constructList(types)])]), | |
695 compiler, monitor: compiler.dumpInfoTask)); | |
696 output.add(n); | |
697 } else if (types != null) { | 684 } else if (types != null) { |
698 output.addBuffer( | 685 parts.add(js.statement('var ${namer.deferredTypesName} = #;', |
699 jsAst.prettyPrint( | 686 constructList(types))); |
700 js.statement('var ${namer.deferredTypesName} = #;', | |
701 constructList(types)), | |
702 compiler, monitor: compiler.dumpInfoTask)); | |
703 if (compiler.enableMinification) { | |
704 output.add('\n'); | |
705 } | |
706 } | 687 } |
688 return new jsAst.Block(parts); | |
707 } | 689 } |
708 | 690 |
709 void emitCompileTimeConstants(CodeOutput output, | 691 jsAst.Statement buildCompileTimeConstants(List<Constant> constants, |
710 List<Constant> constants, | 692 {bool isMainFragment}) { |
711 {bool isMainFragment}) { | |
712 assert(isMainFragment != null); | 693 assert(isMainFragment != null); |
713 | 694 |
714 if (constants.isEmpty) return; | 695 if (constants.isEmpty) return js.comment("No constants in program."); |
715 CodeOutput constantOutput = output; | 696 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
716 if (compiler.hasIncrementalSupport && isMainFragment) { | 697 if (compiler.hasIncrementalSupport && isMainFragment) { |
717 constantOutput = cachedEmittedConstantsBuffer; | 698 parts = cachedEmittedConstantsAst; |
718 } | 699 } |
719 for (Constant constant in constants) { | 700 for (Constant constant in constants) { |
720 ConstantValue constantValue = constant.value; | 701 ConstantValue constantValue = constant.value; |
721 if (compiler.hasIncrementalSupport && isMainFragment) { | 702 if (compiler.hasIncrementalSupport && isMainFragment) { |
722 if (cachedEmittedConstants.contains(constantValue)) continue; | 703 if (cachedEmittedConstants.contains(constantValue)) continue; |
723 cachedEmittedConstants.add(constantValue); | 704 cachedEmittedConstants.add(constantValue); |
724 } | 705 } |
725 jsAst.Expression init = buildConstantInitializer(constantValue); | 706 parts.add(buildConstantInitializer(constantValue)); |
726 constantOutput.addBuffer( | |
727 jsAst.prettyPrint(init, compiler, monitor: compiler.dumpInfoTask)); | |
728 constantOutput.add('$N'); | |
729 } | 707 } |
730 if (compiler.hasIncrementalSupport && isMainFragment) { | 708 |
731 output.addBuffer(constantOutput); | 709 return new jsAst.Block(parts); |
732 } | |
733 } | 710 } |
734 | 711 |
735 jsAst.Expression buildConstantInitializer(ConstantValue constant) { | 712 jsAst.Statement buildConstantInitializer(ConstantValue constant) { |
736 String name = namer.constantName(constant); | 713 String name = namer.constantName(constant); |
737 return js('#.# = #', | 714 return js.statement('#.# = #', |
738 [namer.globalObjectForConstant(constant), name, | 715 [namer.globalObjectForConstant(constant), name, |
739 constantInitializerExpression(constant)]); | 716 constantInitializerExpression(constant)]); |
740 } | 717 } |
741 | 718 |
742 jsAst.Template get makeConstantListTemplate { | 719 jsAst.Template get makeConstantListTemplate { |
743 // TODO(floitsch): there is no harm in caching the template. | 720 // TODO(floitsch): there is no harm in caching the template. |
744 return jsAst.js.uncachedExpressionTemplate( | 721 return jsAst.js.uncachedExpressionTemplate( |
745 '${namer.isolateName}.$makeConstListProperty(#)'); | 722 '${namer.isolateName}.$makeConstListProperty(#)'); |
746 } | 723 } |
747 | 724 |
748 void emitMakeConstantList(CodeOutput output) { | 725 jsAst.Statement buildMakeConstantList() { |
749 output.addBuffer( | 726 if (task.outputContainsConstantList) { |
750 jsAst.prettyPrint( | 727 return js.statement(r''' |
751 // Functions are stored in the hidden class and not as properties in | 728 // Functions are stored in the hidden class and not as properties in |
752 // the object. We never actually look at the value, but only want | 729 // the object. We never actually look at the value, but only want |
753 // to know if the property exists. | 730 // to know if the property exists. |
754 js.statement(r'''#.# = function(list) { | 731 #.# = function (list) { |
755 list.immutable$list = Array; | 732 list.immutable$list = Array; |
756 list.fixed$length = Array; | 733 list.fixed$length = Array; |
757 return list; | 734 return list; |
758 }''', | 735 }''', |
759 [namer.isolateName, makeConstListProperty]), | 736 [namer.isolateName, makeConstListProperty]); |
760 compiler, monitor: compiler.dumpInfoTask)); | 737 } else { |
761 output.add(N); | 738 return js.comment("Output contains no constant list."); |
739 } | |
762 } | 740 } |
763 | 741 |
764 void emitFunctionThatReturnsNull(CodeOutput output) { | 742 jsAst.Statement buildFunctionThatReturnsNull() { |
765 output.addBuffer( | 743 return js.statement('#.# = function() {}', |
766 jsAst.prettyPrint( | 744 [backend.namer.currentIsolate, |
767 js.statement('#.# = function() {}', | 745 backend.rti.getFunctionThatReturnsNullName]); |
768 [backend.namer.currentIsolate, | |
769 backend.rti.getFunctionThatReturnsNullName]), | |
770 compiler, monitor: compiler.dumpInfoTask)); | |
771 output.add(N); | |
772 } | 746 } |
773 | 747 |
774 jsAst.Expression generateFunctionThatReturnsNull() { | 748 jsAst.Expression generateFunctionThatReturnsNull() { |
775 return js("#.#", [backend.namer.currentIsolate, | 749 return js("#.#", [backend.namer.currentIsolate, |
776 backend.rti.getFunctionThatReturnsNullName]); | 750 backend.rti.getFunctionThatReturnsNullName]); |
777 } | 751 } |
778 | 752 |
779 emitMain(CodeOutput output, jsAst.Statement invokeMain) { | 753 buildMain(jsAst.Statement invokeMain) { |
780 if (compiler.isMockCompilation) return; | 754 if (compiler.isMockCompilation) return js.comment("Mock compilation"); |
755 | |
756 List<jsAst.Statement> parts = <jsAst.Statement>[]; | |
781 | 757 |
782 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { | 758 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { |
783 jsAst.Statement nativeBoilerPlate = | 759 parts.add( |
784 NativeGenerator.generateIsolateAffinityTagInitialization( | 760 NativeGenerator.generateIsolateAffinityTagInitialization( |
785 backend, | 761 backend, |
786 generateEmbeddedGlobalAccess, | 762 generateEmbeddedGlobalAccess, |
787 js("convertToFastObject", [])); | 763 js("convertToFastObject", []))); |
788 output.addBuffer(jsAst.prettyPrint( | |
789 nativeBoilerPlate, compiler, monitor: compiler.dumpInfoTask)); | |
790 } | 764 } |
791 | 765 |
792 output.add(';'); | 766 parts..add(js.comment('BEGIN invoke [main].')) |
793 addComment('BEGIN invoke [main].', output); | 767 ..add(invokeMain) |
794 output.addBuffer(jsAst.prettyPrint(invokeMain, | 768 ..add(js.comment('END invoke [main].')); |
795 compiler, monitor: compiler.dumpInfoTask)); | 769 |
796 output.add(N); | 770 return new jsAst.Block(parts); |
797 addComment('END invoke [main].', output); | |
798 } | 771 } |
799 | 772 |
800 void emitInitFunction(CodeOutput output) { | 773 jsAst.Statement buildInitFunction() { |
801 jsAst.Expression allClassesAccess = | 774 jsAst.Expression allClassesAccess = |
802 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); | 775 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
803 jsAst.Expression getTypeFromNameAccess = | 776 jsAst.Expression getTypeFromNameAccess = |
804 generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME); | 777 generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME); |
805 jsAst.Expression interceptorsByTagAccess = | 778 jsAst.Expression interceptorsByTagAccess = |
806 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | 779 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
807 jsAst.Expression leafTagsAccess = | 780 jsAst.Expression leafTagsAccess = |
808 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | 781 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
809 jsAst.Expression finishedClassesAccess = | 782 jsAst.Expression finishedClassesAccess = |
810 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | 783 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
811 jsAst.Expression cyclicThrow = | 784 jsAst.Expression cyclicThrow = |
812 staticFunctionAccess(backend.getCyclicThrowHelper()); | 785 staticFunctionAccess(backend.getCyclicThrowHelper()); |
813 jsAst.Expression laziesAccess = | 786 jsAst.Expression laziesAccess = |
814 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); | 787 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); |
815 | 788 |
816 jsAst.FunctionDeclaration decl = js.statement(''' | 789 return js.statement(''' |
817 function init() { | 790 function init() { |
818 $isolateProperties = Object.create(null); | 791 $isolatePropertiesName = Object.create(null); |
819 #allClasses = Object.create(null); | 792 #allClasses = Object.create(null); |
820 #getTypeFromName = function(name) {return #allClasses[name];}; | 793 #getTypeFromName = function(name) {return #allClasses[name];}; |
821 #interceptorsByTag = Object.create(null); | 794 #interceptorsByTag = Object.create(null); |
822 #leafTags = Object.create(null); | 795 #leafTags = Object.create(null); |
823 #finishedClasses = Object.create(null); | 796 #finishedClasses = Object.create(null); |
824 | 797 |
825 if (#needsLazyInitializer) { | 798 if (#needsLazyInitializer) { |
826 // [staticName] is only provided in non-minified mode. If missing, we | 799 // [staticName] is only provided in non-minified mode. If missing, we |
827 // fall back to [fieldName]. Likewise, [prototype] is optional and | 800 // fall back to [fieldName]. Likewise, [prototype] is optional and |
828 // defaults to the isolateProperties object. | 801 // defaults to the isolateProperties object. |
829 $lazyInitializerName = function (fieldName, getterName, lazyValue, | 802 $lazyInitializerName = function (fieldName, getterName, lazyValue, |
830 staticName, prototype) { | 803 staticName, prototype) { |
831 if (!#lazies) #lazies = Object.create(null); | 804 if (!#lazies) #lazies = Object.create(null); |
832 #lazies[fieldName] = getterName; | 805 #lazies[fieldName] = getterName; |
833 | 806 |
834 // 'prototype' will be undefined except if we are doing an update | 807 // 'prototype' will be undefined except if we are doing an update |
835 // during incremental compilation. In this case we put the lazy | 808 // during incremental compilation. In this case we put the lazy |
836 // field directly on the isolate instead of the isolateProperties. | 809 // field directly on the isolate instead of the isolateProperties. |
837 prototype = prototype || $isolateProperties; | 810 prototype = prototype || $isolatePropertiesName; |
838 var sentinelUndefined = {}; | 811 var sentinelUndefined = {}; |
839 var sentinelInProgress = {}; | 812 var sentinelInProgress = {}; |
840 prototype[fieldName] = sentinelUndefined; | 813 prototype[fieldName] = sentinelUndefined; |
841 | 814 |
842 prototype[getterName] = function () { | 815 prototype[getterName] = function () { |
843 var result = this[fieldName]; | 816 var result = this[fieldName]; |
844 try { | 817 try { |
845 if (result === sentinelUndefined) { | 818 if (result === sentinelUndefined) { |
846 this[fieldName] = sentinelInProgress; | 819 this[fieldName] = sentinelInProgress; |
847 | 820 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
926 'interceptorsByTag': interceptorsByTagAccess, | 899 'interceptorsByTag': interceptorsByTagAccess, |
927 'leafTags': leafTagsAccess, | 900 'leafTags': leafTagsAccess, |
928 'finishedClasses': finishedClassesAccess, | 901 'finishedClasses': finishedClassesAccess, |
929 'needsLazyInitializer': needsLazyInitializer, | 902 'needsLazyInitializer': needsLazyInitializer, |
930 'lazies': laziesAccess, 'cyclicThrow': cyclicThrow, | 903 'lazies': laziesAccess, 'cyclicThrow': cyclicThrow, |
931 'isolatePropertiesName': namer.isolatePropertiesName, | 904 'isolatePropertiesName': namer.isolatePropertiesName, |
932 'outputContainsConstantList': task.outputContainsConstantList, | 905 'outputContainsConstantList': task.outputContainsConstantList, |
933 'makeConstListProperty': makeConstListProperty, | 906 'makeConstListProperty': makeConstListProperty, |
934 'hasIncrementalSupport': compiler.hasIncrementalSupport, | 907 'hasIncrementalSupport': compiler.hasIncrementalSupport, |
935 'lazyInitializerProperty': lazyInitializerProperty,}); | 908 'lazyInitializerProperty': lazyInitializerProperty,}); |
936 | |
937 output.addBuffer( | |
938 jsAst.prettyPrint(decl, compiler, monitor: compiler.dumpInfoTask)); | |
939 if (compiler.enableMinification) { | |
940 output.add('\n'); | |
941 } | |
942 } | 909 } |
943 | 910 |
944 void emitConvertToFastObjectFunction(CodeOutput output) { | 911 jsAst.Statement buildConvertToFastObjectFunction() { |
945 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; | 912 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; |
946 if (DEBUG_FAST_OBJECTS) { | 913 if (DEBUG_FAST_OBJECTS) { |
947 debugCode.add(js.statement(r''' | 914 debugCode.add(js.statement(r''' |
948 // The following only works on V8 when run with option | 915 // The following only works on V8 when run with option |
949 // "--allow-natives-syntax". We use'new Function' because the | 916 // "--allow-natives-syntax". We use'new Function' because the |
950 // miniparser does not understand V8 native syntax. | 917 // miniparser does not understand V8 native syntax. |
951 if (typeof print === "function") { | 918 if (typeof print === "function") { |
952 var HasFastProperties = | 919 var HasFastProperties = |
953 new Function("a", "return %HasFastProperties(a)"); | 920 new Function("a", "return %HasFastProperties(a)"); |
954 print("Size of global object: " | 921 print("Size of global object: " |
955 + String(Object.getOwnPropertyNames(properties).length) | 922 + String(Object.getOwnPropertyNames(properties).length) |
956 + ", fast properties " + HasFastProperties(properties)); | 923 + ", fast properties " + HasFastProperties(properties)); |
957 }''')); | 924 }''')); |
958 } | 925 } |
959 | 926 |
960 jsAst.Statement convertToFastObject = js.statement(r''' | 927 return js.statement(r''' |
961 function convertToFastObject(properties) { | 928 function convertToFastObject(properties) { |
962 // Create an instance that uses 'properties' as prototype. This should | 929 // Create an instance that uses 'properties' as prototype. This should |
963 // make 'properties' a fast object. | 930 // make 'properties' a fast object. |
964 function MyClass() {}; | 931 function MyClass() {}; |
965 MyClass.prototype = properties; | 932 MyClass.prototype = properties; |
966 new MyClass(); | 933 new MyClass(); |
967 #; | 934 #; |
968 return properties; | 935 return properties; |
969 }''', [debugCode]); | 936 }''', [debugCode]); |
970 | |
971 output.addBuffer(jsAst.prettyPrint(convertToFastObject, compiler)); | |
972 output.add(N); | |
973 } | 937 } |
974 | 938 |
975 void emitConvertToSlowObjectFunction(CodeOutput output) { | 939 jsAst.Statement buildConvertToSlowObjectFunction() { |
976 jsAst.Statement convertToSlowObject = js.statement(r''' | 940 return js.statement(r''' |
977 function convertToSlowObject(properties) { | 941 function convertToSlowObject(properties) { |
978 // Add and remove a property to make the object transition into hashmap | 942 // Add and remove a property to make the object transition into hashmap |
979 // mode. | 943 // mode. |
980 properties.__MAGIC_SLOW_PROPERTY = 1; | 944 properties.__MAGIC_SLOW_PROPERTY = 1; |
981 delete properties.__MAGIC_SLOW_PROPERTY; | 945 delete properties.__MAGIC_SLOW_PROPERTY; |
982 return properties; | 946 return properties; |
983 }'''); | 947 }'''); |
984 | |
985 output.addBuffer(jsAst.prettyPrint(convertToSlowObject, compiler)); | |
986 output.add(N); | |
987 } | 948 } |
988 | 949 |
989 void emitSupportsDirectProtoAccess(CodeOutput output) { | 950 jsAst.Statement buildSupportsDirectProtoAccess() { |
990 jsAst.Statement supportsDirectProtoAccess; | 951 jsAst.Statement supportsDirectProtoAccess; |
991 | 952 |
992 if (compiler.hasIncrementalSupport) { | 953 if (compiler.hasIncrementalSupport) { |
993 supportsDirectProtoAccess = js.statement(r''' | 954 supportsDirectProtoAccess = js.statement(r''' |
994 var supportsDirectProtoAccess = false; | 955 var supportsDirectProtoAccess = false; |
995 '''); | 956 '''); |
996 } else { | 957 } else { |
997 supportsDirectProtoAccess = js.statement(r''' | 958 supportsDirectProtoAccess = js.statement(r''' |
998 var supportsDirectProtoAccess = (function () { | 959 var supportsDirectProtoAccess = (function () { |
999 var cls = function () {}; | 960 var cls = function () {}; |
1000 cls.prototype = {'p': {}}; | 961 cls.prototype = {'p': {}}; |
1001 var object = new cls(); | 962 var object = new cls(); |
1002 return object.__proto__ && | 963 return object.__proto__ && |
1003 object.__proto__.p === cls.prototype.p; | 964 object.__proto__.p === cls.prototype.p; |
1004 })(); | 965 })(); |
1005 '''); | 966 '''); |
1006 } | 967 } |
1007 | 968 |
1008 output.addBuffer(jsAst.prettyPrint(supportsDirectProtoAccess, compiler)); | 969 return supportsDirectProtoAccess; |
1009 output.add(N); | |
1010 } | 970 } |
1011 | 971 |
1012 jsAst.Expression generateLibraryDescriptor(LibraryElement library, | 972 jsAst.Expression generateLibraryDescriptor(LibraryElement library, |
1013 Fragment fragment) { | 973 Fragment fragment) { |
1014 var uri = ""; | 974 var uri = ""; |
1015 if (!compiler.enableMinification || backend.mustPreserveUris) { | 975 if (!compiler.enableMinification || backend.mustPreserveUris) { |
1016 uri = library.canonicalUri; | 976 uri = library.canonicalUri; |
1017 if (uri.scheme == 'file' && compiler.outputUri != null) { | 977 if (uri.scheme == 'file' && compiler.outputUri != null) { |
1018 uri = relativize(compiler.outputUri, library.canonicalUri, false); | 978 uri = relativize(compiler.outputUri, library.canonicalUri, false); |
1019 } | 979 } |
(...skipping 19 matching lines...) Expand all Loading... | |
1039 initializer = descriptor.toObjectInitializer(); | 999 initializer = descriptor.toObjectInitializer(); |
1040 } | 1000 } |
1041 | 1001 |
1042 compiler.dumpInfoTask.registerElementAst(library, metadata); | 1002 compiler.dumpInfoTask.registerElementAst(library, metadata); |
1043 compiler.dumpInfoTask.registerElementAst(library, initializer); | 1003 compiler.dumpInfoTask.registerElementAst(library, initializer); |
1044 | 1004 |
1045 List<jsAst.Expression> parts = <jsAst.Expression>[]; | 1005 List<jsAst.Expression> parts = <jsAst.Expression>[]; |
1046 parts..add(js.string(libraryName)) | 1006 parts..add(js.string(libraryName)) |
1047 ..add(js.string(uri.toString())) | 1007 ..add(js.string(uri.toString())) |
1048 ..add(metadata == null ? new jsAst.ArrayHole() : metadata) | 1008 ..add(metadata == null ? new jsAst.ArrayHole() : metadata) |
1049 ..add(js.name(namer.globalObjectFor(library))) | 1009 ..add(js('#', namer.globalObjectFor(library))) |
1050 ..add(initializer); | 1010 ..add(initializer); |
1051 if (library == compiler.mainApp) { | 1011 if (library == compiler.mainApp) { |
1052 parts.add(js.number(1)); | 1012 parts.add(js.number(1)); |
1053 } | 1013 } |
1054 | 1014 |
1055 return new jsAst.ArrayInitializer(parts); | 1015 return new jsAst.ArrayInitializer(parts); |
1056 } | 1016 } |
1057 | 1017 |
1058 void assemblePrecompiledConstructor(OutputUnit outputUnit, | 1018 void assemblePrecompiledConstructor(OutputUnit outputUnit, |
1059 String constructorName, | 1019 String constructorName, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1125 String constructorName = mangledName; | 1085 String constructorName = mangledName; |
1126 jsAst.Expression constructorAst = js('function() {}'); | 1086 jsAst.Expression constructorAst = js('function() {}'); |
1127 List<String> fieldNames = []; | 1087 List<String> fieldNames = []; |
1128 assemblePrecompiledConstructor(mainOutputUnit, | 1088 assemblePrecompiledConstructor(mainOutputUnit, |
1129 constructorName, | 1089 constructorName, |
1130 constructorAst, | 1090 constructorAst, |
1131 fieldNames); | 1091 fieldNames); |
1132 } | 1092 } |
1133 } | 1093 } |
1134 | 1094 |
1135 void emitMangledNames(CodeOutput output) { | 1095 jsAst.Statement buildGlobalObjectSetup(bool isProgramSplit) { |
1096 List<jsAst.Statement> parts = <jsAst.Statement>[]; | |
1097 | |
1098 parts.add(js.comment(""" | |
1099 // The global objects start as so-called "slow objects". For V8, this | |
1100 // means that it won't try to make map transitions as we add properties | |
1101 // to these objects. Later on, we attempt to turn these objects into | |
1102 // fast objects by calling "convertToFastObject" (see | |
1103 // [emitConvertToFastObjectFunction]). | |
1104 """)); | |
1105 | |
1106 for (String globalObject in Namer.reservedGlobalObjectNames) { | |
1107 if (isProgramSplit) { | |
1108 String template = | |
1109 "var #globalObject = #globalsHolder.#globalObject = map();"; | |
1110 parts.add(js.statement(template, {"globalObject": globalObject, | |
1111 "globalsHolder": globalsHolder})); | |
1112 } else { | |
1113 parts.add(js.statement("var #globalObject = map();", | |
1114 {"globalObject": globalObject})); | |
1115 } | |
1116 | |
1117 } | |
1118 | |
1119 return new jsAst.Block(parts); | |
1120 } | |
1121 | |
1122 jsAst.Statement buildConvertGlobalObjectToFastObjects() { | |
1123 List<jsAst.Statement> parts = <jsAst.Statement>[]; | |
1124 | |
1125 for (String globalObject in Namer.reservedGlobalObjectNames) { | |
1126 parts.add(js.statement( | |
1127 '#globalObject = convertToFastObject(#globalObject);', | |
1128 {"globalObject": globalObject})); | |
1129 } | |
1130 | |
1131 return new jsAst.Block(parts); | |
1132 } | |
1133 | |
1134 jsAst.Statement buildDebugFastObjectCode() { | |
1135 List<jsAst.Statement> parts = <jsAst.Statement>[]; | |
1136 | |
1137 if (DEBUG_FAST_OBJECTS) { | |
1138 parts.add(js.statement(r''' | |
1139 // The following only works on V8 when run with option | |
1140 // "--allow-natives-syntax". We use'new Function' because the | |
1141 // miniparser does not understand V8 native syntax. | |
1142 if (typeof print === "function") { | |
1143 var HasFastProperties = | |
1144 new Function("a", "return %HasFastProperties(a)"); | |
1145 print("Size of global helper object: " | |
1146 + String(Object.getOwnPropertyNames(H).length) | |
1147 + ", fast properties " + HasFastProperties(H)); | |
1148 print("Size of global platform object: " | |
1149 + String(Object.getOwnPropertyNames(P).length) | |
1150 + ", fast properties " + HasFastProperties(P)); | |
1151 print("Size of global dart:html object: " | |
1152 + String(Object.getOwnPropertyNames(W).length) | |
1153 + ", fast properties " + HasFastProperties(W)); | |
1154 print("Size of isolate properties object: " | |
1155 + String(Object.getOwnPropertyNames($).length) | |
1156 + ", fast properties " + HasFastProperties($)); | |
1157 print("Size of constant object: " | |
1158 + String(Object.getOwnPropertyNames(C).length) | |
1159 + ", fast properties " + HasFastProperties(C)); | |
1160 var names = Object.getOwnPropertyNames($); | |
1161 for (var i = 0; i < names.length; i++) { | |
1162 print("$." + names[i]); | |
1163 } | |
1164 } | |
1165 ''')); | |
1166 | |
1167 for (String object in Namer.userGlobalObjects) { | |
1168 parts.add(js.statement(''' | |
1169 if (typeof print === "function") { | |
1170 print("Size of " + #objectString + ": " | |
1171 + String(Object.getOwnPropertyNames(#object).length) | |
1172 + ", fast properties " + HasFastProperties(#object)); | |
1173 } | |
1174 ''', {"object": object, "objectString": js.string(object)})); | |
1175 } | |
1176 } | |
1177 | |
1178 return new jsAst.Block(parts); | |
1179 } | |
1180 | |
1181 jsAst.Statement buildMangledNames() { | |
1182 List<jsAst.Statement> parts = <jsAst.Statement>[]; | |
1183 | |
1136 if (!mangledFieldNames.isEmpty) { | 1184 if (!mangledFieldNames.isEmpty) { |
1137 var keys = mangledFieldNames.keys.toList(); | 1185 var keys = mangledFieldNames.keys.toList(); |
1138 keys.sort(); | 1186 keys.sort(); |
1139 var properties = []; | 1187 var properties = []; |
1140 for (String key in keys) { | 1188 for (String key in keys) { |
1141 var value = js.string('${mangledFieldNames[key]}'); | 1189 var value = js.string('${mangledFieldNames[key]}'); |
1142 properties.add(new jsAst.Property(js.string(key), value)); | 1190 properties.add(new jsAst.Property(js.string(key), value)); |
1143 } | 1191 } |
1144 | 1192 |
1145 jsAst.Expression mangledNamesAccess = | 1193 jsAst.Expression mangledNamesAccess = |
1146 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); | 1194 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); |
1147 var map = new jsAst.ObjectInitializer(properties); | 1195 var map = new jsAst.ObjectInitializer(properties); |
1148 output.addBuffer( | 1196 parts.add(js.statement('# = #', [mangledNamesAccess, map])); |
1149 jsAst.prettyPrint( | |
1150 js.statement('# = #', [mangledNamesAccess, map]), | |
1151 compiler, | |
1152 monitor: compiler.dumpInfoTask)); | |
1153 if (compiler.enableMinification) { | |
1154 output.add(';'); | |
1155 } | |
1156 } | 1197 } |
1198 | |
1157 if (!mangledGlobalFieldNames.isEmpty) { | 1199 if (!mangledGlobalFieldNames.isEmpty) { |
1158 var keys = mangledGlobalFieldNames.keys.toList(); | 1200 var keys = mangledGlobalFieldNames.keys.toList(); |
1159 keys.sort(); | 1201 keys.sort(); |
1160 var properties = []; | 1202 var properties = []; |
1161 for (String key in keys) { | 1203 for (String key in keys) { |
1162 var value = js.string('${mangledGlobalFieldNames[key]}'); | 1204 var value = js.string('${mangledGlobalFieldNames[key]}'); |
1163 properties.add(new jsAst.Property(js.string(key), value)); | 1205 properties.add(new jsAst.Property(js.string(key), value)); |
1164 } | 1206 } |
1165 jsAst.Expression mangledGlobalNamesAccess = | 1207 jsAst.Expression mangledGlobalNamesAccess = |
1166 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); | 1208 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); |
1167 var map = new jsAst.ObjectInitializer(properties); | 1209 var map = new jsAst.ObjectInitializer(properties); |
1168 output.addBuffer( | 1210 parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map])); |
1169 jsAst.prettyPrint( | |
1170 js.statement('# = #', [mangledGlobalNamesAccess, map]), | |
1171 compiler, | |
1172 monitor: compiler.dumpInfoTask)); | |
1173 if (compiler.enableMinification) { | |
1174 output.add(';'); | |
1175 } | |
1176 } | 1211 } |
1212 | |
1213 return new jsAst.Block(parts); | |
1177 } | 1214 } |
1178 | 1215 |
1179 void checkEverythingEmitted(Iterable<Element> elements) { | 1216 void checkEverythingEmitted(Iterable<Element> elements) { |
1180 List<Element> pendingStatics; | 1217 List<Element> pendingStatics; |
1181 if (!compiler.hasIncrementalSupport) { | 1218 if (!compiler.hasIncrementalSupport) { |
1182 pendingStatics = | 1219 pendingStatics = |
1183 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); | 1220 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); |
1184 | 1221 |
1185 pendingStatics.forEach((element) => | 1222 pendingStatics.forEach((element) => |
1186 compiler.reportInfo( | 1223 compiler.reportInfo( |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1228 codeOutputListeners = <CodeOutputListener>[lineColumnCollector]; | 1265 codeOutputListeners = <CodeOutputListener>[lineColumnCollector]; |
1229 } | 1266 } |
1230 | 1267 |
1231 CodeOutput mainOutput = | 1268 CodeOutput mainOutput = |
1232 new StreamCodeOutput(compiler.outputProvider('', 'js'), | 1269 new StreamCodeOutput(compiler.outputProvider('', 'js'), |
1233 codeOutputListeners); | 1270 codeOutputListeners); |
1234 outputBuffers[mainOutputUnit] = mainOutput; | 1271 outputBuffers[mainOutputUnit] = mainOutput; |
1235 | 1272 |
1236 bool isProgramSplit = program.isSplit; | 1273 bool isProgramSplit = program.isSplit; |
1237 | 1274 |
1238 mainOutput.add(buildGeneratedBy()); | 1275 List<jsAst.Statement> statements = <jsAst.Statement>[]; |
1239 addComment(HOOKS_API_USAGE, mainOutput); | 1276 |
1277 statements..add(buildGeneratedBy()) | |
1278 ..add(js.comment(HOOKS_API_USAGE)); | |
1240 | 1279 |
1241 if (isProgramSplit) { | 1280 if (isProgramSplit) { |
1242 /// For deferred loading we communicate the initializers via this global | 1281 /// For deferred loading we communicate the initializers via this global |
1243 /// variable. The deferred hunks will add their initialization to this. | 1282 /// variable. The deferred hunks will add their initialization to this. |
1244 /// The semicolon is important in minified mode, without it the | 1283 /// The semicolon is important in minified mode, without it the |
1245 /// following parenthesis looks like a call to the object literal. | 1284 /// following parenthesis looks like a call to the object literal. |
1246 mainOutput.add( | 1285 statements.add( |
1247 'self.${deferredInitializers} = self.${deferredInitializers} || ' | 1286 js.statement('self.#deferredInitializers = ' |
1248 'Object.create(null);$n'); | 1287 'self.#deferredInitializers || Object.create(null);', |
1288 {'deferredInitializers': deferredInitializers})); | |
1249 } | 1289 } |
1250 | 1290 |
1251 // Using a named function here produces easier to read stack traces in | 1291 // Collect the AST for the decriptors |
1252 // Chrome/V8. | |
1253 mainOutput.add('(function(${namer.currentIsolate})$_{\n'); | |
1254 emitSupportsDirectProtoAccess(mainOutput); | |
1255 if (compiler.hasIncrementalSupport) { | |
1256 mainOutput.addBuffer(jsAst.prettyPrint(js.statement( | |
1257 """ | |
1258 { | |
1259 #helper = #helper || Object.create(null); | |
1260 #helper.patch = function(a) { eval(a)}; | |
1261 #helper.schemaChange = #schemaChange; | |
1262 #helper.addMethod = #addMethod; | |
1263 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) { | |
1264 var descriptor = Object.create(null); | |
1265 this.addStubs(descriptor, array, name, isStatic, []); | |
1266 return descriptor; | |
1267 }; | |
1268 }""", | |
1269 { 'helper': js('this.#', [namer.incrementalHelperName]), | |
1270 'schemaChange': buildSchemaChangeFunction(), | |
1271 'addMethod': buildIncrementalAddMethod() }), compiler)); | |
1272 } | |
1273 if (isProgramSplit) { | |
1274 /// We collect all the global state, so it can be passed to the | |
1275 /// initializer of deferred files. | |
1276 mainOutput.add('var ${globalsHolder}$_=${_}Object.create(null)$N'); | |
1277 } | |
1278 | |
1279 jsAst.Statement mapFunction = js.statement(''' | |
1280 // [map] returns an object that V8 shouldn't try to optimize with a hidden | |
1281 // class. This prevents a potential performance problem where V8 tries to build | |
1282 // a hidden class for an object used as a hashMap. | |
1283 // It requires fewer characters to declare a variable as a parameter than | |
1284 // with `var`. | |
1285 function map(x) { | |
1286 x = Object.create(null); | |
1287 x.x = 0; | |
1288 delete x.x; | |
1289 return x; | |
1290 } | |
1291 '''); | |
1292 mainOutput.addBuffer(jsAst.prettyPrint(mapFunction, compiler)); | |
1293 for (String globalObject in Namer.reservedGlobalObjectNames) { | |
1294 // The global objects start as so-called "slow objects". For V8, this | |
1295 // means that it won't try to make map transitions as we add properties | |
1296 // to these objects. Later on, we attempt to turn these objects into | |
1297 // fast objects by calling "convertToFastObject" (see | |
1298 // [emitConvertToFastObjectFunction]). | |
1299 mainOutput.add('var ${globalObject}$_=${_}'); | |
1300 if(isProgramSplit) { | |
1301 mainOutput.add('${globalsHolder}.$globalObject$_=${_}'); | |
1302 } | |
1303 mainOutput.add('map()$N'); | |
1304 } | |
1305 | |
1306 mainOutput.add('function ${namer.isolateName}()$_{}\n'); | |
1307 if (isProgramSplit) { | |
1308 mainOutput.add( | |
1309 '${globalsHolder}.${namer.isolateName}$_=$_${namer.isolateName}$N' | |
1310 '${globalsHolder}.$initName$_=${_}$initName$N' | |
1311 '${globalsHolder}.$setupProgramName$_=$_' | |
1312 '$setupProgramName$N'); | |
1313 } | |
1314 mainOutput.add('init()$N$n'); | |
1315 mainOutput.add('$isolateProperties$_=$_$isolatePropertiesName$N'); | |
1316 | |
1317 emitFunctionThatReturnsNull(mainOutput); | |
1318 | |
1319 Iterable<LibraryElement> libraries = | |
1320 task.outputLibraryLists[mainOutputUnit]; | |
1321 if (libraries == null) libraries = []; | |
1322 emitMangledNames(mainOutput); | |
1323 | |
1324 Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment]; | 1292 Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment]; |
1325 if (descriptors == null) descriptors = const {}; | 1293 if (descriptors == null) descriptors = const {}; |
1326 | 1294 |
1327 checkEverythingEmitted(descriptors.keys); | 1295 checkEverythingEmitted(descriptors.keys); |
1328 | 1296 |
1297 Iterable<LibraryElement> libraries = | |
1298 task.outputLibraryLists[mainOutputUnit]; | |
1299 if (libraries == null) libraries = []; | |
1300 | |
1329 List<jsAst.Expression> parts = <jsAst.Expression>[]; | 1301 List<jsAst.Expression> parts = <jsAst.Expression>[]; |
1330 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1302 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
1331 parts.add(generateLibraryDescriptor(library, mainFragment)); | 1303 parts.add(generateLibraryDescriptor(library, mainFragment)); |
1332 descriptors.remove(library); | 1304 descriptors.remove(library); |
1333 } | 1305 } |
1334 | 1306 |
1335 if (descriptors.isNotEmpty) { | 1307 if (descriptors.isNotEmpty) { |
1336 List<Element> remainingLibraries = descriptors.keys | 1308 List<Element> remainingLibraries = descriptors.keys |
1337 .where((Element e) => e is LibraryElement) | 1309 .where((Element e) => e is LibraryElement) |
1338 .toList(); | 1310 .toList(); |
1339 | 1311 |
1340 // The remaining descriptors are only accessible through reflection. | 1312 // The remaining descriptors are only accessible through reflection. |
1341 // The program builder does not collect libraries that only | 1313 // The program builder does not collect libraries that only |
1342 // contain typedefs that are used for reflection. | 1314 // contain typedefs that are used for reflection. |
1343 for (LibraryElement element in remainingLibraries) { | 1315 for (LibraryElement element in remainingLibraries) { |
1344 assert(element is LibraryElement || compiler.hasIncrementalSupport); | 1316 assert(element is LibraryElement || compiler.hasIncrementalSupport); |
1345 if (element is LibraryElement) { | 1317 if (element is LibraryElement) { |
1346 parts.add(generateLibraryDescriptor(element, mainFragment)); | 1318 parts.add(generateLibraryDescriptor(element, mainFragment)); |
1347 descriptors.remove(element); | 1319 descriptors.remove(element); |
1348 } | 1320 } |
1349 } | 1321 } |
1350 } | 1322 } |
1351 jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts); | 1323 jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts); |
1352 | 1324 |
1353 bool needsNativeSupport = program.needsNativeSupport; | 1325 // Using a named function here produces easier to read stack traces in |
1354 mainOutput.addBuffer( | 1326 // Chrome/V8. |
1355 jsAst.prettyPrint( | 1327 statements.add(js.statement(""" |
1356 buildSetupProgram(program, compiler, backend, namer, this), | 1328 (function() { |
1357 compiler)); | 1329 // No renaming in the top-level function to save the locals for the |
1330 // nested context where they will be used more. We have to put the | |
1331 // comment into a hole as the parser strips out comments right away. | |
1332 #disableVariableRenaming; | |
1333 #supportsDirectProtoAccess; | |
1358 | 1334 |
1359 // The argument to reflectionDataParser is assigned to a temporary 'dart' | 1335 if (#hasIncrementalSupport) { |
1360 // so that 'dart.' will appear as the prefix to dart methods in stack | 1336 #helper = #helper || Object.create(null); |
1361 // traces and profile entries. | 1337 #helper.patch = function(a) { eval(a)}; |
1362 mainOutput..add('var dart =') | 1338 #helper.schemaChange = #schemaChange; |
1363 ..addBuffer(jsAst.prettyPrint(descriptorsAst, compiler, | 1339 #helper.addMethod = #addMethod; |
1364 monitor: compiler.dumpInfoTask)) | 1340 #helper.extractStubs = |
1365 ..add('$N'); | 1341 function(array, name, isStatic, originalDescriptor) { |
1366 if (compiler.useContentSecurityPolicy) { | 1342 var descriptor = Object.create(null); |
1367 jsAst.Statement precompiledFunctionAst = | 1343 this.addStubs(descriptor, array, name, isStatic, []); |
1368 buildCspPrecompiledFunctionFor(mainOutputUnit); | 1344 return descriptor; |
1369 mainOutput.addBuffer( | 1345 }; |
1370 jsAst.prettyPrint( | 1346 } |
1371 precompiledFunctionAst, | |
1372 compiler, | |
1373 monitor: compiler.dumpInfoTask, | |
1374 allowVariableMinification: false)); | |
1375 mainOutput.add(N); | |
1376 } | |
1377 | 1347 |
1378 mainOutput.add('$setupProgramName(dart, 0)$N'); | 1348 if (#isProgramSplit) { |
1349 /// We collect all the global state, so it can be passed to the | |
1350 /// initializer of deferred files. | |
1351 var #globalsHolder = Object.create(null) | |
1352 } | |
1379 | 1353 |
1380 interceptorEmitter.emitGetInterceptorMethods(mainOutput); | 1354 // [map] returns an object that V8 shouldn't try to optimize with a |
1381 interceptorEmitter.emitOneShotInterceptors(mainOutput); | 1355 // hidden class. This prevents a potential performance problem where V8 |
1356 // tries to build a hidden class for an object used as a hashMap. | |
1357 // It requires fewer characters to declare a variable as a parameter than | |
1358 // with `var`. | |
1359 function map(x) { | |
1360 x = Object.create(null); | |
1361 x.x = 0; | |
1362 delete x.x; | |
1363 return x; | |
1364 } | |
1382 | 1365 |
1383 if (task.outputContainsConstantList) { | 1366 #globalObjectSetup; |
1384 emitMakeConstantList(mainOutput); | |
1385 } | |
1386 | 1367 |
1387 // Constants in checked mode call into RTI code to set type information | 1368 function #isolateName() {} |
1388 // which may need getInterceptor (and one-shot interceptor) methods, so | |
1389 // we have to make sure that [emitGetInterceptorMethods] and | |
1390 // [emitOneShotInterceptors] have been called. | |
1391 emitCompileTimeConstants( | |
1392 mainOutput, mainFragment.constants, isMainFragment: true); | |
1393 | 1369 |
1394 emitDeferredBoilerPlate(mainOutput, deferredLoadHashes); | 1370 if (#isProgramSplit) { |
1371 #globalsHolder.#isolateName = #isolateName; | |
1372 #globalsHolder.#initName = #initName; | |
1373 #globalsHolder.#setupProgramName = #setupProgramName; | |
1374 } | |
1375 | |
1376 init(); | |
1377 | |
1378 var ${namer.currentIsolate} = #isolatePropertiesName; | |
1379 | |
1380 #functionThatReturnsNull; | |
1381 | |
1382 #mangledNames; | |
1383 | |
1384 #setupProgram; | |
1385 | |
1386 // The argument to reflectionDataParser is assigned to a temporary 'dart' | |
1387 // so that 'dart.' will appear as the prefix to dart methods in stack | |
1388 // traces and profile entries. | |
1389 var dart = #descriptors; | |
1390 | |
1391 #setupProgramName(dart, 0); | |
1392 | |
1393 #cspPrecompiledFunctions; | |
1394 | |
1395 #getInterceptorMethods; | |
1396 #oneShotInterceptors; | |
1397 | |
1398 #makeConstantList; | |
1399 | |
1400 // Constants in checked mode call into RTI code to set type information | |
1401 // which may need getInterceptor (and one-shot interceptor) methods, so | |
1402 // we have to make sure that [emitGetInterceptorMethods] and | |
1403 // [emitOneShotInterceptors] have been called. | |
1404 #compileTimeConstants; | |
1405 | |
1406 // Static field initializations require the classes and compile-time | |
1407 // constants to be set up. | |
1408 #staticNonFinalInitializers; | |
1409 | |
1410 #deferredBoilerPlate; | |
1411 | |
1412 #typeToInterceptorMap; | |
1413 | |
1414 #lazyStaticFields; | |
1415 | |
1416 ${namer.currentIsolate} = null; | |
1417 | |
1418 #isolateName = $finishIsolateConstructorName(#isolateName); | |
1419 | |
1420 ${namer.currentIsolate} = new #isolateName(); | |
1421 | |
1422 #metadata; | |
1423 | |
1424 #convertToFastObject; | |
1425 #convertToSlowObject; | |
1426 | |
1427 #convertGlobalObjectsToFastObjects; | |
1428 #debugFastObjects; | |
1429 | |
1430 #init; | |
1431 | |
1432 #main; | |
1433 })(); | |
1434 """, { | |
1435 "disableVariableRenaming": js.comment("/* ::norenaming:: */"), | |
1436 "hasIncrementalSupport": compiler.hasIncrementalSupport, | |
1437 "helper": js('this.#', [namer.incrementalHelperName]), | |
1438 "schemaChange": buildSchemaChangeFunction(), | |
1439 "addMethod": buildIncrementalAddMethod(), | |
1440 "isProgramSplit": isProgramSplit, | |
1441 "supportsDirectProtoAccess": buildSupportsDirectProtoAccess(), | |
1442 "globalsHolder": globalsHolder, | |
1443 "globalObjectSetup": buildGlobalObjectSetup(isProgramSplit), | |
1444 "isolateName": namer.isolateName, | |
1445 "isolatePropertiesName": js(isolatePropertiesName), | |
1446 "initName": initName, | |
1447 "functionThatReturnsNull": buildFunctionThatReturnsNull(), | |
1448 "mangledNames": buildMangledNames(), | |
1449 "setupProgram": buildSetupProgram(program, compiler, backend, namer, this) , | |
1450 "setupProgramName": setupProgramName, | |
1451 "descriptors": descriptorsAst, | |
1452 "cspPrecompiledFunctions": buildCspPrecompiledFunctionFor(mainOutputUnit), | |
1453 "getInterceptorMethods": interceptorEmitter.buildGetInterceptorMethods(), | |
1454 "oneShotInterceptors": interceptorEmitter.buildOneShotInterceptors(), | |
1455 "makeConstantList": buildMakeConstantList(), | |
1456 "compileTimeConstants": buildCompileTimeConstants(mainFragment.constants, | |
1457 isMainFragment: true), | |
1458 "deferredBoilerPlate": buildDeferredBoilerPlate(deferredLoadHashes), | |
1459 "staticNonFinalInitializers": buildStaticNonFinalFieldInitializations( | |
1460 mainOutputUnit), | |
1461 "typeToInterceptorMap": | |
1462 interceptorEmitter.buildTypeToInterceptorMap(program), | |
1463 "lazyStaticFields": buildLazilyInitializedStaticFields(), | |
1464 "metadata": buildMetadata(program, mainOutputUnit), | |
1465 "convertToFastObject": buildConvertToFastObjectFunction(), | |
1466 "convertToSlowObject": buildConvertToSlowObjectFunction(), | |
1467 "convertGlobalObjectsToFastObjects": | |
1468 buildConvertGlobalObjectToFastObjects(), | |
1469 "debugFastObjects": buildDebugFastObjectCode(), | |
1470 "init": buildInitFunction(), | |
1471 "main": buildMain(mainFragment.invokeMain) | |
1472 })); | |
1473 | |
1474 mainOutput.addBuffer(jsAst.prettyPrint(new jsAst.Program(statements), | |
1475 compiler, | |
1476 monitor: compiler.dumpInfoTask)); | |
1395 | 1477 |
1396 if (compiler.deferredMapUri != null) { | 1478 if (compiler.deferredMapUri != null) { |
1397 outputDeferredMap(); | 1479 outputDeferredMap(); |
1398 } | 1480 } |
1399 | 1481 |
1400 // Static field initializations require the classes and compile-time | |
1401 // constants to be set up. | |
1402 emitStaticNonFinalFieldInitializations(mainOutput, mainOutputUnit); | |
1403 interceptorEmitter.emitTypeToInterceptorMap(program, mainOutput); | |
1404 if (compiler.enableMinification) { | |
1405 mainOutput.add(';'); | |
1406 } | |
1407 emitLazilyInitializedStaticFields(mainOutput); | |
1408 | |
1409 mainOutput.add('\n'); | |
1410 | |
1411 emitMetadata(program, mainOutput, mainOutputUnit); | |
1412 | |
1413 isolateProperties = isolatePropertiesName; | |
1414 // The following code should not use the short-hand for the | |
1415 // initialStatics. | |
1416 mainOutput.add('${namer.currentIsolate}$_=${_}null$N'); | |
1417 | |
1418 emitFinishIsolateConstructorInvocation(mainOutput); | |
1419 mainOutput.add( | |
1420 '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N'); | |
1421 | |
1422 emitConvertToFastObjectFunction(mainOutput); | |
1423 emitConvertToSlowObjectFunction(mainOutput); | |
1424 | |
1425 for (String globalObject in Namer.reservedGlobalObjectNames) { | |
1426 mainOutput.add('$globalObject = convertToFastObject($globalObject)$N'); | |
1427 } | |
1428 if (DEBUG_FAST_OBJECTS) { | |
1429 mainOutput.add(r''' | |
1430 // The following only works on V8 when run with option | |
1431 // "--allow-natives-syntax". We use'new Function' because the | |
1432 // miniparser does not understand V8 native syntax. | |
1433 if (typeof print === "function") { | |
1434 var HasFastProperties = | |
1435 new Function("a", "return %HasFastProperties(a)"); | |
1436 print("Size of global helper object: " | |
1437 + String(Object.getOwnPropertyNames(H).length) | |
1438 + ", fast properties " + HasFastProperties(H)); | |
1439 print("Size of global platform object: " | |
1440 + String(Object.getOwnPropertyNames(P).length) | |
1441 + ", fast properties " + HasFastProperties(P)); | |
1442 print("Size of global dart:html object: " | |
1443 + String(Object.getOwnPropertyNames(W).length) | |
1444 + ", fast properties " + HasFastProperties(W)); | |
1445 print("Size of isolate properties object: " | |
1446 + String(Object.getOwnPropertyNames($).length) | |
1447 + ", fast properties " + HasFastProperties($)); | |
1448 print("Size of constant object: " | |
1449 + String(Object.getOwnPropertyNames(C).length) | |
1450 + ", fast properties " + HasFastProperties(C)); | |
1451 var names = Object.getOwnPropertyNames($); | |
1452 for (var i = 0; i < names.length; i++) { | |
1453 print("$." + names[i]); | |
1454 } | |
1455 } | |
1456 '''); | |
1457 for (String object in Namer.userGlobalObjects) { | |
1458 mainOutput.add(''' | |
1459 if (typeof print === "function") { | |
1460 print("Size of $object: " | |
1461 + String(Object.getOwnPropertyNames($object).length) | |
1462 + ", fast properties " + HasFastProperties($object)); | |
1463 } | |
1464 '''); | |
1465 } | |
1466 } | |
1467 | |
1468 emitInitFunction(mainOutput); | |
1469 emitMain(mainOutput, mainFragment.invokeMain); | |
1470 | |
1471 mainOutput.add('})()\n'); | |
1472 | |
1473 | |
1474 if (generateSourceMap) { | 1482 if (generateSourceMap) { |
1475 mainOutput.add( | 1483 mainOutput.add( |
1476 generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri)); | 1484 generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri)); |
1477 } | 1485 } |
1478 | 1486 |
1479 mainOutput.close(); | 1487 mainOutput.close(); |
1480 | 1488 |
1481 if (generateSourceMap) { | 1489 if (generateSourceMap) { |
1482 outputSourceMap(mainOutput, lineColumnCollector, '', | 1490 outputSourceMap(mainOutput, lineColumnCollector, '', |
1483 compiler.sourceMapUri, compiler.outputUri); | 1491 compiler.sourceMapUri, compiler.outputUri); |
1484 } | 1492 } |
1485 } | 1493 } |
1486 | 1494 |
1487 /// Used by incremental compilation to patch up the prototype of | 1495 /// Used by incremental compilation to patch up the prototype of |
1488 /// [oldConstructor] for use as prototype of [newConstructor]. | 1496 /// [oldConstructor] for use as prototype of [newConstructor]. |
1489 jsAst.Fun buildSchemaChangeFunction() { | 1497 jsAst.Fun buildSchemaChangeFunction() { |
1498 if (!compiler.hasIncrementalSupport) return null; | |
1490 return js(''' | 1499 return js(''' |
1491 function(newConstructor, oldConstructor, superclass) { | 1500 function(newConstructor, oldConstructor, superclass) { |
1492 // Invariant: newConstructor.prototype has no interesting properties besides | 1501 // Invariant: newConstructor.prototype has no interesting properties besides |
1493 // generated accessors. These are copied to oldPrototype which will be | 1502 // generated accessors. These are copied to oldPrototype which will be |
1494 // updated by other incremental changes. | 1503 // updated by other incremental changes. |
1495 if (superclass != null) { | 1504 if (superclass != null) { |
1496 this.inheritFrom(newConstructor, superclass); | 1505 this.inheritFrom(newConstructor, superclass); |
1497 } | 1506 } |
1498 var oldPrototype = oldConstructor.prototype; | 1507 var oldPrototype = oldConstructor.prototype; |
1499 var newPrototype = newConstructor.prototype; | 1508 var newPrototype = newConstructor.prototype; |
(...skipping 12 matching lines...) Expand all Loading... | |
1512 } | 1521 } |
1513 | 1522 |
1514 /// Used by incremental compilation to patch up an object ([holder]) with a | 1523 /// Used by incremental compilation to patch up an object ([holder]) with a |
1515 /// new (or updated) method. [arrayOrFunction] is either the new method, or | 1524 /// new (or updated) method. [arrayOrFunction] is either the new method, or |
1516 /// an array containing the method (see | 1525 /// an array containing the method (see |
1517 /// [ContainerBuilder.addMemberMethodFromInfo]). [name] is the name of the | 1526 /// [ContainerBuilder.addMemberMethodFromInfo]). [name] is the name of the |
1518 /// new method. [isStatic] tells if method is static (or | 1527 /// new method. [isStatic] tells if method is static (or |
1519 /// top-level). [globalFunctionsAccess] is a reference to | 1528 /// top-level). [globalFunctionsAccess] is a reference to |
1520 /// [embeddedNames.GLOBAL_FUNCTIONS]. | 1529 /// [embeddedNames.GLOBAL_FUNCTIONS]. |
1521 jsAst.Fun buildIncrementalAddMethod() { | 1530 jsAst.Fun buildIncrementalAddMethod() { |
1531 if (!compiler.hasIncrementalSupport) return null; | |
1522 return js(r""" | 1532 return js(r""" |
1523 function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { | 1533 function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { |
1524 var arrayOrFunction = originalDescriptor[name]; | 1534 var arrayOrFunction = originalDescriptor[name]; |
1525 var method; | 1535 var method; |
1526 if (arrayOrFunction.constructor === Array) { | 1536 if (arrayOrFunction.constructor === Array) { |
1527 var existing = holder[name]; | 1537 var existing = holder[name]; |
1528 var array = arrayOrFunction; | 1538 var array = arrayOrFunction; |
1529 | 1539 |
1530 // Each method may have a number of stubs associated. For example, if an | 1540 // Each method may have a number of stubs associated. For example, if an |
1531 // instance method supports multiple arguments, a stub for each matching | 1541 // instance method supports multiple arguments, a stub for each matching |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1632 | 1642 |
1633 return emitDeferredCode(program, outputs); | 1643 return emitDeferredCode(program, outputs); |
1634 } | 1644 } |
1635 | 1645 |
1636 int emitProgram(ProgramBuilder programBuilder) { | 1646 int emitProgram(ProgramBuilder programBuilder) { |
1637 Program program = programBuilder.buildProgram( | 1647 Program program = programBuilder.buildProgram( |
1638 storeFunctionTypesInMetadata: true); | 1648 storeFunctionTypesInMetadata: true); |
1639 | 1649 |
1640 assembleProgram(program); | 1650 assembleProgram(program); |
1641 | 1651 |
1642 // Shorten the code by using [namer.currentIsolate] as temporary. | |
1643 isolateProperties = namer.currentIsolate; | |
1644 | |
1645 // Emit deferred units first, so we have their hashes. | 1652 // Emit deferred units first, so we have their hashes. |
1646 // Map from OutputUnit to a hash of its content. The hash uniquely | 1653 // Map from OutputUnit to a hash of its content. The hash uniquely |
1647 // identifies the code of the output-unit. It does not include | 1654 // identifies the code of the output-unit. It does not include |
1648 // boilerplate JS code, like the sourcemap directives or the hash | 1655 // boilerplate JS code, like the sourcemap directives or the hash |
1649 // itself. | 1656 // itself. |
1650 Map<OutputUnit, String> deferredLoadHashes = | 1657 Map<OutputUnit, String> deferredLoadHashes = |
1651 emitDeferredOutputUnits(program); | 1658 emitDeferredOutputUnits(program); |
1652 emitMainOutputUnit(program, deferredLoadHashes); | 1659 emitMainOutputUnit(program, deferredLoadHashes); |
1653 | 1660 |
1654 if (backend.requiresPreamble && | 1661 if (backend.requiresPreamble && |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1687 } | 1694 } |
1688 if (owner == null) { | 1695 if (owner == null) { |
1689 compiler.internalError(element, 'Owner is null.'); | 1696 compiler.internalError(element, 'Owner is null.'); |
1690 } | 1697 } |
1691 return elementDescriptors | 1698 return elementDescriptors |
1692 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) | 1699 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) |
1693 .putIfAbsent(owner, () => new ClassBuilder(owner, namer)); | 1700 .putIfAbsent(owner, () => new ClassBuilder(owner, namer)); |
1694 } | 1701 } |
1695 | 1702 |
1696 /// Emits support-code for deferred loading into [output]. | 1703 /// Emits support-code for deferred loading into [output]. |
1697 void emitDeferredBoilerPlate(CodeOutput output, | 1704 jsAst.Statement buildDeferredBoilerPlate( |
1698 Map<OutputUnit, String> deferredLoadHashes) { | 1705 Map<OutputUnit, String> deferredLoadHashes) { |
1699 jsAst.Statement functions = js.statement(''' | 1706 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
1707 | |
1708 parts.add(js.statement(''' | |
1700 { | 1709 { |
1701 // Function for checking if a hunk is loaded given its hash. | 1710 // Function for checking if a hunk is loaded given its hash. |
1702 #isHunkLoaded = function(hunkHash) { | 1711 #isHunkLoaded = function(hunkHash) { |
1703 return !!$deferredInitializers[hunkHash]; | 1712 return !!$deferredInitializers[hunkHash]; |
1704 }; | 1713 }; |
1705 #deferredInitialized = new Object(null); | 1714 #deferredInitialized = new Object(null); |
1706 // Function for checking if a hunk is initialized given its hash. | 1715 // Function for checking if a hunk is initialized given its hash. |
1707 #isHunkInitialized = function(hunkHash) { | 1716 #isHunkInitialized = function(hunkHash) { |
1708 return #deferredInitialized[hunkHash]; | 1717 return #deferredInitialized[hunkHash]; |
1709 }; | 1718 }; |
1710 // Function for initializing a loaded hunk, given its hash. | 1719 // Function for initializing a loaded hunk, given its hash. |
1711 #initializeLoadedHunk = function(hunkHash) { | 1720 #initializeLoadedHunk = function(hunkHash) { |
1712 $deferredInitializers[hunkHash]( | 1721 $deferredInitializers[hunkHash]( |
1713 $globalsHolder, ${namer.currentIsolate}); | 1722 $globalsHolder, ${namer.currentIsolate}); |
1714 #deferredInitialized[hunkHash] = true; | 1723 #deferredInitialized[hunkHash] = true; |
1715 }; | 1724 }; |
1716 } | 1725 } |
1717 ''', {"isHunkLoaded": generateEmbeddedGlobalAccess( | 1726 ''', {"isHunkLoaded": generateEmbeddedGlobalAccess( |
1718 embeddedNames.IS_HUNK_LOADED), | 1727 embeddedNames.IS_HUNK_LOADED), |
1719 "isHunkInitialized": generateEmbeddedGlobalAccess( | 1728 "isHunkInitialized": generateEmbeddedGlobalAccess( |
1720 embeddedNames.IS_HUNK_INITIALIZED), | 1729 embeddedNames.IS_HUNK_INITIALIZED), |
1721 "initializeLoadedHunk": generateEmbeddedGlobalAccess( | 1730 "initializeLoadedHunk": generateEmbeddedGlobalAccess( |
1722 embeddedNames.INITIALIZE_LOADED_HUNK), | 1731 embeddedNames.INITIALIZE_LOADED_HUNK), |
1723 "deferredInitialized": generateEmbeddedGlobalAccess( | 1732 "deferredInitialized": generateEmbeddedGlobalAccess( |
1724 embeddedNames.DEFERRED_INITIALIZED)}); | 1733 embeddedNames.DEFERRED_INITIALIZED)})); |
1725 output.addBuffer(jsAst.prettyPrint(functions, | 1734 |
1726 compiler, monitor: compiler.dumpInfoTask)); | |
1727 // Write a javascript mapping from Deferred import load ids (derrived | 1735 // Write a javascript mapping from Deferred import load ids (derrived |
1728 // from the import prefix.) to a list of lists of uris of hunks to load, | 1736 // from the import prefix.) to a list of lists of uris of hunks to load, |
1729 // and a corresponding mapping to a list of hashes used by | 1737 // and a corresponding mapping to a list of hashes used by |
1730 // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED. | 1738 // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED. |
1731 Map<String, List<String>> deferredLibraryUris = | 1739 Map<String, List<String>> deferredLibraryUris = |
1732 new Map<String, List<String>>(); | 1740 new Map<String, List<String>>(); |
1733 Map<String, List<String>> deferredLibraryHashes = | 1741 Map<String, List<String>> deferredLibraryHashes = |
1734 new Map<String, List<String>>(); | 1742 new Map<String, List<String>>(); |
1735 compiler.deferredLoadTask.hunksToLoad.forEach( | 1743 compiler.deferredLoadTask.hunksToLoad.forEach( |
1736 (String loadId, List<OutputUnit>outputUnits) { | 1744 (String loadId, List<OutputUnit>outputUnits) { |
(...skipping 13 matching lines...) Expand all Loading... | |
1750 List<jsAst.Property> properties = new List<jsAst.Property>(); | 1758 List<jsAst.Property> properties = new List<jsAst.Property>(); |
1751 mapping.forEach((String key, List<String> values) { | 1759 mapping.forEach((String key, List<String> values) { |
1752 properties.add(new jsAst.Property(js.escapedString(key), | 1760 properties.add(new jsAst.Property(js.escapedString(key), |
1753 new jsAst.ArrayInitializer( | 1761 new jsAst.ArrayInitializer( |
1754 values.map(js.escapedString).toList()))); | 1762 values.map(js.escapedString).toList()))); |
1755 }); | 1763 }); |
1756 jsAst.Node initializer = | 1764 jsAst.Node initializer = |
1757 new jsAst.ObjectInitializer(properties, isOneLiner: true); | 1765 new jsAst.ObjectInitializer(properties, isOneLiner: true); |
1758 | 1766 |
1759 jsAst.Node globalName = generateEmbeddedGlobalAccess(name); | 1767 jsAst.Node globalName = generateEmbeddedGlobalAccess(name); |
1760 output.addBuffer(jsAst.prettyPrint( | 1768 parts.add(js.statement("# = #", [globalName, initializer])); |
1761 js("# = #", [globalName, initializer]), | |
1762 compiler, monitor: compiler.dumpInfoTask)); | |
1763 output.add('$N'); | |
1764 } | 1769 } |
1765 | 1770 |
1766 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); | 1771 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); |
1767 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, | 1772 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, |
1768 deferredLibraryHashes); | 1773 deferredLibraryHashes); |
1774 | |
1775 return new jsAst.Block(parts); | |
1769 } | 1776 } |
1770 | 1777 |
1771 /// Emits code for all output units except the main. | 1778 /// Emits code for all output units except the main. |
1772 /// Returns a mapping from outputUnit to a hash of the corresponding hunk that | 1779 /// Returns a mapping from outputUnit to a hash of the corresponding hunk that |
1773 /// can be used for calling the initializer. | 1780 /// can be used for calling the initializer. |
1774 Map<OutputUnit, String> emitDeferredCode( | 1781 Map<OutputUnit, String> emitDeferredCode( |
1775 Program program, | 1782 Program program, |
1776 Map<OutputUnit, jsAst.Expression> deferredAsts) { | 1783 Map<OutputUnit, jsAst.Expression> deferredAsts) { |
1777 | 1784 |
1778 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); | 1785 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); |
(...skipping 14 matching lines...) Expand all Loading... | |
1793 } | 1800 } |
1794 | 1801 |
1795 String partPrefix = | 1802 String partPrefix = |
1796 backend.deferredPartFileName(outputUnit.name, addExtension: false); | 1803 backend.deferredPartFileName(outputUnit.name, addExtension: false); |
1797 CodeOutput output = new StreamCodeOutput( | 1804 CodeOutput output = new StreamCodeOutput( |
1798 compiler.outputProvider(partPrefix, 'part.js'), | 1805 compiler.outputProvider(partPrefix, 'part.js'), |
1799 outputListeners); | 1806 outputListeners); |
1800 | 1807 |
1801 outputBuffers[outputUnit] = output; | 1808 outputBuffers[outputUnit] = output; |
1802 | 1809 |
1803 output | 1810 List<jsAst.Statement> body = <jsAst.Statement>[]; |
1804 ..add(buildGeneratedBy()) | 1811 |
1805 ..add('${deferredInitializers}.current$_=$_' | 1812 // No renaming in the top-level function to save the locals for the |
1806 'function$_(${globalsHolder}) {$N'); | 1813 // nested context where they will be used more. |
1814 body.add(js.comment("/* ::norenaming:: ")); | |
1815 | |
1807 for (String globalObject in Namer.reservedGlobalObjectNames) { | 1816 for (String globalObject in Namer.reservedGlobalObjectNames) { |
1808 output | 1817 body.add(js.statement('var #object = ${globalsHolder}.#object;', |
1809 .add('var $globalObject$_=$_' | 1818 {'object': globalObject})); |
1810 '${globalsHolder}.$globalObject$N'); | |
1811 } | 1819 } |
1812 output | 1820 body..add(js.statement('var init = ${globalsHolder}.init;')) |
1813 ..add('var init$_=$_${globalsHolder}.init$N') | 1821 ..add(js.statement('var $setupProgramName = ' |
1814 ..add('var $setupProgramName$_=$_' | 1822 '$globalsHolder.$setupProgramName;')) |
1815 '$globalsHolder.$setupProgramName$N') | 1823 ..add(js.statement('var ${namer.isolateName} = ' |
1816 ..add('var ${namer.isolateName}$_=$_' | 1824 '${globalsHolder}.${namer.isolateName};')); |
1817 '${globalsHolder}.${namer.isolateName}$N'); | |
1818 String typesAccess = | 1825 String typesAccess = |
1819 generateEmbeddedGlobalAccessString(embeddedNames.TYPES); | 1826 generateEmbeddedGlobalAccessString(embeddedNames.TYPES); |
1820 if (libraryDescriptor != null) { | 1827 if (libraryDescriptor != null) { |
1821 // TODO(ahe): This defines a lot of properties on the | 1828 // TODO(ahe): This defines a lot of properties on the |
1822 // Isolate.prototype object. We know this will turn it into a | 1829 // Isolate.prototype object. We know this will turn it into a |
1823 // slow object in V8, so instead we should do something similar | 1830 // slow object in V8, so instead we should do something similar |
1824 // to Isolate.$finishIsolateConstructor. | 1831 // to Isolate.$finishIsolateConstructor. |
1825 output | 1832 body..add(js.statement('var ${namer.currentIsolate} = ' |
1826 ..add('var ${namer.currentIsolate}$_=$_$isolatePropertiesName$N') | 1833 '$isolatePropertiesName;')) |
1827 // The argument to reflectionDataParser is assigned to a temporary | 1834 // The argument to reflectionDataParser is assigned to a temporary |
1828 // 'dart' so that 'dart.' will appear as the prefix to dart methods | 1835 // 'dart' so that 'dart.' will appear as the prefix to dart methods |
1829 // in stack traces and profile entries. | 1836 // in stack traces and profile entries. |
1830 ..add('var dart = $n ') | 1837 ..add(js.statement('var dart = #', libraryDescriptor)); |
1831 ..addBuffer(jsAst.prettyPrint(libraryDescriptor, compiler, | |
1832 monitor: compiler.dumpInfoTask)) | |
1833 ..add('$N'); | |
1834 | 1838 |
1835 if (compiler.useContentSecurityPolicy) { | 1839 if (compiler.useContentSecurityPolicy) { |
1836 jsAst.Statement precompiledFunctionAst = | 1840 body.add(buildCspPrecompiledFunctionFor(outputUnit)); |
1837 buildCspPrecompiledFunctionFor(outputUnit); | |
1838 | |
1839 output.addBuffer( | |
1840 jsAst.prettyPrint( | |
1841 precompiledFunctionAst, compiler, | |
1842 monitor: compiler.dumpInfoTask, | |
1843 allowVariableMinification: false)); | |
1844 output.add(N); | |
1845 } | 1841 } |
1846 output.add('$setupProgramName(dart, ${typesAccess}.length)$N'); | 1842 body.add( |
1843 js.statement('$setupProgramName(dart, ${typesAccess}.length);')); | |
1847 } | 1844 } |
1848 | 1845 |
1849 if (task.metadataCollector.types[outputUnit] != null) { | 1846 if (task.metadataCollector.types[outputUnit] != null) { |
1850 emitMetadata(program, output, outputUnit); | 1847 body..add(buildMetadata(program, outputUnit)) |
1851 output.add('${typesAccess}.' | 1848 ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, ' |
1852 'push.apply(${typesAccess},$_${namer.deferredTypesName})$N'); | 1849 '${namer.deferredTypesName});')); |
1853 } | 1850 } |
1854 | 1851 |
1855 // Set the currentIsolate variable to the current isolate (which is | 1852 // Set the currentIsolate variable to the current isolate (which is |
1856 // provided as second argument). | 1853 // provided as second argument). |
1857 // We need to do this, because we use the same variable for setting up | 1854 // We need to do this, because we use the same variable for setting up |
1858 // the isolate-properties and for storing the current isolate. During | 1855 // the isolate-properties and for storing the current isolate. During |
1859 // the setup (the code above this lines) we must set the variable to | 1856 // the setup (the code above this lines) we must set the variable to |
1860 // the isolate-properties. | 1857 // the isolate-properties. |
1861 // After we have done the setup it must point to the current Isolate. | 1858 // After we have done the setup it must point to the current Isolate. |
1862 // Otherwise all methods/functions accessing isolate variables will | 1859 // Otherwise all methods/functions accessing isolate variables will |
1863 // access the wrong object. | 1860 // access the wrong object. |
1864 output.add("${namer.currentIsolate}$_=${_}arguments[1]$N"); | 1861 body.add(js.statement("${namer.currentIsolate} = arguments[1];")); |
1865 | 1862 |
1866 emitCompileTimeConstants( | 1863 body.add(buildCompileTimeConstants(fragment.constants, |
1867 output, fragment.constants, isMainFragment: false); | 1864 isMainFragment: false)); |
1868 emitStaticNonFinalFieldInitializations(output, outputUnit); | 1865 body.add(buildStaticNonFinalFieldInitializations(outputUnit)); |
1869 | 1866 |
1870 output.add('}$N'); | 1867 List<jsAst.Statement> statements = <jsAst.Statement>[]; |
1868 | |
1869 statements..add(buildGeneratedBy()) | |
1870 ..add(js.statement('${deferredInitializers}.current = ' | |
1871 """function (${globalsHolder}) { | |
1872 # | |
1873 } | |
1874 """, [body])); | |
1875 | |
1876 output.addBuffer(jsAst.prettyPrint(new jsAst.Program(statements), | |
1877 compiler, | |
1878 monitor: compiler.dumpInfoTask)); | |
1879 | |
1871 // Make a unique hash of the code (before the sourcemaps are added) | 1880 // Make a unique hash of the code (before the sourcemaps are added) |
1872 // This will be used to retrieve the initializing function from the global | 1881 // This will be used to retrieve the initializing function from the global |
1873 // variable. | 1882 // variable. |
1874 String hash = hasher.getHash(); | 1883 String hash = hasher.getHash(); |
1875 | 1884 |
1876 output.add('${deferredInitializers}["$hash"]$_=$_' | 1885 output.add('$N${deferredInitializers}["$hash"]$_=$_' |
1877 '${deferredInitializers}.current$N'); | 1886 '${deferredInitializers}.current$N'); |
1878 | 1887 |
1879 if (generateSourceMap) { | 1888 if (generateSourceMap) { |
1880 | |
1881 Uri mapUri, partUri; | 1889 Uri mapUri, partUri; |
1882 Uri sourceMapUri = compiler.sourceMapUri; | 1890 Uri sourceMapUri = compiler.sourceMapUri; |
1883 Uri outputUri = compiler.outputUri; | 1891 Uri outputUri = compiler.outputUri; |
1884 | 1892 |
1885 String partName = "$partPrefix.part"; | 1893 String partName = "$partPrefix.part"; |
1886 | 1894 |
1887 if (sourceMapUri != null) { | 1895 if (sourceMapUri != null) { |
1888 String mapFileName = partName + ".js.map"; | 1896 String mapFileName = partName + ".js.map"; |
1889 List<String> mapSegments = sourceMapUri.pathSegments.toList(); | 1897 List<String> mapSegments = sourceMapUri.pathSegments.toList(); |
1890 mapSegments[mapSegments.length - 1] = mapFileName; | 1898 mapSegments[mapSegments.length - 1] = mapFileName; |
(...skipping 13 matching lines...) Expand all Loading... | |
1904 mapUri, partUri); | 1912 mapUri, partUri); |
1905 } else { | 1913 } else { |
1906 output.close(); | 1914 output.close(); |
1907 } | 1915 } |
1908 | 1916 |
1909 hunkHashes[outputUnit] = hash; | 1917 hunkHashes[outputUnit] = hash; |
1910 } | 1918 } |
1911 return hunkHashes; | 1919 return hunkHashes; |
1912 } | 1920 } |
1913 | 1921 |
1914 String buildGeneratedBy() { | 1922 jsAst.Comment buildGeneratedBy() { |
1915 var suffix = ''; | 1923 String suffix = ''; |
1916 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; | 1924 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; |
1917 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; | 1925 String msg = '// Generated by dart2js, the Dart to JavaScript ' |
1926 'compiler$suffix.'; | |
1927 return new jsAst.Comment(msg); | |
1918 } | 1928 } |
1919 | 1929 |
1920 void outputSourceMap(CodeOutput output, | 1930 void outputSourceMap(CodeOutput output, |
1921 LineColumnProvider lineColumnProvider, | 1931 LineColumnProvider lineColumnProvider, |
1922 String name, | 1932 String name, |
1923 [Uri sourceMapUri, | 1933 [Uri sourceMapUri, |
1924 Uri fileUri]) { | 1934 Uri fileUri]) { |
1925 if (!generateSourceMap) return; | 1935 if (!generateSourceMap) return; |
1926 // Create a source file for the compilation output. This allows using | 1936 // Create a source file for the compilation output. This allows using |
1927 // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder]. | 1937 // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder]. |
(...skipping 24 matching lines...) Expand all Loading... | |
1952 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 1962 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
1953 if (element.isInstanceMember) { | 1963 if (element.isInstanceMember) { |
1954 cachedClassBuilders.remove(element.enclosingClass); | 1964 cachedClassBuilders.remove(element.enclosingClass); |
1955 | 1965 |
1956 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 1966 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
1957 | 1967 |
1958 } | 1968 } |
1959 } | 1969 } |
1960 } | 1970 } |
1961 } | 1971 } |
OLD | NEW |