diff options
author | Szabolcs Berecz <szabolcs.berecz@gmail.com> | 2012-01-29 01:24:28 +0100 |
---|---|---|
committer | Szabolcs Berecz <szabolcs.berecz@gmail.com> | 2012-02-16 21:36:58 +0100 |
commit | 01ee3de96dcae707fb8fee28e93af0515519c603 (patch) | |
tree | e4dcd0e7ba8ab1036abd92dbfaecc2cb9fa14175 /src | |
parent | b8b19b1ca1de01083cf0975226a34424bd729a5b (diff) | |
download | scala-01ee3de96dcae707fb8fee28e93af0515519c603.tar.gz scala-01ee3de96dcae707fb8fee28e93af0515519c603.tar.bz2 scala-01ee3de96dcae707fb8fee28e93af0515519c603.zip |
replace methods containing a synchronized body with synchronized methods
The following:
def f = synchronized { ... }
will be rewritten to:
<synchronized> def f = ...
which is then emitted to the classfile with the synchronized flag set.
Inlining of such transformed methods are disabled for now
This transformation is not done on methods defined in a trait.
Diffstat (limited to 'src')
6 files changed, 46 insertions, 2 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index b4b0a7335d..485955c5c4 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -734,6 +734,7 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val ScalaStrictFPAttr = getRequiredClass("scala.annotation.strictfp") lazy val SerializableAttr = getRequiredClass("scala.annotation.serializable") // @serializable is deprecated lazy val SwitchClass = getRequiredClass("scala.annotation.switch") + lazy val SynchronizedAttr = getRequiredClass("scala.annotation.synchronized") lazy val TailrecClass = getRequiredClass("scala.annotation.tailrec") lazy val VarargsClass = getRequiredClass("scala.annotation.varargs") lazy val uncheckedStableClass = getRequiredClass("scala.annotation.unchecked.uncheckedStable") diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 77ed2f6a1b..25d6192e74 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -557,6 +557,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr) + def isSynchronized = hasAnnotation(SynchronizedAttr) def isSerializable = ( info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass) || hasAnnotation(SerializableAttr) // last part can be removed, @serializable annotation is deprecated diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index b5232fff09..9de0ec6610 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -859,6 +859,9 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with if (method.native) flags |= ACC_NATIVE + if (m.symbol.isSynchronized) + flags |= ACC_SYNCHRONIZED + jmethod = jclass.addNewMethod(flags, javaName(m.symbol), resTpe, diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 66f802f74f..4598141e8b 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -558,7 +558,7 @@ abstract class Inliners extends SubComponent { } def isStampedForInlining(stack: TypeStack) = - !sameSymbols && inc.m.hasCode && shouldInline && isSafeToInline(stack) + !sameSymbols && inc.m.hasCode && shouldInline && isSafeToInline(stack) && !inc.m.symbol.isSynchronized def logFailure(stack: TypeStack) = log( """|inline failed for %s: @@ -576,6 +576,7 @@ abstract class Inliners extends SubComponent { def failureReason(stack: TypeStack) = if (!inc.m.hasCode) "bytecode was unavailable" else if (!isSafeToInline(stack)) "it is unsafe (target may reference private fields)" + else if (inc.m.symbol.isSynchronized) "method is synchronized" else "of a bug (run with -Ylog:inline -Ydebug for more information)" def canAccess(level: NonPublicRefs.Value) = level match { diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 1655ad09c4..97b9caaa73 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -173,6 +173,29 @@ abstract class TailCalls extends Transform { trees map (t => transform(t, nctx)) } + /** + * Transforms methods with synchronized body into synchronized methods + */ + private def transformSynchronizedMethods(tree: Tree): Tree = { + def isSelfSynchronized(body: Apply) = body.fun match { + case TypeApply(fun @ Select(This(_), _), List(TypeTree())) + if (fun.symbol == Object_synchronized && + fun.qualifier.symbol == tree.symbol.enclClass && + !tree.symbol.enclClass.isTrait) => true + case _ => false + } + + tree match { + case DefDef(mods, name, tparams, vparamss, tpt, rhs @ Apply(_, List(body))) + if (isSelfSynchronized(rhs)) => + val res = treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, body) + res.symbol withAnnotation AnnotationInfo(SynchronizedAttr.tpe, Nil, Nil) + res + case _ => + tree + } + } + override def transform(tree: Tree): Tree = { /** A possibly polymorphic apply to be considered for tail call transformation. */ @@ -222,7 +245,7 @@ abstract class TailCalls extends Transform { else rewriteTailCall(receiver) } - tree match { + transformSynchronizedMethods(tree) match { case dd @ DefDef(mods, name, tparams, vparams, tpt, rhs) => val newCtx = new Context(dd) diff --git a/src/library/scala/annotation/synchronized.scala b/src/library/scala/annotation/synchronized.scala new file mode 100644 index 0000000000..9470c7173c --- /dev/null +++ b/src/library/scala/annotation/synchronized.scala @@ -0,0 +1,15 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.annotation + +/** + * If this annotation is present on a method, the synchronized flag will be emitted. + * FIXME This should be internal to the compiler + */ +private[scala] class synchronized extends StaticAnnotation |