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

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

Issue 1220333003: dart2js: Rename emitters. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart2js.js_emitter;
6
7 // TODO(ahe): Share these with js_helper.dart.
8 const FUNCTION_INDEX = 0;
9 const NAME_INDEX = 1;
10 const CALL_NAME_INDEX = 2;
11 const REQUIRED_PARAMETER_INDEX = 3;
12 const OPTIONAL_PARAMETER_INDEX = 4;
13 const DEFAULT_ARGUMENTS_INDEX = 5;
14
15 const bool VALIDATE_DATA = false;
16
17 const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1;
18 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1;
19 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST);
20 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST);
21 const RANGE3_ADJUST =
22 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST);
23
24 const String setupProgramName ='setupProgram';
25 // TODO(floitsch): make sure this property can't clash with anything. It's
26 // unlikely since it lives on types, but still.
27 const String typeNameProperty = r'builtin$cls';
28
29 jsAst.Statement buildSetupProgram(Program program, Compiler compiler,
30 JavaScriptBackend backend,
31 Namer namer,
32 OldEmitter emitter) {
33
34 jsAst.Expression typeInformationAccess =
35 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPE_INFORMATION);
36 jsAst.Expression globalFunctionsAccess =
37 emitter.generateEmbeddedGlobalAccess(embeddedNames.GLOBAL_FUNCTIONS);
38 jsAst.Expression staticsAccess =
39 emitter.generateEmbeddedGlobalAccess(embeddedNames.STATICS);
40 jsAst.Expression interceptedNamesAccess =
41 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES);
42 jsAst.Expression mangledGlobalNamesAccess =
43 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
44 jsAst.Expression mangledNamesAccess =
45 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
46 jsAst.Expression librariesAccess =
47 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES);
48 jsAst.Expression typesAccess =
49 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPES);
50 jsAst.Expression createNewIsolateFunctionAccess =
51 emitter.generateEmbeddedGlobalAccess(embeddedNames.CREATE_NEW_ISOLATE);
52 jsAst.Expression classIdExtractorAccess =
53 emitter.generateEmbeddedGlobalAccess(embeddedNames.CLASS_ID_EXTRACTOR);
54 jsAst.Expression allClassesAccess =
55 emitter.generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
56 jsAst.Expression precompiledAccess =
57 emitter.generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED);
58 jsAst.Expression finishedClassesAccess =
59 emitter.generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES);
60 jsAst.Expression interceptorsByTagAccess =
61 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
62 jsAst.Expression leafTagsAccess =
63 emitter.generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
64 jsAst.Expression initializeEmptyInstanceAccess =
65 emitter.generateEmbeddedGlobalAccess(
66 embeddedNames.INITIALIZE_EMPTY_INSTANCE);
67 jsAst.Expression classFieldsExtractorAccess =
68 emitter.generateEmbeddedGlobalAccess(
69 embeddedNames.CLASS_FIELDS_EXTRACTOR);
70 jsAst.Expression instanceFromClassIdAccess =
71 emitter.generateEmbeddedGlobalAccess(
72 embeddedNames.INSTANCE_FROM_CLASS_ID);
73
74 String reflectableField = namer.reflectableField;
75 String reflectionInfoField = namer.reflectionInfoField;
76 String reflectionNameField = namer.reflectionNameField;
77 String metadataIndexField = namer.metadataIndexField;
78 String defaultValuesField = namer.defaultValuesField;
79 String methodsWithOptionalArgumentsField =
80 namer.methodsWithOptionalArgumentsField;
81 String unmangledNameIndex = backend.mustRetainMetadata
82 ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3'
83 : ' 2 * optionalParameterCount + requiredParameterCount + 3';
84 String receiverParamName = compiler.enableMinification ? "r" : "receiver";
85 String valueParamName = compiler.enableMinification ? "v" : "value";
86 String space = compiler.enableMinification ? "" : " ";
87 String _ = space;
88
89 String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
90 jsAst.Expression nativeInfoAccess = js('prototype[$specProperty]', []);
91 jsAst.Expression constructorAccess = js('constructor', []);
92 Function subclassReadGenerator =
93 (jsAst.Expression subclass) => js('allClasses[#]', subclass);
94 jsAst.Statement nativeInfoHandler = emitter.
95 buildNativeInfoHandler(nativeInfoAccess, constructorAccess,
96 subclassReadGenerator, interceptorsByTagAccess,
97 leafTagsAccess);
98
99 Map<String, dynamic> holes =
100 {'needsClassSupport': emitter.needsClassSupport,
101 'libraries': librariesAccess,
102 'mangledNames': mangledNamesAccess,
103 'mangledGlobalNames': mangledGlobalNamesAccess,
104 'statics': staticsAccess,
105 'typeInformation': typeInformationAccess,
106 'globalFunctions': globalFunctionsAccess,
107 'enabledInvokeOn': compiler.enabledInvokeOn,
108 'interceptedNames': interceptedNamesAccess,
109 'interceptedNamesSet': emitter.generateInterceptedNamesSet(),
110 'notInCspMode': !compiler.useContentSecurityPolicy,
111 'inCspMode': compiler.useContentSecurityPolicy,
112 'deferredAction': namer.deferredAction,
113 'hasIsolateSupport': program.hasIsolateSupport,
114 'fieldNamesProperty': js.string(OldEmitter.FIELD_NAMES_PROPERTY_NAME),
115 'hasIncrementalSupport': compiler.hasIncrementalSupport,
116 'incrementalHelper': namer.accessIncrementalHelper,
117 'createNewIsolateFunction': createNewIsolateFunctionAccess,
118 'isolateName': namer.isolateName,
119 'classIdExtractor': classIdExtractorAccess,
120 'classFieldsExtractor': classFieldsExtractorAccess,
121 'instanceFromClassId': instanceFromClassIdAccess,
122 'initializeEmptyInstance': initializeEmptyInstanceAccess,
123 'allClasses': allClassesAccess,
124 'debugFastObjects': DEBUG_FAST_OBJECTS,
125 'isTreeShakingDisabled': backend.isTreeShakingDisabled,
126 'precompiled': precompiledAccess,
127 'finishedClassesAccess': finishedClassesAccess,
128 'needsMixinSupport': emitter.needsMixinSupport,
129 'needsNativeSupport': program.needsNativeSupport,
130 'isInterceptorClass': namer.operatorIs(backend.jsInterceptorClass),
131 'isObject' : namer.operatorIs(compiler.objectClass),
132 'specProperty': js.string(namer.nativeSpecProperty),
133 'trivialNsmHandlers': emitter.buildTrivialNsmHandlers(),
134 'hasRetainedMetadata': backend.hasRetainedMetadata,
135 'types': typesAccess,
136 'objectClassName': js.quoteName(
137 namer.runtimeTypeName(compiler.objectClass)),
138 'needsStructuredMemberInfo': emitter.needsStructuredMemberInfo,
139 'usesMangledNames':
140 compiler.mirrorsLibrary != null || compiler.enabledFunctionApply,
141 'tearOffCode': buildTearOffCode(backend),
142 'nativeInfoHandler': nativeInfoHandler,
143 'operatorIsPrefix' : js.string(namer.operatorIsPrefix),
144 'deferredActionString': js.string(namer.deferredAction)};
145
146 String skeleton = '''
147 function $setupProgramName(programData, typesOffset) {
148 "use strict";
149 if (#needsClassSupport) {
150
151 function generateAccessor(fieldDescriptor, accessors, cls) {
152 var fieldInformation = fieldDescriptor.split("-");
153 var field = fieldInformation[0];
154 var len = field.length;
155 var code = field.charCodeAt(len - 1);
156 var reflectable;
157 if (fieldInformation.length > 1) reflectable = true;
158 else reflectable = false;
159 code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST))
160 ? code - $RANGE1_ADJUST
161 : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST))
162 ? code - $RANGE2_ADJUST
163 : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST))
164 ? code - $RANGE3_ADJUST
165 : $NO_FIELD_CODE;
166
167 if (code) { // needsAccessor
168 var getterCode = code & 3;
169 var setterCode = code >> 2;
170 var accessorName = field = field.substring(0, len - 1);
171
172 var divider = field.indexOf(":");
173 if (divider > 0) { // Colon never in first position.
174 accessorName = field.substring(0, divider);
175 field = field.substring(divider + 1);
176 }
177
178 if (getterCode) { // needsGetter
179 var args = (getterCode & 2) ? "$receiverParamName" : "";
180 var receiver = (getterCode & 1) ? "this" : "$receiverParamName";
181 var body = "return " + receiver + "." + field;
182 var property =
183 cls + ".prototype.${namer.getterPrefix}" + accessorName + "=";
184 var fn = "function(" + args + "){" + body + "}";
185 if (reflectable)
186 accessors.push(property + "\$reflectable(" + fn + ");\\n");
187 else
188 accessors.push(property + fn + ";\\n");
189 }
190
191 if (setterCode) { // needsSetter
192 var args = (setterCode & 2)
193 ? "$receiverParamName,${_}$valueParamName"
194 : "$valueParamName";
195 var receiver = (setterCode & 1) ? "this" : "$receiverParamName";
196 var body = receiver + "." + field + "$_=$_$valueParamName";
197 var property =
198 cls + ".prototype.${namer.setterPrefix}" + accessorName + "=";
199 var fn = "function(" + args + "){" + body + "}";
200 if (reflectable)
201 accessors.push(property + "\$reflectable(" + fn + ");\\n");
202 else
203 accessors.push(property + fn + ";\\n");
204 }
205 }
206
207 return field;
208 }
209
210 // First the class name, then the field names in an array and the members
211 // (inside an Object literal).
212 // The caller can also pass in the constructor as a function if needed.
213 //
214 // Example:
215 // defineClass("A", ["x", "y"], {
216 // foo\$1: function(y) {
217 // print(this.x + y);
218 // },
219 // bar\$2: function(t, v) {
220 // this.x = t - v;
221 // },
222 // });
223 function defineClass(name, fields) {
224 var accessors = [];
225
226 var str = "function " + name + "(";
227 var body = "";
228 if (#hasIsolateSupport) { var fieldNames = ""; }
229
230 for (var i = 0; i < fields.length; i++) {
231 if(i != 0) str += ", ";
232
233 var field = generateAccessor(fields[i], accessors, name);
234 if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; }
235 var parameter = "p_" + field;
236 str += parameter;
237 body += ("this." + field + " = " + parameter + ";\\n");
238 }
239 if (supportsDirectProtoAccess) {
240 body += "this." + #deferredActionString + "();";
241 }
242 str += ") {\\n" + body + "}\\n";
243 str += name + ".$typeNameProperty=\\"" + name + "\\";\\n";
244 str += "\$desc=\$collectedClasses." + name + "[1];\\n";
245 str += name + ".prototype = \$desc;\\n";
246 if (typeof defineClass.name != "string") {
247 str += name + ".name=\\"" + name + "\\";\\n";
248 }
249 if (#hasIsolateSupport) {
250 str += name + "." + #fieldNamesProperty + "=[" + fieldNames
251 + "];\\n";
252 }
253 str += accessors.join("");
254
255 return str;
256 }
257
258 if (#hasIncrementalSupport) {
259 #incrementalHelper.defineClass = defineClass;
260 }
261
262 if (#hasIsolateSupport) {
263 #createNewIsolateFunction = function() { return new #isolateName(); };
264
265 #classIdExtractor = function(o) { return o.constructor.name; };
266
267 #classFieldsExtractor = function(o) {
268 var fieldNames = o.constructor.#fieldNamesProperty;
269 if (!fieldNames) return []; // TODO(floitsch): do something else here.
270 var result = [];
271 result.length = fieldNames.length;
272 for (var i = 0; i < fieldNames.length; i++) {
273 result[i] = o[fieldNames[i]];
274 }
275 return result;
276 };
277
278 #instanceFromClassId = function(name) { return new #allClasses[name](); };
279
280 #initializeEmptyInstance = function(name, o, fields) {
281 #allClasses[name].apply(o, fields);
282 return o; //
283 }
284 }
285
286 // If the browser supports changing the prototype via __proto__, we make
287 // use of that feature. Otherwise, we copy the properties into a new
288 // constructor.
289 var inheritFrom = supportsDirectProtoAccess ?
290 function(constructor, superConstructor) {
291 var prototype = constructor.prototype;
292 prototype.__proto__ = superConstructor.prototype;
293 // Use a function for `true` here, as functions are stored in the
294 // hidden class and not as properties in the object.
295 prototype.constructor = constructor;
296 prototype[#operatorIsPrefix + constructor.name] = constructor;
297 return convertToFastObject(prototype);
298 } :
299 function() {
300 function tmp() {}
301 return function (constructor, superConstructor) {
302 tmp.prototype = superConstructor.prototype;
303 var object = new tmp();
304 convertToSlowObject(object);
305 var properties = constructor.prototype;
306 var members = Object.keys(properties);
307 for (var i = 0; i < members.length; i++) {
308 var member = members[i];
309 object[member] = properties[member];
310 }
311 // Use a function for `true` here, as functions are stored in the
312 // hidden class and not as properties in the object.
313 object[#operatorIsPrefix + constructor.name] = constructor;
314 object.constructor = constructor;
315 constructor.prototype = object;
316 return object;
317 };
318 }();
319
320 if (#hasIncrementalSupport) {
321 #incrementalHelper.inheritFrom = inheritFrom;
322 }
323
324 // Class descriptions are collected in a JS object.
325 // 'finishClasses' takes all collected descriptions and sets up
326 // the prototype.
327 // Once set up, the constructors prototype field satisfy:
328 // - it contains all (local) members.
329 // - its internal prototype (__proto__) points to the superclass'
330 // prototype field.
331 // - the prototype's constructor field points to the JavaScript
332 // constructor.
333 // For engines where we have access to the '__proto__' we can manipulate
334 // the object literal directly. For other engines we have to create a new
335 // object and copy over the members.
336 function finishClasses(processedClasses) {
337 if (#debugFastObjects)
338 print("Number of classes: " +
339 Object.getOwnPropertyNames(processedClasses.collected).length);
340
341 var allClasses = #allClasses;
342
343 if (#inCspMode) {
344 var constructors = #precompiled(processedClasses.collected);
345 }
346
347 if (#notInCspMode) {
348 processedClasses.combinedConstructorFunction +=
349 "return [\\n" + processedClasses.constructorsList.join(",\\n ") +
350 "\\n]";
351 var constructors =
352 new Function("\$collectedClasses",
353 processedClasses.combinedConstructorFunction)
354 (processedClasses.collected);
355 processedClasses.combinedConstructorFunction = null;
356 }
357
358 for (var i = 0; i < constructors.length; i++) {
359 var constructor = constructors[i];
360 var cls = constructor.name;
361 var desc = processedClasses.collected[cls];
362 var globalObject = desc[0];
363 desc = desc[1];
364 if (#isTreeShakingDisabled)
365 constructor["${namer.metadataField}"] = desc;
366 allClasses[cls] = constructor;
367 globalObject[cls] = constructor;
368 }
369 constructors = null;
370
371 var finishedClasses = #finishedClassesAccess;
372
373 function finishClass(cls) {
374
375 if (finishedClasses[cls]) return;
376 finishedClasses[cls] = true;
377
378 var superclass = processedClasses.pending[cls];
379
380 if (#needsMixinSupport) {
381 if (superclass && superclass.indexOf("+") > 0) {
382 var s = superclass.split("+");
383 superclass = s[0];
384 var mixinClass = s[1];
385 finishClass(mixinClass);
386 var mixin = allClasses[mixinClass];
387 var mixinPrototype = mixin.prototype;
388 var clsPrototype = allClasses[cls].prototype;
389
390 var properties = Object.keys(mixinPrototype);
391 for (var i = 0; i < properties.length; i++) {
392 var d = properties[i];
393 if (!hasOwnProperty.call(clsPrototype, d))
394 clsPrototype[d] = mixinPrototype[d];
395 }
396 }
397 }
398
399 // The superclass is only false (empty string) for the Dart Object
400 // class. The minifier together with noSuchMethod can put methods on
401 // the Object.prototype object, and they show through here, so we check
402 // that we have a string.
403 if (!superclass || typeof superclass != "string") {
404 // Inlined special case of InheritFrom here for performance reasons.
405 // Fix up the the Dart Object class' prototype.
406 var constructor = allClasses[cls];
407 var prototype = constructor.prototype;
408 prototype.constructor = constructor;
409 prototype.#isObject = constructor;
410 prototype.#deferredAction = function() {};
411 return;
412 }
413 finishClass(superclass);
414 var superConstructor = allClasses[superclass];
415
416 if (!superConstructor) {
417 superConstructor = existingIsolateProperties[superclass];
418 }
419
420 var constructor = allClasses[cls];
421 var prototype = inheritFrom(constructor, superConstructor);
422
423 if (#needsMixinSupport) {
424 if (mixinPrototype) {
425 prototype.#deferredAction
426 = mixinDeferredActionHelper(mixinPrototype, prototype);
427 }
428 }
429
430 if (#needsNativeSupport) {
431 if (Object.prototype.hasOwnProperty.call(prototype, #specProperty)) {
432 #nativeInfoHandler;
433 // As native classes can come into existence without a constructor
434 // call, we have to ensure that the class has been fully
435 // initialized.
436 prototype.#deferredAction();
437 }
438 }
439 // Interceptors (or rather their prototypes) are also used without
440 // first instantiating them first.
441 if (prototype.#isInterceptorClass) {
442 prototype.#deferredAction();
443 }
444 }
445
446 #trivialNsmHandlers;
447
448 var properties = Object.keys(processedClasses.pending);
449 for (var i = 0; i < properties.length; i++) finishClass(properties[i]);
450 }
451
452 // Generic handler for deferred class setup. The handler updates the
453 // prototype that it is installed on (it traverses the prototype chain
454 // of [this] to find itself) and then removes itself. It recurses by
455 // calling deferred handling again, which terminates on Object due to
456 // the final handler.
457 function finishAddStubsHelper() {
458 var prototype = this;
459 // Find the actual prototype that this handler is installed on.
460 while (!prototype.hasOwnProperty(#deferredActionString)) {
461 prototype = prototype.__proto__;
462 }
463 delete prototype.#deferredAction; // Intended to make it slow, too.
464 var properties = Object.keys(prototype);
465 for (var index = 0; index < properties.length; index++) {
466 var property = properties[index];
467 var firstChar = property.charCodeAt(0);
468 var elem;
469 // We have to filter out some special properties that are used for
470 // metadata in descriptors. Currently, we filter everything that
471 // starts with + or *. This has to stay in sync with the special
472 // properties that are used by processClassData below.
473 if (property !== "${namer.classDescriptorProperty}" &&
474 property !== "$reflectableField" &&
475 firstChar !== 43 && // 43 is aka "+".
476 firstChar !== 42 && // 42 is aka "*"
477 (elem = prototype[property]) != null &&
478 elem.constructor === Array &&
479 property !== "<>") {
480 addStubs(prototype, elem, property, false, []);
481 }
482 }
483 convertToFastObject(prototype);
484 prototype = prototype.__proto__;
485 // Call other handlers.
486 prototype.#deferredAction();
487 }
488
489 if (#needsMixinSupport) {
490 // Returns a deferred class setup handler that first invokes the
491 // handler on [mixinPrototype] and then resumes handling on
492 // [targetPrototype]. If [targetPrototype] already has a handler
493 // installed, the handler is preserved in the generated closure and
494 // thus can be safely overwritten.
495 function mixinDeferredActionHelper(mixinPrototype, targetPrototype) {
496 var chain;
497 if (targetPrototype.hasOwnProperty(#deferredActionString)) {
498 chain = targetPrototype.#deferredAction;
499 }
500 return function foo() {
501 var prototype = this;
502 // Find the actual prototype that this handler is installed on.
503 while (!prototype.hasOwnProperty(#deferredActionString)) {
504 prototype = prototype.__proto__;
505 }
506 if (chain) {
507 prototype.#deferredAction = chain;
508 } else {
509 delete prototype.#deferredAction;
510 convertToFastObject(prototype);
511 }
512 mixinPrototype.#deferredAction();
513 prototype.#deferredAction();
514 }
515 }
516 }
517
518 function processClassData(cls, descriptor, processedClasses) {
519 descriptor = convertToSlowObject(descriptor); // Use a slow object.
520 var previousProperty;
521 var properties = Object.keys(descriptor);
522 var hasDeferredWork = false;
523 var shouldDeferWork =
524 supportsDirectProtoAccess && cls != #objectClassName;
525 for (var i = 0; i < properties.length; i++) {
526 var property = properties[i];
527 var firstChar = property.charCodeAt(0);
528 if (property === "static") {
529 processStatics(#statics[cls] = descriptor.static,
530 processedClasses);
531 delete descriptor.static;
532 } else if (firstChar === 43) { // 43 is "+".
533 mangledNames[previousProperty] = property.substring(1);
534 var flag = descriptor[property];
535 if (flag > 0)
536 descriptor[previousProperty].$reflectableField = flag;
537 } else if (firstChar === 42) { // 42 is "*"
538 descriptor[previousProperty].$defaultValuesField =
539 descriptor[property];
540 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
541 if (!optionalMethods) {
542 descriptor.$methodsWithOptionalArgumentsField = optionalMethods={}
543 }
544 optionalMethods[property] = previousProperty;
545 } else {
546 var elem = descriptor[property];
547 if (property !== "${namer.classDescriptorProperty}" &&
548 elem != null &&
549 elem.constructor === Array &&
550 property !== "<>") {
551 if (shouldDeferWork) {
552 hasDeferredWork = true;
553 } else {
554 addStubs(descriptor, elem, property, false, []);
555 }
556 } else {
557 previousProperty = property;
558 }
559 }
560 }
561
562 if (hasDeferredWork)
563 descriptor.#deferredAction = finishAddStubsHelper;
564
565 /* The 'fields' are either a constructor function or a
566 * string encoding fields, constructor and superclass. Gets the
567 * superclass and fields in the format
568 * 'Super;field1,field2'
569 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor.
570 */
571 var classData = descriptor["${namer.classDescriptorProperty}"],
572 split, supr, fields = classData;
573
574 if (#hasRetainedMetadata)
575 if (typeof classData == "object" &&
576 classData instanceof Array) {
577 classData = fields = classData[0];
578 }
579 // ${ClassBuilder.fieldEncodingDescription}.
580 var s = fields.split(";");
581 fields = s[1] ? s[1].split(",") : [];
582 supr = s[0];
583 // ${ClassBuilder.functionTypeEncodingDescription}.
584 split = supr.split(":");
585 if (split.length == 2) {
586 supr = split[0];
587 var functionSignature = split[1];
588 if (functionSignature)
589 descriptor.${namer.operatorSignature} = function(s) {
590 return function() {
591 return #types[s];
592 };
593 }(functionSignature);
594 }
595
596 if (supr) processedClasses.pending[cls] = supr;
597 if (#notInCspMode) {
598 processedClasses.combinedConstructorFunction +=
599 defineClass(cls, fields);
600 processedClasses.constructorsList.push(cls);
601 }
602 processedClasses.collected[cls] = [globalObject, descriptor];
603 classes.push(cls);
604 }
605 }
606
607 function processStatics(descriptor, processedClasses) {
608 var properties = Object.keys(descriptor);
609 for (var i = 0; i < properties.length; i++) {
610 var property = properties[i];
611 if (property === "${namer.classDescriptorProperty}") continue;
612 var element = descriptor[property];
613 var firstChar = property.charCodeAt(0);
614 var previousProperty;
615 if (firstChar === 43) { // 43 is "+".
616 mangledGlobalNames[previousProperty] = property.substring(1);
617 var flag = descriptor[property];
618 if (flag > 0)
619 descriptor[previousProperty].$reflectableField = flag;
620 if (element && element.length)
621 #typeInformation[previousProperty] = element;
622 } else if (firstChar === 42) { // 42 is "*"
623 globalObject[previousProperty].$defaultValuesField = element;
624 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
625 if (!optionalMethods) {
626 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {}
627 }
628 optionalMethods[property] = previousProperty;
629 } else if (typeof element === "function") {
630 globalObject[previousProperty = property] = element;
631 functions.push(property);
632 #globalFunctions[property] = element;
633 } else if (element.constructor === Array) {
634 if (#needsStructuredMemberInfo) {
635 addStubs(globalObject, element, property, true, functions);
636 }
637 } else {
638 // We will not enter this case if no classes are defined.
639 if (#needsClassSupport) {
640 previousProperty = property;
641 processClassData(property, element, processedClasses);
642 }
643 }
644 }
645 }
646
647 if (#needsStructuredMemberInfo) {
648
649 // See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of
650 // [array].
651
652 // Processes the stub declaration given by [array] and stores the results
653 // in the corresponding [prototype]. [name] is the property name in
654 // [prototype] that the stub declaration belongs to.
655 // If [isStatic] is true, the property being processed belongs to a static
656 // function and thus is stored as a global. In that case we also add all
657 // generated functions to the [functions] array, which is used by the
658 // mirrors system to enumerate all static functions of a library. For
659 // non-static functions we might still add some functions to [functions] but
660 // the information is thrown away at the call site. This is to avoid
661 // conditionals.
662 function addStubs(prototype, array, name, isStatic, functions) {
663 var index = $FUNCTION_INDEX, alias = array[index], f;
664 if (typeof alias == "string") {
665 f = array[++index];
666 } else {
667 f = alias;
668 alias = name;
669 }
670 var funcs = [prototype[name] = prototype[alias] = f];
671 f.\$stubName = name;
672 functions.push(name);
673 for (index++; index < array.length; index++) {
674 f = array[index];
675 if (typeof f != "function") break;
676 if (!isStatic) {
677 f.\$stubName = ${readString("array", "++index")};
678 }
679 funcs.push(f);
680 if (f.\$stubName) {
681 prototype[f.\$stubName] = f;
682 functions.push(f.\$stubName);
683 }
684 }
685
686 for (var i = 0; i < funcs.length; index++, i++) {
687 funcs[i].\$callName = ${readString("array", "index")};
688 }
689 var getterStubName = ${readString("array", "index")};
690 array = array.slice(++index);
691 var requiredParameterInfo = ${readInt("array", "0")};
692 var requiredParameterCount = requiredParameterInfo >> 1;
693 var isAccessor = (requiredParameterInfo & 1) === 1;
694 var isSetter = requiredParameterInfo === 3;
695 var isGetter = requiredParameterInfo === 1;
696 var optionalParameterInfo = ${readInt("array", "1")};
697 var optionalParameterCount = optionalParameterInfo >> 1;
698 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1;
699 var isIntercepted =
700 requiredParameterCount + optionalParameterCount != funcs[0].length;
701 var functionTypeIndex = ${readFunctionType("array", "2")};
702 if (typeof functionTypeIndex == "number")
703 ${readFunctionType("array", "2")} = functionTypeIndex + typesOffset;
704 var unmangledNameIndex = $unmangledNameIndex;
705
706 if (getterStubName) {
707 f = tearOff(funcs, array, isStatic, name, isIntercepted);
708 prototype[name].\$getter = f;
709 f.\$getterStub = true;
710 // Used to create an isolate using spawnFunction.
711 if (isStatic) {
712 #globalFunctions[name] = f;
713 functions.push(getterStubName);
714 }
715 prototype[getterStubName] = f;
716 funcs.push(f);
717 f.\$stubName = getterStubName;
718 f.\$callName = null;
719 // Update the interceptedNames map (which only exists if `invokeOn` was
720 // enabled).
721 if (#enabledInvokeOn)
722 if (isIntercepted) #interceptedNames[getterStubName] = 1;
723 }
724
725 if (#usesMangledNames) {
726 var isReflectable = array.length > unmangledNameIndex;
727 if (isReflectable) {
728 funcs[0].$reflectableField = 1;
729 funcs[0].$reflectionInfoField = array;
730 for (var i = 1; i < funcs.length; i++) {
731 funcs[i].$reflectableField = 2;
732 funcs[i].$reflectionInfoField = array;
733 }
734 var mangledNames = isStatic ? #mangledGlobalNames : #mangledNames;
735 var unmangledName = ${readString("array", "unmangledNameIndex")};
736 // The function is either a getter, a setter, or a method.
737 // If it is a method, it might also have a tear-off closure.
738 // The unmangledName is the same as the getter-name.
739 var reflectionName = unmangledName;
740 if (getterStubName) mangledNames[getterStubName] = reflectionName;
741 if (isSetter) {
742 reflectionName += "=";
743 } else if (!isGetter) {
744 reflectionName += ":" +
745 (requiredParameterCount + optionalParameterCount);
746 }
747 mangledNames[name] = reflectionName;
748 funcs[0].$reflectionNameField = reflectionName;
749 funcs[0].$metadataIndexField = unmangledNameIndex + 1;
750 if (optionalParameterCount) prototype[unmangledName + "*"] = funcs[0];
751 }
752 }
753 }
754
755 #tearOffCode;
756 }
757
758 if (#hasIncrementalSupport) {
759 #incrementalHelper.addStubs = addStubs;
760 }
761
762 var functionCounter = 0;
763 if (!#libraries) #libraries = [];
764 if (!#mangledNames) #mangledNames = map();
765 if (!#mangledGlobalNames) #mangledGlobalNames = map();
766 if (!#statics) #statics = map();
767 if (!#typeInformation) #typeInformation = map();
768 if (!#globalFunctions) #globalFunctions = map();
769 if (#enabledInvokeOn)
770 if (!#interceptedNames) #interceptedNames = #interceptedNamesSet;
771 var libraries = #libraries;
772 var mangledNames = #mangledNames;
773 var mangledGlobalNames = #mangledGlobalNames;
774 var hasOwnProperty = Object.prototype.hasOwnProperty;
775 var length = programData.length;
776 var processedClasses = map();
777 processedClasses.collected = map();
778 processedClasses.pending = map();
779 if (#notInCspMode) {
780 processedClasses.constructorsList = [];
781 // For every class processed [processedClasses.combinedConstructorFunction]
782 // will be updated with the corresponding constructor function.
783 processedClasses.combinedConstructorFunction =
784 "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+
785 "var \$desc;\\n";
786 }
787 for (var i = 0; i < length; i++) {
788 var data = programData[i];
789
790 // [data] contains these elements:
791 // 0. The library name (not unique).
792 // 1. The library URI (unique).
793 // 2. A function returning the metadata associated with this library.
794 // 3. The global object to use for this library.
795 // 4. An object literal listing the members of the library.
796 // 5. This element is optional and if present it is true and signals that this
797 // library is the root library (see dart:mirrors IsolateMirror.rootLibrary).
798 //
799 // The entries of [data] are built in [assembleProgram] above.
800
801 var name = data[0];
802 var uri = data[1];
803 var metadata = data[2];
804 var globalObject = data[3];
805 var descriptor = data[4];
806 var isRoot = !!data[5];
807 var fields = descriptor && descriptor["${namer.classDescriptorProperty}"];
808 if (fields instanceof Array) fields = fields[0];
809 var classes = [];
810 var functions = [];
811 processStatics(descriptor, processedClasses);
812 libraries.push([name, uri, classes, functions, metadata, fields, isRoot,
813 globalObject]);
814 }
815 if (#needsClassSupport) finishClasses(processedClasses);
816 }''';
817
818 // TODO(zarah): Remove empty else branches in output when if(#hole) is false.
819 return js.statement(skeleton, holes);
820 }
821
822 String readString(String array, String index) {
823 return readChecked(
824 array, index, 'result != null && typeof result != "string"', 'string');
825 }
826
827 String readInt(String array, String index) {
828 return readChecked(
829 array, index,
830 'result != null && (typeof result != "number" || (result|0) !== result)',
831 'int');
832 }
833
834 String readFunctionType(String array, String index) {
835 return readChecked(
836 array, index,
837 'result != null && '
838 '(typeof result != "number" || (result|0) !== result) && '
839 'typeof result != "function"',
840 'function or int');
841 }
842
843 String readChecked(String array, String index, String check, String type) {
844 if (!VALIDATE_DATA) return '$array[$index]';
845 return '''
846 (function() {
847 var result = $array[$index];
848 if ($check) {
849 throw new Error(
850 name + ": expected value of type \'$type\' at index " + ($index) +
851 " but got " + (typeof result));
852 }
853 return result;
854 })()''';
855 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/nsm_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