summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-02-22 16:05:08 -0800
committerPaul Phillips <paulp@improving.org>2012-02-22 16:08:12 -0800
commita983f2b30c352f3d62f0ac615044dcd45b1b1618 (patch)
treef8d7c602c1983452a448260973f19a42a9987215
parentd6ed9e20fea676345f17b477f484becc9c48069a (diff)
downloadscala-a983f2b30c352f3d62f0ac615044dcd45b1b1618.tar.gz
scala-a983f2b30c352f3d62f0ac615044dcd45b1b1618.tar.bz2
scala-a983f2b30c352f3d62f0ac615044dcd45b1b1618.zip
Revert recent elidable commits.
On epfl jenkins, elidable.scala fails with: [partest] java.lang.VerifyError: (class: Test$, method: main signature: ([Ljava/lang/String;)V) Unable to pop operand off an empty stack [partest] [partest] at Test.main(elidable.scala) Strangely it is fine for me on OSX with either apple's jvm or openjdk. Since tests were not running for a while I don't know which of the recent elidable commits is responsible, so given present time demands all I can do is revert them all. Revert "Fix for SI-5215: scalac crash when @elidable used in trait" This reverts commit 5e52ce9a13f12ef159e25ac80c6be2803ec48950. Revert "Fix for SI-5215 part 2: generate return value when eliding method calls" This reverts commit 61c9b4f01d99a81e15391b270bd1b5a895f65ffd. Revert "Eliminating duplication in zero creation." This reverts commit fbb7865e137e83660257fdc79d19d29ff39c775b. Revert "Disallow eliding when Nothing is expected" This reverts commit f26a47c4e8bda2f6c689b4e9b0bb5c64ccf4c699.
-rw-r--r--src/compiler/scala/reflect/internal/TreeGen.scala27
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala18
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala16
-rw-r--r--test/files/neg/elide-to-nothing.check4
-rw-r--r--test/files/neg/elide-to-nothing.flags1
-rw-r--r--test/files/neg/elide-to-nothing.scala31
-rw-r--r--test/files/run/elidable.check15
-rw-r--r--test/files/run/elidable.scala73
8 files changed, 33 insertions, 152 deletions
diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala
index cc882ad5ed..e537c6b83f 100644
--- a/src/compiler/scala/reflect/internal/TreeGen.scala
+++ b/src/compiler/scala/reflect/internal/TreeGen.scala
@@ -250,19 +250,20 @@ abstract class TreeGen {
* var x: T = _
* which is appropriate to the given Type.
*/
- def mkZero(tp: Type): Tree = Literal(mkConstantZero(tp)) setType tp
-
- def mkConstantZero(tp: Type): Constant = tp.typeSymbol match {
- case UnitClass => Constant(())
- case BooleanClass => Constant(false)
- case FloatClass => Constant(0.0f)
- case DoubleClass => Constant(0.0d)
- case ByteClass => Constant(0.toByte)
- case ShortClass => Constant(0.toShort)
- case IntClass => Constant(0)
- case LongClass => Constant(0L)
- case CharClass => Constant(0.toChar)
- case _ => Constant(null)
+ def mkZero(tp: Type): Tree = {
+ val tree = tp.typeSymbol match {
+ case UnitClass => Literal(Constant())
+ case BooleanClass => Literal(Constant(false))
+ case FloatClass => Literal(Constant(0.0f))
+ case DoubleClass => Literal(Constant(0.0d))
+ case ByteClass => Literal(Constant(0.toByte))
+ case ShortClass => Literal(Constant(0.toShort))
+ case IntClass => Literal(Constant(0))
+ case LongClass => Literal(Constant(0L))
+ case CharClass => Literal(Constant(0.toChar))
+ case _ => Literal(Constant(null))
+ }
+ tree setType tp
}
def mkZeroContravariantAfterTyper(tp: Type): Tree = {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index b9675b8270..9e801e3ea8 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -876,23 +876,7 @@ abstract class GenICode extends SubComponent {
val (newCtx, resKind) = genPrimitiveOp(app, ctx, expectedType)
generatedType = resKind
newCtx
- } else if (sym.elisionLevel.exists (_ < settings.elidebelow.value || settings.noassertions.value)) {
- // XXX settings.noassertions.value temporarily retained to avoid
- // breakage until a reasonable interface is settled upon.
- debuglog("Eliding call from " + tree.symbol.owner + " to " + sym +
- " based on its elision threshold of " + sym.elisionLevel.get)
- if (expectedType.isValueType) {
- ctx.bb.emit(CONSTANT(global.gen.mkConstantZero(expectedType.toType)), tree.pos)
- generatedType = expectedType
- }
- else if (expectedType.isNothingType) unit.error(tree.pos, "Cannot elide where Nothing is required.")
- else {
- ctx.bb.emit(CONSTANT(Constant(null)), tree.pos)
- generatedType = NullReference
- }
- ctx
- }
- else { // normal method call
+ } else { // normal method call
debuglog("Gen CALL_METHOD with sym: " + sym + " isStaticSymbol: " + sym.isStaticMember);
val invokeStyle =
if (sym.isStaticMember)
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 8b735455ba..b458d305a5 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -452,6 +452,19 @@ abstract class UnCurry extends InfoTransform
}
}
+ /** For removing calls to specially designated methods.
+ */
+ def elideIntoUnit(tree: Tree): Tree = Literal(Constant()) setPos tree.pos setType UnitClass.tpe
+ def isElidable(tree: Tree) = {
+ val sym = treeInfo.methPart(tree).symbol
+ // XXX settings.noassertions.value temporarily retained to avoid
+ // breakage until a reasonable interface is settled upon.
+ sym != null && sym.elisionLevel.exists(x => x < settings.elidebelow.value || settings.noassertions.value) && {
+ log("Eliding call from " + tree.symbol.owner + " to " + sym + " based on its elision threshold of " + sym.elisionLevel.get)
+ true
+ }
+ }
+
// ------ The tree transformers --------------------------------------------------------
def mainTransform(tree: Tree): Tree = {
@@ -489,7 +502,8 @@ abstract class UnCurry extends InfoTransform
finally this.inConstructorFlag = saved
}
- tree match {
+ if (isElidable(tree)) elideIntoUnit(tree)
+ else tree match {
case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
if (dd.symbol hasAnnotation VarargsClass) saveRepeatedParams(dd)
withNeedLift(false) {
diff --git a/test/files/neg/elide-to-nothing.check b/test/files/neg/elide-to-nothing.check
deleted file mode 100644
index 3ef05aac9a..0000000000
--- a/test/files/neg/elide-to-nothing.check
+++ /dev/null
@@ -1,4 +0,0 @@
-elide-to-nothing.scala:14: error: Cannot elide where Nothing is required.
- val b: Nothing = unimplemented()
- ^
-one error found
diff --git a/test/files/neg/elide-to-nothing.flags b/test/files/neg/elide-to-nothing.flags
deleted file mode 100644
index 59a512e547..0000000000
--- a/test/files/neg/elide-to-nothing.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xelide-below 500
diff --git a/test/files/neg/elide-to-nothing.scala b/test/files/neg/elide-to-nothing.scala
deleted file mode 100644
index 5008e8bc1d..0000000000
--- a/test/files/neg/elide-to-nothing.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/** Test which should fail compilation */
-class ElysianFailed {
-
- import ElysianField._
-
- // fine
- val a: Int = myInt
-
- // fine
- unimplemented()
-
- // not fine
- val b: Nothing = unimplemented()
-
-}
-
-object ElysianField {
-
- import annotation.elidable
-
- @elidable(100) def unimplemented(): Nothing = throw new UnsupportedOperationException
-
- @elidable(100) def myInt: Int = 17
-
-}
-
-
-
-
-
diff --git a/test/files/run/elidable.check b/test/files/run/elidable.check
index 88cf98e0d1..4ce04f0040 100644
--- a/test/files/run/elidable.check
+++ b/test/files/run/elidable.check
@@ -1,14 +1 @@
-Good for me, I was not elided. Test.f3
-Good for me, I was not elided. O.f3
-Good for me, I was not elided. C.f1
-Good for me, I was not elided. C.f2
-()
-false
-0
-0
-0
-0
-0
-0.0
-0.0
-null
+Good for me, I was not elided.
diff --git a/test/files/run/elidable.scala b/test/files/run/elidable.scala
index a2f29d2caf..264efbad59 100644
--- a/test/files/run/elidable.scala
+++ b/test/files/run/elidable.scala
@@ -1,85 +1,16 @@
import annotation._
import elidable._
-trait T {
- @elidable(FINEST) def f1()
- @elidable(SEVERE) def f2()
- @elidable(FINEST) def f3() = assert(false, "Should have been elided.")
- def f4()
-}
-
-class C extends T {
- def f1() = println("Good for me, I was not elided. C.f1")
- def f2() = println("Good for me, I was not elided. C.f2")
- @elidable(FINEST) def f4() = assert(false, "Should have been elided.")
-}
-
-object O {
- @elidable(FINEST) def f1() = assert(false, "Should have been elided.")
- @elidable(INFO) def f2() = assert(false, "Should have been elided.")
- @elidable(SEVERE) def f3() = println("Good for me, I was not elided. O.f3")
- @elidable(INFO) def f4 = assert(false, "Should have been elided (no parens).")
-}
-
object Test {
@elidable(FINEST) def f1() = assert(false, "Should have been elided.")
@elidable(INFO) def f2() = assert(false, "Should have been elided.")
- @elidable(SEVERE) def f3() = println("Good for me, I was not elided. Test.f3")
+ @elidable(SEVERE) def f3() = println("Good for me, I was not elided.")
@elidable(INFO) def f4 = assert(false, "Should have been elided (no parens).")
-
- @elidable(FINEST) def f5() = {}
- @elidable(FINEST) def f6() = true
- @elidable(FINEST) def f7() = 1:Byte
- @elidable(FINEST) def f8() = 1:Short
- @elidable(FINEST) def f9() = 1:Char
- @elidable(FINEST) def fa() = 1
- @elidable(FINEST) def fb() = 1l
- @elidable(FINEST) def fc() = 1.0f
- @elidable(FINEST) def fd() = 1.0
- @elidable(FINEST) def fe() = "s"
-
+
def main(args: Array[String]): Unit = {
f1()
f2()
f3()
f4
- O.f1()
- O.f2()
- O.f3()
- O.f4
-
- val c = new C
- c.f1()
- c.f2()
- c.f3()
- c.f4()
-
- // make sure a return value is still available when eliding a call
- println(f5())
- println(f6())
- println(f7())
- println(f8())
- println(f9().toInt)
- println(fa())
- println(fb())
- println(fc())
- println(fd())
- println(fe())
-
- // this one won't show up in the output because a call to f1 is elidable when accessed through T
- (c:T).f1()
-
- // Test whether the method definitions are still available.
- List("Test", "Test$", "O", "O$", "C", "T") foreach { className =>
- List("f1", "f2", "f3", "f4") foreach { methodName =>
- Class.forName(className).getMethod(methodName)
- }
- }
- List("Test", "Test$") foreach { className =>
- List("f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe") foreach { methodName =>
- Class.forName(className).getMethod(methodName)
- }
- }
- Class.forName("T$class").getMethod("f3", classOf[T])
}
}