| 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 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 isNative: element.isNative); | 382 isNative: element.isNative); |
| 383 } | 383 } |
| 384 _classes[element] = result; | 384 _classes[element] = result; |
| 385 return result; | 385 return result; |
| 386 } | 386 } |
| 387 | 387 |
| 388 bool _methodNeedsStubs(FunctionElement method) { | 388 bool _methodNeedsStubs(FunctionElement method) { |
| 389 return !method.functionSignature.optionalParameters.isEmpty; | 389 return !method.functionSignature.optionalParameters.isEmpty; |
| 390 } | 390 } |
| 391 | 391 |
| 392 bool _methodCanBeReflected(FunctionElement method) { |
| 393 return backend.isAccessibleByReflection(method) || |
| 394 // During incremental compilation, we have to assume that reflection |
| 395 // *might* get enabled. |
| 396 _compiler.hasIncrementalSupport; |
| 397 } |
| 398 |
| 392 bool _methodCanBeApplied(FunctionElement method) { | 399 bool _methodCanBeApplied(FunctionElement method) { |
| 393 return _compiler.enabledFunctionApply && | 400 return _compiler.enabledFunctionApply && |
| 394 _compiler.world.getMightBePassedToApply(method); | 401 _compiler.world.getMightBePassedToApply(method); |
| 395 } | 402 } |
| 396 | 403 |
| 397 // TODO(herhut): Refactor incremental compilation and remove method. | 404 // TODO(herhut): Refactor incremental compilation and remove method. |
| 398 Method buildMethodHackForIncrementalCompilation(FunctionElement element) { | 405 Method buildMethodHackForIncrementalCompilation(FunctionElement element) { |
| 399 assert(_compiler.hasIncrementalSupport); | 406 assert(_compiler.hasIncrementalSupport); |
| 400 if (element.isInstanceMember) { | 407 if (element.isInstanceMember) { |
| 401 return _buildMethod(element); | 408 return _buildMethod(element); |
| 402 } else { | 409 } else { |
| 403 return _buildStaticMethod(element); | 410 return _buildStaticMethod(element); |
| 404 } | 411 } |
| 405 } | 412 } |
| 406 | 413 |
| 407 DartMethod _buildMethod(FunctionElement element) { | 414 DartMethod _buildMethod(FunctionElement element) { |
| 408 String name = namer.getNameOfInstanceMember(element); | 415 String name = namer.getNameOfInstanceMember(element); |
| 409 js.Expression code = backend.generatedCode[element]; | 416 js.Expression code = backend.generatedCode[element]; |
| 410 | 417 |
| 411 // TODO(kasperl): Figure out under which conditions code is null. | 418 // TODO(kasperl): Figure out under which conditions code is null. |
| 412 if (code == null) return null; | 419 if (code == null) return null; |
| 413 | 420 |
| 414 bool canTearOff = false; | 421 bool canTearOff = false; |
| 415 String tearOffName; | 422 String tearOffName; |
| 416 bool isClosure = false; | 423 bool isClosure = false; |
| 417 bool isNotApplyTarget = !element.isFunction || element.isAccessor; | 424 bool isNotApplyTarget = !element.isFunction || element.isAccessor; |
| 418 | 425 |
| 419 final bool needsStubs = _methodNeedsStubs(element); | 426 final bool needsStubs = _methodNeedsStubs(element); |
| 427 final bool canBeReflected = _methodCanBeReflected(element); |
| 420 final bool canBeApplied = _methodCanBeApplied(element); | 428 final bool canBeApplied = _methodCanBeApplied(element); |
| 421 final bool hasSuperAlias = backend.isAliasedSuperMember(element); | 429 final bool hasSuperAlias = backend.isAliasedSuperMember(element); |
| 422 | 430 |
| 423 if (isNotApplyTarget) { | 431 if (isNotApplyTarget) { |
| 424 canTearOff = false; | 432 canTearOff = false; |
| 425 } else { | 433 } else { |
| 426 if (element.enclosingClass.isClosure) { | 434 if (element.enclosingClass.isClosure) { |
| 427 canTearOff = false; | 435 canTearOff = false; |
| 428 isClosure = true; | 436 isClosure = true; |
| 429 } else { | 437 } else { |
| 430 // Careful with operators. | 438 // Careful with operators. |
| 431 canTearOff = universe.hasInvokedGetter(element, _compiler.world); | 439 canTearOff = universe.hasInvokedGetter(element, _compiler.world) || |
| 440 (canBeReflected && !element.isOperator); |
| 432 assert(canTearOff || | 441 assert(canTearOff || |
| 433 !universe.methodsNeedingSuperGetter.contains(element)); | 442 !universe.methodsNeedingSuperGetter.contains(element)); |
| 434 tearOffName = namer.getterName(element); | 443 tearOffName = namer.getterName(element); |
| 435 } | 444 } |
| 436 } | 445 } |
| 437 | 446 |
| 438 if (canTearOff) { | 447 if (canTearOff) { |
| 439 assert(invariant(element, !element.isGenerativeConstructor)); | 448 assert(invariant(element, !element.isGenerativeConstructor)); |
| 440 assert(invariant(element, !element.isGenerativeConstructorBody)); | 449 assert(invariant(element, !element.isGenerativeConstructorBody)); |
| 441 assert(invariant(element, !element.isConstructor)); | 450 assert(invariant(element, !element.isConstructor)); |
| 442 } | 451 } |
| 443 | 452 |
| 444 return new InstanceMethod(element, name, code, needsTearOff: canTearOff, | 453 return new InstanceMethod(element, name, code, needsTearOff: canTearOff, |
| 445 tearOffName: tearOffName, isClosure: isClosure, | 454 tearOffName: tearOffName, isClosure: isClosure, |
| 446 hasSuperAlias: hasSuperAlias, canBeApplied: canBeApplied, | 455 hasSuperAlias: hasSuperAlias, canBeApplied: canBeApplied, |
| 447 needsStubs: needsStubs); | 456 canBeReflected: canBeReflected, needsStubs: needsStubs); |
| 448 } | 457 } |
| 449 | 458 |
| 450 /// Builds a stub method. | 459 /// Builds a stub method. |
| 451 /// | 460 /// |
| 452 /// Stub methods may have an element that can be used for code-size | 461 /// Stub methods may have an element that can be used for code-size |
| 453 /// attribution. | 462 /// attribution. |
| 454 Method _buildStubMethod(String name, js.Expression code, | 463 Method _buildStubMethod(String name, js.Expression code, |
| 455 {Element element}) { | 464 {Element element}) { |
| 456 return new StubMethod(name, code, element: element); | 465 return new StubMethod(name, code, element: element); |
| 457 } | 466 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 554 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
| 546 return new StaticStubMethod(name, holder, code); | 555 return new StaticStubMethod(name, holder, code); |
| 547 }); | 556 }); |
| 548 } | 557 } |
| 549 | 558 |
| 550 StaticMethod _buildStaticMethod(FunctionElement element) { | 559 StaticMethod _buildStaticMethod(FunctionElement element) { |
| 551 String name = namer.getNameOfMember(element); | 560 String name = namer.getNameOfMember(element); |
| 552 String holder = namer.globalObjectFor(element); | 561 String holder = namer.globalObjectFor(element); |
| 553 js.Expression code = backend.generatedCode[element]; | 562 js.Expression code = backend.generatedCode[element]; |
| 554 | 563 |
| 564 final bool isNotApplyTarget = !element.isConstructor && !element.isAccessor; |
| 555 final bool needsStubs = _methodNeedsStubs(element); | 565 final bool needsStubs = _methodNeedsStubs(element); |
| 556 final bool canBeApplied = _methodCanBeApplied(element); | 566 final bool canBeApplied = _methodCanBeApplied(element); |
| 567 final bool canBeReflected = _methodCanBeReflected(element); |
| 557 | 568 |
| 558 final bool isApplyTarget = !element.isConstructor && !element.isAccessor; | 569 final bool needsTearOff = isNotApplyTarget && (canBeReflected || |
| 559 final bool needsTearOff = isApplyTarget && | 570 universe.staticFunctionsNeedingGetter.contains(element)); |
| 560 universe.staticFunctionsNeedingGetter.contains(element); | |
| 561 | 571 |
| 562 final String tearOffName = | 572 final String tearOffName = |
| 563 needsTearOff ? namer.getStaticClosureName(element) : null; | 573 needsTearOff ? namer.getStaticClosureName(element) : null; |
| 564 | 574 |
| 565 return new StaticMethod(element, | 575 return new StaticMethod(element, |
| 566 name, _registry.registerHolder(holder), code, | 576 name, _registry.registerHolder(holder), code, |
| 567 needsTearOff: needsTearOff, | 577 needsTearOff: needsTearOff, |
| 568 tearOffName: tearOffName, | 578 tearOffName: tearOffName, |
| 569 canBeApplied: canBeApplied, | 579 canBeApplied: canBeApplied, |
| 580 canBeReflected: canBeReflected, |
| 570 needsStubs: needsStubs); | 581 needsStubs: needsStubs); |
| 571 } | 582 } |
| 572 | 583 |
| 573 void _registerConstants(OutputUnit outputUnit, | 584 void _registerConstants(OutputUnit outputUnit, |
| 574 Iterable<ConstantValue> constantValues) { | 585 Iterable<ConstantValue> constantValues) { |
| 575 // `constantValues` is null if an outputUnit doesn't contain any constants. | 586 // `constantValues` is null if an outputUnit doesn't contain any constants. |
| 576 if (constantValues == null) return; | 587 if (constantValues == null) return; |
| 577 for (ConstantValue constantValue in constantValues) { | 588 for (ConstantValue constantValue in constantValues) { |
| 578 _registry.registerConstant(outputUnit, constantValue); | 589 _registry.registerConstant(outputUnit, constantValue); |
| 579 assert(!_constants.containsKey(constantValue)); | 590 assert(!_constants.containsKey(constantValue)); |
| 580 String name = namer.constantName(constantValue); | 591 String name = namer.constantName(constantValue); |
| 581 String constantObject = namer.globalObjectForConstant(constantValue); | 592 String constantObject = namer.globalObjectForConstant(constantValue); |
| 582 Holder holder = _registry.registerHolder(constantObject); | 593 Holder holder = _registry.registerHolder(constantObject); |
| 583 Constant constant = new Constant(name, holder, constantValue); | 594 Constant constant = new Constant(name, holder, constantValue); |
| 584 _constants[constantValue] = constant; | 595 _constants[constantValue] = constant; |
| 585 } | 596 } |
| 586 } | 597 } |
| 587 } | 598 } |
| OLD | NEW |