Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |