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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart

Issue 974803002: Defer addStubs to class instantiation time. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased and fixes. Created 5 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 // TODO(ahe): Share these with js_helper.dart. 7 // TODO(ahe): Share these with js_helper.dart.
8 const FUNCTION_INDEX = 0; 8 const FUNCTION_INDEX = 0;
9 const NAME_INDEX = 1; 9 const NAME_INDEX = 1;
10 const CALL_NAME_INDEX = 2; 10 const CALL_NAME_INDEX = 2;
11 const REQUIRED_PARAMETER_INDEX = 3; 11 const REQUIRED_PARAMETER_INDEX = 3;
12 const OPTIONAL_PARAMETER_INDEX = 4; 12 const OPTIONAL_PARAMETER_INDEX = 4;
13 const DEFAULT_ARGUMENTS_INDEX = 5; 13 const DEFAULT_ARGUMENTS_INDEX = 5;
14 14
15 const bool VALIDATE_DATA = false; 15 const bool VALIDATE_DATA = false;
16 16
17 // TODO(zarah): Rename this when renaming this file. 17 // TODO(zarah): Rename this when renaming this file.
18 String get parseReflectionDataName => 'parseReflectionData'; 18 String get parseReflectionDataName => 'parseReflectionData';
19 19
20 jsAst.Expression getReflectionDataParser(OldEmitter oldEmitter, 20 jsAst.Statement getReflectionDataParser(OldEmitter oldEmitter,
21 JavaScriptBackend backend, 21 JavaScriptBackend backend,
22 bool needsNativeSupport) { 22 bool needsNativeSupport) {
23 Namer namer = backend.namer; 23 Namer namer = backend.namer;
24 Compiler compiler = backend.compiler; 24 Compiler compiler = backend.compiler;
25 CodeEmitterTask emitter = backend.emitter; 25 CodeEmitterTask emitter = backend.emitter;
26 26
27 String reflectableField = namer.reflectableField; 27 String reflectableField = namer.reflectableField;
28 String reflectionInfoField = namer.reflectionInfoField; 28 String reflectionInfoField = namer.reflectionInfoField;
29 String reflectionNameField = namer.reflectionNameField; 29 String reflectionNameField = namer.reflectionNameField;
30 String metadataIndexField = namer.metadataIndexField; 30 String metadataIndexField = namer.metadataIndexField;
31 String defaultValuesField = namer.defaultValuesField; 31 String defaultValuesField = namer.defaultValuesField;
32 String methodsWithOptionalArgumentsField = 32 String methodsWithOptionalArgumentsField =
(...skipping 13 matching lines...) Expand all
46 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES); 46 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES);
47 jsAst.Expression mangledGlobalNamesAccess = 47 jsAst.Expression mangledGlobalNamesAccess =
48 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); 48 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
49 jsAst.Expression mangledNamesAccess = 49 jsAst.Expression mangledNamesAccess =
50 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); 50 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
51 jsAst.Expression librariesAccess = 51 jsAst.Expression librariesAccess =
52 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES); 52 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES);
53 jsAst.Expression typesAccess = 53 jsAst.Expression typesAccess =
54 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPES); 54 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPES);
55 55
56
56 jsAst.Statement processClassData = js.statement('''{ 57 jsAst.Statement processClassData = js.statement('''{
58 // For convenience, this method can be called with a prototype as argument
59 // or, if it was bound to an object, by invoking it as a method. Therefore,
60 // if prototype is undefined, this is used as prototype.
61 function finishAddStubsHelper(prototype) {
62 var prototype = prototype || this;
63 var object;
64 while (prototype.#deferredAction != #markerFun) {
65 if (prototype.hasOwnProperty(#deferredActionString)) {
66 delete prototype.#deferredAction; // Intended to make it slow, too.
67 var properties = Object.keys(prototype);
68 for (var index = 0; index < properties.length; index++) {
69 var property = properties[index];
70 var firstChar = property.charCodeAt(0);
71 var elem;
72 // We have to filter out some special properties that are used for
73 // metadata in descriptors. Currently, we filter everything that
74 // starts with + or *. This has to stay in sync with the special
75 // properties that are used by processClassData below.
76 if (property !== "${namer.classDescriptorProperty}" &&
77 property !== "$reflectableField" &&
78 firstChar !== 43 && // 43 is aka "+".
79 firstChar !== 42 && // 42 is aka "*"
80 (elem = prototype[property]) != null &&
81 elem.constructor === Array &&
82 property !== "<>") {
83 addStubs(prototype, elem, property, false, []);
84 }
85 }
86 convertToFastObject(prototype);
87 }
88 prototype = prototype.__proto__;
89 }
90 }
91
57 function processClassData(cls, descriptor, processedClasses) { 92 function processClassData(cls, descriptor, processedClasses) {
58 descriptor = convertToSlowObject(descriptor); // Use a slow object. 93 descriptor = convertToSlowObject(descriptor); // Use a slow object.
59 var previousProperty; 94 var previousProperty;
60 var properties = Object.keys(descriptor); 95 var properties = Object.keys(descriptor);
96 var hasDeferredWork = false;
97 var shouldDeferWork = supportsDirectProtoAccess && cls != #objectClassName;
61 for (var i = 0; i < properties.length; i++) { 98 for (var i = 0; i < properties.length; i++) {
62 var property = properties[i]; 99 var property = properties[i];
63 var firstChar = property.charCodeAt(0); 100 var firstChar = property.charCodeAt(0);
64 if (property === "static") { 101 if (property === "static") {
65 processStatics(#embeddedStatics[cls] = descriptor.static, 102 processStatics(#embeddedStatics[cls] = descriptor.static,
66 processedClasses); 103 processedClasses);
104 delete descriptor.static;
67 } else if (firstChar === 43) { // 43 is "+". 105 } else if (firstChar === 43) { // 43 is "+".
68 mangledNames[previousProperty] = property.substring(1); 106 mangledNames[previousProperty] = property.substring(1);
69 var flag = descriptor[property]; 107 var flag = descriptor[property];
70 if (flag > 0) 108 if (flag > 0)
71 descriptor[previousProperty].$reflectableField = flag; 109 descriptor[previousProperty].$reflectableField = flag;
72 } else if (firstChar === 42) { // 42 is "*" 110 } else if (firstChar === 42) { // 42 is "*"
73 descriptor[previousProperty].$defaultValuesField = descriptor[property]; 111 descriptor[previousProperty].$defaultValuesField = descriptor[property];
74 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; 112 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
75 if (!optionalMethods) { 113 if (!optionalMethods) {
76 descriptor.$methodsWithOptionalArgumentsField = optionalMethods={} 114 descriptor.$methodsWithOptionalArgumentsField = optionalMethods={}
77 } 115 }
78 optionalMethods[property] = previousProperty; 116 optionalMethods[property] = previousProperty;
79 } else { 117 } else {
80 var elem = descriptor[property]; 118 var elem = descriptor[property];
81 if (property !== "${namer.classDescriptorProperty}" && 119 if (property !== "${namer.classDescriptorProperty}" &&
82 elem != null && 120 elem != null &&
83 elem.constructor === Array && 121 elem.constructor === Array &&
84 property !== "<>") { 122 property !== "<>") {
85 addStubs(descriptor, elem, property, false, []); 123 if (shouldDeferWork) {
124 hasDeferredWork = true;
125 } else {
126 addStubs(descriptor, elem, property, false, []);
127 }
86 } else { 128 } else {
87 previousProperty = property; 129 previousProperty = property;
88 } 130 }
89 } 131 }
90 } 132 }
133
134 if (hasDeferredWork)
135 descriptor.#deferredAction = finishAddStubsHelper;
91 136
92 /* The 'fields' are either a constructor function or a 137 /* The 'fields' are either a constructor function or a
93 * string encoding fields, constructor and superclass. Gets the 138 * string encoding fields, constructor and superclass. Gets the
94 * superclass and fields in the format 139 * superclass and fields in the format
95 * 'Super;field1,field2' 140 * 'Super;field1,field2'
96 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. 141 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor.
97 */ 142 */
98 var classData = descriptor["${namer.classDescriptorProperty}"], 143 var classData = descriptor["${namer.classDescriptorProperty}"],
99 split, supr, fields = classData; 144 split, supr, fields = classData;
100 145
(...skipping 20 matching lines...) Expand all
121 } 166 }
122 167
123 if (supr) processedClasses.pending[cls] = supr; 168 if (supr) processedClasses.pending[cls] = supr;
124 if (#notInCspMode) { 169 if (#notInCspMode) {
125 processedClasses.combinedConstructorFunction += defineClass(cls, fields); 170 processedClasses.combinedConstructorFunction += defineClass(cls, fields);
126 processedClasses.constructorsList.push(cls); 171 processedClasses.constructorsList.push(cls);
127 } 172 }
128 processedClasses.collected[cls] = [globalObject, descriptor]; 173 processedClasses.collected[cls] = [globalObject, descriptor];
129 classes.push(cls); 174 classes.push(cls);
130 } 175 }
131 }''', {'embeddedStatics': staticsAccess, 176 }''', {'deferredAction': namer.deferredAction,
177 'deferredActionString': js.string(namer.deferredAction),
178 'embeddedStatics': staticsAccess,
132 'hasRetainedMetadata': backend.hasRetainedMetadata, 179 'hasRetainedMetadata': backend.hasRetainedMetadata,
180 'markerFun': oldEmitter.markerFun,
133 'types': typesAccess, 181 'types': typesAccess,
134 'notInCspMode': !compiler.useContentSecurityPolicy}); 182 'notInCspMode': !compiler.useContentSecurityPolicy,
183 'objectClassName':
184 js.string(namer.runtimeTypeName(compiler.objectClass))});
135 185
136 // TODO(zarah): Remove empty else branches in output when if(#hole) is false. 186 // TODO(zarah): Remove empty else branches in output when if(#hole) is false.
137 jsAst.Statement processStatics = js.statement(''' 187 jsAst.Statement processStatics = js.statement('''
138 function processStatics(descriptor, processedClasses) { 188 function processStatics(descriptor, processedClasses) {
139 var properties = Object.keys(descriptor); 189 var properties = Object.keys(descriptor);
140 for (var i = 0; i < properties.length; i++) { 190 for (var i = 0; i < properties.length; i++) {
141 var property = properties[i]; 191 var property = properties[i];
142 if (property === "${namer.classDescriptorProperty}") continue; 192 if (property === "${namer.classDescriptorProperty}") continue;
143 var element = descriptor[property]; 193 var element = descriptor[property];
144 var firstChar = property.charCodeAt(0); 194 var firstChar = property.charCodeAt(0);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 'globalFunctions': globalFunctionsAccess, 228 'globalFunctions': globalFunctionsAccess,
179 'hasClasses': oldEmitter.needsClassSupport, 229 'hasClasses': oldEmitter.needsClassSupport,
180 'needsStructuredMemberInfo': oldEmitter.needsStructuredMemberInfo}); 230 'needsStructuredMemberInfo': oldEmitter.needsStructuredMemberInfo});
181 231
182 232
183 /** 233 /**
184 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of 234 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of
185 * [array]. 235 * [array].
186 */ 236 */
187 jsAst.Statement addStubs = js.statement(''' 237 jsAst.Statement addStubs = js.statement('''
188 function addStubs(descriptor, array, name, isStatic, functions) { 238 // Processes the stub declaration given by [array] and stores the results
239 // in the corresponding [prototype]. [name] is the property name in
240 // [prototype] that the stub declaration belongs to.
241 // If [isStatic] is true, the property being processed belongs to a static
242 // function and thus is stored as a global. In that case we also add all
243 // generated functions to the [functions] array, which is used by the mirrors
244 // system to enumerate all static functions of a library. For non-static
245 // functions we might still add some functions to [functions] but the
246 // information is thrown away at the call site. This is to avoid conditionals.
247 function addStubs(prototype, array, name, isStatic, functions) {
189 var index = $FUNCTION_INDEX, alias = array[index], f; 248 var index = $FUNCTION_INDEX, alias = array[index], f;
190 if (typeof alias == "string") { 249 if (typeof alias == "string") {
191 f = array[++index]; 250 f = array[++index];
192 } else { 251 } else {
193 f = alias; 252 f = alias;
194 alias = name; 253 alias = name;
195 } 254 }
196 var funcs = [descriptor[name] = descriptor[alias] = f]; 255 var funcs = [prototype[name] = prototype[alias] = f];
197 f.\$stubName = name; 256 f.\$stubName = name;
198 functions.push(name); 257 functions.push(name);
199 for (; index < array.length; index += 2) { 258 for (; index < array.length; index += 2) {
200 f = array[index + 1]; 259 f = array[index + 1];
201 if (typeof f != "function") break; 260 if (typeof f != "function") break;
202 f.\$stubName = ${readString("array", "index + 2")}; 261 f.\$stubName = ${readString("array", "index + 2")};
203 funcs.push(f); 262 funcs.push(f);
204 if (f.\$stubName) { 263 if (f.\$stubName) {
205 descriptor[f.\$stubName] = f; 264 prototype[f.\$stubName] = f;
206 functions.push(f.\$stubName); 265 functions.push(f.\$stubName);
207 } 266 }
208 } 267 }
209 index++; 268 index++;
210 for (var i = 0; i < funcs.length; index++, i++) { 269 for (var i = 0; i < funcs.length; index++, i++) {
211 funcs[i].\$callName = ${readString("array", "index")}; 270 funcs[i].\$callName = ${readString("array", "index")};
212 } 271 }
213 var getterStubName = ${readString("array", "index")}; 272 var getterStubName = ${readString("array", "index")};
214 array = array.slice(++index); 273 array = array.slice(++index);
215 var requiredParameterInfo = ${readInt("array", "0")}; 274 var requiredParameterInfo = ${readInt("array", "0")};
216 var requiredParameterCount = requiredParameterInfo >> 1; 275 var requiredParameterCount = requiredParameterInfo >> 1;
217 var isAccessor = (requiredParameterInfo & 1) === 1; 276 var isAccessor = (requiredParameterInfo & 1) === 1;
218 var isSetter = requiredParameterInfo === 3; 277 var isSetter = requiredParameterInfo === 3;
219 var isGetter = requiredParameterInfo === 1; 278 var isGetter = requiredParameterInfo === 1;
220 var optionalParameterInfo = ${readInt("array", "1")}; 279 var optionalParameterInfo = ${readInt("array", "1")};
221 var optionalParameterCount = optionalParameterInfo >> 1; 280 var optionalParameterCount = optionalParameterInfo >> 1;
222 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1; 281 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1;
223 var isIntercepted = 282 var isIntercepted =
224 requiredParameterCount + optionalParameterCount != funcs[0].length; 283 requiredParameterCount + optionalParameterCount != funcs[0].length;
225 var functionTypeIndex = ${readFunctionType("array", "2")}; 284 var functionTypeIndex = ${readFunctionType("array", "2")};
226 var unmangledNameIndex = $unmangledNameIndex; 285 var unmangledNameIndex = $unmangledNameIndex;
227 286
228 if (getterStubName) { 287 if (getterStubName) {
229 f = tearOff(funcs, array, isStatic, name, isIntercepted); 288 f = tearOff(funcs, array, isStatic, name, isIntercepted);
230 descriptor[name].\$getter = f; 289 prototype[name].\$getter = f;
231 f.\$getterStub = true; 290 f.\$getterStub = true;
232 // Used to create an isolate using spawnFunction. 291 // Used to create an isolate using spawnFunction.
233 if (isStatic) #globalFunctions[name] = f; 292 if (isStatic) {
234 descriptor[getterStubName] = f; 293 #globalFunctions[name] = f;
294 functions.push(getterStubName);
295 }
296 prototype[getterStubName] = f;
235 funcs.push(f); 297 funcs.push(f);
236 if (getterStubName) functions.push(getterStubName);
237 f.\$stubName = getterStubName; 298 f.\$stubName = getterStubName;
238 f.\$callName = null; 299 f.\$callName = null;
239 // Update the interceptedNames map (which only exists if `invokeOn` was 300 // Update the interceptedNames map (which only exists if `invokeOn` was
240 // enabled). 301 // enabled).
241 if (#enabledInvokeOn) 302 if (#enabledInvokeOn)
242 if (isIntercepted) #interceptedNames[getterStubName] = 1; 303 if (isIntercepted) #interceptedNames[getterStubName] = 1;
243 } 304 }
244 305
245 if (#usesMangledNames) { 306 if (#usesMangledNames) {
246 var isReflectable = array.length > unmangledNameIndex; 307 var isReflectable = array.length > unmangledNameIndex;
(...skipping 11 matching lines...) Expand all
258 if (getterStubName) mangledNames[getterStubName] = reflectionName; 319 if (getterStubName) mangledNames[getterStubName] = reflectionName;
259 if (isSetter) { 320 if (isSetter) {
260 reflectionName += "="; 321 reflectionName += "=";
261 } else if (!isGetter) { 322 } else if (!isGetter) {
262 reflectionName += ":" + requiredParameterCount + 323 reflectionName += ":" + requiredParameterCount +
263 ":" + optionalParameterCount; 324 ":" + optionalParameterCount;
264 } 325 }
265 mangledNames[name] = reflectionName; 326 mangledNames[name] = reflectionName;
266 funcs[0].$reflectionNameField = reflectionName; 327 funcs[0].$reflectionNameField = reflectionName;
267 funcs[0].$metadataIndexField = unmangledNameIndex + 1; 328 funcs[0].$metadataIndexField = unmangledNameIndex + 1;
268 if (optionalParameterCount) descriptor[unmangledName + "*"] = funcs[0]; 329 if (optionalParameterCount) prototype[unmangledName + "*"] = funcs[0];
269 } 330 }
270 } 331 }
271 } 332 }
272 ''', {'globalFunctions': globalFunctionsAccess, 333 ''', {'globalFunctions': globalFunctionsAccess,
273 'enabledInvokeOn': compiler.enabledInvokeOn, 334 'enabledInvokeOn': compiler.enabledInvokeOn,
274 'interceptedNames': interceptedNamesAccess, 335 'interceptedNames': interceptedNamesAccess,
275 'usesMangledNames': 336 'usesMangledNames':
276 compiler.mirrorsLibrary != null || compiler.enabledFunctionApply, 337 compiler.mirrorsLibrary != null || compiler.enabledFunctionApply,
277 'mangledGlobalNames': mangledGlobalNamesAccess, 338 'mangledGlobalNames': mangledGlobalNamesAccess,
278 'mangledNames': mangledNamesAccess}); 339 'mangledNames': mangledNamesAccess});
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 'precompiled': oldEmitter 481 'precompiled': oldEmitter
421 .generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED)}); 482 .generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED)});
422 483
423 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[]; 484 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[];
424 if (compiler.hasIncrementalSupport) { 485 if (compiler.hasIncrementalSupport) {
425 incrementalSupport.add( 486 incrementalSupport.add(
426 js.statement( 487 js.statement(
427 '#.addStubs = addStubs;', [namer.accessIncrementalHelper])); 488 '#.addStubs = addStubs;', [namer.accessIncrementalHelper]));
428 } 489 }
429 490
430 return js(''' 491 return js.statement('''
431 function $parseReflectionDataName(reflectionData) { 492 function $parseReflectionDataName(reflectionData) {
432 "use strict"; 493 "use strict";
433 if (#needsClassSupport) { 494 if (#needsClassSupport) {
434 #defineClass; 495 #defineClass;
435 #inheritFrom; 496 #inheritFrom;
436 #finishClasses; 497 #finishClasses;
437 #processClassData; 498 #processClassData;
438 } 499 }
439 #processStatics; 500 #processStatics;
440 if (#needsStructuredMemberInfo) { 501 if (#needsStructuredMemberInfo) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 (function() { 545 (function() {
485 var result = $array[$index]; 546 var result = $array[$index];
486 if ($check) { 547 if ($check) {
487 throw new Error( 548 throw new Error(
488 name + ": expected value of type \'$type\' at index " + ($index) + 549 name + ": expected value of type \'$type\' at index " + ($index) +
489 " but got " + (typeof result)); 550 " but got " + (typeof result));
490 } 551 }
491 return result; 552 return result;
492 })()'''; 553 })()''';
493 } 554 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart ('k') | pkg/compiler/lib/src/ssa/codegen_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698