Fixes to interpreter, now passes 003-omnibus-opcodes.

- NPE checks on monitor-enter/exit
- Check for unresolvable classes in check_cast/instance_of
- Fix float/double to int/long

Change-Id: I61d72411bc3ee360c5261016c87ca6cfe077cf21
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 0cbe799..d8031c1 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -34,6 +34,11 @@
 namespace art {
 namespace interpreter {
 
+static const int32_t kMaxInt = std::numeric_limits<int32_t>::max();
+static const int32_t kMinInt = std::numeric_limits<int32_t>::min();
+static const int64_t kMaxLong = std::numeric_limits<int64_t>::max();
+static const int64_t kMinLong = std::numeric_limits<int64_t>::min();
+
 static void UnstartedRuntimeInvoke(Thread* self, AbstractMethod* target_method,
                                    Object* receiver, JValue* args, JValue* result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -502,7 +507,6 @@
 
 static void DoIntDivide(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
     int32_t dividend, int32_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  const int32_t kMinInt = std::numeric_limits<int32_t>::min();
   if (UNLIKELY(divisor == 0)) {
     self->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
   } else if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
@@ -514,7 +518,6 @@
 
 static void DoIntRemainder(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
     int32_t dividend, int32_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  const int32_t kMinInt = std::numeric_limits<int32_t>::min();
   if (UNLIKELY(divisor == 0)) {
     self->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
   } else if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
@@ -526,7 +529,6 @@
 
 static void DoLongDivide(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
     int64_t dividend, int64_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  const int32_t kMinLong = std::numeric_limits<int64_t>::min();
   if (UNLIKELY(divisor == 0)) {
     self->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
   } else if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
@@ -538,7 +540,6 @@
 
 static void DoLongRemainder(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
     int64_t dividend, int64_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  const int32_t kMinLong = std::numeric_limits<int64_t>::min();
   if (UNLIKELY(divisor == 0)) {
     self->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
   } else if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
@@ -696,27 +697,47 @@
       case Instruction::CONST_CLASS:
         shadow_frame.SetReferenceAndVReg(dec_insn.vA, mh.ResolveClass(dec_insn.vB));
         break;
-      case Instruction::MONITOR_ENTER:
-        DoMonitorEnter(self, shadow_frame.GetReference(dec_insn.vA));
+      case Instruction::MONITOR_ENTER: {
+        Object* obj = shadow_frame.GetReference(dec_insn.vA);
+        if (UNLIKELY(obj == NULL)) {
+          ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
+        } else {
+          DoMonitorEnter(self, obj);
+        }
         break;
-      case Instruction::MONITOR_EXIT:
-        DoMonitorExit(self, shadow_frame.GetReference(dec_insn.vA));
+      }
+      case Instruction::MONITOR_EXIT: {
+        Object* obj = shadow_frame.GetReference(dec_insn.vA);
+        if (UNLIKELY(obj == NULL)) {
+          ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
+        } else {
+          DoMonitorExit(self, obj);
+        }
         break;
+      }
       case Instruction::CHECK_CAST: {
         Class* c = mh.ResolveClass(dec_insn.vB);
-        Object* obj = shadow_frame.GetReference(dec_insn.vA);
-        if (UNLIKELY(obj != NULL && !obj->InstanceOf(c))) {
-          self->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
-              "%s cannot be cast to %s",
-              PrettyDescriptor(obj->GetClass()).c_str(),
-              PrettyDescriptor(c).c_str());
+        if (UNLIKELY(c == NULL)) {
+          CHECK(self->IsExceptionPending());
+        } else {
+          Object* obj = shadow_frame.GetReference(dec_insn.vA);
+          if (UNLIKELY(obj != NULL && !obj->InstanceOf(c))) {
+            self->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
+                "%s cannot be cast to %s",
+                PrettyDescriptor(obj->GetClass()).c_str(),
+                PrettyDescriptor(c).c_str());
+          }
         }
         break;
       }
       case Instruction::INSTANCE_OF: {
         Class* c = mh.ResolveClass(dec_insn.vC);
-        Object* obj = shadow_frame.GetReference(dec_insn.vB);
-        shadow_frame.SetVReg(dec_insn.vA, (obj != NULL && obj->InstanceOf(c)) ? 1 : 0);
+        if (UNLIKELY(c == NULL)) {
+          CHECK(self->IsExceptionPending());
+        } else {
+          Object* obj = shadow_frame.GetReference(dec_insn.vB);
+          shadow_frame.SetVReg(dec_insn.vA, (obj != NULL && obj->InstanceOf(c)) ? 1 : 0);
+        }
         break;
       }
       case Instruction::ARRAY_LENGTH:  {
@@ -825,7 +846,7 @@
         int64_t val1 = shadow_frame.GetVRegLong(dec_insn.vB);
         int64_t val2 = shadow_frame.GetVRegLong(dec_insn.vC);
         int32_t result;
-        if (val1 < val2) {
+        if (val1 > val2) {
           result = 1;
         } else if (val1 == val2) {
           result = 0;
@@ -1295,21 +1316,61 @@
       case Instruction::LONG_TO_DOUBLE:
         shadow_frame.SetVRegDouble(dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB));
         break;
-      case Instruction::FLOAT_TO_INT:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVRegFloat(dec_insn.vB));
+      case Instruction::FLOAT_TO_INT: {
+        float val = shadow_frame.GetVRegFloat(dec_insn.vB);
+        if (val != val) {
+          shadow_frame.SetVReg(dec_insn.vA, 0);
+        } else if (val > static_cast<float>(kMaxInt)) {
+          shadow_frame.SetVReg(dec_insn.vA, kMaxInt);
+        } else if (val < static_cast<float>(kMinInt)) {
+          shadow_frame.SetVReg(dec_insn.vA, kMinInt);
+        } else {
+          shadow_frame.SetVReg(dec_insn.vA, val);
+        }
         break;
-      case Instruction::FLOAT_TO_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA, shadow_frame.GetVRegFloat(dec_insn.vB));
+      }
+      case Instruction::FLOAT_TO_LONG: {
+        float val = shadow_frame.GetVRegFloat(dec_insn.vB);
+        if (val != val) {
+          shadow_frame.SetVRegLong(dec_insn.vA, 0);
+        } else if (val > static_cast<float>(kMaxLong)) {
+          shadow_frame.SetVRegLong(dec_insn.vA, kMaxLong);
+        } else if (val < static_cast<float>(kMinLong)) {
+          shadow_frame.SetVRegLong(dec_insn.vA, kMinLong);
+        } else {
+          shadow_frame.SetVRegLong(dec_insn.vA, val);
+        }
         break;
+      }
       case Instruction::FLOAT_TO_DOUBLE:
         shadow_frame.SetVRegDouble(dec_insn.vA, shadow_frame.GetVRegFloat(dec_insn.vB));
         break;
-      case Instruction::DOUBLE_TO_INT:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVRegDouble(dec_insn.vB));
+      case Instruction::DOUBLE_TO_INT: {
+        double val = shadow_frame.GetVRegDouble(dec_insn.vB);
+        if (val != val) {
+          shadow_frame.SetVReg(dec_insn.vA, 0);
+        } else if (val > static_cast<double>(kMaxInt)) {
+          shadow_frame.SetVReg(dec_insn.vA, kMaxInt);
+        } else if (val < static_cast<double>(kMinInt)) {
+          shadow_frame.SetVReg(dec_insn.vA, kMinInt);
+        } else {
+          shadow_frame.SetVReg(dec_insn.vA, val);
+        }
         break;
-      case Instruction::DOUBLE_TO_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA, shadow_frame.GetVRegDouble(dec_insn.vB));
+      }
+      case Instruction::DOUBLE_TO_LONG: {
+        double val = shadow_frame.GetVRegDouble(dec_insn.vB);
+        if (val != val) {
+          shadow_frame.SetVRegLong(dec_insn.vA, 0);
+        } else if (val > static_cast<double>(kMaxLong)) {
+          shadow_frame.SetVRegLong(dec_insn.vA, kMaxLong);
+        } else if (val < static_cast<double>(kMinLong)) {
+          shadow_frame.SetVRegLong(dec_insn.vA, kMinLong);
+        } else {
+          shadow_frame.SetVRegLong(dec_insn.vA, val);
+        }
         break;
+      }
       case Instruction::DOUBLE_TO_FLOAT:
         shadow_frame.SetVRegFloat(dec_insn.vA, shadow_frame.GetVRegDouble(dec_insn.vB));
         break;