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

Side by Side Diff: lib/compiler/implementation/emitter.dart

Issue 10052020: Reduce size by emitting $.foo instead of Isolate.prototype.foo. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove another Isolate.prototype. Created 8 years, 8 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
« no previous file with comments | « no previous file | lib/compiler/implementation/namer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 /** 5 /**
6 * A function element that represents a closure call. The signature is copied 6 * A function element that represents a closure call. The signature is copied
7 * from the given element. 7 * from the given element.
8 */ 8 */
9 class ClosureInvocationElement extends FunctionElement { 9 class ClosureInvocationElement extends FunctionElement {
10 ClosureInvocationElement(SourceString name, 10 ClosureInvocationElement(SourceString name,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 : namer = compiler.namer, 43 : namer = compiler.namer,
44 nativeEmitter = new NativeEmitter(compiler), 44 nativeEmitter = new NativeEmitter(compiler),
45 generatedClasses = new Set<ClassElement>(), 45 generatedClasses = new Set<ClassElement>(),
46 mainBuffer = new StringBuffer(), 46 mainBuffer = new StringBuffer(),
47 super(compiler); 47 super(compiler);
48 48
49 String get name() => 'CodeEmitter'; 49 String get name() => 'CodeEmitter';
50 50
51 String get inheritsName() => '${namer.ISOLATE}.\$inherits'; 51 String get inheritsName() => '${namer.ISOLATE}.\$inherits';
52 52
53 String get objectClassName() {
54 ClassElement objectClass =
55 compiler.coreLibrary.find(const SourceString('Object'));
56 return namer.isolatePropertyAccess(objectClass);
57 }
58
59 void addInheritFunctionIfNecessary() { 53 void addInheritFunctionIfNecessary() {
60 if (addedInheritFunction) return; 54 if (addedInheritFunction) return;
61 addedInheritFunction = true; 55 addedInheritFunction = true;
62 mainBuffer.add('$inheritsName = '); 56 mainBuffer.add('$inheritsName = ');
63 mainBuffer.add(INHERIT_FUNCTION); 57 mainBuffer.add(INHERIT_FUNCTION);
64 mainBuffer.add(';\n'); 58 mainBuffer.add(';\n');
65 } 59 }
66 60
67 void addParameterStub(FunctionElement member, 61 void addParameterStub(FunctionElement member,
68 String attachTo(String invocationName), 62 String attachTo(String invocationName),
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 FunctionParameters parameters = member.computeParameters(compiler); 172 FunctionParameters parameters = member.computeParameters(compiler);
179 for (Selector selector in selectors) { 173 for (Selector selector in selectors) {
180 if (!selector.applies(parameters)) continue; 174 if (!selector.applies(parameters)) continue;
181 addParameterStub(member, attachTo, buffer, selector, isNative); 175 addParameterStub(member, attachTo, buffer, selector, isNative);
182 } 176 }
183 } 177 }
184 178
185 void addInstanceMember(Element member, 179 void addInstanceMember(Element member,
186 String attachTo(String name), 180 String attachTo(String name),
187 StringBuffer buffer, 181 StringBuffer buffer,
182 String isolatePrototype,
188 [bool isNative = false]) { 183 [bool isNative = false]) {
189 // TODO(floitsch): we don't need to deal with members of 184 // TODO(floitsch): we don't need to deal with members of
190 // uninstantiated classes, that have been overwritten by subclasses. 185 // uninstantiated classes, that have been overwritten by subclasses.
191 186
192 if (member.kind === ElementKind.FUNCTION 187 if (member.kind === ElementKind.FUNCTION
193 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY 188 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY
194 || member.kind === ElementKind.GETTER 189 || member.kind === ElementKind.GETTER
195 || member.kind === ElementKind.SETTER) { 190 || member.kind === ElementKind.SETTER) {
196 if (member.modifiers !== null && member.modifiers.isAbstract()) return; 191 if (member.modifiers !== null && member.modifiers.isAbstract()) return;
197 String codeBlock = compiler.universe.generatedCode[member]; 192 String codeBlock = compiler.universe.generatedCode[member];
(...skipping 24 matching lines...) Expand all
222 String getterName = namer.getterName(member.getLibrary(), member.name); 217 String getterName = namer.getterName(member.getLibrary(), member.name);
223 String name = 218 String name =
224 isNative ? member.name.slowToString() : namer.getName(member); 219 isNative ? member.name.slowToString() : namer.getName(member);
225 buffer.add('${attachTo(getterName)} = function(){\n'); 220 buffer.add('${attachTo(getterName)} = function(){\n');
226 buffer.add(' return this.$name;\n};\n'); 221 buffer.add(' return this.$name;\n};\n');
227 } 222 }
228 } else { 223 } else {
229 compiler.internalError('unexpected kind: "${member.kind}"', 224 compiler.internalError('unexpected kind: "${member.kind}"',
230 element: member); 225 element: member);
231 } 226 }
232 emitExtraAccessors(member, attachTo, buffer); 227 emitExtraAccessors(member, attachTo, buffer, isolatePrototype);
233 } 228 }
234 229
235 bool generateFieldInits(ClassElement classElement, 230 bool generateFieldInits(ClassElement classElement,
236 StringBuffer argumentsBuffer, 231 StringBuffer argumentsBuffer,
237 StringBuffer bodyBuffer) { 232 StringBuffer bodyBuffer) {
238 bool isFirst = true; 233 bool isFirst = true;
239 void generateFieldInit(ClassElement enclosingClass, Element member) { 234 void generateFieldInit(ClassElement enclosingClass, Element member) {
240 // TODO(floitsch): make sure there are no name clashes. 235 // TODO(floitsch): make sure there are no name clashes.
241 String className = namer.getName(enclosingClass); 236 String className = namer.getName(enclosingClass);
242 if (!isFirst) argumentsBuffer.add(', '); 237 if (!isFirst) argumentsBuffer.add(', ');
243 isFirst = false; 238 isFirst = false;
244 String memberName = namer.instanceFieldName(member.getLibrary(), 239 String memberName = namer.instanceFieldName(member.getLibrary(),
245 member.name); 240 member.name);
246 argumentsBuffer.add('${className}_$memberName'); 241 argumentsBuffer.add('${className}_$memberName');
247 bodyBuffer.add(' this.$memberName = ${className}_$memberName;\n'); 242 bodyBuffer.add(' this.$memberName = ${className}_$memberName;\n');
248 } 243 }
249 244
250 classElement.forEachInstanceField(generateFieldInit, 245 classElement.forEachInstanceField(generateFieldInit,
251 includeBackendMembers: true, 246 includeBackendMembers: true,
252 includeSuperMembers: true); 247 includeSuperMembers: true);
253 } 248 }
254 249
255 void emitInherits(ClassElement cls, StringBuffer buffer) { 250 void emitInherits(ClassElement cls,
251 StringBuffer buffer,
252 String isolatePrototype) {
256 ClassElement superclass = cls.superclass; 253 ClassElement superclass = cls.superclass;
257 if (superclass !== null) { 254 if (superclass !== null) {
258 addInheritFunctionIfNecessary(); 255 addInheritFunctionIfNecessary();
259 String className = namer.isolatePropertyAccess(cls); 256 String className = namer.getName(cls);
260 String superName = namer.isolatePropertyAccess(superclass); 257 String superName = namer.getName(superclass);
261 buffer.add('${inheritsName}($className, $superName);\n'); 258 buffer.add('${inheritsName}($isolatePrototype.$className, ');
259 buffer.add('$isolatePrototype.$superName);\n');
262 } 260 }
263 } 261 }
264 262
265 void ensureGenerated(ClassElement classElement, StringBuffer buffer) { 263 void ensureGenerated(ClassElement classElement,
264 StringBuffer buffer,
265 String isolatePrototype) {
266 if (classElement == null) return; 266 if (classElement == null) return;
267 if (generatedClasses.contains(classElement)) return; 267 if (generatedClasses.contains(classElement)) return;
268 generatedClasses.add(classElement); 268 generatedClasses.add(classElement);
269 generateClass(classElement, buffer); 269 generateClass(classElement, buffer, isolatePrototype);
270 } 270 }
271 271
272 void generateClass(ClassElement classElement, StringBuffer buffer) { 272 void generateClass(ClassElement classElement,
273 ensureGenerated(classElement.superclass, buffer); 273 StringBuffer buffer,
274 String isolatePrototype) {
275 ensureGenerated(classElement.superclass, buffer, isolatePrototype);
274 276
275 if (classElement.isNative()) { 277 if (classElement.isNative()) {
276 nativeEmitter.generateNativeClass(classElement); 278 nativeEmitter.generateNativeClass(classElement);
277 return; 279 return;
278 } else { 280 } else {
279 // TODO(ngeoffray): Instead of switching between buffer, we 281 // TODO(ngeoffray): Instead of switching between buffer, we
280 // should create code sections, and decide where to emit them at 282 // should create code sections, and decide where to emit them at
281 // the end. 283 // the end.
282 buffer = mainBuffer; 284 buffer = mainBuffer;
283 } 285 }
284 286
285 String className = namer.isolatePropertyAccess(classElement); 287 String className = '${isolatePrototype}.${namer.getName(classElement)}';
286 String constructorName = namer.safeName(classElement.name.slowToString()); 288 String constructorName = namer.safeName(classElement.name.slowToString());
287 buffer.add('$className = function $constructorName('); 289 buffer.add('$className = function $constructorName(');
288 StringBuffer bodyBuffer = new StringBuffer(); 290 StringBuffer bodyBuffer = new StringBuffer();
289 // If the class is never instantiated we still need to set it up for 291 // If the class is never instantiated we still need to set it up for
290 // inheritance purposes, but we can leave its JavaScript constructor empty. 292 // inheritance purposes, but we can leave its JavaScript constructor empty.
291 if (compiler.universe.instantiatedClasses.contains(classElement)) { 293 if (compiler.universe.instantiatedClasses.contains(classElement)) {
292 generateFieldInits(classElement, buffer, bodyBuffer); 294 generateFieldInits(classElement, buffer, bodyBuffer);
293 } 295 }
294 buffer.add(') {\n'); 296 buffer.add(') {\n');
295 buffer.add(bodyBuffer); 297 buffer.add(bodyBuffer);
296 buffer.add('};\n'); 298 buffer.add('};\n');
297 299
298 emitInherits(classElement, buffer); 300 emitInherits(classElement, buffer, isolatePrototype);
299 301
300 String attachTo(String name) => '$className.prototype.$name'; 302 String attachTo(String name) => '$className.prototype.$name';
301 303
302 classElement.forEachMember(includeBackendMembers: true, 304 classElement.forEachMember(includeBackendMembers: true,
303 f: (ClassElement enclosing, Element member) { 305 f: (ClassElement enclosing, Element member) {
304 if (member.isInstanceMember()) { 306 if (member.isInstanceMember()) {
305 addInstanceMember(member, attachTo, buffer); 307 addInstanceMember(member, attachTo, buffer, isolatePrototype);
306 } 308 }
307 }); 309 });
308 310
309 generateTypeTests(classElement, (Element other) { 311 generateTypeTests(classElement, (Element other) {
310 buffer.add('${attachTo(namer.operatorIs(other))} = '); 312 buffer.add('${attachTo(namer.operatorIs(other))} = ');
311 if (nativeEmitter.requiresNativeIsCheck(other)) { 313 if (nativeEmitter.requiresNativeIsCheck(other)) {
312 buffer.add('function() { return true; }'); 314 buffer.add('function() { return true; }');
313 } else { 315 } else {
314 buffer.add('true'); 316 buffer.add('true');
315 } 317 }
316 buffer.add(';\n'); 318 buffer.add(';\n');
317 }); 319 });
318 320
319 if (classElement === compiler.objectClass && compiler.enabledNoSuchMethod) { 321 if (classElement === compiler.objectClass && compiler.enabledNoSuchMethod) {
320 // Emit the noSuchMethods on the Object prototype now, so that 322 // Emit the noSuchMethods on the Object prototype now, so that
321 // the code in the dynamicMethod can find them. Note that the 323 // the code in the dynamicMethod can find them. Note that the
322 // code in dynamicMethod is invoked before analyzing the full JS 324 // code in dynamicMethod is invoked before analyzing the full JS
323 // script. 325 // script.
324 emitNoSuchMethodCalls(buffer); 326 emitNoSuchMethodCalls(buffer, isolatePrototype);
325 } 327 }
326 } 328 }
327 329
328 void generateTypeTests(ClassElement cls, 330 void generateTypeTests(ClassElement cls,
329 void generateTypeTest(ClassElement element)) { 331 void generateTypeTest(ClassElement element)) {
330 if (compiler.universe.isChecks.contains(cls)) { 332 if (compiler.universe.isChecks.contains(cls)) {
331 generateTypeTest(cls); 333 generateTypeTest(cls);
332 } 334 }
333 generateInterfacesIsTests(cls, generateTypeTest, new Set<Element>()); 335 generateInterfacesIsTests(cls, generateTypeTest, new Set<Element>());
334 } 336 }
335 337
336 void generateInterfacesIsTests(ClassElement cls, 338 void generateInterfacesIsTests(ClassElement cls,
337 void generateTypeTest(ClassElement element), 339 void generateTypeTest(ClassElement element),
338 Set<Element> alreadyGenerated) { 340 Set<Element> alreadyGenerated) {
339 for (Type interfaceType in cls.interfaces) { 341 for (Type interfaceType in cls.interfaces) {
340 Element element = interfaceType.element; 342 Element element = interfaceType.element;
341 if (!alreadyGenerated.contains(element) && 343 if (!alreadyGenerated.contains(element) &&
342 compiler.universe.isChecks.contains(element)) { 344 compiler.universe.isChecks.contains(element)) {
343 alreadyGenerated.add(element); 345 alreadyGenerated.add(element);
344 generateTypeTest(element); 346 generateTypeTest(element);
345 } 347 }
346 generateInterfacesIsTests(element, generateTypeTest, alreadyGenerated); 348 generateInterfacesIsTests(element, generateTypeTest, alreadyGenerated);
347 } 349 }
348 } 350 }
349 351
350 void emitClasses(StringBuffer buffer) { 352 void emitClasses(StringBuffer buffer, String isolatePrototype) {
351 for (ClassElement element in compiler.universe.instantiatedClasses) { 353 for (ClassElement element in compiler.universe.instantiatedClasses) {
352 ensureGenerated(element, buffer); 354 ensureGenerated(element, buffer, isolatePrototype);
353 } 355 }
354 } 356 }
355 357
356 void emitStaticFunctionsWithNamer(StringBuffer buffer, 358 void emitStaticFunctionsWithNamer(StringBuffer buffer,
359 String isolatePrototype,
357 Map<Element, String> generatedCode, 360 Map<Element, String> generatedCode,
358 String functionNamer(Element element)) { 361 String functionNamer(Element element)) {
359 generatedCode.forEach((Element element, String codeBlock) { 362 generatedCode.forEach((Element element, String codeBlock) {
360 if (!element.isInstanceMember()) { 363 if (!element.isInstanceMember()) {
361 buffer.add('${functionNamer(element)} = '); 364 buffer.add(isolatePrototype);
365 buffer.add('.${functionNamer(element)} = ');
362 buffer.add(codeBlock); 366 buffer.add(codeBlock);
363 buffer.add(';\n\n'); 367 buffer.add(';\n\n');
364 } 368 }
365 }); 369 });
366 } 370 }
367 371
368 void emitStaticFunctions(StringBuffer buffer) { 372 void emitStaticFunctions(StringBuffer buffer, String isolatePrototype) {
369 emitStaticFunctionsWithNamer(buffer, 373 emitStaticFunctionsWithNamer(buffer,
374 isolatePrototype,
370 compiler.universe.generatedCode, 375 compiler.universe.generatedCode,
371 namer.isolatePropertyAccess); 376 namer.getName);
372 emitStaticFunctionsWithNamer(buffer, 377 emitStaticFunctionsWithNamer(buffer,
378 isolatePrototype,
373 compiler.universe.generatedBailoutCode, 379 compiler.universe.generatedBailoutCode,
374 namer.isolateBailoutPropertyAccess); 380 namer.getBailoutName);
375 } 381 }
376 382
377 void emitStaticFunctionGetters(StringBuffer buffer) { 383 void emitStaticFunctionGetters(StringBuffer buffer, String isolatePrototype) {
378 Set<FunctionElement> functionsNeedingGetter = 384 Set<FunctionElement> functionsNeedingGetter =
379 compiler.universe.staticFunctionsNeedingGetter; 385 compiler.universe.staticFunctionsNeedingGetter;
380 for (FunctionElement element in functionsNeedingGetter) { 386 for (FunctionElement element in functionsNeedingGetter) {
381 // The static function does not have the correct name. Since 387 // The static function does not have the correct name. Since
382 // [addParameterStubs] use the name to create its stubs we simply 388 // [addParameterStubs] use the name to create its stubs we simply
383 // create a fake element with the correct name. 389 // create a fake element with the correct name.
384 // Note: the callElement will not have any enclosingElement. 390 // Note: the callElement will not have any enclosingElement.
385 FunctionElement callElement = 391 FunctionElement callElement =
386 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); 392 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element);
387 String staticName = namer.isolatePropertyAccess(element); 393 String staticName = namer.getName(element);
388 int parameterCount = element.parameterCount(compiler); 394 int parameterCount = element.parameterCount(compiler);
389 String invocationName = 395 String invocationName =
390 namer.instanceMethodName(element.getLibrary(), callElement.name, 396 namer.instanceMethodName(element.getLibrary(), callElement.name,
391 parameterCount); 397 parameterCount);
392 buffer.add("$staticName.$invocationName = $staticName;\n"); 398 buffer.add(isolatePrototype);
393 addParameterStubs(callElement, (name) => '$staticName.$name', buffer); 399 buffer.add(".$staticName.$invocationName = ");
400 buffer.add(isolatePrototype);
401 buffer.add(".$staticName;\n");
402 addParameterStubs(callElement,
403 (name) => '$isolatePrototype.$staticName.$name',
404 buffer);
394 } 405 }
395 } 406 }
396 407
397 void emitDynamicFunctionGetter(StringBuffer buffer, 408 void emitDynamicFunctionGetter(StringBuffer buffer,
409 String isolatePrototype,
398 String attachTo(String invocationName), 410 String attachTo(String invocationName),
399 FunctionElement member) { 411 FunctionElement member) {
400 // For every method that has the same name as a property-get we create a 412 // For every method that has the same name as a property-get we create a
401 // getter that returns a bound closure. Say we have a class 'A' with method 413 // getter that returns a bound closure. Say we have a class 'A' with method
402 // 'foo' and somewhere in the code there is a dynamic property get of 414 // 'foo' and somewhere in the code there is a dynamic property get of
403 // 'foo'. Then we generate the following code (in pseudo Dart): 415 // 'foo'. Then we generate the following code (in pseudo Dart):
404 // 416 //
405 // class A { 417 // class A {
406 // foo(x, y, z) { ... } // Original function. 418 // foo(x, y, z) { ... } // Original function.
407 // get foo() { return new BoundClosure499(this); } 419 // get foo() { return new BoundClosure499(this); }
408 // } 420 // }
409 // class BoundClosure499 extends Closure { 421 // class BoundClosure499 extends Closure {
410 // var self; 422 // var self;
411 // BoundClosure499(this.self); 423 // BoundClosure499(this.self);
412 // $call3(x, y, z) { return self.foo(x, y, z); } 424 // $call3(x, y, z) { return self.foo(x, y, z); }
413 // } 425 // }
414 426
415 // TODO(floitsch): share the closure classes with other classes 427 // TODO(floitsch): share the closure classes with other classes
416 // if they share methods with the same signature. 428 // if they share methods with the same signature.
417 429
418 // The closure class. 430 // The closure class.
419 SourceString name = const SourceString("BoundClosure"); 431 SourceString name = const SourceString("BoundClosure");
420 ClassElement closureClassElement = 432 ClassElement closureClassElement =
421 new ClosureClassElement(compiler, member.getCompilationUnit()); 433 new ClosureClassElement(compiler, member.getCompilationUnit());
422 String isolateAccess = namer.isolatePropertyAccess(closureClassElement); 434 String mangledName = namer.getName(closureClassElement);
423 ensureGenerated(closureClassElement.superclass, buffer); 435 ensureGenerated(closureClassElement.superclass, buffer, isolatePrototype);
424 436
425 // Define the constructor with a name so that Object.toString can 437 // Define the constructor with a name so that Object.toString can
426 // find the class name of the closure class. 438 // find the class name of the closure class.
427 buffer.add("$isolateAccess = function $name(self) "); 439 buffer.add(isolatePrototype);
Lasse Reichstein Nielsen 2012/04/12 09:45:32 We should add an "<<" operator to StringBuffer :)
floitsch 2012/04/12 11:26:56 hehe.
440 buffer.add(".$mangledName = function $name(self) ");
428 buffer.add("{ this.self = self; };\n"); 441 buffer.add("{ this.self = self; };\n");
429 emitInherits(closureClassElement, buffer); 442 emitInherits(closureClassElement, buffer, isolatePrototype);
430 443
431 String prototype = "$isolateAccess.prototype"; 444 String prototype = "$isolatePrototype.$mangledName.prototype";
432 445
433 // Now add the methods on the closure class. The instance method does not 446 // Now add the methods on the closure class. The instance method does not
434 // have the correct name. Since [addParameterStubs] use the name to create 447 // have the correct name. Since [addParameterStubs] use the name to create
435 // its stubs we simply create a fake element with the correct name. 448 // its stubs we simply create a fake element with the correct name.
436 // Note: the callElement will not have any enclosingElement. 449 // Note: the callElement will not have any enclosingElement.
437 FunctionElement callElement = 450 FunctionElement callElement =
438 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); 451 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member);
439 452
440 int parameterCount = member.parameterCount(compiler); 453 int parameterCount = member.parameterCount(compiler);
441 String invocationName = 454 String invocationName =
442 namer.instanceMethodName(member.getLibrary(), 455 namer.instanceMethodName(member.getLibrary(),
443 callElement.name, parameterCount); 456 callElement.name, parameterCount);
444 String targetName = namer.instanceMethodName(member.getLibrary(), 457 String targetName = namer.instanceMethodName(member.getLibrary(),
445 member.name, parameterCount); 458 member.name, parameterCount);
446 List<String> arguments = new List<String>(parameterCount); 459 List<String> arguments = new List<String>(parameterCount);
447 for (int i = 0; i < parameterCount; i++) { 460 for (int i = 0; i < parameterCount; i++) {
448 arguments[i] = "arg$i"; 461 arguments[i] = "arg$i";
449 } 462 }
450 String joinedArgs = Strings.join(arguments, ", "); 463 String joinedArgs = Strings.join(arguments, ", ");
451 buffer.add("$prototype.$invocationName = function($joinedArgs) {\n"); 464 buffer.add("$prototype.$invocationName = function($joinedArgs) {\n");
452 buffer.add(" return this.self.$targetName($joinedArgs);\n"); 465 buffer.add(" return this.self.$targetName($joinedArgs);\n");
453 buffer.add("};\n"); 466 buffer.add("};\n");
454 addParameterStubs(callElement, 467 addParameterStubs(callElement,
455 (invocationName) => '$prototype.$invocationName', 468 (stubName) => '$prototype.$stubName',
456 buffer); 469 buffer);
457 470
458 // And finally the getter. 471 // And finally the getter.
459 String getterName = namer.getterName(member.getLibrary(), member.name); 472 String getterName = namer.getterName(member.getLibrary(), member.name);
460 String closureClass = namer.isolateAccess(closureClassElement); 473 String closureClass = namer.isolateAccess(closureClassElement);
461 buffer.add("${attachTo(getterName)} = function() {\n"); 474 buffer.add("${attachTo(getterName)} = function() {\n");
462 buffer.add(" return new $closureClass(this);\n"); 475 buffer.add(" return new $closureClass(this);\n");
463 buffer.add("};\n"); 476 buffer.add("};\n");
464 } 477 }
465 478
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 if (!staticNonFinalFields.isEmpty()) buffer.add('\n'); 519 if (!staticNonFinalFields.isEmpty()) buffer.add('\n');
507 for (Element element in staticNonFinalFields) { 520 for (Element element in staticNonFinalFields) {
508 buffer.add(' this.${namer.getName(element)} = '); 521 buffer.add(' this.${namer.getName(element)} = ');
509 compiler.withCurrentElement(element, () { 522 compiler.withCurrentElement(element, () {
510 handler.writeJsCodeForVariable(buffer, element); 523 handler.writeJsCodeForVariable(buffer, element);
511 }); 524 });
512 buffer.add(';\n'); 525 buffer.add(';\n');
513 } 526 }
514 } 527 }
515 528
516 void emitCompileTimeConstants(StringBuffer buffer) { 529 void emitCompileTimeConstants(StringBuffer buffer, String isolatePrototype) {
517 ConstantHandler handler = compiler.constantHandler; 530 ConstantHandler handler = compiler.constantHandler;
518 List<Constant> constants = handler.getConstantsForEmission(); 531 List<Constant> constants = handler.getConstantsForEmission();
519 String prototype = "${namer.ISOLATE}.prototype";
520 bool addedMakeConstantList = false; 532 bool addedMakeConstantList = false;
521 for (Constant constant in constants) { 533 for (Constant constant in constants) {
522 if (!addedMakeConstantList && constant.isList()) { 534 if (!addedMakeConstantList && constant.isList()) {
523 addedMakeConstantList = true; 535 addedMakeConstantList = true;
524 emitMakeConstantList(prototype, buffer); 536 emitMakeConstantList(buffer, isolatePrototype);
525 } 537 }
526 String name = handler.getNameForConstant(constant); 538 String name = handler.getNameForConstant(constant);
527 buffer.add('$prototype.$name = '); 539 buffer.add('$isolatePrototype.$name = ');
528 handler.writeJsCode(buffer, constant); 540 handler.writeJsCode(buffer, constant);
529 buffer.add(';\n'); 541 buffer.add(';\n');
530 } 542 }
531 } 543 }
532 544
533 void emitMakeConstantList(String prototype, StringBuffer buffer) { 545 void emitMakeConstantList(StringBuffer buffer, String isolatePrototype) {
534 buffer.add(prototype); 546 buffer.add(isolatePrototype);
535 buffer.add(@'''.makeConstantList = function(list) { 547 buffer.add(@'''.makeConstantList = function(list) {
536 list.immutable$list = true; 548 list.immutable$list = true;
537 list.fixed$length = true; 549 list.fixed$length = true;
538 return list; 550 return list;
539 }; 551 };
540 '''); 552 ''');
541 } 553 }
542 554
543 void emitStaticFinalFieldInitializations(StringBuffer buffer) { 555 void emitStaticFinalFieldInitializations(StringBuffer buffer,
556 String isolatePrototype) {
544 ConstantHandler handler = compiler.constantHandler; 557 ConstantHandler handler = compiler.constantHandler;
545 List<VariableElement> staticFinalFields = 558 List<VariableElement> staticFinalFields =
546 handler.getStaticFinalFieldsForEmission(); 559 handler.getStaticFinalFieldsForEmission();
547 for (VariableElement element in staticFinalFields) { 560 for (VariableElement element in staticFinalFields) {
548 buffer.add('${namer.isolatePropertyAccess(element)} = '); 561 buffer.add(isolatePrototype);
562 buffer.add('.${namer.getName(element)} = ');
549 compiler.withCurrentElement(element, () { 563 compiler.withCurrentElement(element, () {
550 handler.writeJsCodeForVariable(buffer, element); 564 handler.writeJsCodeForVariable(buffer, element);
551 }); 565 });
552 buffer.add(';\n'); 566 buffer.add(';\n');
553 } 567 }
554 } 568 }
555 569
556 void emitExtraAccessors(Element member, 570 void emitExtraAccessors(Element member,
557 String attachTo(String name), 571 String attachTo(String name),
558 StringBuffer buffer) { 572 StringBuffer buffer,
573 String isolatePrototype) {
559 if (member.kind == ElementKind.GETTER || member.kind == ElementKind.FIELD) { 574 if (member.kind == ElementKind.GETTER || member.kind == ElementKind.FIELD) {
560 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; 575 Set<Selector> selectors = compiler.universe.invokedNames[member.name];
561 if (selectors !== null && !selectors.isEmpty()) { 576 if (selectors !== null && !selectors.isEmpty()) {
562 compiler.emitter.emitCallStubForGetter( 577 compiler.emitter.emitCallStubForGetter(
563 buffer, attachTo, member, selectors); 578 buffer, attachTo, member, selectors);
564 } 579 }
565 } else if (member.kind == ElementKind.FUNCTION) { 580 } else if (member.kind == ElementKind.FUNCTION) {
566 if (compiler.universe.invokedGetters.contains(member.name)) { 581 if (compiler.universe.invokedGetters.contains(member.name)) {
567 compiler.emitter.emitDynamicFunctionGetter( 582 compiler.emitter.emitDynamicFunctionGetter(
568 buffer, attachTo, member); 583 buffer, isolatePrototype, attachTo, member);
569 } 584 }
570 } 585 }
571 } 586 }
572 587
573 void emitNoSuchMethodCalls(StringBuffer buffer) { 588 void emitNoSuchMethodCalls(StringBuffer buffer, String isolatePrototype) {
Lasse Reichstein Nielsen 2012/04/12 09:45:32 Instead of passing isolatePrototype everywhere, co
floitsch 2012/04/12 11:26:56 Done.
574 // Do not generate no such method calls if there is no class. 589 // Do not generate no such method calls if there is no class.
575 if (compiler.universe.instantiatedClasses.isEmpty()) return; 590 if (compiler.universe.instantiatedClasses.isEmpty()) return;
576 591
577 ClassElement objectClass = 592 ClassElement objectClass =
578 compiler.coreLibrary.find(const SourceString('Object')); 593 compiler.coreLibrary.find(const SourceString('Object'));
579 String className = namer.isolatePropertyAccess(objectClass); 594 String className = namer.getName(objectClass);
580 String prototype = '$className.prototype'; 595 String prototype = '$isolatePrototype.$className.prototype';
596 String runtimeObjectPrototype =
597 '${namer.isolateAccess(objectClass)}.prototype';
581 String noSuchMethodName = 598 String noSuchMethodName =
582 namer.instanceMethodName(null, Compiler.NO_SUCH_METHOD, 2); 599 namer.instanceMethodName(null, Compiler.NO_SUCH_METHOD, 2);
583 Collection<LibraryElement> libraries = 600 Collection<LibraryElement> libraries =
584 compiler.universe.libraries.getValues(); 601 compiler.universe.libraries.getValues();
585 602
586 void generateMethod(String methodName, String jsName, Selector selector) { 603 void generateMethod(String methodName, String jsName, Selector selector) {
587 buffer.add('$prototype.$jsName = function'); 604 buffer.add('$prototype.$jsName = function');
588 StringBuffer args = new StringBuffer(); 605 StringBuffer args = new StringBuffer();
589 for (int i = 0; i < selector.argumentCount; i++) { 606 for (int i = 0; i < selector.argumentCount; i++) {
590 if (i != 0) args.add(', '); 607 if (i != 0) args.add(', ');
591 args.add('arg$i'); 608 args.add('arg$i');
592 } 609 }
593 // We need to check if the object has a noSuchMethod. If not, it 610 // We need to check if the object has a noSuchMethod. If not, it
594 // means the object is a native object, and we can just call our 611 // means the object is a native object, and we can just call our
595 // generic noSuchMethod. Note that when calling this method, the 612 // generic noSuchMethod. Note that when calling this method, the
596 // 'this' object is not a Dart object. 613 // 'this' object is not a Dart object.
597 buffer.add(' ($args) {\n'); 614 buffer.add(' ($args) {\n');
598 buffer.add(' return this.$noSuchMethodName\n'); 615 buffer.add(' return this.$noSuchMethodName\n');
599 buffer.add(" ? this.$noSuchMethodName('$methodName', [$args])\n"); 616 buffer.add(" ? this.$noSuchMethodName('$methodName', [$args])\n");
600 buffer.add(" : $objectClassName.prototype.$noSuchMethodName.call("); 617 buffer.add(" : $runtimeObjectPrototype.$noSuchMethodName.call(");
601 buffer.add("this, '$methodName', [$args])\n"); 618 buffer.add("this, '$methodName', [$args])\n");
602 buffer.add('}\n'); 619 buffer.add('}\n');
603 } 620 }
604 621
605 compiler.universe.invokedNames.forEach((SourceString methodName, 622 compiler.universe.invokedNames.forEach((SourceString methodName,
606 Set<Selector> selectors) { 623 Set<Selector> selectors) {
607 if (objectClass.lookupLocalMember(methodName) === null 624 if (objectClass.lookupLocalMember(methodName) === null
608 && methodName != Namer.OPERATOR_EQUALS) { 625 && methodName != Namer.OPERATOR_EQUALS) {
609 for (Selector selector in selectors) { 626 for (Selector selector in selectors) {
610 if (methodName.isPrivate()) { 627 if (methodName.isPrivate()) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 } else { 723 } else {
707 ${mainCall}; 724 ${mainCall};
708 } 725 }
709 """); 726 """);
710 } 727 }
711 728
712 String assembleProgram() { 729 String assembleProgram() {
713 measure(() { 730 measure(() {
714 mainBuffer.add('function ${namer.ISOLATE}() {'); 731 mainBuffer.add('function ${namer.ISOLATE}() {');
715 emitStaticNonFinalFieldInitializations(mainBuffer); 732 emitStaticNonFinalFieldInitializations(mainBuffer);
716 mainBuffer.add('}\n\n'); 733 mainBuffer.add('};\n\n');
717 emitClasses(mainBuffer); 734 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
718 emitStaticFunctions(mainBuffer); 735 String isolatePrototype = namer.CURRENT_ISOLATE;
719 emitStaticFunctionGetters(mainBuffer); 736 mainBuffer.add('var $isolatePrototype = ${namer.ISOLATE}.prototype;\n');
720 emitCompileTimeConstants(mainBuffer); 737 emitClasses(mainBuffer, isolatePrototype);
721 emitStaticFinalFieldInitializations(mainBuffer); 738 emitStaticFunctions(mainBuffer, isolatePrototype);
722 nativeEmitter.emitDynamicDispatchMetadata(); 739 emitStaticFunctionGetters(mainBuffer, isolatePrototype);
740 emitCompileTimeConstants(mainBuffer, isolatePrototype);
741 emitStaticFinalFieldInitializations(mainBuffer, isolatePrototype);
742
723 mainBuffer.add( 743 mainBuffer.add(
724 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); 744 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n');
745 nativeEmitter.emitDynamicDispatchMetadata();
725 nativeEmitter.assembleCode(mainBuffer); 746 nativeEmitter.assembleCode(mainBuffer);
726 emitMain(mainBuffer); 747 emitMain(mainBuffer);
727 compiler.assembledCode = mainBuffer.toString(); 748 compiler.assembledCode = mainBuffer.toString();
728 }); 749 });
729 return compiler.assembledCode; 750 return compiler.assembledCode;
730 } 751 }
731 } 752 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/namer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698