Skip to content

Commit ee611cd

Browse files
committed
SI-8601 Don't treat int/long division, or arraylength, as dead-code
`{i, l}div` and `{i, l}rem` throw an `ArithmeticException` if the divisor is 0. `arraylength` throws a `NullPointerException` on a null reference. JVM Spec: > The only integer operations that can throw an exception are the > integer divide instructions (idiv and ldiv) and the integer > remainder instructions (irem and lrem), which throw an > ArithmeticException if the divisor is zero. > The Java virtual machine's floating-point operators do not throw > runtime exceptions > If the arrayref is null, the arraylength instruction throws a > NullPointerException. I checked the other primitives in `ICode` to see if anything else should be considered as live code. Pure: // jvm : {i, l, f, d}neg case class Negation(kind: TypeKind) extends Primitive // jvm : if{eq, ne, lt, ge, le, gt}, if{null, nonnull} // if_icmp{eq, ne, lt, ge, le, gt}, if_acmp{eq,ne} case class Test(op: TestOp, kind: TypeKind, zero: Boolean) extends Primitive // jvm : lcmp, {f, d}cmp{l, g} case class Comparison(op: ComparisonOp, kind: TypeKind) extends Primitive Impure: {i, l}{div, rem}, otherwise pure // jvm : {i, l, f, d}{add, sub, mul, div, rem} case class Arithmetic(op: ArithmeticOp, kind: TypeKind) extends Primitive Pure (overflow is silent, NaN.toInt is defined): // jvm : {i, l}{and, or, xor} case class Logical(op: LogicalOp, kind: TypeKind) extends Primitive // jvm : {i, l}{shl, ushl, shr} case class Shift(op: ShiftOp, kind: TypeKind) extends Primitive // jvm : i2{l, f, d}, l2{i, f, d}, f2{i, l, d}, d2{i, l, f}, i2{b, c, s} case class Conversion(src: TypeKind, dst: TypeKind) extends Primitive Impure! May NPE! // jvm : arraylength case class ArrayLength(kind: TypeKind) extends Primitive Pure (we know that StringBuilder.{<init>, append, toString} are pure and `append` is null safe.) // jvm : It should call the appropiate 'append' method on StringBuffer case class StringConcat(el: TypeKind) extends Primitive // jvm: it should create a new StringBuffer case object StartConcat extends Primitive // jvm: convert StringBuffer to a String case object EndConcat extends Primitive
1 parent 7872ea4 commit ee611cd

File tree

5 files changed

+28
-0
lines changed

5 files changed

+28
-0
lines changed

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

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

0 commit comments

Comments
 (0)