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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart

Issue 1229923005: dart2js: support tear-offs in the startup emitter. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Reupload Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.startup_emitter.model_emitter; 5 part of dart2js.js_emitter.startup_emitter.model_emitter;
6 6
7 const String deferredExtension = "part.js"; 7 const String deferredExtension = "part.js";
8 /// For deferred loading we communicate the initializers via this global var. 8 /// For deferred loading we communicate the initializers via this global var.
9 const String deferredInitializersGlobal = r"$__dart_deferred_initializers__"; 9 const String deferredInitializersGlobal = r"$__dart_deferred_initializers__";
10 10
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 // The runtime ensures that const-lists cannot be modified. 109 // The runtime ensures that const-lists cannot be modified.
110 function makeConstList(list) { 110 function makeConstList(list) {
111 // By assigning a function to the properties they become part of the 111 // By assigning a function to the properties they become part of the
112 // hidden class. The actual values of the fields don't matter, since we 112 // hidden class. The actual values of the fields don't matter, since we
113 // only check if they exist. 113 // only check if they exist.
114 list.immutable\$list = Array; 114 list.immutable\$list = Array;
115 list.fixed\$length = Array; 115 list.fixed\$length = Array;
116 return list; 116 return list;
117 } 117 }
118 118
119 // TODO(floitsch): provide code for tear-offs. 119 // This variable is used by the tearOffCode to guarantee unique functions per
120 // tear-offs.
121 var functionCounter = 0;
122 #tearOffCode;
123
124 // Each deferred hunk comes with its own types which are added to the end
125 // of the types-array.
126 // The `funTypes` passed to the `installTearOff` function below is relative to
127 // the hunk the function comes from. The `typesOffset` variable encodes the
128 // offset at which the new types will be added.
129 var typesOffset = 0;
130
131 // Adapts the stored data, so it's suitable for a tearOff call.
132 // TODO(floitsch): Change tearOffCode to accept the data directly, or create a
133 // different tearOffCode?
134 function installTearOff(container, getterName,
135 isStatic, isIntercepted, requiredParameterCount,
Siggi Cherem (dart-lang) 2015/07/22 20:51:28 missing 1 space of indentation (FWIW, I don't thin
floitsch 2015/07/29 17:27:15 Done.
136 optionalParameterDefaultValues,
137 callNames, funNames, funType) {
138 var funs = [];
139 for (var i = 0; i < funNames.length; i++) {
140 var fun = container[funNames[i]];
141 fun.#callName = callNames[i];
142 funs.push(fun);
143 }
144
145 funs[0][#argumentCount] = requiredParameterCount;
146 funs[0][#defaultArgumentValues] = optionalParameterDefaultValues;
147 var reflectionInfo = funType;
148 if (typeof reflectionInfo == "number") {
149 // The reflectionInfo can either be a function, or a pointer into the types
150 // table. If it points into the types-table we need to update the index,
151 // in case the tear-off is part of a deferred hunk.
152 reflectionInfo = reflectionInfo + typesOffset;
153 }
154 var name = funNames[0];
155 container[getterName] =
156 tearOff(funs, reflectionInfo, isStatic, name, isIntercepted);
157 }
120 158
121 // Instead of setting the interceptor tags directly we use this update 159 // Instead of setting the interceptor tags directly we use this update
122 // function. This makes it easier for deferred fragments to contribute to the 160 // function. This makes it easier for deferred fragments to contribute to the
123 // embedded global. 161 // embedded global.
124 function setOrUpdateInterceptorsByTag(newTags) { 162 function setOrUpdateInterceptorsByTag(newTags) {
125 var tags = #embeddedInterceptorTags; 163 var tags = #embeddedInterceptorTags;
126 if (!tags) { 164 if (!tags) {
127 #embeddedInterceptorTags = newTags; 165 #embeddedInterceptorTags = newTags;
128 return; 166 return;
129 } 167 }
130 copyProperties(newTags, tags); 168 copyProperties(newTags, tags);
131 } 169 }
132 170
133 // Instead of setting the leaf tags directly we use this update 171 // Instead of setting the leaf tags directly we use this update
134 // function. This makes it easier for deferred fragments to contribute to the 172 // function. This makes it easier for deferred fragments to contribute to the
135 // embedded global. 173 // embedded global.
136 function setOrUpdateLeafTags(newTags) { 174 function setOrUpdateLeafTags(newTags) {
137 var tags = #embeddedLeafTags; 175 var tags = #embeddedLeafTags;
138 if (!tags) { 176 if (!tags) {
139 #embeddedLeafTags = newTags; 177 #embeddedLeafTags = newTags;
140 return; 178 return;
141 } 179 }
142 copyProperties(newTags, tags); 180 copyProperties(newTags, tags);
143 } 181 }
144 182
145 // Updates the types embedded global. 183 // Updates the types embedded global.
146 function updateTypes(newTypes) { 184 function updateTypes(newTypes) {
147 var types = #embeddedTypes; 185 var types = #embeddedTypes;
148 types.push.apply(types, newTypes); 186 types.push.apply(types, newTypes);
187 // This relies on the fact that types are added *after* the tear-offs have
Siggi Cherem (dart-lang) 2015/07/22 20:51:28 nit: move the comment above the push call?
floitsch 2015/07/29 17:27:15 Done. and added more comments.
188 // been installed.
149 } 189 }
150 190
151 // Updates the given holder with the properties of the [newHolder]. 191 // Updates the given holder with the properties of the [newHolder].
152 // This function is used when a deferred fragment is initialized. 192 // This function is used when a deferred fragment is initialized.
153 function updateHolder(holder, newHolder) { 193 function updateHolder(holder, newHolder) {
154 // TODO(floitsch): updating the prototype (instead of copying) is 194 // TODO(floitsch): updating the prototype (instead of copying) is
155 // *horribly* inefficient in Firefox. There we should just copy the 195 // *horribly* inefficient in Firefox. There we should just copy the
156 // properties. 196 // properties.
157 var oldPrototype = holder.__proto__; 197 var oldPrototype = holder.__proto__;
158 newHolder.__proto__ = oldPrototype; 198 newHolder.__proto__ = oldPrototype;
159 holder.__proto__ = newHolder; 199 holder.__proto__ = newHolder;
160 return holder; 200 return holder;
161 } 201 }
162 202
163 // Every deferred hunk (i.e. fragment) is a function that we can invoke to 203 // Every deferred hunk (i.e. fragment) is a function that we can invoke to
164 // initialize it. At this moment it contributes its data to the main hunk. 204 // initialize it. At this moment it contributes its data to the main hunk.
165 function initializeDeferredHunk(hunk) { 205 function initializeDeferredHunk(hunk) {
206 // Update the typesOffset for the next deferred library.
207 typesOffset = #embeddedTypes.length;
208
166 // TODO(floitsch): extend natives. 209 // TODO(floitsch): extend natives.
167 hunk(inherit, mixin, lazy, makeConstList, installTearOff, 210 hunk(inherit, mixin, lazy, makeConstList, installTearOff,
168 updateHolder, updateTypes, updateInterceptorsByTag, updateLeafTags, 211 updateHolder, updateTypes, updateInterceptorsByTag, updateLeafTags,
169 #embeddedGlobalsObject, #holdersList, #staticState); 212 #embeddedGlobalsObject, #holdersList, #staticState);
170 } 213 }
171 214
172 // Creates the holders. 215 // Creates the holders.
173 #holders; 216 #holders;
174 // TODO(floitsch): if name is not set (for example in IE), run through all 217 // TODO(floitsch): if name is not set (for example in IE), run through all
175 // functions and set the name. 218 // functions and set the name.
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 326
284 js.Statement emitMainFragment(Program program) { 327 js.Statement emitMainFragment(Program program) {
285 MainFragment fragment = program.fragments.first; 328 MainFragment fragment = program.fragments.first;
286 329
287 return js.js.statement(mainBoilerplate, 330 return js.js.statement(mainBoilerplate,
288 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), 331 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
289 'typeNameProperty': js.string(ModelEmitter.typeNameProperty), 332 'typeNameProperty': js.string(ModelEmitter.typeNameProperty),
290 'cyclicThrow': backend.emitter.staticFunctionAccess( 333 'cyclicThrow': backend.emitter.staticFunctionAccess(
291 backend.getCyclicThrowHelper()), 334 backend.getCyclicThrowHelper()),
292 'operatorIsPrefix': js.string(namer.operatorIsPrefix), 335 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
336 'tearOffCode': new js.Block(buildTearOffCode(backend)),
293 'embeddedTypes': generateEmbeddedGlobalAccess(TYPES), 337 'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
294 'embeddedInterceptorTags': 338 'embeddedInterceptorTags':
295 generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG), 339 generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG),
296 'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS), 340 'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS),
297 'embeddedGlobalsObject': js.js("init"), 341 'embeddedGlobalsObject': js.js("init"),
298 'holdersList': new js.ArrayInitializer(program.holders.map((holder) { 342 'holdersList': new js.ArrayInitializer(program.holders.map((holder) {
299 return js.js("#", holder.name); 343 return js.js("#", holder.name);
300 }).toList()), 344 }).toList()),
301 'staticStateDeclaration': new js.VariableDeclaration( 345 'staticStateDeclaration': new js.VariableDeclaration(
302 namer.staticStateHolder, allowRename: false), 346 namer.staticStateHolder, allowRename: false),
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 [classReference(cls), js.quoteName(method.aliasName), 668 [classReference(cls), js.quoteName(method.aliasName),
625 classReference(cls), js.quoteName(method.name)])); 669 classReference(cls), js.quoteName(method.name)]));
626 670
627 } 671 }
628 } 672 }
629 } 673 }
630 } 674 }
631 return new js.Block(assignments); 675 return new js.Block(assignments);
632 } 676 }
633 677
678 /// Encodes the optional default values so that the runtime Function.apply
679 /// can use them.
680 js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) {
681 // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole].
682 if (method.optionalParameterDefaultValues is List) {
683 List<ConstantValue> defaultValues = method.optionalParameterDefaultValues;
684 Iterable<js.Expression> elements =
685 defaultValues.map(generateConstantReference);
686 return new js.ArrayInitializer(elements.toList());
687 } else {
688 Map<String, ConstantValue> defaultValues =
689 method.optionalParameterDefaultValues;
690 List<js.Property> properties = <js.Property>[];
691 defaultValues.forEach((String name, ConstantValue value) {
692 properties.add(new js.Property(js.string(name),
693 generateConstantReference(value)));
694 });
695 return new js.ObjectInitializer(properties);
696 }
697 }
698
699 /// Emits the statement that installs a tear off for a method.
700 ///
701 /// Tear-offs might be passed to `Function.apply` which means that all
702 /// calling-conventions (with or without optional positional/named arguments)
703 /// are possible. As such, the tear-off needs enough information to fill in
704 /// missing parameters.
705 js.Statement emitInstallTearOff(js.Expression container, DartMethod method) {
706 List<js.Name> callNames = <js.Name>[];
707 List<js.Name> funNames = <js.Name>[];
708
709 callNames.add(method.callName);
710 funNames.add(method.name);
711 for (ParameterStubMethod stubMethod in method.parameterStubs) {
712 callNames.add(stubMethod.callName);
713 funNames.add(stubMethod.name);
714 }
715
716 js.ArrayInitializer callNameArray =
717 new js.ArrayInitializer(callNames.map(js.quoteName).toList());
718 js.ArrayInitializer funNameArray =
719 new js.ArrayInitializer(funNames.map(js.quoteName).toList());
720
721 bool isIntercepted = false;
722 if (method is InstanceMethod) {
723 isIntercepted = backend.isInterceptedMethod(method.element);
724 }
725 int requiredParameterCount = 0;
726 js.Expression optionalParameterDefaultValues = new js.LiteralNull();
727 if (method.canBeApplied) {
728 requiredParameterCount = method.requiredParameterCount;
729 optionalParameterDefaultValues =
730 _encodeOptionalParameterDefaultValues(method);
731 }
732
733 // TODO(floitsch): this can be more efficient.
Siggi Cherem (dart-lang) 2015/07/22 20:51:28 what are you referring to by `this`?
floitsch 2015/07/29 17:27:15 removed. The tear-off function is redirecting to a
734 return js.js.statement('''
735 installTearOff(#container, #getterName, #isStatic, #isIntercepted,
736 #requiredParameterCount, #optionalParameterDefaultValues,
737 #callNames, #funNames, #funType)''',
738 {
739 "container": container,
740 "getterName": js.quoteName(method.tearOffName),
741 "isStatic": new js.LiteralBool(method.isStatic),
742 "isIntercepted": new js.LiteralBool(isIntercepted),
743 "requiredParameterCount": js.number(requiredParameterCount),
744 "optionalParameterDefaultValues": optionalParameterDefaultValues,
745 "callNames": callNameArray,
746 "funNames": funNameArray,
747 "funType": method.functionType,
748 });
749 }
750
634 /// Emits the section that installs tear-off getters. 751 /// Emits the section that installs tear-off getters.
635 js.Statement emitInstallTearOffs(fragment) { 752 js.Statement emitInstallTearOffs(Fragment fragment) {
636 throw new UnimplementedError('emitInstallTearOffs'); 753 List<js.Statement> inits = <js.Statement>[];
754
755 for (Library library in fragment.libraries) {
756 for (StaticMethod method in library.statics) {
757 // TODO(floitsch): can there be anything else than a StaticDartMethod?
758 if (method is StaticDartMethod) {
759 if (method.needsTearOff) {
760 Holder holder = method.holder;
761 inits.add(
762 emitInstallTearOff(new js.VariableUse(holder.name), method));
763 }
764 }
765 }
766 for (Class cls in library.classes) {
767 for (InstanceMethod method in cls.methods) {
768 if (method.needsTearOff) {
769 js.Expression container = js.js("#.prototype", classReference(cls));
770 inits.add(emitInstallTearOff(container, method));
771 }
772 }
773 }
774 }
775 return new js.Block(inits);
637 } 776 }
638 777
639 /// Emits the constants section. 778 /// Emits the constants section.
640 js.Statement emitConstants(Fragment fragment) { 779 js.Statement emitConstants(Fragment fragment) {
641 List<js.Statement> assignments = <js.Statement>[]; 780 List<js.Statement> assignments = <js.Statement>[];
642 for (Constant constant in fragment.constants) { 781 for (Constant constant in fragment.constants) {
643 // TODO(floitsch): instead of just updating the constant holder, we should 782 // TODO(floitsch): instead of just updating the constant holder, we should
644 // find the constants that don't have any dependency on other constants 783 // find the constants that don't have any dependency on other constants
645 // and create an object-literal with them (and assign it to the 784 // and create an object-literal with them (and assign it to the
646 // constant-holder variable). 785 // constant-holder variable).
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 } 827 }
689 828
690 emitEmbeddedGlobals(program) { 829 emitEmbeddedGlobals(program) {
691 throw new UnimplementedError('emitEmbeddedGlobals'); 830 throw new UnimplementedError('emitEmbeddedGlobals');
692 } 831 }
693 832
694 emitNativeSupport(fragment) { 833 emitNativeSupport(fragment) {
695 throw new UnimplementedError('emitNativeSupport'); 834 throw new UnimplementedError('emitNativeSupport');
696 } 835 }
697 } 836 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart ('k') | pkg/compiler/lib/src/patch_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698