Interpreter fixes.

- Fixed filled_new_array to handle negative array size and wrong types.
  Also added support for objects.
- Fixed not_int/long and neg_int/long.
- Masked shift amounts.
- Disabled return type check to allow exceptions to be thrown when type
  doesn't match the method prototype.

Change-Id: I68162a121f3ba53fd6c40a31f0b6aa9ba925ea2d
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 5aa4c2d..f4091be 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -405,11 +405,6 @@
   } else {
     UnstartedRuntimeInvoke(self, target_method, receiver, arg_array.get(), result);
   }
-  // Check the return type if the result is non-null. We do the GetReturnType
-  // after the null check to avoid resolution when there's an exception pending.
-  if (result->GetL() != NULL && !mh.GetReturnType()->IsPrimitive()) {
-    CHECK(mh.GetReturnType()->IsAssignableFrom(result->GetL()->GetClass()));
-  }
   mh.ChangeMethod(shadow_frame.GetMethod());
 }
 
@@ -768,24 +763,48 @@
         bool is_range = (dec_insn.opcode == Instruction::FILLED_NEW_ARRAY_RANGE);
         int32_t length = dec_insn.vA;
         CHECK(is_range || length <= 5);
+        if (UNLIKELY(length < 0)) {
+          self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", length);
+          break;
+        }
         Class* arrayClass = ResolveVerifyAndClinit(dec_insn.vB, shadow_frame.GetMethod(), self, false, true);
+        if (UNLIKELY(arrayClass == NULL)) {
+          CHECK(self->IsExceptionPending());
+          break;
+        }
         CHECK(arrayClass->IsArrayClass());
-        if (arrayClass->GetComponentType()->IsPrimitiveInt()) {
-          IntArray* newArray = IntArray::Alloc(self, length);
-          if (newArray != NULL) {
-            for (int32_t i = 0; i < length; ++i) {
-              if (is_range) {
-                newArray->Set(i, shadow_frame.GetVReg(dec_insn.vC + i));
+        Class* componentClass = arrayClass->GetComponentType();
+        if (UNLIKELY(componentClass->IsPrimitive() && !componentClass->IsPrimitiveInt())) {
+          if (componentClass->IsPrimitiveLong() || componentClass->IsPrimitiveDouble()) {
+            self->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
+                                     "Bad filled array request for type %s",
+                                     PrettyDescriptor(componentClass).c_str());
+          } else {
+            self->ThrowNewExceptionF("Ljava/lang/InternalError;",
+                                     "Found type %s; filled-new-array not implemented for anything but \'int\'",
+                                     PrettyDescriptor(componentClass).c_str());
+          }
+          break;
+        }
+        Object* newArray = Array::Alloc(self, arrayClass, length);
+        if (newArray != NULL) {
+          for (int32_t i = 0; i < length; ++i) {
+            if (is_range) {
+              if (componentClass->IsPrimitiveInt()) {
+                newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(dec_insn.vC + i));
               } else {
-                newArray->Set(i, shadow_frame.GetVReg(dec_insn.arg[i]));
+                newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(dec_insn.vC + i));
+              }
+            } else {
+              if (componentClass->IsPrimitiveInt()) {
+                newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(dec_insn.arg[i]));
+              } else {
+                newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(dec_insn.arg[i]));
               }
             }
           }
-          result_register.SetL(newArray);
-        } else {
-          UNIMPLEMENTED(FATAL) << inst->DumpString(&mh.GetDexFile())
-              << " for array type: " << PrettyDescriptor(arrayClass);
         }
+        result_register.SetL(newArray);
         break;
       }
       case Instruction::CMPL_FLOAT: {
@@ -1287,13 +1306,13 @@
         shadow_frame.SetVReg(dec_insn.vA, -shadow_frame.GetVReg(dec_insn.vB));
         break;
       case Instruction::NOT_INT:
-        shadow_frame.SetVReg(dec_insn.vA, 0 ^ shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVReg(dec_insn.vA, ~shadow_frame.GetVReg(dec_insn.vB));
         break;
       case Instruction::NEG_LONG:
         shadow_frame.SetVRegLong(dec_insn.vA, -shadow_frame.GetVRegLong(dec_insn.vB));
         break;
       case Instruction::NOT_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA, 0 ^ shadow_frame.GetVRegLong(dec_insn.vB));
+        shadow_frame.SetVRegLong(dec_insn.vA, ~shadow_frame.GetVRegLong(dec_insn.vB));
         break;
       case Instruction::NEG_FLOAT:
         shadow_frame.SetVRegFloat(dec_insn.vA, -shadow_frame.GetVRegFloat(dec_insn.vB));
@@ -1407,17 +1426,17 @@
                     shadow_frame.GetVReg(dec_insn.vC));
         break;
       case Instruction::SHL_INT:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vB) << shadow_frame.GetVReg(dec_insn.vC));
+        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) <<
+                             (shadow_frame.GetVReg(dec_insn.vC) & 0x1f));
         break;
       case Instruction::SHR_INT:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vB) >> shadow_frame.GetVReg(dec_insn.vC));
+        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) >>
+                             (shadow_frame.GetVReg(dec_insn.vC) & 0x1f));
         break;
       case Instruction::USHR_INT:
         shadow_frame.SetVReg(dec_insn.vA,
                              static_cast<uint32_t>(shadow_frame.GetVReg(dec_insn.vB)) >>
-                             shadow_frame.GetVReg(dec_insn.vC));
+                             (shadow_frame.GetVReg(dec_insn.vC) & 0x1f));
         break;
       case Instruction::AND_INT:
         shadow_frame.SetVReg(dec_insn.vA,
@@ -1472,17 +1491,17 @@
       case Instruction::SHL_LONG:
         shadow_frame.SetVRegLong(dec_insn.vA,
                                  shadow_frame.GetVRegLong(dec_insn.vB) <<
-                                 shadow_frame.GetVReg(dec_insn.vC));
+                                 (shadow_frame.GetVReg(dec_insn.vC) & 0x3f));
         break;
       case Instruction::SHR_LONG:
         shadow_frame.SetVRegLong(dec_insn.vA,
                                  shadow_frame.GetVRegLong(dec_insn.vB) >>
-                                 shadow_frame.GetVReg(dec_insn.vC));
+                                 (shadow_frame.GetVReg(dec_insn.vC) & 0x3f));
         break;
       case Instruction::USHR_LONG:
         shadow_frame.SetVRegLong(dec_insn.vA,
                                  static_cast<uint64_t>(shadow_frame.GetVRegLong(dec_insn.vB)) >>
-                                 shadow_frame.GetVReg(dec_insn.vC));
+                                 (shadow_frame.GetVReg(dec_insn.vC) & 0x3f));
         break;
       case Instruction::ADD_FLOAT:
         shadow_frame.SetVRegFloat(dec_insn.vA,
@@ -1551,17 +1570,17 @@
                        shadow_frame.GetVReg(dec_insn.vB));
         break;
       case Instruction::SHL_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vA) << shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vA) <<
+                             (shadow_frame.GetVReg(dec_insn.vB) & 0x1f));
         break;
       case Instruction::SHR_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vA) >> shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vA) >>
+                             (shadow_frame.GetVReg(dec_insn.vB) & 0x1f));
         break;
       case Instruction::USHR_INT_2ADDR:
         shadow_frame.SetVReg(dec_insn.vA,
                              static_cast<uint32_t>(shadow_frame.GetVReg(dec_insn.vA)) >>
-                             shadow_frame.GetVReg(dec_insn.vB));
+                             (shadow_frame.GetVReg(dec_insn.vB) & 0x1f));
         break;
       case Instruction::AND_INT_2ADDR:
         shadow_frame.SetVReg(dec_insn.vA,
@@ -1620,17 +1639,17 @@
       case Instruction::SHL_LONG_2ADDR:
         shadow_frame.SetVRegLong(dec_insn.vA,
                                  shadow_frame.GetVRegLong(dec_insn.vA) <<
-                                 shadow_frame.GetVReg(dec_insn.vB));
+                                 (shadow_frame.GetVReg(dec_insn.vB) & 0x3f));
         break;
       case Instruction::SHR_LONG_2ADDR:
         shadow_frame.SetVRegLong(dec_insn.vA,
                                  shadow_frame.GetVRegLong(dec_insn.vA) >>
-                                 shadow_frame.GetVReg(dec_insn.vB));
+                                 (shadow_frame.GetVReg(dec_insn.vB) & 0x3f));
         break;
       case Instruction::USHR_LONG_2ADDR:
         shadow_frame.SetVRegLong(dec_insn.vA,
                                  static_cast<uint64_t>(shadow_frame.GetVRegLong(dec_insn.vA)) >>
-                                 shadow_frame.GetVReg(dec_insn.vB));
+                                 (shadow_frame.GetVReg(dec_insn.vB) & 0x3f));
         break;
       case Instruction::ADD_FLOAT_2ADDR:
         shadow_frame.SetVRegFloat(dec_insn.vA,
@@ -1717,15 +1736,17 @@
         shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) ^ dec_insn.vC);
         break;
       case Instruction::SHL_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) << dec_insn.vC);
+        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) <<
+                             (dec_insn.vC & 0x1f));
         break;
       case Instruction::SHR_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) >> dec_insn.vC);
+        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) >>
+                             (dec_insn.vC & 0x1f));
         break;
       case Instruction::USHR_INT_LIT8:
         shadow_frame.SetVReg(dec_insn.vA,
                              static_cast<uint32_t>(shadow_frame.GetVReg(dec_insn.vB)) >>
-                             dec_insn.vC);
+                             (dec_insn.vC & 0x1f));
         break;
       default:
         LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(&mh.GetDexFile());