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