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