summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan@lightbend.com>2016-08-19 11:07:00 -0700
committerAdriaan Moors <adriaan@lightbend.com>2016-08-29 09:54:08 +0200
commitb2e0911ded57f33e9600c6337a307c0fe1877eff (patch)
treef7b25cd3240a85cd2c16b68ca5d62fdba1c84ab7 /test
parentc3b5f1bab3fc65296fcc596f3378ff940b4fb92c (diff)
downloadscala-b2e0911ded57f33e9600c6337a307c0fe1877eff.tar.gz
scala-b2e0911ded57f33e9600c6337a307c0fe1877eff.tar.bz2
scala-b2e0911ded57f33e9600c6337a307c0fe1877eff.zip
Fields does bitmaps & synch for lazy vals & modules
Essentially, we fuse mixin and lazyvals into the fields phase. With fields mixing in trait members into subclasses, we have all info needed to compute bitmaps, and thus we can synthesize the synchronisation logic as well. By doing this before erasure we get better signatures, and before specialized means specialized lazy vals work now. Mixins is now almost reduced to its essence: implementing super accessors and forwarders. It still synthesizes accessors for param accessors and early init trait vals. Concretely, trait lazy vals are mixed into subclasses with the needed synchronization logic in place, as do lazy vals in classes and methods. Similarly, modules are initialized using double checked locking. Since the code to initialize a module is short, we do not emit compute methods for modules (anymore). For simplicity, local lazy vals do not get a compute method either. The strange corner case of constant-typed final lazy vals is resolved in favor of laziness, by no longer assigning a constant type to a lazy val (see widenIfNecessary in namers). If you explicitly ask for something lazy, you get laziness; with the constant-typedness implicit, it yields to the conflicting `lazy` modifier because it is explicit. Co-Authored-By: Lukas Rytz <lukas@lightbend.com> Fixes scala/scala-dev#133 Inspired by dotc, desugar a local `lazy val x = rhs` into ``` val x$lzy = new scala.runtime.LazyInt() def x(): Int = { x$lzy.synchronized { if (!x$lzy.initialized) { x$lzy.initialized = true x$lzy.value = rhs } x$lzy.value } } ``` Note that the 2.11 decoding (into a local variable and a bitmap) also creates boxes for local lazy vals, in fact two for each lazy val: ``` def f = { lazy val x = 0 x } ``` desugars to ``` public int f() { IntRef x$lzy = IntRef.zero(); VolatileByteRef bitmap$0 = VolatileByteRef.create((byte)0); return this.x$1(x$lzy, bitmap$0); } private final int x$lzycompute$1(IntRef x$lzy$1, VolatileByteRef bitmap$0$1) { C c = this; synchronized (c) { if ((byte)(bitmap$0$1.elem & 1) == 0) { x$lzy$1.elem = 0; bitmap$0$1.elem = (byte)(bitmap$0$1.elem | 1); } return x$lzy$1.elem; } } private final int x$1(IntRef x$lzy$1, VolatileByteRef bitmap$0$1) { return (byte)(bitmap$0$1.elem & 1) == 0 ? this.x$lzycompute$1(x$lzy$1, bitmap$0$1) : x$lzy$1.elem; } ``` An additional problem with the above encoding is that the `lzycompute` method synchronizes on `this`. In connection with the new lambda encoding that no longer generates anonymous classes, captured lazy vals no longer synchronize on the lambda object. The new encoding solves this problem (scala/scala-dev#133) by synchronizing on the lazy holder. Currently, we don't exploit the fact that the initialized field is `@volatile`, because it's not clear the performance is needed for local lazy vals (as they are not contended, and as soon as the VM warms up, biased locking should deal with that) Note, be very very careful when moving to double-checked locking, as this needs a different variation than the one we use for class-member lazy vals. A read of a volatile field of a class does not necessarily impart any knowledge about a "subsequent" read of another non-volatile field of the same object. A pair of volatile reads and write can be used to implement a lock, but it's not clear if the complexity is worth an unproven performance gain. (Once the performance gain is proven, let's change the encoding.) - don't explicitly init bitmap in bytecode - must apply method to () explicitly after uncurry
Diffstat (limited to 'test')
-rw-r--r--test/files/neg/t6446-additional.check21
-rw-r--r--test/files/neg/t6446-missing.check19
-rw-r--r--test/files/neg/t6446-show-phases.check19
-rw-r--r--test/files/neg/t7494-no-options.check21
-rw-r--r--test/files/run/analyzerPlugins.check4
-rw-r--r--test/files/run/delambdafy_t6028.check6
-rw-r--r--test/files/run/lazy-locals-2.scala322
-rw-r--r--test/files/run/lazy_local_labels.check9
-rw-r--r--test/files/run/lazy_local_labels.scala28
-rw-r--r--test/files/run/programmatic-main.check19
-rw-r--r--test/files/run/t3569.check2
-rw-r--r--test/files/run/t3569.scala8
-rw-r--r--test/files/run/t5552.check4
-rw-r--r--test/files/run/t5552.scala10
-rw-r--r--test/files/run/t6028.check6
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala3
16 files changed, 430 insertions, 71 deletions
diff --git a/test/files/neg/t6446-additional.check b/test/files/neg/t6446-additional.check
index 45db63317c..23df978cd9 100644
--- a/test/files/neg/t6446-additional.check
+++ b/test/files/neg/t6446-additional.check
@@ -10,19 +10,18 @@ superaccessors 6 add super accessors in traits and nested classes
pickler 8 serialize symbol tables
refchecks 9 reference/override checking, translate nested objects
uncurry 10 uncurry, translate function values to anonymous classes
- fields 11 synthesize accessors and fields
+ fields 11 synthesize accessors and fields, including bitmaps for la...
tailcalls 12 replace tail calls by jumps
specialize 13 @specialized-driven class and method specialization
explicitouter 14 this refs to outer pointers
erasure 15 erase types, add interfaces for traits
posterasure 16 clean up erased inline classes
- lazyvals 17 allocate bitmaps, translate lazy vals into lazified defs
- lambdalift 18 move nested functions to top level
- constructors 19 move field definitions into constructors
- flatten 20 eliminate inner classes
- mixin 21 mixin composition
- cleanup 22 platform-specific cleanups, generate reflective calls
- delambdafy 23 remove lambdas
- jvm 24 generate JVM bytecode
- ploogin 25 A sample phase that does so many things it's kind of hard...
- terminal 26 the last phase during a compilation run
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ delambdafy 22 remove lambdas
+ jvm 23 generate JVM bytecode
+ ploogin 24 A sample phase that does so many things it's kind of hard...
+ terminal 25 the last phase during a compilation run
diff --git a/test/files/neg/t6446-missing.check b/test/files/neg/t6446-missing.check
index 04523d18e6..c0a8fea140 100644
--- a/test/files/neg/t6446-missing.check
+++ b/test/files/neg/t6446-missing.check
@@ -11,18 +11,17 @@ superaccessors 6 add super accessors in traits and nested classes
pickler 8 serialize symbol tables
refchecks 9 reference/override checking, translate nested objects
uncurry 10 uncurry, translate function values to anonymous classes
- fields 11 synthesize accessors and fields
+ fields 11 synthesize accessors and fields, including bitmaps for la...
tailcalls 12 replace tail calls by jumps
specialize 13 @specialized-driven class and method specialization
explicitouter 14 this refs to outer pointers
erasure 15 erase types, add interfaces for traits
posterasure 16 clean up erased inline classes
- lazyvals 17 allocate bitmaps, translate lazy vals into lazified defs
- lambdalift 18 move nested functions to top level
- constructors 19 move field definitions into constructors
- flatten 20 eliminate inner classes
- mixin 21 mixin composition
- cleanup 22 platform-specific cleanups, generate reflective calls
- delambdafy 23 remove lambdas
- jvm 24 generate JVM bytecode
- terminal 25 the last phase during a compilation run
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ delambdafy 22 remove lambdas
+ jvm 23 generate JVM bytecode
+ terminal 24 the last phase during a compilation run
diff --git a/test/files/neg/t6446-show-phases.check b/test/files/neg/t6446-show-phases.check
index 03f8273c17..cf8595db5d 100644
--- a/test/files/neg/t6446-show-phases.check
+++ b/test/files/neg/t6446-show-phases.check
@@ -10,18 +10,17 @@ superaccessors 6 add super accessors in traits and nested classes
pickler 8 serialize symbol tables
refchecks 9 reference/override checking, translate nested objects
uncurry 10 uncurry, translate function values to anonymous classes
- fields 11 synthesize accessors and fields
+ fields 11 synthesize accessors and fields, including bitmaps for la...
tailcalls 12 replace tail calls by jumps
specialize 13 @specialized-driven class and method specialization
explicitouter 14 this refs to outer pointers
erasure 15 erase types, add interfaces for traits
posterasure 16 clean up erased inline classes
- lazyvals 17 allocate bitmaps, translate lazy vals into lazified defs
- lambdalift 18 move nested functions to top level
- constructors 19 move field definitions into constructors
- flatten 20 eliminate inner classes
- mixin 21 mixin composition
- cleanup 22 platform-specific cleanups, generate reflective calls
- delambdafy 23 remove lambdas
- jvm 24 generate JVM bytecode
- terminal 25 the last phase during a compilation run
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ delambdafy 22 remove lambdas
+ jvm 23 generate JVM bytecode
+ terminal 24 the last phase during a compilation run
diff --git a/test/files/neg/t7494-no-options.check b/test/files/neg/t7494-no-options.check
index bb143e8644..138d2fe9a3 100644
--- a/test/files/neg/t7494-no-options.check
+++ b/test/files/neg/t7494-no-options.check
@@ -11,19 +11,18 @@ superaccessors 6 add super accessors in traits and nested classes
pickler 8 serialize symbol tables
refchecks 9 reference/override checking, translate nested objects
uncurry 10 uncurry, translate function values to anonymous classes
- fields 11 synthesize accessors and fields
+ fields 11 synthesize accessors and fields, including bitmaps for la...
tailcalls 12 replace tail calls by jumps
specialize 13 @specialized-driven class and method specialization
explicitouter 14 this refs to outer pointers
erasure 15 erase types, add interfaces for traits
posterasure 16 clean up erased inline classes
- lazyvals 17 allocate bitmaps, translate lazy vals into lazified defs
- lambdalift 18 move nested functions to top level
- constructors 19 move field definitions into constructors
- flatten 20 eliminate inner classes
- mixin 21 mixin composition
- cleanup 22 platform-specific cleanups, generate reflective calls
- delambdafy 23 remove lambdas
- jvm 24 generate JVM bytecode
- ploogin 25 A sample phase that does so many things it's kind of hard...
- terminal 26 the last phase during a compilation run
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ delambdafy 22 remove lambdas
+ jvm 23 generate JVM bytecode
+ ploogin 24 A sample phase that does so many things it's kind of hard...
+ terminal 25 the last phase during a compilation run
diff --git a/test/files/run/analyzerPlugins.check b/test/files/run/analyzerPlugins.check
index 9643079b83..64b68db242 100644
--- a/test/files/run/analyzerPlugins.check
+++ b/test/files/run/analyzerPlugins.check
@@ -39,7 +39,7 @@ pluginsPt(?, Trees$TypeBoundsTree) [2]
pluginsPt(?, Trees$TypeDef) [1]
pluginsPt(?, Trees$TypeTree) [32]
pluginsPt(?, Trees$Typed) [1]
-pluginsPt(?, Trees$ValDef) [21]
+pluginsPt(?, Trees$ValDef) [13]
pluginsPt(Any, Trees$Literal) [2]
pluginsPt(Any, Trees$Typed) [1]
pluginsPt(Array[Any], Trees$ArrayValue) [1]
@@ -109,7 +109,7 @@ pluginsTyped(<notype>, Trees$ClassDef) [2]
pluginsTyped(<notype>, Trees$DefDef) [14]
pluginsTyped(<notype>, Trees$PackageDef) [1]
pluginsTyped(<notype>, Trees$TypeDef) [1]
-pluginsTyped(<notype>, Trees$ValDef) [21]
+pluginsTyped(<notype>, Trees$ValDef) [13]
pluginsTyped(=> Boolean @testAnn, Trees$Select) [1]
pluginsTyped(=> Double, Trees$Select) [1]
pluginsTyped(=> Int, Trees$Select) [5]
diff --git a/test/files/run/delambdafy_t6028.check b/test/files/run/delambdafy_t6028.check
index 8b0ae7e9b9..b188928c09 100644
--- a/test/files/run/delambdafy_t6028.check
+++ b/test/files/run/delambdafy_t6028.check
@@ -42,7 +42,7 @@ 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$lzycompute$1(barParam$1: String, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = {
+ final <stable> private[this] def MethodLocalObject$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);
@@ -50,10 +50,6 @@ package <empty> {
});
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]();
final <artifact> private[this] def $anonfun$tryy$1(tryyParam$1: String, tryyLocal$1: runtime.ObjectRef): Unit = try {
tryyLocal$1.elem = tryyParam$1
} finally ()
diff --git a/test/files/run/lazy-locals-2.scala b/test/files/run/lazy-locals-2.scala
new file mode 100644
index 0000000000..cb905d3bef
--- /dev/null
+++ b/test/files/run/lazy-locals-2.scala
@@ -0,0 +1,322 @@
+object Logs {
+ val logBuf = new collection.mutable.StringBuilder()
+ def log(m: Any): Unit = { if (logBuf.nonEmpty) logBuf.append(":"); logBuf.append(m) }
+ def checkLog(expected: String): Unit = {
+ val res = logBuf.toString
+ assert(res == expected, s"expected:\n$expected\nfound:\n$res")
+ logBuf.clear()
+ }
+}
+
+import Logs._
+
+class C {
+ def getInt : Int = { log("getInt"); 1 }
+ def getString: String = { log("getString"); "s" }
+ def getUnit : Unit = { log("getUnit") }
+
+ lazy val t1 = getInt
+ lazy val t2 = getString
+ lazy val t3 = getUnit
+ checkLog("")
+
+ def m1 = {
+ lazy val t1 = getInt
+ t1 + t1
+ }
+ def m2 = {
+ lazy val t1 = getString
+ t1 + t1
+ }
+ def m3 = {
+ lazy val t1 = getUnit
+ log(t1); log(t1)
+ }
+ checkLog("")
+
+
+ val vl1 = {
+ lazy val t1 = getInt
+ t1 + t1
+ }
+ val vl2 = {
+ lazy val t1 = getString
+ t1 + t1
+ }
+ val vl3 = {
+ lazy val t1 = getUnit
+ log(t1); log(t1)
+ }
+ checkLog("getInt:getString:getUnit:():()")
+
+
+ var vr1 = {
+ lazy val t1 = getInt
+ t1 + t1
+ }
+ var vr2 = {
+ lazy val t1 = getString
+ t1 + t1
+ }
+ var vr3 = {
+ lazy val t1 = getUnit
+ log(t1); log(t1)
+ }
+ checkLog("getInt:getString:getUnit:():()")
+
+
+ lazy val lvl1 = {
+ lazy val t1 = getInt
+ t1 + t1
+ }
+ lazy val lvl2 = {
+ lazy val t1 = getString
+ t1 + t1
+ }
+ lazy val lvl3 = {
+ lazy val t1 = getUnit
+ log(t1); log(t1)
+ }
+ checkLog("")
+
+
+ {
+ lazy val t1 = getInt
+ lazy val t2 = getString
+ lazy val t3 = getUnit
+
+ log(t1 + t1)
+ log(t2 + t2)
+ log(t3); log(t3)
+ }
+ checkLog("getInt:2:getString:ss:getUnit:():()")
+
+
+ def run(): Unit = {
+ log(t1); log(t1);
+ log(t2); log(t2);
+ log(t3); log(t3);
+ checkLog("getInt:1:1:getString:s:s:getUnit:():()")
+
+ log(m1); log(m1)
+ log(m2); log(m2)
+ log(m3); log(m3)
+ checkLog("getInt:2:getInt:2:getString:ss:getString:ss:getUnit:():():():getUnit:():():()")
+
+ log(vl1); log(vl1)
+ log(vl2); log(vl2)
+ log(vl3); log(vl3)
+ checkLog("2:2:ss:ss:():()")
+
+ log(vr1); log(vr1); vr1 = 393; log(vr1)
+ log(vr2); log(vr2); vr2 = "h"; log(vr2)
+ log(vr3); log(vr3); vr3 = () ; log(vr3)
+ checkLog("2:2:393:ss:ss:h:():():()")
+
+ log(lvl1); log(lvl1)
+ log(lvl2); log(lvl2)
+ log(lvl3); log(lvl3)
+ checkLog("getInt:2:2:getString:ss:ss:getUnit:():():():()")
+ }
+}
+
+trait T {
+ def getInt : Int = { log("getInt"); 1 }
+ def getString: String = { log("getString"); "s" }
+ def getUnit : Unit = { log("getUnit") }
+
+ lazy val t1 = getInt
+ lazy val t2 = getString
+ lazy val t3 = getUnit
+ checkLog("")
+
+ def m1 = {
+ lazy val t1 = getInt
+ t1 + t1
+ }
+ def m2 = {
+ lazy val t1 = getString
+ t1 + t1
+ }
+ def m3 = {
+ lazy val t1 = getUnit
+ log(t1); log(t1)
+ }
+ checkLog("")
+
+
+ val vl1 = {
+ lazy val t1 = getInt
+ t1 + t1
+ }
+ val vl2 = {
+ lazy val t1 = getString
+ t1 + t1
+ }
+ val vl3 = {
+ lazy val t1 = getUnit
+ log(t1); log(t1)
+ }
+ checkLog("getInt:getString:getUnit:():()")
+
+
+ var vr1 = {
+ lazy val t1 = getInt
+ t1 + t1
+ }
+ var vr2 = {
+ lazy val t1 = getString
+ t1 + t1
+ }
+ var vr3 = {
+ lazy val t1 = getUnit
+ log(t1); log(t1)
+ }
+ checkLog("getInt:getString:getUnit:():()")
+
+
+ lazy val lvl1 = {
+ lazy val t1 = getInt
+ t1 + t1
+ }
+ lazy val lvl2 = {
+ lazy val t1 = getString
+ t1 + t1
+ }
+ lazy val lvl3 = {
+ lazy val t1 = getUnit
+ log(t1); log(t1)
+ }
+ checkLog("")
+
+
+ {
+ lazy val t1 = getInt
+ lazy val t2 = getString
+ lazy val t3 = getUnit
+
+ log(t1 + t1)
+ log(t2 + t2)
+ log(t3); log(t3)
+ }
+ checkLog("getInt:2:getString:ss:getUnit:():()")
+
+
+ def run(): Unit = {
+ log(t1); log(t1);
+ log(t2); log(t2);
+ log(t3); log(t3);
+ checkLog("getInt:1:1:getString:s:s:getUnit:():()")
+
+ log(m1); log(m1)
+ log(m2); log(m2)
+ log(m3); log(m3)
+ checkLog("getInt:2:getInt:2:getString:ss:getString:ss:getUnit:():():():getUnit:():():()")
+
+ log(vl1); log(vl1)
+ log(vl2); log(vl2)
+ log(vl3); log(vl3)
+ checkLog("2:2:ss:ss:():()")
+
+ log(vr1); log(vr1); vr1 = 393; log(vr1)
+ log(vr2); log(vr2); vr2 = "h"; log(vr2)
+ log(vr3); log(vr3); vr3 = () ; log(vr3)
+ checkLog("2:2:393:ss:ss:h:():():()")
+
+ log(lvl1); log(lvl1)
+ log(lvl2); log(lvl2)
+ log(lvl3); log(lvl3)
+ checkLog("getInt:2:2:getString:ss:ss:getUnit:():():():()")
+ }
+}
+
+class D extends T
+
+class D1 extends T {
+ override lazy val t1 = { log("o-t1"); -1 }
+ checkLog("")
+
+ override def m1 = { log("o-m1"); -2 }
+ override val m2 = { log("o-m2"); "n" }
+ override lazy val m3 = { log("o-m3") }
+ checkLog("o-m2")
+
+ override val vl1 = { log("o-vl1"); -3 }
+ checkLog("o-vl1")
+
+ override lazy val lvl1 = { log("o-lvl1"); -4 }
+ checkLog("")
+
+ override def run(): Unit = {
+ log(t1); log(t1)
+ checkLog("o-t1:-1:-1")
+
+ log(m1); log(m1)
+ log(m2); log(m2)
+ log(m3); log(m3)
+ checkLog("o-m1:-2:o-m1:-2:n:n:o-m3:():()")
+
+ log(vl1); log(vl1)
+ checkLog("-3:-3")
+
+ log(lvl1); log(lvl1)
+ checkLog("o-lvl1:-4:-4")
+ }
+}
+
+class E {
+ object T { log("init T"); override def toString = "T" }
+ def m = { object T { log("init T"); val x = 1 }; T.x }
+ checkLog("")
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val c = new C
+ c.run()
+
+ val lzyComputeMethods = c.getClass.getDeclaredMethods.filter(_.getName contains "lzycompute").map(_.getName).toList.sorted
+ val expComputeMethods = List("lvl1$lzycompute", "lvl2$lzycompute", "lvl3$lzycompute", "t1$lzycompute", "t2$lzycompute", "t3$lzycompute")
+ assert(
+ lzyComputeMethods == expComputeMethods,
+ s"wrong lzycompute methods. expected:\n$expComputeMethods\nfound:\n$lzyComputeMethods")
+
+ val fields = c.getClass.getDeclaredFields.toList.sortBy(_.getName).map(_.toString)
+ val expFields = List(
+ "private volatile byte C.bitmap$0",
+ "private int C.lvl1",
+ "private java.lang.String C.lvl2",
+ "private scala.runtime.BoxedUnit C.lvl3",
+ "private int C.t1",
+ "private java.lang.String C.t2",
+ "private scala.runtime.BoxedUnit C.t3",
+ "private final int C.vl1",
+ "private final java.lang.String C.vl2",
+ "private final scala.runtime.BoxedUnit C.vl3",
+ "private int C.vr1",
+ "private java.lang.String C.vr2",
+ "private scala.runtime.BoxedUnit C.vr3")
+ assert(
+ fields == expFields,
+ s"wrong fields. expected:\n$expFields\nfound:\n$fields")
+
+
+ val d = new D
+ d.run()
+
+ val dFields = d.getClass.getDeclaredFields.toList.sortBy(_.getName).map(_.toString)
+ assert(
+ dFields == expFields.map(_.replaceAll(" C.", " D.")),
+ s"wrong fields. expected:\n$expFields\nfound:\n$fields")
+
+
+ val d1 = new D1
+ d1.run()
+
+ val e = new E
+ log(e.T); log(e.T)
+ checkLog("init T:T:T")
+ log(e.m); log(e.m)
+ checkLog("init T:1:init T:1")
+ }
+}
diff --git a/test/files/run/lazy_local_labels.check b/test/files/run/lazy_local_labels.check
new file mode 100644
index 0000000000..e42c8fb8ce
--- /dev/null
+++ b/test/files/run/lazy_local_labels.check
@@ -0,0 +1,9 @@
+HI
+HI
+HI
+HI
+HI
+HI
+HI
+HI
+HI
diff --git a/test/files/run/lazy_local_labels.scala b/test/files/run/lazy_local_labels.scala
new file mode 100644
index 0000000000..f4a1cdf689
--- /dev/null
+++ b/test/files/run/lazy_local_labels.scala
@@ -0,0 +1,28 @@
+// should print HI nine times to indicate the lazy val has been re-initialized on every iteration
+object Test extends App {
+ def fooDo: Unit = {
+ var i = 3
+ do {
+ lazy val x = { println("HI"); 1 }
+ i -= x
+ } while(i > 0)
+ }
+
+ def fooWhile: Unit = {
+ var i = 3
+ while(i > 0) {
+ lazy val x = { println("HI"); 1 }
+ i -= x
+ }
+ }
+
+ @annotation.tailrec def fooTail(i: Int): Unit = {
+ lazy val x = { println("HI"); 1 }
+ if (i > 0) fooTail(i - x)
+ }
+
+
+ fooWhile
+ fooDo
+ fooTail(3)
+}
diff --git a/test/files/run/programmatic-main.check b/test/files/run/programmatic-main.check
index 03f8273c17..cf8595db5d 100644
--- a/test/files/run/programmatic-main.check
+++ b/test/files/run/programmatic-main.check
@@ -10,18 +10,17 @@ superaccessors 6 add super accessors in traits and nested classes
pickler 8 serialize symbol tables
refchecks 9 reference/override checking, translate nested objects
uncurry 10 uncurry, translate function values to anonymous classes
- fields 11 synthesize accessors and fields
+ fields 11 synthesize accessors and fields, including bitmaps for la...
tailcalls 12 replace tail calls by jumps
specialize 13 @specialized-driven class and method specialization
explicitouter 14 this refs to outer pointers
erasure 15 erase types, add interfaces for traits
posterasure 16 clean up erased inline classes
- lazyvals 17 allocate bitmaps, translate lazy vals into lazified defs
- lambdalift 18 move nested functions to top level
- constructors 19 move field definitions into constructors
- flatten 20 eliminate inner classes
- mixin 21 mixin composition
- cleanup 22 platform-specific cleanups, generate reflective calls
- delambdafy 23 remove lambdas
- jvm 24 generate JVM bytecode
- terminal 25 the last phase during a compilation run
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ delambdafy 22 remove lambdas
+ jvm 23 generate JVM bytecode
+ terminal 24 the last phase during a compilation run
diff --git a/test/files/run/t3569.check b/test/files/run/t3569.check
index a9fb5ff32e..e0e1d6c405 100644
--- a/test/files/run/t3569.check
+++ b/test/files/run/t3569.check
@@ -2,6 +2,8 @@
private final int Test$X.val1
private final int Test$X.val2
private final int Test$X.val3
+private int Test$X.const1
+private int Test$X.const2
private int Test$X.lval1
private int Test$X.lval2
private int Test$X.lval3
diff --git a/test/files/run/t3569.scala b/test/files/run/t3569.scala
index eb3b424439..7da4de9e95 100644
--- a/test/files/run/t3569.scala
+++ b/test/files/run/t3569.scala
@@ -4,7 +4,13 @@ object Test {
lazy val lv = scala.util.Random.nextInt()
- class X(final var x: Int) {
+ trait T { final lazy val const1 = 1 } // no fields
+
+ class X(final var x: Int) extends T {
+ // a lazy val does not receive a constant type, for backwards compat (e.g. for the repl)
+ // besides, since you explicitly wanted something lazy, we'll give you something lazy! (a field and a bitmap)
+ final lazy val const2 = 2
+
final var var1: Int = 0
final private var var2: Int = 0
final private[this] var var3: Int = 0
diff --git a/test/files/run/t5552.check b/test/files/run/t5552.check
index a19a60840e..73ad9cf824 100644
--- a/test/files/run/t5552.check
+++ b/test/files/run/t5552.check
@@ -1,2 +1,6 @@
+lazy: 3
(3,3)
+(3,3)
+lazy: 3.0
+(3.0,3.0)
(3.0,3.0)
diff --git a/test/files/run/t5552.scala b/test/files/run/t5552.scala
index afb8a1f0be..5b717f9e13 100644
--- a/test/files/run/t5552.scala
+++ b/test/files/run/t5552.scala
@@ -1,10 +1,14 @@
class C[@specialized(Int) A](a:A) {
- lazy val b = (a, a)
+ lazy val b = {println(s"lazy: $a"); (a, a)} // there should only be two instances of "lazy" in the output
def c = b
}
object Test {
def main(args:Array[String]) {
- println(new C(3).c)
- println(new C(3.0).c)
+ val cInt = new C(3)
+ println(cInt.c)
+ println(cInt.c)
+ val cFloat = new C(3.0)
+ println(cFloat.c)
+ println(cFloat.c)
}
}
diff --git a/test/files/run/t6028.check b/test/files/run/t6028.check
index 532d177300..c2e3ca58d8 100644
--- a/test/files/run/t6028.check
+++ b/test/files/run/t6028.check
@@ -54,7 +54,7 @@ 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$lzycompute$1(barParam$1: Int, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = {
+ final <stable> private[this] def MethodLocalObject$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);
@@ -62,10 +62,6 @@ package <empty> {
});
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]();
@SerialVersionUID(value = 0) final <synthetic> class $anonfun$tryy$1 extends scala.runtime.AbstractFunction0$mcV$sp with Serializable {
def <init>($outer: T, tryyParam$1: Int, tryyLocal$1: runtime.IntRef): <$anon: Function0> = {
$anonfun$tryy$1.super.<init>();
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala
index 56da0e2493..eae5385147 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala
@@ -105,7 +105,6 @@ class ScalaInlineInfoTest extends BytecodeTesting {
("x4$(LT;)I", MethodInlineInfo(true ,false,false)),
("x5()I", MethodInlineInfo(true, false,false)),
("x5$(LT;)I", MethodInlineInfo(true ,false,false)),
- ("L$lzycompute$1(Lscala/runtime/VolatileObjectRef;)LT$L$2$;", MethodInlineInfo(true, false,false)),
("L$1(Lscala/runtime/VolatileObjectRef;)LT$L$2$;", MethodInlineInfo(true, false,false)),
("nest$1()I", MethodInlineInfo(true, false,false)),
("$init$(LT;)V", MethodInlineInfo(true,false,false))),
@@ -118,7 +117,6 @@ class ScalaInlineInfoTest extends BytecodeTesting {
val infoC = inlineInfo(c)
val expectC = InlineInfo(false, None, Map(
"O()LT$O$;" -> MethodInlineInfo(true ,false,false),
- "O$lzycompute()LT$O$;" -> MethodInlineInfo(true, false,false),
"f6()I" -> MethodInlineInfo(false,false,false),
"x1()I" -> MethodInlineInfo(false,false,false),
"T$_setter_$x1_$eq(I)V" -> MethodInlineInfo(false,false,false),
@@ -181,7 +179,6 @@ class ScalaInlineInfoTest extends BytecodeTesting {
val infoC = inlineInfo(c)
val expected = Map(
"<init>()V" -> MethodInlineInfo(false,false,false),
- "O$lzycompute()LC$O$;" -> MethodInlineInfo(true,false,false),
"O()LC$O$;" -> MethodInlineInfo(true,false,false))
assert(infoC.methodInfos == expected, mapDiff(infoC.methodInfos, expected))
assertSameMethods(c, expected.keySet)