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

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: Use JS_NAME and fix deferred loading. 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 function finishAddStubsHelper(prototype) {
59 var prototype = prototype || this;
floitsch 2015/03/11 13:59:33 document this.
herhut 2015/03/13 12:28:52 Done.
60 var object;
61 while (prototype.#deferredAction != #markerFun) {
62 if (prototype.hasOwnProperty(#deferredActionString)) {
63 delete prototype.#deferredAction; // Intended to make it slow, too.
64 var properties = Object.keys(prototype);
65 for (var index = 0; index < properties.length; index++) {
66 var property = properties[index];
67 var firstChar = property.charCodeAt(0);
68 var elem;
69 // We have to filter out some special properties that are used for
70 // metadata in descriptors. Currently, we filter everything that
71 // starts with + or *. This has to stay in sync with the special
72 // properties that are used by processClassData below.
73 if (property !== "${namer.classDescriptorProperty}" &&
74 property !== "$reflectableField" &&
75 firstChar !== 43 && // 43 is aka "+".
76 firstChar !== 42 && // 42 is aka "*"
77 (elem = prototype[property]) != null &&
78 elem.constructor === Array &&
79 property !== "<>") {
80 addStubs(prototype, elem, property, false, null);
81 }
82 }
83 convertToFastObject(prototype);
84 }
85 prototype = prototype.__proto__;
86 }
87 }
88
57 function processClassData(cls, descriptor, processedClasses) { 89 function processClassData(cls, descriptor, processedClasses) {
58 var newDesc = map(); // Use a slow object. 90 descriptor = convertToSlowObject(descriptor); // Use a slow object.
59 var previousProperty; 91 var previousProperty;
60 var properties = Object.keys(descriptor); 92 var properties = Object.keys(descriptor);
93 var hasDeferredWork = false;
94 var deferWork = supportsDirectProtoAccess && cls != #objectClassName;
floitsch 2015/03/11 13:59:33 shouldDeferWork ? shouldAddStubsEagerly = !... sho
herhut 2015/03/13 12:28:52 Done.
61 for (var i = 0; i < properties.length; i++) { 95 for (var i = 0; i < properties.length; i++) {
62 var property = properties[i]; 96 var property = properties[i];
63 var firstChar = property.substring(0, 1); 97 var firstChar = property.charCodeAt(0);
64 if (property === "static") { 98 if (property === "static") {
65 processStatics(#embeddedStatics[cls] = descriptor[property], 99 processStatics(#embeddedStatics[cls] = descriptor.static,
66 processedClasses); 100 processedClasses);
67 } else if (firstChar === "+") { 101 delete descriptor.static;
102 } else if (firstChar === 43) { // 43 is aka "+".
floitsch 2015/03/11 13:59:33 is aka -> "is" or "aka".
herhut 2015/03/13 12:28:52 Argh, missed that one. Thanks, done.
68 mangledNames[previousProperty] = property.substring(1); 103 mangledNames[previousProperty] = property.substring(1);
69 var flag = descriptor[property]; 104 var flag = descriptor[property];
70 if (flag > 0) 105 if (flag > 0)
71 descriptor[previousProperty].$reflectableField = flag; 106 descriptor[previousProperty].$reflectableField = flag;
72 } else if (firstChar === "*") { 107 } else if (firstChar === 42) { // 42 is "*"
73 newDesc[previousProperty].$defaultValuesField = descriptor[property]; 108 descriptor[previousProperty].$defaultValuesField = descriptor[property];
74 var optionalMethods = newDesc.$methodsWithOptionalArgumentsField; 109 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
75 if (!optionalMethods) { 110 if (!optionalMethods) {
76 newDesc.$methodsWithOptionalArgumentsField = optionalMethods={} 111 descriptor.$methodsWithOptionalArgumentsField = optionalMethods={}
77 } 112 }
78 optionalMethods[property] = previousProperty; 113 optionalMethods[property] = previousProperty;
79 } else { 114 } else {
80 var elem = descriptor[property]; 115 var elem = descriptor[property];
81 if (property !== "${namer.classDescriptorProperty}" && 116 if (property !== "${namer.classDescriptorProperty}" &&
82 elem != null && 117 elem != null &&
83 elem.constructor === Array && 118 elem.constructor === Array &&
84 property !== "<>") { 119 property !== "<>") {
85 addStubs(newDesc, elem, property, false, []); 120 if (deferWork) {
121 hasDeferredWork = true;
122 } else {
123 addStubs(descriptor, elem, property, false, null);
124 }
86 } else { 125 } else {
87 newDesc[previousProperty = property] = elem; 126 previousProperty = property;
88 } 127 }
89 } 128 }
90 } 129 }
130
131 if (hasDeferredWork)
132 descriptor.#deferredAction = finishAddStubsHelper;
91 133
92 /* The 'fields' are either a constructor function or a 134 /* The 'fields' are either a constructor function or a
93 * string encoding fields, constructor and superclass. Gets the 135 * string encoding fields, constructor and superclass. Gets the
94 * superclass and fields in the format 136 * superclass and fields in the format
95 * 'Super;field1,field2' 137 * 'Super;field1,field2'
96 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. 138 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor.
97 */ 139 */
98 var classData = newDesc["${namer.classDescriptorProperty}"], 140 var classData = descriptor["${namer.classDescriptorProperty}"],
99 split, supr, fields = classData; 141 split, supr, fields = classData;
100 142
101 if (#hasRetainedMetadata) 143 if (#hasRetainedMetadata)
102 if (typeof classData == "object" && 144 if (typeof classData == "object" &&
103 classData instanceof Array) { 145 classData instanceof Array) {
104 classData = fields = classData[0]; 146 classData = fields = classData[0];
105 } 147 }
106 // ${ClassBuilder.fieldEncodingDescription}. 148 // ${ClassBuilder.fieldEncodingDescription}.
107 var s = fields.split(";"); 149 var s = fields.split(";");
108 fields = s[1] == "" ? [] : s[1].split(","); 150 fields = s[1] == "" ? [] : s[1].split(",");
109 supr = s[0]; 151 supr = s[0];
110 // ${ClassBuilder.functionTypeEncodingDescription}. 152 // ${ClassBuilder.functionTypeEncodingDescription}.
111 split = supr.split(":"); 153 split = supr.split(":");
112 if (split.length == 2) { 154 if (split.length == 2) {
113 supr = split[0]; 155 supr = split[0];
114 var functionSignature = split[1]; 156 var functionSignature = split[1];
115 if (functionSignature) 157 if (functionSignature)
116 newDesc.${namer.operatorSignature} = function(s) { 158 descriptor.${namer.operatorSignature} = function(s) {
117 return function() { 159 return function() {
118 return #types[s]; 160 return #types[s];
119 }; 161 };
120 }(functionSignature); 162 }(functionSignature);
121 } 163 }
122 164
123 if (supr) processedClasses.pending[cls] = supr; 165 if (supr) processedClasses.pending[cls] = supr;
124 if (#notInCspMode) { 166 if (#notInCspMode) {
125 processedClasses.combinedConstructorFunction += defineClass(cls, fields); 167 processedClasses.combinedConstructorFunction += defineClass(cls, fields);
126 processedClasses.constructorsList.push(cls); 168 processedClasses.constructorsList.push(cls);
127 } 169 }
128 processedClasses.collected[cls] = [globalObject, newDesc]; 170 processedClasses.collected[cls] = [globalObject, descriptor];
129 classes.push(cls); 171 classes.push(cls);
130 } 172 }
131 }''', {'embeddedStatics': staticsAccess, 173 }''', {'deferredAction': namer.deferredAction,
174 'deferredActionString': js.string(namer.deferredAction),
175 'embeddedStatics': staticsAccess,
132 'hasRetainedMetadata': backend.hasRetainedMetadata, 176 'hasRetainedMetadata': backend.hasRetainedMetadata,
177 'markerFun': oldEmitter.markerFun,
133 'types': typesAccess, 178 'types': typesAccess,
134 'notInCspMode': !compiler.useContentSecurityPolicy}); 179 'notInCspMode': !compiler.useContentSecurityPolicy,
180 'objectClassName':
181 js.string(namer.runtimeTypeName(compiler.objectClass))});
135 182
136 // TODO(zarah): Remove empty else branches in output when if(#hole) is false. 183 // TODO(zarah): Remove empty else branches in output when if(#hole) is false.
137 jsAst.Statement processStatics = js.statement(''' 184 jsAst.Statement processStatics = js.statement('''
138 function processStatics(descriptor, processedClasses) { 185 function processStatics(descriptor, processedClasses) {
139 var properties = Object.keys(descriptor); 186 var properties = Object.keys(descriptor);
140 for (var i = 0; i < properties.length; i++) { 187 for (var i = 0; i < properties.length; i++) {
141 var property = properties[i]; 188 var property = properties[i];
142 if (property === "${namer.classDescriptorProperty}") continue; 189 if (property === "${namer.classDescriptorProperty}") continue;
143 var element = descriptor[property]; 190 var element = descriptor[property];
144 var firstChar = property.substring(0, 1); 191 var firstChar = property.charCodeAt(0);
145 var previousProperty; 192 var previousProperty;
146 if (firstChar === "+") { 193 if (firstChar === 43) { // 43 is "+".
147 mangledGlobalNames[previousProperty] = property.substring(1); 194 mangledGlobalNames[previousProperty] = property.substring(1);
148 var flag = descriptor[property]; 195 var flag = descriptor[property];
149 if (flag > 0) 196 if (flag > 0)
150 descriptor[previousProperty].$reflectableField = flag; 197 descriptor[previousProperty].$reflectableField = flag;
151 if (element && element.length) 198 if (element && element.length)
152 #typeInformation[previousProperty] = element; 199 #typeInformation[previousProperty] = element;
153 } else if (firstChar === "*") { 200 } else if (firstChar === 42) { // 42 is "*"
154 globalObject[previousProperty].$defaultValuesField = element; 201 globalObject[previousProperty].$defaultValuesField = element;
155 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; 202 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
156 if (!optionalMethods) { 203 if (!optionalMethods) {
157 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} 204 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {}
158 } 205 }
159 optionalMethods[property] = previousProperty; 206 optionalMethods[property] = previousProperty;
160 } else if (typeof element === "function") { 207 } else if (typeof element === "function") {
161 globalObject[previousProperty = property] = element; 208 globalObject[previousProperty = property] = element;
162 functions.push(property); 209 functions.push(property);
163 #globalFunctions[property] = element; 210 #globalFunctions[property] = element;
(...skipping 14 matching lines...) Expand all
178 'globalFunctions': globalFunctionsAccess, 225 'globalFunctions': globalFunctionsAccess,
179 'hasClasses': oldEmitter.needsClassSupport, 226 'hasClasses': oldEmitter.needsClassSupport,
180 'needsStructuredMemberInfo': oldEmitter.needsStructuredMemberInfo}); 227 'needsStructuredMemberInfo': oldEmitter.needsStructuredMemberInfo});
181 228
182 229
183 /** 230 /**
184 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of 231 * See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of
185 * [array]. 232 * [array].
186 */ 233 */
187 jsAst.Statement addStubs = js.statement(''' 234 jsAst.Statement addStubs = js.statement('''
188 function addStubs(descriptor, array, name, isStatic, functions) { 235 function addStubs(descriptor, array, name, isStatic, functions) {
floitsch 2015/03/11 13:59:33 Since you seem to know what these arguments are, p
herhut 2015/03/13 12:28:52 Done.
189 var index = $FUNCTION_INDEX, alias = array[index], f; 236 var index = $FUNCTION_INDEX, alias = array[index], f;
190 if (typeof alias == "string") { 237 if (typeof alias == "string") {
191 f = array[++index]; 238 f = array[++index];
192 } else { 239 } else {
193 f = alias; 240 f = alias;
194 alias = name; 241 alias = name;
195 } 242 }
196 var funcs = [descriptor[name] = descriptor[alias] = f]; 243 var funcs = [descriptor[name] = descriptor[alias] = f];
197 f.\$stubName = name; 244 f.\$stubName = name;
198 functions.push(name); 245 if (isStatic) functions.push(name);
floitsch 2015/03/11 13:59:33 Is this necessary in this CL?
herhut 2015/03/13 12:28:52 Great catch. That was a left-over from an experime
199 for (; index < array.length; index += 2) { 246 for (; index < array.length; index += 2) {
200 f = array[index + 1]; 247 f = array[index + 1];
201 if (typeof f != "function") break; 248 if (typeof f != "function") break;
202 f.\$stubName = ${readString("array", "index + 2")}; 249 f.\$stubName = ${readString("array", "index + 2")};
203 funcs.push(f); 250 funcs.push(f);
204 if (f.\$stubName) { 251 if (f.\$stubName) {
205 descriptor[f.\$stubName] = f; 252 descriptor[f.\$stubName] = f;
206 functions.push(f.\$stubName); 253 if (isStatic) functions.push(f.\$stubName);
207 } 254 }
208 } 255 }
209 index++; 256 index++;
210 for (var i = 0; i < funcs.length; index++, i++) { 257 for (var i = 0; i < funcs.length; index++, i++) {
211 funcs[i].\$callName = ${readString("array", "index")}; 258 funcs[i].\$callName = ${readString("array", "index")};
212 } 259 }
213 var getterStubName = ${readString("array", "index")}; 260 var getterStubName = ${readString("array", "index")};
214 array = array.slice(++index); 261 array = array.slice(++index);
215 var requiredParameterInfo = ${readInt("array", "0")}; 262 var requiredParameterInfo = ${readInt("array", "0")};
216 var requiredParameterCount = requiredParameterInfo >> 1; 263 var requiredParameterCount = requiredParameterInfo >> 1;
217 var isAccessor = (requiredParameterInfo & 1) === 1; 264 var isAccessor = (requiredParameterInfo & 1) === 1;
218 var isSetter = requiredParameterInfo === 3; 265 var isSetter = requiredParameterInfo === 3;
219 var isGetter = requiredParameterInfo === 1; 266 var isGetter = requiredParameterInfo === 1;
220 var optionalParameterInfo = ${readInt("array", "1")}; 267 var optionalParameterInfo = ${readInt("array", "1")};
221 var optionalParameterCount = optionalParameterInfo >> 1; 268 var optionalParameterCount = optionalParameterInfo >> 1;
222 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1; 269 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1;
223 var isIntercepted = 270 var isIntercepted =
224 requiredParameterCount + optionalParameterCount != funcs[0].length; 271 requiredParameterCount + optionalParameterCount != funcs[0].length;
225 var functionTypeIndex = ${readFunctionType("array", "2")}; 272 var functionTypeIndex = ${readFunctionType("array", "2")};
226 var unmangledNameIndex = $unmangledNameIndex; 273 var unmangledNameIndex = $unmangledNameIndex;
227 274
228 if (getterStubName) { 275 if (getterStubName) {
229 f = tearOff(funcs, array, isStatic, name, isIntercepted); 276 f = tearOff(funcs, array, isStatic, name, isIntercepted);
230 descriptor[name].\$getter = f; 277 descriptor[name].\$getter = f;
231 f.\$getterStub = true; 278 f.\$getterStub = true;
232 // Used to create an isolate using spawnFunction. 279 // Used to create an isolate using spawnFunction.
233 if (isStatic) #globalFunctions[name] = f; 280 if (isStatic) {
281 #globalFunctions[name] = f;
282 functions.push(getterStubName);
283 }
234 descriptor[getterStubName] = f; 284 descriptor[getterStubName] = f;
235 funcs.push(f); 285 funcs.push(f);
236 if (getterStubName) functions.push(getterStubName);
237 f.\$stubName = getterStubName; 286 f.\$stubName = getterStubName;
238 f.\$callName = null; 287 f.\$callName = null;
239 // Update the interceptedNames map (which only exists if `invokeOn` was 288 // Update the interceptedNames map (which only exists if `invokeOn` was
240 // enabled). 289 // enabled).
241 if (#enabledInvokeOn) 290 if (#enabledInvokeOn)
242 if (isIntercepted) #interceptedNames[getterStubName] = 1; 291 if (isIntercepted) #interceptedNames[getterStubName] = 1;
243 } 292 }
244 293
245 if (#usesMangledNames) { 294 if (#usesMangledNames) {
246 var isReflectable = array.length > unmangledNameIndex; 295 var isReflectable = array.length > unmangledNameIndex;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 'precompiled': oldEmitter 469 'precompiled': oldEmitter
421 .generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED)}); 470 .generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED)});
422 471
423 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[]; 472 List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[];
424 if (compiler.hasIncrementalSupport) { 473 if (compiler.hasIncrementalSupport) {
425 incrementalSupport.add( 474 incrementalSupport.add(
426 js.statement( 475 js.statement(
427 '#.addStubs = addStubs;', [namer.accessIncrementalHelper])); 476 '#.addStubs = addStubs;', [namer.accessIncrementalHelper]));
428 } 477 }
429 478
430 return js(''' 479 return js.statement('''
431 function $parseReflectionDataName(reflectionData) { 480 function $parseReflectionDataName(reflectionData) {
432 "use strict"; 481 "use strict";
433 if (#needsClassSupport) { 482 if (#needsClassSupport) {
434 #defineClass; 483 #defineClass;
435 #inheritFrom; 484 #inheritFrom;
436 #finishClasses; 485 #finishClasses;
437 #processClassData; 486 #processClassData;
438 } 487 }
439 #processStatics; 488 #processStatics;
440 if (#needsStructuredMemberInfo) { 489 if (#needsStructuredMemberInfo) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 (function() { 533 (function() {
485 var result = $array[$index]; 534 var result = $array[$index];
486 if ($check) { 535 if ($check) {
487 throw new Error( 536 throw new Error(
488 name + ": expected value of type \'$type\' at index " + ($index) + 537 name + ": expected value of type \'$type\' at index " + ($index) +
489 " but got " + (typeof result)); 538 " but got " + (typeof result));
490 } 539 }
491 return result; 540 return result;
492 })()'''; 541 })()''';
493 } 542 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698