Skip to content

Commit 0d98397

Browse files
committed
Merge pull request #3760 from retronym/ticket/8601
Reining back over-eager optimizations.
2 parents 7872ea4 + dcade51 commit 0d98397

File tree

10 files changed

+61
-7
lines changed

10 files changed

+61
-7
lines changed

src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,10 @@ abstract class ClosureElimination extends SubComponent {
5656
case (BOX(t1), UNBOX(t2)) if (t1 == t2) =>
5757
Some(Nil)
5858

59-
case (LOAD_FIELD(sym, isStatic), DROP(_)) if !sym.hasAnnotation(definitions.VolatileAttr) =>
60-
if (isStatic)
61-
Some(Nil)
62-
else
63-
Some(DROP(REFERENCE(definitions.ObjectClass)) :: Nil)
59+
// Can't eliminate (LOAD_FIELD, DROP) without eliding side effects:
60+
// - static class initialization
61+
// - NPE if the receiver is null
62+
// We could replace the LOAD/DROP with a null check to preserve semantics.
6463

6564
case _ => None
6665
}

src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,9 @@ abstract class DeadCodeElimination extends SubComponent {
167167
set += idx
168168
localStores(key) = set
169169

170-
case RETURN(_) | JUMP(_) | CJUMP(_, _, _, _) | CZJUMP(_, _, _, _) | STORE_FIELD(_, _) |
170+
case RETURN(_) | JUMP(_) | CJUMP(_, _, _, _) | CZJUMP(_, _, _, _) | STORE_FIELD(_, _) | LOAD_FIELD(_, _) | // Why LOAD_FIELD? It can NPE!
171171
THROW(_) | LOAD_ARRAY_ITEM(_) | STORE_ARRAY_ITEM(_) | SCOPE_ENTER(_) | SCOPE_EXIT(_) | STORE_THIS(_) |
172-
LOAD_EXCEPTION(_) | SWITCH(_, _) | MONITOR_ENTER() | MONITOR_EXIT() | CHECK_CAST(_) =>
172+
LOAD_EXCEPTION(_) | SWITCH(_, _) | MONITOR_ENTER() | MONITOR_EXIT() | CHECK_CAST(_) | CREATE_ARRAY(_, _) =>
173173
moveToWorkList()
174174

175175
case CALL_METHOD(m1, _) if isSideEffecting(m1) =>
@@ -193,6 +193,8 @@ abstract class DeadCodeElimination extends SubComponent {
193193
moveToWorkListIf(necessary)
194194
case LOAD_MODULE(sym) if isLoadNeeded(sym) =>
195195
moveToWorkList() // SI-4859 Module initialization might side-effect.
196+
case CALL_PRIMITIVE(Arithmetic(DIV | REM, INT | LONG) | ArrayLength(_)) =>
197+
moveToWorkList() // SI-8601 Might divide by zero
196198
case _ => ()
197199
moveToWorkListIf(cond = false)
198200
}

test/files/run/t8601.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-optimize

test/files/run/t8601.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object Test {
2+
def idiv(x: Int): Unit = x / 0
3+
def ldiv(x: Long): Unit = x / 0
4+
def irem(x: Int): Unit = x % 0
5+
def lrem(x: Long): Unit = x % 0
6+
7+
def check(x: => Any) = try { x; sys.error("failed to throw divide by zero!") } catch { case _: ArithmeticException => }
8+
9+
def main(args: Array[String]) {
10+
check(idiv(1))
11+
check(ldiv(1L))
12+
check(irem(1))
13+
check(lrem(1L))
14+
}
15+
}

test/files/run/t8601b.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-optimize

test/files/run/t8601b.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
object Test {
2+
def len(x: Array[String]): Unit = x.length
3+
def load(x: Array[String]): Unit = x(0)
4+
def newarray(i: Int): Unit = new Array[Int](i)
5+
6+
def check(x: => Any) = try { x; sys.error("failed to throw NPE!") } catch { case _: NullPointerException => }
7+
def checkNegSize(x: => Any) = try { x; sys.error("failed to throw NegativeArraySizeException!") } catch { case _: NegativeArraySizeException => }
8+
9+
def main(args: Array[String]) {
10+
check(len(null)) // bug: did not NPE
11+
check(load(null))
12+
checkNegSize(newarray(-1))
13+
}
14+
}

test/files/run/t8601c.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-optimize

test/files/run/t8601c.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
object Test {
2+
def loadField(x: scala.runtime.IntRef): Unit = x.elem
3+
def storeField(x: scala.runtime.IntRef): Unit = x.elem = 42
4+
5+
def check(x: => Any) = try { x; sys.error("failed to throw NPE!") } catch { case _: NullPointerException => }
6+
7+
def main(args: Array[String]) {
8+
check(loadField(null)) // bug: did not NPE under -Ydead-code
9+
check(storeField(null))
10+
11+
}
12+
}

test/files/run/t8601d.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-optimize

test/files/run/t8601d.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Test {
2+
def monitor(x: AnyRef): Unit = {x.synchronized(()); ()}
3+
def check(x: => Any) = try { x; sys.error("failed to throw NPE") } catch { case _: NullPointerException => }
4+
5+
def main(args: Array[String]) {
6+
check(monitor(null))
7+
}
8+
}

0 commit comments

Comments
 (0)