diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2015-08-21 14:00:46 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2015-10-08 14:09:59 +1000 |
commit | 571ed0312031a0826f65d40b27933d16b9617fbe (patch) | |
tree | dcd841aaa63b1b97d47eab76a5d3e2afc53ac75d /test/files/run | |
parent | 5614baf08b2da56532b580c7e2f70cf357832970 (diff) | |
download | scala-571ed0312031a0826f65d40b27933d16b9617fbe.tar.gz scala-571ed0312031a0826f65d40b27933d16b9617fbe.tar.bz2 scala-571ed0312031a0826f65d40b27933d16b9617fbe.zip |
Desugar module var and accessor in refchecks/lazyvals
Rather than leaving it until mixin.
The broader motivation is to simplify the mixin phase of the
compiler before we get rid of implementatation classes in
favour of using JDK8 default interface methods.
The current code in mixin is used for both lazy val and modules,
and puts the "slow path" code that uses the monitor into a
dedicated method (`moduleName$lzyCompute`). I tracked this
back to a3d4d17b77. I can't tell from that commit whether the
performance sensititivity was related to modules or lazy vals,
from the commit message I'd say the latter.
As the initialization code for a module is just a constructor call,
rather than an arbitraryly large chunk of code for a lazy initializer,
this commit opts to inline the `lzycompute` method.
During refchecks, mixin module accessors are added to classes, so
that mixed in and defined modules are translated uniformly. Trait
owned modules get an accessor method with an empty body (that shares
the module symbol), but no module var.
Defer synthesis of the double checked locking idiom to the lazyvals
phase, which gets us a step closer to a unified translation of
modules and lazy vals.
I had to change the `atOwner` methods to to avoid using the
non-existent module class of a module accessor method as the
current owner. This fixes a latent bug. Without this change,
retypechecking of the module accessor method during erasure crashes
with an accessibility error selecting the module var.
In the process, I've tweaked a tree generation utility method
to wvoid synthesizing redundant blocks in module desugaring.
Diffstat (limited to 'test/files/run')
-rw-r--r-- | test/files/run/delambdafy_t6028.check | 12 | ||||
-rw-r--r-- | test/files/run/t6028.check | 12 | ||||
-rw-r--r-- | test/files/run/trait-defaults-modules.scala | 20 | ||||
-rw-r--r-- | test/files/run/trait-defaults-modules2/T_1.scala | 4 | ||||
-rw-r--r-- | test/files/run/trait-defaults-modules2/Test_2.scala | 5 | ||||
-rw-r--r-- | test/files/run/trait-defaults-modules3.scala | 8 |
6 files changed, 57 insertions, 4 deletions
diff --git a/test/files/run/delambdafy_t6028.check b/test/files/run/delambdafy_t6028.check index 885fc3c9f3..c8c4b1cb4c 100644 --- a/test/files/run/delambdafy_t6028.check +++ b/test/files/run/delambdafy_t6028.check @@ -38,10 +38,18 @@ package <empty> { <synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer; <synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer }; - final <stable> private[this] def MethodLocalObject$1(barParam$1: String, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = { - MethodLocalObject$module$1.elem = new T#MethodLocalObject$2.type(T.this, barParam$1); + final <stable> private[this] def MethodLocalObject$lzycompute$1(barParam$1: String, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = { + T.this.synchronized({ + if (MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type]().eq(null)) + MethodLocalObject$module$1.elem = new T#MethodLocalObject$2.type(T.this, barParam$1); + scala.runtime.BoxedUnit.UNIT + }); MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type]() }; + final <stable> private[this] def MethodLocalObject$1(barParam$1: String, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = if (MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type]().eq(null)) + T.this.MethodLocalObject$lzycompute$1(barParam$1, MethodLocalObject$module$1) + else + MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type](); abstract trait MethodLocalTrait$1$class extends Object with T#MethodLocalTrait$1 { def /*MethodLocalTrait$1$class*/$init$(barParam$1: String): Unit = { () diff --git a/test/files/run/t6028.check b/test/files/run/t6028.check index a768f32976..b3d20a9902 100644 --- a/test/files/run/t6028.check +++ b/test/files/run/t6028.check @@ -50,10 +50,18 @@ package <empty> { <synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer; <synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer }; - final <stable> private[this] def MethodLocalObject$1(barParam$1: Int, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = { - MethodLocalObject$module$1.elem = new T#MethodLocalObject$2.type(T.this, barParam$1); + final <stable> private[this] def MethodLocalObject$lzycompute$1(barParam$1: Int, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = { + T.this.synchronized({ + if (MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type]().eq(null)) + MethodLocalObject$module$1.elem = new T#MethodLocalObject$2.type(T.this, barParam$1); + scala.runtime.BoxedUnit.UNIT + }); MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type]() }; + final <stable> private[this] def MethodLocalObject$1(barParam$1: Int, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = if (MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type]().eq(null)) + T.this.MethodLocalObject$lzycompute$1(barParam$1, MethodLocalObject$module$1) + else + MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type](); abstract trait MethodLocalTrait$1$class extends Object with T#MethodLocalTrait$1 { def /*MethodLocalTrait$1$class*/$init$(barParam$1: Int): Unit = { () diff --git a/test/files/run/trait-defaults-modules.scala b/test/files/run/trait-defaults-modules.scala new file mode 100644 index 0000000000..93fc74baff --- /dev/null +++ b/test/files/run/trait-defaults-modules.scala @@ -0,0 +1,20 @@ +trait T1 { def a: Any } + +trait T2 extends T1 { object a; object b; private object c; def usec: Any = c} +trait T3 extends T2 + +class C1 extends T1 { object a; object b } +class C2 extends C1 +class C3 extends T2 +class C4 extends T3 + +object Test { + def main(args: Array[String]): Unit = { + val (c1, c2, c3, c4) = (new C1, new C2, new C3, new C4) + c1.a; c1.b; (c1: T1).a + c2.a; c2.b; (c2: T1).a + c3.a; c3.b; (c3: T1).a; c3.usec + c4.a; c4.b; (c4: T1).a; c4.usec + } + +} diff --git a/test/files/run/trait-defaults-modules2/T_1.scala b/test/files/run/trait-defaults-modules2/T_1.scala new file mode 100644 index 0000000000..962acdade1 --- /dev/null +++ b/test/files/run/trait-defaults-modules2/T_1.scala @@ -0,0 +1,4 @@ +trait T { + private object O + def useO: Any = O +} diff --git a/test/files/run/trait-defaults-modules2/Test_2.scala b/test/files/run/trait-defaults-modules2/Test_2.scala new file mode 100644 index 0000000000..a1c49f5ddd --- /dev/null +++ b/test/files/run/trait-defaults-modules2/Test_2.scala @@ -0,0 +1,5 @@ +object Test extends T { + def main(args: Array[String]): Unit = { + useO + } +} diff --git a/test/files/run/trait-defaults-modules3.scala b/test/files/run/trait-defaults-modules3.scala new file mode 100644 index 0000000000..8790a95f4c --- /dev/null +++ b/test/files/run/trait-defaults-modules3.scala @@ -0,0 +1,8 @@ +object Test { + def main(args: Array[String]): Unit = { + object O + val x = O + val y = O + assert(x eq y) + } +} |