Skip to content

Commit

Permalink
Merge pull request #324 from pbatko/null-isas-instanceof
Browse files Browse the repository at this point in the history
Fix null.isInstanceOf
  • Loading branch information
densh committed Oct 20, 2016
2 parents da891ce + e84419c commit 3d6211d
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,44 @@ import nir._, Inst.Let

/** Translates instance checks to range checks on type ids. */
class IsLowering(implicit fresh: Fresh, top: Top) extends Pass {
override def preInst = {

override def preInst = eliminateIs

private def eliminateIs: PartialFunction[Inst, Seq[Inst]] = {
case Let(n, Op.Is(_, Val.Zero(_))) =>
Seq(Let(n, Op.Copy(Val.False)))

case isInst @ Let(n, Op.Is(ty, obj)) =>
val isNullV = Val.Local(fresh(), Type.Bool)
val isIsV = Val.Local(fresh(), Type.Bool)

val thenL = fresh()
val elseL = fresh()
val contL = fresh()

val thenResultV = Val.Local(fresh(), Type.Bool)
val elseResultV = Val.Local(fresh(), Type.Bool)

Seq(
// if
Let(isNullV.name,
Op.Comp(Comp.Ieq, Type.Ptr, obj, Val.Zero(Type.Ptr))),
Inst.If(isNullV, Next(thenL), Next(elseL)),
// then
Inst.Label(thenL, Seq.empty),
Let(thenResultV.name, Op.Copy(Val.False)),
Inst.Jump(Next.Label(contL, Seq(thenResultV))),
// else
Inst.Label(elseL, Seq.empty)) ++
doEliminateIs(Let(elseResultV.name, Op.Is(ty, obj))) ++
Seq(Inst.Jump(Next.Label(contL, Seq(elseResultV))),
// cont
Inst.Label(contL, Seq(isIsV)),
Let(n, Op.Copy(isIsV)))
case other => Seq(other)
}

private def doEliminateIs: PartialFunction[Inst, Seq[Inst]] = {
case Let(n, Op.Is(ClassRef(cls), obj)) if cls.range.length == 1 =>
val typeptr = Val.Local(fresh(), Type.Ptr)

Expand Down Expand Up @@ -53,6 +90,7 @@ class IsLowering(implicit fresh: Fresh, top: Top) extends Pass {
Seq(Val.I32(0), id, Val.I32(trt.id)))),
Let(n, Op.Load(Type.Bool, boolptr))
)
case other => Seq(other)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package scala.scalanative.native

object InstanceOfSuite extends tests.Suite {

// asInstanceOf

// test("expects anyRef.asInstanceOf[String] fail") {
// shouldNotGetHere((new AnyRef).asInstanceOf[String])
// }

test("expects \"\".asInstanceOf[String] succeed") {
assertNotNull("".asInstanceOf[String])
}

test("expects null.asInstanceOf[String] should succeed") {
assertNull(null.asInstanceOf[String])
}

test("expects a.asInstanceOf[String], where a = null should succeed") {
castNullToString(null)
}

def castNullToString(x: AnyRef): Unit = {
if (x.isInstanceOf[String]) {
assertNull(x.asInstanceOf[String])
}

}

def assertNull(s: String): Unit = {
assert(s == null)
}

def assertNotNull(s: String): Unit = {
assert(s != null)
}

def shouldNotGetHere(s: String): Unit = {
assert(false)
}

// isInstanceOf

test("expects (new AnyRef).asInstanceOf[AnyRef] should succeeds") {
(new AnyRef).asInstanceOf[AnyRef]
}

test("expects anyRef.isInstanceOf[String] == false") {
val anyRef = new AnyRef
assert(!anyRef.isInstanceOf[String])
}

test("expects literal null.isInstanceOf[String] == false") {
assert(!null.isInstanceOf[String])
}

test("expects \"\".isInstanceOf[String] == true") {
assert("".isInstanceOf[String])
}

test("expects a.isInstanceOf[String] == true, where a = \"\"") {
assertIsInstanceOfString("", "")
}

test("expects a.isInstanceOf[String] == false, where a = null") {
assertNullIsNotInstanceOfString(null, null)
}

def assertNullIsNotInstanceOfString(a: AnyRef, b: AnyRef): Unit = {
assert(!a.isInstanceOf[String])
assert(!b.isInstanceOf[String])
}

def assertIsInstanceOfString(a: AnyRef, b: AnyRef): Unit = {
assert(a.isInstanceOf[String])
assert(b.isInstanceOf[String])
}

}
1 change: 1 addition & 0 deletions unit-tests/src/main/scala/tests/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ object Main {
scala.scalanative.issues._337,
scala.scalanative.native.CStringSuite,
scala.scalanative.native.CInteropSuite,
scala.scalanative.native.InstanceOfSuite,
scala.ArrayIntCopySuite,
scala.ArrayDoubleCopySuite,
scala.ArrayObjectCopySuite
Expand Down

0 comments on commit 3d6211d

Please sign in to comment.