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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart

Issue 1221333015: dart2js: Move field-visiting code to the program-builder. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Remove bad show line. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 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 class ClassEmitter extends CodeEmitterHelper { 7 class ClassEmitter extends CodeEmitterHelper {
8 8
9 ClassStubGenerator get _stubGenerator => 9 ClassStubGenerator get _stubGenerator =>
10 new ClassStubGenerator(compiler, namer, backend); 10 new ClassStubGenerator(compiler, namer, backend);
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 for (DartType interface in classElement.interfaces) { 351 for (DartType interface in classElement.interfaces) {
352 types.add(task.metadataCollector.reifyType(interface)); 352 types.add(task.metadataCollector.reifyType(interface));
353 } 353 }
354 // TODO(herhut): Fix use of reflection name here. 354 // TODO(herhut): Fix use of reflection name here.
355 enclosingBuilder.addPropertyByName("+$reflectionName", 355 enclosingBuilder.addPropertyByName("+$reflectionName",
356 new jsAst.ArrayInitializer(types)); 356 new jsAst.ArrayInitializer(types));
357 } 357 }
358 } 358 }
359 } 359 }
360 360
361 /**
362 * Invokes [f] for each of the fields of [element].
363 *
364 * [element] must be a [ClassElement] or a [LibraryElement].
365 *
366 * If [element] is a [ClassElement], the static fields of the class are
367 * visited if [visitStatics] is true and the instance fields are visited if
368 * [visitStatics] is false.
369 *
370 * If [element] is a [LibraryElement], [visitStatics] must be true.
371 *
372 * When visiting the instance fields of a class, the fields of its superclass
373 * are also visited if the class is instantiated.
374 *
375 * Invariant: [element] must be a declaration element.
376 */
377 void visitFields(Element element, bool visitStatics, AcceptField f) {
378 assert(invariant(element, element.isDeclaration));
379
380 bool isClass = false;
381 bool isLibrary = false;
382 if (element.isClass) {
383 isClass = true;
384 } else if (element.isLibrary) {
385 isLibrary = true;
386 assert(invariant(element, visitStatics));
387 } else {
388 throw new SpannableAssertionFailure(
389 element, 'Expected a ClassElement or a LibraryElement.');
390 }
391
392 // If the class is never instantiated we still need to set it up for
393 // inheritance purposes, but we can simplify its JavaScript constructor.
394 bool isInstantiated =
395 compiler.codegenWorld.directlyInstantiatedClasses.contains(element);
396
397 void visitField(Element holder, FieldElement field) {
398 assert(invariant(element, field.isDeclaration));
399
400 // Keep track of whether or not we're dealing with a field mixin
401 // into a native class.
402 bool isMixinNativeField =
403 isClass && element.isNative && holder.isMixinApplication;
404
405 // See if we can dynamically create getters and setters.
406 // We can only generate getters and setters for [element] since
407 // the fields of super classes could be overwritten with getters or
408 // setters.
409 bool needsGetter = false;
410 bool needsSetter = false;
411 if (isLibrary || isMixinNativeField || holder == element) {
412 needsGetter = fieldNeedsGetter(field);
413 needsSetter = fieldNeedsSetter(field);
414 }
415
416 if ((isInstantiated && !holder.isNative)
417 || needsGetter
418 || needsSetter) {
419 jsAst.Name accessorName = namer.fieldAccessorName(field);
420 jsAst.Name fieldName = namer.fieldPropertyName(field);
421 bool needsCheckedSetter = false;
422 if (compiler.enableTypeAssertions
423 && needsSetter
424 && !canAvoidGeneratedCheckedSetter(field)) {
425 needsCheckedSetter = true;
426 needsSetter = false;
427 }
428 // Getters and setters with suffixes will be generated dynamically.
429 f(field, fieldName, accessorName, needsGetter, needsSetter,
430 needsCheckedSetter);
431 }
432 }
433
434 if (isLibrary) {
435 LibraryElement library = element;
436 library.implementation.forEachLocalMember((Element member) {
437 if (member.isField) visitField(library, member);
438 });
439 } else if (visitStatics) {
440 ClassElement cls = element;
441 cls.implementation.forEachStaticField(visitField);
442 } else {
443 ClassElement cls = element;
444 // TODO(kasperl): We should make sure to only emit one version of
445 // overridden fields. Right now, we rely on the ordering so the
446 // fields pulled in from mixins are replaced with the fields from
447 // the class definition.
448
449 // If a class is not instantiated then we add the field just so we can
450 // generate the field getter/setter dynamically. Since this is only
451 // allowed on fields that are in [element] we don't need to visit
452 // superclasses for non-instantiated classes.
453 cls.implementation.forEachInstanceField(
454 visitField, includeSuperAndInjectedMembers: isInstantiated);
455 }
456 }
457
458 void recordMangledField(Element member, 361 void recordMangledField(Element member,
459 jsAst.Name accessorName, 362 jsAst.Name accessorName,
460 String memberName) { 363 String memberName) {
461 if (!backend.shouldRetainGetter(member)) return; 364 if (!backend.shouldRetainGetter(member)) return;
462 String previousName; 365 String previousName;
463 if (member.isInstanceMember) { 366 if (member.isInstanceMember) {
464 previousName = emitter.mangledFieldNames.putIfAbsent( 367 previousName = emitter.mangledFieldNames.putIfAbsent(
465 namer.deriveGetterName(accessorName), 368 namer.deriveGetterName(accessorName),
466 () => memberName); 369 () => memberName);
467 } else { 370 } else {
468 previousName = emitter.mangledGlobalFieldNames.putIfAbsent( 371 previousName = emitter.mangledGlobalFieldNames.putIfAbsent(
469 accessorName, 372 accessorName,
470 () => memberName); 373 () => memberName);
471 } 374 }
472 assert(invariant(member, previousName == memberName, 375 assert(invariant(member, previousName == memberName,
473 message: '$previousName != ${memberName}')); 376 message: '$previousName != ${memberName}'));
474 } 377 }
475 378
476 bool fieldNeedsGetter(VariableElement field) {
477 assert(field.isField);
478 if (fieldAccessNeverThrows(field)) return false;
479 if (backend.shouldRetainGetter(field)) return true;
480 return field.isClassMember &&
481 compiler.codegenWorld.hasInvokedGetter(field, compiler.world);
482 }
483
484 bool fieldNeedsSetter(VariableElement field) {
485 assert(field.isField);
486 if (fieldAccessNeverThrows(field)) return false;
487 if (field.isFinal || field.isConst) return false;
488 if (backend.shouldRetainSetter(field)) return true;
489 return field.isClassMember &&
490 compiler.codegenWorld.hasInvokedSetter(field, compiler.world);
491 }
492
493 static bool fieldAccessNeverThrows(VariableElement field) {
494 return
495 // We never access a field in a closure (a captured variable) without
496 // knowing that it is there. Therefore we don't need to use a getter
497 // (that will throw if the getter method is missing), but can always
498 // access the field directly.
499 field is ClosureFieldElement;
500 }
501
502 bool canAvoidGeneratedCheckedSetter(VariableElement member) {
503 // We never generate accessors for top-level/static fields.
504 if (!member.isInstanceMember) return true;
505 DartType type = member.type;
506 return type.treatAsDynamic || (type.element == compiler.objectClass);
507 }
508
509 void generateCheckedSetter(Element member, 379 void generateCheckedSetter(Element member,
510 jsAst.Name fieldName, 380 jsAst.Name fieldName,
511 jsAst.Name accessorName, 381 jsAst.Name accessorName,
512 ClassBuilder builder) { 382 ClassBuilder builder) {
513 jsAst.Expression code = backend.generatedCode[member]; 383 jsAst.Expression code = backend.generatedCode[member];
514 assert(code != null); 384 assert(code != null);
515 jsAst.Name setterName = namer.deriveSetterName(accessorName); 385 jsAst.Name setterName = namer.deriveSetterName(accessorName);
516 compiler.dumpInfoTask.registerElementAst(member, 386 compiler.dumpInfoTask.registerElementAst(member,
517 builder.addProperty(setterName, code)); 387 builder.addProperty(setterName, code));
518 generateReflectionDataForFieldGetterOrSetter( 388 generateReflectionDataForFieldGetterOrSetter(
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 ? new Selector.getter(member.name, member.library) 437 ? new Selector.getter(member.name, member.library)
568 : new Selector.setter(member.name, member.library); 438 : new Selector.setter(member.name, member.library);
569 String reflectionName = emitter.getReflectionName(selector, name); 439 String reflectionName = emitter.getReflectionName(selector, name);
570 if (reflectionName != null) { 440 if (reflectionName != null) {
571 var reflectable = 441 var reflectable =
572 js(backend.isAccessibleByReflection(member) ? '1' : '0'); 442 js(backend.isAccessibleByReflection(member) ? '1' : '0');
573 builder.addPropertyByName('+$reflectionName', reflectable); 443 builder.addPropertyByName('+$reflectionName', reflectable);
574 } 444 }
575 } 445 }
576 } 446 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/code_emitter_task.dart ('k') | pkg/compiler/lib/src/js_emitter/full_emitter/declarations.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698