From 254ad276ca07c20a2782678a234c75ea1e7b9e83 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 3 Aug 2011 01:20:11 +0000 Subject: Took a different tack on avoiding unnecessarily... Took a different tack on avoiding unnecessarily final bytecode methods after discovering the inliner is not a fan of any reduction in finality. Restored the application of the lateFINAL flag in makeNotPrivate, and switched to sorting out who is ACC_FINAL and who isn't in genjvm. Review by dragos. --- src/compiler/scala/reflect/internal/Symbols.scala | 14 +++++++------- src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 17 ++++++++++++++--- src/compiler/scala/tools/nsc/backend/opt/Inliners.scala | 2 +- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 3167bbc5de..30e9f38cbe 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -1644,13 +1644,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def makeNotPrivate(base: Symbol) { if (this.isPrivate) { setFlag(notPRIVATE) - // Marking these methods final causes problems for proxies - // which use subclassing. If people write their code with no - // usage of final, we probably shouldn't introduce it ourselves - // unless we know it is safe. - // - // if (isMethod && !isDeferred) - // setFlag(lateFINAL) + // Marking these methods final causes problems for proxies which use subclassing. If people + // write their code with no usage of final, we probably shouldn't introduce it ourselves + // unless we know it is safe. ... Unfortunately if they aren't marked final the inliner + // thinks it can't inline them. So once again marking lateFINAL, and in genjvm we no longer + // generate ACC_FINAL on "final" methods which are actually lateFINAL. + if (isMethod && !isDeferred) + setFlag(lateFINAL) if (!isStaticModule && !isClassConstructor) { expandName(base) if (isModule) moduleClass.makeNotPrivate(base) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 0036fd8060..2acd343ac1 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -1905,14 +1905,25 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with def mkFlags(args: Int*) = args.foldLeft(0)(_ | _) // constructors of module classes should be private // PP: why are they only being marked private at this stage and not earlier? - val isConsideredPrivate = + val privateFlag = sym.isPrivate || (sym.isPrimaryConstructor && isTopLevelModule(sym.owner)) + // This does not check .isFinal (which checks flags for the FINAL flag), + // instead checking rawflags for that flag so as to exclude symbols which + // received lateFINAL. These symbols are eligible for inlining, but to + // avoid breaking proxy software which depends on subclassing, we avoid + // insisting on their finality in the bytecode. + val finalFlag = ( + ((sym.rawflags & Flags.FINAL) != 0) + && !sym.enclClass.isInterface + && !sym.isClassConstructor + ) + mkFlags( - if (isConsideredPrivate) ACC_PRIVATE else ACC_PUBLIC, + if (privateFlag) ACC_PRIVATE else ACC_PUBLIC, if (sym.isDeferred || sym.hasAbstractFlag) ACC_ABSTRACT else 0, if (sym.isInterface) ACC_INTERFACE else 0, - if (sym.isFinal && !sym.enclClass.isInterface && !sym.isClassConstructor) ACC_FINAL else 0, + if (finalFlag) ACC_FINAL else 0, if (sym.isStaticMember) ACC_STATIC else 0, if (sym.isBridge || sym.hasFlag(Flags.MIXEDIN) && sym.isMethod) ACC_BRIDGE else 0, if (sym.isClass && !sym.isInterface) ACC_SUPER else 0, diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index cf9bf3cdeb..3bded8cca4 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -187,7 +187,7 @@ abstract class Inliners extends SubComponent { } else warnNoInline( if (!isAvailable) "bytecode was not available" - else "it is not final" + else "it can be overridden" ) inlined } -- cgit v1.2.3