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

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

Issue 882713008: Move computation of method flags into model. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library dart2js.js_emitter.program_builder; 5 library dart2js.js_emitter.program_builder;
6 6
7 import 'js_emitter.dart' show computeMixinClass; 7 import 'js_emitter.dart' show computeMixinClass;
8 import 'model.dart'; 8 import 'model.dart';
9 9
10 import '../common.dart'; 10 import '../common.dart';
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 List<Field> staticFieldsForReflection = _buildFields(library, visitStatics); 259 List<Field> staticFieldsForReflection = _buildFields(library, visitStatics);
260 260
261 return new Library(library, uri, statics, classes, 261 return new Library(library, uri, statics, classes,
262 staticFieldsForReflection); 262 staticFieldsForReflection);
263 } 263 }
264 264
265 /// HACK for Try. 265 /// HACK for Try.
266 /// 266 ///
267 /// Returns a class that contains the fields of a class. 267 /// Returns a class that contains the fields of a class.
268 Class buildClassWithFieldsForTry(ClassElement element) { 268 Class buildClassWithFieldsForTry(ClassElement element) {
269 assert(_compiler.hasIncrementalSupport);
269 bool onlyForRti = _task.typeTestRegistry.rtiNeededClasses.contains(element); 270 bool onlyForRti = _task.typeTestRegistry.rtiNeededClasses.contains(element);
270 271
271 List<Field> instanceFields = 272 List<Field> instanceFields =
272 onlyForRti ? const <Field>[] : _buildFields(element, false); 273 onlyForRti ? const <Field>[] : _buildFields(element, false);
273 274
274 String name = namer.getNameOfClass(element); 275 String name = namer.getNameOfClass(element);
275 String holderName = namer.globalObjectFor(element); 276 String holderName = namer.globalObjectFor(element);
276 Holder holder = _registry.registerHolder(holderName); 277 Holder holder = _registry.registerHolder(holderName);
277 bool isInstantiated = 278 bool isInstantiated =
278 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); 279 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element);
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 isChecks, 368 isChecks,
368 typeTests.functionTypeIndex, 369 typeTests.functionTypeIndex,
369 isDirectlyInstantiated: isInstantiated, 370 isDirectlyInstantiated: isInstantiated,
370 onlyForRti: onlyForRti, 371 onlyForRti: onlyForRti,
371 isNative: element.isNative); 372 isNative: element.isNative);
372 } 373 }
373 _classes[element] = result; 374 _classes[element] = result;
374 return result; 375 return result;
375 } 376 }
376 377
377 Method _buildMethod(FunctionElement element, js.Expression code) { 378 bool _methodNeedsStubs(FunctionElement method) {
379 return !method.functionSignature.optionalParameters.isEmpty;
380 }
381
382 bool _methodCanBeReflected(FunctionElement method) {
383 return backend.isAccessibleByReflection(method) ||
384 // During incremental compilation, we have to assume that reflection
385 // *might* get enabled.
386 _compiler.hasIncrementalSupport;
387 }
388
389 bool _methodCanBeApplied(FunctionElement method) {
390 return _compiler.enabledFunctionApply &&
391 _compiler.world.getMightBePassedToApply(method);
392 }
393
394 // Hack for Try!
395 Method buildMethodForTry(FunctionElement element) {
floitsch 2015/01/28 16:10:39 As discussed: change name.
herhut 2015/01/29 10:24:21 now buildMethodHackForIncrementalCompilation
396 assert(_compiler.hasIncrementalSupport);
397 if (element.isInstanceMember) {
398 js.Expression code = backend.generatedCode[element];
399 return _buildMethod(element, code);
400 } else {
401 return _buildStaticMethod(element);
402 }
403 }
404
405 // TODO(herhut): Why does this get code passed in and statics don't?
floitsch 2015/01/28 16:10:39 Probably just an oversight.
herhut 2015/01/29 10:24:21 Changed.
406 DartMethod _buildMethod(FunctionElement element, js.Expression code) {
378 String name = namer.getNameOfInstanceMember(element); 407 String name = namer.getNameOfInstanceMember(element);
379 // TODO(floitsch): compute `needsTearOff`. 408
380 return new Method(element, name, code, needsTearOff: false); 409 bool canTearOff = false;
410 String tearOffName;
411 bool isClosure = false;
412 bool isNotApplyTarget = !element.isFunction || element.isAccessor;
413
414 final bool needsStubs = _methodNeedsStubs(element);
415 final bool canBeReflected = _methodCanBeReflected(element);
416 final bool canBeApplied = _methodCanBeApplied(element);
417 final bool hasSuperAlias = backend.isAliasedSuperMember(element);
418
419 if (isNotApplyTarget) {
420 canTearOff = false;
421 } else {
422 if (element.enclosingClass.isClosure) {
423 canTearOff = false;
424 isClosure = true;
425 } else {
426 // Careful with operators.
427 canTearOff = universe.hasInvokedGetter(element, _compiler.world) ||
428 (canBeReflected && !element.isOperator);
429 assert(canTearOff ||
430 !universe.methodsNeedingSuperGetter.contains(element));
431 tearOffName = namer.getterName(element);
432 }
433 }
434
435 if (canTearOff) {
436 assert(invariant(element, !element.isGenerativeConstructor));
437 assert(invariant(element, !element.isGenerativeConstructorBody));
438 assert(invariant(element, !element.isConstructor));
439 }
440
441 return new InstanceMethod(element, name, code, needsTearOff: canTearOff,
442 tearOffName: tearOffName, isClosure: isClosure,
443 hasSuperAlias: hasSuperAlias, canBeApplied: canBeApplied,
444 canBeReflected: canBeReflected, needsStubs: needsStubs);
381 } 445 }
382 446
383 /// Builds a stub method. 447 /// Builds a stub method.
384 /// 448 ///
385 /// Stub methods may have an element that can be used for code-size 449 /// Stub methods may have an element that can be used for code-size
386 /// attribution. 450 /// attribution.
387 Method _buildStubMethod(String name, js.Expression code, 451 Method _buildStubMethod(String name, js.Expression code,
388 {Element element}) { 452 {Element element}) {
389 // TODO(floitsch): compute `needsTearOff`. 453 return new StubMethod(name, code, element: element);
390 return new StubMethod(name, code, needsTearOff: false, element: element);
391 } 454 }
392 455
393 // The getInterceptor methods directly access the prototype of classes. 456 // The getInterceptor methods directly access the prototype of classes.
394 // We must evaluate these classes eagerly so that the prototype is 457 // We must evaluate these classes eagerly so that the prototype is
395 // accessible. 458 // accessible.
396 void _markEagerInterceptorClasses() { 459 void _markEagerInterceptorClasses() {
397 Map<String, Set<ClassElement>> specializedGetInterceptors = 460 Map<String, Set<ClassElement>> specializedGetInterceptors =
398 backend.specializedGetInterceptors; 461 backend.specializedGetInterceptors;
399 for (Set<ClassElement> classes in specializedGetInterceptors.values) { 462 for (Set<ClassElement> classes in specializedGetInterceptors.values) {
400 for (ClassElement element in classes) { 463 for (ClassElement element in classes) {
(...skipping 10 matching lines...) Expand all
411 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); 474 String holderName = namer.globalObjectFor(backend.interceptorsLibrary);
412 Holder holder = _registry.registerHolder(holderName); 475 Holder holder = _registry.registerHolder(holderName);
413 476
414 Map<String, Set<ClassElement>> specializedGetInterceptors = 477 Map<String, Set<ClassElement>> specializedGetInterceptors =
415 backend.specializedGetInterceptors; 478 backend.specializedGetInterceptors;
416 List<String> names = specializedGetInterceptors.keys.toList()..sort(); 479 List<String> names = specializedGetInterceptors.keys.toList()..sort();
417 return names.map((String name) { 480 return names.map((String name) {
418 Set<ClassElement> classes = specializedGetInterceptors[name]; 481 Set<ClassElement> classes = specializedGetInterceptors[name];
419 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); 482 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes);
420 // TODO(floitsch): compute `needsTearOff`. 483 // TODO(floitsch): compute `needsTearOff`.
484 // TODO(herhut): Can these actually ever be torn off?
floitsch 2015/01/28 16:10:39 Until we find a case where it can be, let's just r
herhut 2015/01/29 10:24:21 Done.
421 return new StaticStubMethod(name, holder, code, needsTearOff: false); 485 return new StaticStubMethod(name, holder, code, needsTearOff: false);
422 }); 486 });
423 } 487 }
424 488
425 List<Field> _buildFields(Element holder, bool visitStatics) { 489 List<Field> _buildFields(Element holder, bool visitStatics) {
426 List<Field> fields = <Field>[]; 490 List<Field> fields = <Field>[];
427 _task.oldEmitter.classEmitter.visitFields( 491 _task.oldEmitter.classEmitter.visitFields(
428 holder, visitStatics, (VariableElement field, 492 holder, visitStatics, (VariableElement field,
429 String name, 493 String name,
430 String accessorName, 494 String accessorName,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 return names.map((String name) { 543 return names.map((String name) {
480 js.Expression code = stubGenerator.generateOneShotInterceptor(name); 544 js.Expression code = stubGenerator.generateOneShotInterceptor(name);
481 return new StaticStubMethod(name, holder, code, needsTearOff: false); 545 return new StaticStubMethod(name, holder, code, needsTearOff: false);
482 }); 546 });
483 } 547 }
484 548
485 StaticMethod _buildStaticMethod(FunctionElement element) { 549 StaticMethod _buildStaticMethod(FunctionElement element) {
486 String name = namer.getNameOfMember(element); 550 String name = namer.getNameOfMember(element);
487 String holder = namer.globalObjectFor(element); 551 String holder = namer.globalObjectFor(element);
488 js.Expression code = backend.generatedCode[element]; 552 js.Expression code = backend.generatedCode[element];
489 bool needsTearOff = 553
490 universe.staticFunctionsNeedingGetter.contains(element); 554 final bool isNotApplyTarget = !element.isConstructor && !element.isAccessor;
491 // TODO(floitsch): add tear-off name: namer.getStaticClosureName(element). 555 final bool needsStubs = _methodNeedsStubs(element);
556 final bool canBeApplied = _methodCanBeApplied(element);
557 final bool canBeReflected = _methodCanBeReflected(element);
558
559 final bool needsTearOff = isNotApplyTarget && (canBeReflected ||
560 universe.staticFunctionsNeedingGetter.contains(element));
561
562 final String tearOffName =
563 needsTearOff ? namer.getStaticClosureName(element) : null;
564
492 return new StaticMethod(element, 565 return new StaticMethod(element,
493 name, _registry.registerHolder(holder), code, 566 name, _registry.registerHolder(holder), code,
494 needsTearOff: needsTearOff); 567 needsTearOff: needsTearOff,
568 tearOffName: tearOffName,
569 canBeApplied: canBeApplied,
570 canBeReflected: canBeReflected,
571 needsStubs: needsStubs);
495 } 572 }
496 573
497 void _registerConstants(OutputUnit outputUnit, 574 void _registerConstants(OutputUnit outputUnit,
498 Iterable<ConstantValue> constantValues) { 575 Iterable<ConstantValue> constantValues) {
499 // `constantValues` is null if an outputUnit doesn't contain any constants. 576 // `constantValues` is null if an outputUnit doesn't contain any constants.
500 if (constantValues == null) return; 577 if (constantValues == null) return;
501 for (ConstantValue constantValue in constantValues) { 578 for (ConstantValue constantValue in constantValues) {
502 _registry.registerConstant(outputUnit, constantValue); 579 _registry.registerConstant(outputUnit, constantValue);
503 assert(!_constants.containsKey(constantValue)); 580 assert(!_constants.containsKey(constantValue));
504 String name = namer.constantName(constantValue); 581 String name = namer.constantName(constantValue);
505 String constantObject = namer.globalObjectForConstant(constantValue); 582 String constantObject = namer.globalObjectForConstant(constantValue);
506 Holder holder = _registry.registerHolder(constantObject); 583 Holder holder = _registry.registerHolder(constantObject);
507 Constant constant = new Constant(name, holder, constantValue); 584 Constant constant = new Constant(name, holder, constantValue);
508 _constants[constantValue] = constant; 585 _constants[constantValue] = constant;
509 } 586 }
510 } 587 }
511 } 588 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698