summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSzabolcs Berecz <szabolcs.berecz@gmail.com>2012-01-29 01:24:28 +0100
committerSzabolcs Berecz <szabolcs.berecz@gmail.com>2012-02-16 21:36:58 +0100
commit01ee3de96dcae707fb8fee28e93af0515519c603 (patch)
treee4dcd0e7ba8ab1036abd92dbfaecc2cb9fa14175 /src
parentb8b19b1ca1de01083cf0975226a34424bd729a5b (diff)
downloadscala-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')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala1
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala25
-rw-r--r--src/library/scala/annotation/synchronized.scala15
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