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

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: use unused api 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 10 matching lines...) Expand all
289 290
290 List<Method> methods = []; 291 List<Method> methods = [];
291 List<StubMethod> callStubs = <StubMethod>[]; 292 List<StubMethod> callStubs = <StubMethod>[];
292 293
293 void visitMember(ClassElement enclosing, Element member) { 294 void visitMember(ClassElement enclosing, Element member) {
294 assert(invariant(element, member.isDeclaration)); 295 assert(invariant(element, member.isDeclaration));
295 assert(invariant(element, element == enclosing)); 296 assert(invariant(element, element == enclosing));
296 297
297 if (Elements.isNonAbstractInstanceMember(member)) { 298 if (Elements.isNonAbstractInstanceMember(member)) {
298 js.Expression code = backend.generatedCode[member]; 299 js.Expression code = backend.generatedCode[member];
299 // TODO(kasperl): Figure out under which conditions code is null. 300 // TODO(herhut): Remove once _buildMethod can no longer return null.
300 if (code != null) methods.add(_buildMethod(member, code)); 301 Method method = _buildMethod(member);
302 if (method != null) methods.add(method);
301 } 303 }
302 if (member.isGetter || member.isField) { 304 if (member.isGetter || member.isField) {
303 Set<Selector> selectors = 305 Set<Selector> selectors =
304 _compiler.codegenWorld.invokedNames[member.name]; 306 _compiler.codegenWorld.invokedNames[member.name];
305 if (selectors != null && !selectors.isEmpty) { 307 if (selectors != null && !selectors.isEmpty) {
306 ClassStubGenerator generator = 308 ClassStubGenerator generator =
307 new ClassStubGenerator(_compiler, namer, backend); 309 new ClassStubGenerator(_compiler, namer, backend);
308 Map<String, js.Expression> callStubsForMember = 310 Map<String, js.Expression> callStubsForMember =
309 generator.generateCallStubsForGetter(member, selectors); 311 generator.generateCallStubsForGetter(member, selectors);
310 callStubsForMember.forEach((String name, js.Expression code) { 312 callStubsForMember.forEach((String name, js.Expression code) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 isChecks, 369 isChecks,
368 typeTests.functionTypeIndex, 370 typeTests.functionTypeIndex,
369 isDirectlyInstantiated: isInstantiated, 371 isDirectlyInstantiated: isInstantiated,
370 onlyForRti: onlyForRti, 372 onlyForRti: onlyForRti,
371 isNative: element.isNative); 373 isNative: element.isNative);
372 } 374 }
373 _classes[element] = result; 375 _classes[element] = result;
374 return result; 376 return result;
375 } 377 }
376 378
377 Method _buildMethod(FunctionElement element, js.Expression code) { 379 bool _methodNeedsStubs(FunctionElement method) {
380 return !method.functionSignature.optionalParameters.isEmpty;
381 }
382
383 bool _methodCanBeReflected(FunctionElement method) {
384 return backend.isAccessibleByReflection(method) ||
385 // During incremental compilation, we have to assume that reflection
386 // *might* get enabled.
387 _compiler.hasIncrementalSupport;
388 }
389
390 bool _methodCanBeApplied(FunctionElement method) {
391 return _compiler.enabledFunctionApply &&
392 _compiler.world.getMightBePassedToApply(method);
393 }
394
395 // TODO(herhut): Refactor incremental compilation and remove method.
396 Method buildMethodHackForIncrementalCompilation(FunctionElement element) {
397 assert(_compiler.hasIncrementalSupport);
398 if (element.isInstanceMember) {
399 return _buildMethod(element);
400 } else {
401 return _buildStaticMethod(element);
402 }
403 }
404
405 DartMethod _buildMethod(FunctionElement element) {
378 String name = namer.getNameOfInstanceMember(element); 406 String name = namer.getNameOfInstanceMember(element);
379 // TODO(floitsch): compute `needsTearOff`. 407 js.Expression code = backend.generatedCode[element];
380 return new Method(element, name, code, needsTearOff: false); 408
409 // TODO(kasperl): Figure out under which conditions code is null.
410 if (code == null) return null;
411
412 bool canTearOff = false;
413 String tearOffName;
414 bool isClosure = false;
415 bool isNotApplyTarget = !element.isFunction || element.isAccessor;
416
417 final bool needsStubs = _methodNeedsStubs(element);
418 final bool canBeReflected = _methodCanBeReflected(element);
419 final bool canBeApplied = _methodCanBeApplied(element);
420 final bool hasSuperAlias = backend.isAliasedSuperMember(element);
421
422 if (isNotApplyTarget) {
423 canTearOff = false;
424 } else {
425 if (element.enclosingClass.isClosure) {
426 canTearOff = false;
427 isClosure = true;
428 } else {
429 // Careful with operators.
430 canTearOff = universe.hasInvokedGetter(element, _compiler.world) ||
431 (canBeReflected && !element.isOperator);
432 assert(canTearOff ||
433 !universe.methodsNeedingSuperGetter.contains(element));
434 tearOffName = namer.getterName(element);
435 }
436 }
437
438 if (canTearOff) {
439 assert(invariant(element, !element.isGenerativeConstructor));
440 assert(invariant(element, !element.isGenerativeConstructorBody));
441 assert(invariant(element, !element.isConstructor));
442 }
443
444 return new InstanceMethod(element, name, code, needsTearOff: canTearOff,
445 tearOffName: tearOffName, isClosure: isClosure,
446 hasSuperAlias: hasSuperAlias, canBeApplied: canBeApplied,
447 canBeReflected: canBeReflected, needsStubs: needsStubs);
381 } 448 }
382 449
383 /// Builds a stub method. 450 /// Builds a stub method.
384 /// 451 ///
385 /// Stub methods may have an element that can be used for code-size 452 /// Stub methods may have an element that can be used for code-size
386 /// attribution. 453 /// attribution.
387 Method _buildStubMethod(String name, js.Expression code, 454 Method _buildStubMethod(String name, js.Expression code,
388 {Element element}) { 455 {Element element}) {
389 // TODO(floitsch): compute `needsTearOff`. 456 return new StubMethod(name, code, element: element);
390 return new StubMethod(name, code, needsTearOff: false, element: element);
391 } 457 }
392 458
393 // The getInterceptor methods directly access the prototype of classes. 459 // The getInterceptor methods directly access the prototype of classes.
394 // We must evaluate these classes eagerly so that the prototype is 460 // We must evaluate these classes eagerly so that the prototype is
395 // accessible. 461 // accessible.
396 void _markEagerInterceptorClasses() { 462 void _markEagerInterceptorClasses() {
397 Map<String, Set<ClassElement>> specializedGetInterceptors = 463 Map<String, Set<ClassElement>> specializedGetInterceptors =
398 backend.specializedGetInterceptors; 464 backend.specializedGetInterceptors;
399 for (Set<ClassElement> classes in specializedGetInterceptors.values) { 465 for (Set<ClassElement> classes in specializedGetInterceptors.values) {
400 for (ClassElement element in classes) { 466 for (ClassElement element in classes) {
401 Class cls = _classes[element]; 467 Class cls = _classes[element];
402 if (cls != null) cls.isEager = true; 468 if (cls != null) cls.isEager = true;
403 } 469 }
404 } 470 }
405 } 471 }
406 472
407 Iterable<StaticMethod> _generateGetInterceptorMethods() { 473 Iterable<StaticMethod> _generateGetInterceptorMethods() {
408 InterceptorStubGenerator stubGenerator = 474 InterceptorStubGenerator stubGenerator =
409 new InterceptorStubGenerator(_compiler, namer, backend); 475 new InterceptorStubGenerator(_compiler, namer, backend);
410 476
411 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); 477 String holderName = namer.globalObjectFor(backend.interceptorsLibrary);
412 Holder holder = _registry.registerHolder(holderName); 478 Holder holder = _registry.registerHolder(holderName);
413 479
414 Map<String, Set<ClassElement>> specializedGetInterceptors = 480 Map<String, Set<ClassElement>> specializedGetInterceptors =
415 backend.specializedGetInterceptors; 481 backend.specializedGetInterceptors;
416 List<String> names = specializedGetInterceptors.keys.toList()..sort(); 482 List<String> names = specializedGetInterceptors.keys.toList()..sort();
417 return names.map((String name) { 483 return names.map((String name) {
418 Set<ClassElement> classes = specializedGetInterceptors[name]; 484 Set<ClassElement> classes = specializedGetInterceptors[name];
419 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); 485 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes);
420 // TODO(floitsch): compute `needsTearOff`. 486 return new StaticStubMethod(name, holder, code);
421 return new StaticStubMethod(name, holder, code, needsTearOff: false);
422 }); 487 });
423 } 488 }
424 489
425 List<Field> _buildFields(Element holder, bool visitStatics) { 490 List<Field> _buildFields(Element holder, bool visitStatics) {
426 List<Field> fields = <Field>[]; 491 List<Field> fields = <Field>[];
427 _task.oldEmitter.classEmitter.visitFields( 492 _task.oldEmitter.classEmitter.visitFields(
428 holder, visitStatics, (VariableElement field, 493 holder, visitStatics, (VariableElement field,
429 String name, 494 String name,
430 String accessorName, 495 String accessorName,
431 bool needsGetter, 496 bool needsGetter,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 Iterable<StaticMethod> _generateOneShotInterceptors() { 536 Iterable<StaticMethod> _generateOneShotInterceptors() {
472 InterceptorStubGenerator stubGenerator = 537 InterceptorStubGenerator stubGenerator =
473 new InterceptorStubGenerator(_compiler, namer, backend); 538 new InterceptorStubGenerator(_compiler, namer, backend);
474 539
475 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); 540 String holderName = namer.globalObjectFor(backend.interceptorsLibrary);
476 Holder holder = _registry.registerHolder(holderName); 541 Holder holder = _registry.registerHolder(holderName);
477 542
478 List<String> names = backend.oneShotInterceptors.keys.toList()..sort(); 543 List<String> names = backend.oneShotInterceptors.keys.toList()..sort();
479 return names.map((String name) { 544 return names.map((String name) {
480 js.Expression code = stubGenerator.generateOneShotInterceptor(name); 545 js.Expression code = stubGenerator.generateOneShotInterceptor(name);
481 return new StaticStubMethod(name, holder, code, needsTearOff: false); 546 return new StaticStubMethod(name, holder, code);
482 }); 547 });
483 } 548 }
484 549
485 StaticMethod _buildStaticMethod(FunctionElement element) { 550 StaticMethod _buildStaticMethod(FunctionElement element) {
486 String name = namer.getNameOfMember(element); 551 String name = namer.getNameOfMember(element);
487 String holder = namer.globalObjectFor(element); 552 String holder = namer.globalObjectFor(element);
488 js.Expression code = backend.generatedCode[element]; 553 js.Expression code = backend.generatedCode[element];
489 bool needsTearOff = 554
490 universe.staticFunctionsNeedingGetter.contains(element); 555 final bool isNotApplyTarget = !element.isConstructor && !element.isAccessor;
491 // TODO(floitsch): add tear-off name: namer.getStaticClosureName(element). 556 final bool needsStubs = _methodNeedsStubs(element);
557 final bool canBeApplied = _methodCanBeApplied(element);
558 final bool canBeReflected = _methodCanBeReflected(element);
559
560 final bool needsTearOff = isNotApplyTarget && (canBeReflected ||
561 universe.staticFunctionsNeedingGetter.contains(element));
562
563 final String tearOffName =
564 needsTearOff ? namer.getStaticClosureName(element) : null;
565
492 return new StaticMethod(element, 566 return new StaticMethod(element,
493 name, _registry.registerHolder(holder), code, 567 name, _registry.registerHolder(holder), code,
494 needsTearOff: needsTearOff); 568 needsTearOff: needsTearOff,
569 tearOffName: tearOffName,
570 canBeApplied: canBeApplied,
571 canBeReflected: canBeReflected,
572 needsStubs: needsStubs);
495 } 573 }
496 574
497 void _registerConstants(OutputUnit outputUnit, 575 void _registerConstants(OutputUnit outputUnit,
498 Iterable<ConstantValue> constantValues) { 576 Iterable<ConstantValue> constantValues) {
499 // `constantValues` is null if an outputUnit doesn't contain any constants. 577 // `constantValues` is null if an outputUnit doesn't contain any constants.
500 if (constantValues == null) return; 578 if (constantValues == null) return;
501 for (ConstantValue constantValue in constantValues) { 579 for (ConstantValue constantValue in constantValues) {
502 _registry.registerConstant(outputUnit, constantValue); 580 _registry.registerConstant(outputUnit, constantValue);
503 assert(!_constants.containsKey(constantValue)); 581 assert(!_constants.containsKey(constantValue));
504 String name = namer.constantName(constantValue); 582 String name = namer.constantName(constantValue);
505 String constantObject = namer.globalObjectForConstant(constantValue); 583 String constantObject = namer.globalObjectForConstant(constantValue);
506 Holder holder = _registry.registerHolder(constantObject); 584 Holder holder = _registry.registerHolder(constantObject);
507 Constant constant = new Constant(name, holder, constantValue); 585 Constant constant = new Constant(name, holder, constantValue);
508 _constants[constantValue] = constant; 586 _constants[constantValue] = constant;
509 } 587 }
510 } 588 }
511 } 589 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart ('k') | pkg/compiler/lib/src/use_unused_api.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698