Unify static and instance helpers for get/put.

Change-Id: I2bb0f73ecdf665acba3f490a01eb4ad73103bc74
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 0338027..7197754 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -2234,91 +2234,91 @@
       break;
 
     case Instruction::IGET_BOOLEAN:
-      VerifyIGet(dec_insn, reg_types_.Boolean(), true);
+      VerifyISGet(dec_insn, reg_types_.Boolean(), true, false);
       break;
     case Instruction::IGET_BYTE:
-      VerifyIGet(dec_insn, reg_types_.Byte(), true);
+      VerifyISGet(dec_insn, reg_types_.Byte(), true, false);
       break;
     case Instruction::IGET_CHAR:
-      VerifyIGet(dec_insn, reg_types_.Char(), true);
+      VerifyISGet(dec_insn, reg_types_.Char(), true, false);
       break;
     case Instruction::IGET_SHORT:
-      VerifyIGet(dec_insn, reg_types_.Short(), true);
+      VerifyISGet(dec_insn, reg_types_.Short(), true, false);
       break;
     case Instruction::IGET:
-      VerifyIGet(dec_insn, reg_types_.Integer(), true);
+      VerifyISGet(dec_insn, reg_types_.Integer(), true, false);
       break;
     case Instruction::IGET_WIDE:
-      VerifyIGet(dec_insn, reg_types_.Long(), true);
+      VerifyISGet(dec_insn, reg_types_.Long(), true, false);
       break;
     case Instruction::IGET_OBJECT:
-      VerifyIGet(dec_insn, reg_types_.JavaLangObject(), false);
+      VerifyISGet(dec_insn, reg_types_.JavaLangObject(), false, false);
       break;
 
     case Instruction::IPUT_BOOLEAN:
-      VerifyIPut(dec_insn, reg_types_.Boolean(), true);
+      VerifyISPut(dec_insn, reg_types_.Boolean(), true, false);
       break;
     case Instruction::IPUT_BYTE:
-      VerifyIPut(dec_insn, reg_types_.Byte(), true);
+      VerifyISPut(dec_insn, reg_types_.Byte(), true, false);
       break;
     case Instruction::IPUT_CHAR:
-      VerifyIPut(dec_insn, reg_types_.Char(), true);
+      VerifyISPut(dec_insn, reg_types_.Char(), true, false);
       break;
     case Instruction::IPUT_SHORT:
-      VerifyIPut(dec_insn, reg_types_.Short(), true);
+      VerifyISPut(dec_insn, reg_types_.Short(), true, false);
       break;
     case Instruction::IPUT:
-      VerifyIPut(dec_insn, reg_types_.Integer(), true);
+      VerifyISPut(dec_insn, reg_types_.Integer(), true, false);
       break;
     case Instruction::IPUT_WIDE:
-      VerifyIPut(dec_insn, reg_types_.Long(), true);
+      VerifyISPut(dec_insn, reg_types_.Long(), true, false);
       break;
     case Instruction::IPUT_OBJECT:
-      VerifyIPut(dec_insn, reg_types_.JavaLangObject(), false);
+      VerifyISPut(dec_insn, reg_types_.JavaLangObject(), false, false);
       break;
 
     case Instruction::SGET_BOOLEAN:
-      VerifySGet(dec_insn, reg_types_.Boolean(), true);
+      VerifyISGet(dec_insn, reg_types_.Boolean(), true, true);
       break;
     case Instruction::SGET_BYTE:
-      VerifySGet(dec_insn, reg_types_.Byte(), true);
+      VerifyISGet(dec_insn, reg_types_.Byte(), true, true);
       break;
     case Instruction::SGET_CHAR:
-      VerifySGet(dec_insn, reg_types_.Char(), true);
+      VerifyISGet(dec_insn, reg_types_.Char(), true, true);
       break;
     case Instruction::SGET_SHORT:
-      VerifySGet(dec_insn, reg_types_.Short(), true);
+      VerifyISGet(dec_insn, reg_types_.Short(), true, true);
       break;
     case Instruction::SGET:
-      VerifySGet(dec_insn, reg_types_.Integer(), true);
+      VerifyISGet(dec_insn, reg_types_.Integer(), true, true);
       break;
     case Instruction::SGET_WIDE:
-      VerifySGet(dec_insn, reg_types_.Long(), true);
+      VerifyISGet(dec_insn, reg_types_.Long(), true, true);
       break;
     case Instruction::SGET_OBJECT:
-      VerifySGet(dec_insn, reg_types_.JavaLangObject(), false);
+      VerifyISGet(dec_insn, reg_types_.JavaLangObject(), false, true);
       break;
 
     case Instruction::SPUT_BOOLEAN:
-      VerifySPut(dec_insn, reg_types_.Boolean(), true);
+      VerifyISPut(dec_insn, reg_types_.Boolean(), true, true);
       break;
     case Instruction::SPUT_BYTE:
-      VerifySPut(dec_insn, reg_types_.Byte(), true);
+      VerifyISPut(dec_insn, reg_types_.Byte(), true, true);
       break;
     case Instruction::SPUT_CHAR:
-      VerifySPut(dec_insn, reg_types_.Char(), true);
+      VerifyISPut(dec_insn, reg_types_.Char(), true, true);
       break;
     case Instruction::SPUT_SHORT:
-      VerifySPut(dec_insn, reg_types_.Short(), true);
+      VerifyISPut(dec_insn, reg_types_.Short(), true, true);
       break;
     case Instruction::SPUT:
-      VerifySPut(dec_insn, reg_types_.Integer(), true);
+      VerifyISPut(dec_insn, reg_types_.Integer(), true, true);
       break;
     case Instruction::SPUT_WIDE:
-      VerifySPut(dec_insn, reg_types_.Long(), true);
+      VerifyISPut(dec_insn, reg_types_.Long(), true, true);
       break;
     case Instruction::SPUT_OBJECT:
-      VerifySPut(dec_insn, reg_types_.JavaLangObject(), false);
+      VerifyISPut(dec_insn, reg_types_.JavaLangObject(), false, true);
       break;
 
     case Instruction::INVOKE_VIRTUAL:
@@ -2425,16 +2425,16 @@
             if (this_type.IsZero()) {
               /* null pointer always passes (and always fails at runtime) */
             } else {
-              Class* this_class = this_type.GetClass();
-              if (this_type.IsUninitializedReference() || this_class == NULL) {
-                Fail(VERIFY_ERROR_GENERIC) << "interface call on uninitialized";
+              if (this_type.IsUninitializedTypes()) {
+                Fail(VERIFY_ERROR_GENERIC) << "interface call on uninitialized object "
+                    << this_type;
                 break;
               }
-              if (!this_class->IsObjectClass() && !called_interface->IsAssignableFrom(this_class)) {
+              if (this_type.IsReference() && !this_type.GetClass()->IsObjectClass() &&
+                  !called_interface->IsAssignableFrom(this_type.GetClass())) {
                 Fail(VERIFY_ERROR_GENERIC) << "unable to match abstract method '"
                                            << PrettyMethod(abs_method) << "' with "
-                                           << PrettyDescriptor(this_class->GetDescriptor())
-                                           << " interfaces";
+                                           << this_type << "'s implemented interfaces";
                 break;
               }
             }
@@ -3234,104 +3234,6 @@
   }
 }
 
-void DexVerifier::VerifySGet(const Instruction::DecodedInstruction& dec_insn,
-                             const RegType& insn_type, bool is_primitive) {
-  Field* field = GetStaticField(dec_insn.vB_);
-  if (field != NULL) {
-    DCHECK(field->GetDeclaringClass()->IsResolved());
-    Class* field_class = field->GetType();
-    Class* insn_class = insn_type.GetClass();
-    if (is_primitive) {
-      if (field_class == insn_class ||
-          (field_class->IsPrimitiveFloat() && insn_class->IsPrimitiveInt()) ||
-          (field_class->IsPrimitiveDouble() && insn_class->IsPrimitiveLong())) {
-        // expected that read is of the correct primitive type or that int reads are reading
-        // floats or long reads are reading doubles
-      } else {
-        // This is a global failure rather than a class change failure as the instructions and
-        // the descriptors for the type should have been consistent within the same file at
-        // compile time
-        Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
-                                   << " to be of type " << PrettyClass(insn_class)
-                                   << " but found type " << PrettyClass(field_class) << " in sget";
-        return;
-      }
-    } else {
-      if (!insn_class->IsAssignableFrom(field_class)) {
-        Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
-                                   << " to be of type " << PrettyClass(insn_class)
-                                   << " but found type " << PrettyClass(field_class)
-                                   << " in sget-object";
-        return;
-      }
-    }
-    work_line_->SetRegisterType(dec_insn.vA_, reg_types_.FromClass(field_class));
-  }
-}
-
-void DexVerifier::VerifySPut(const Instruction::DecodedInstruction& dec_insn,
-                             const RegType& insn_type, bool is_primitive) {
-  Field* field = GetStaticField(dec_insn.vB_);
-  if (field != NULL) {
-    DCHECK(field->GetDeclaringClass()->IsResolved());
-    if (field->IsFinal() && field->GetDeclaringClass() != method_->GetDeclaringClass()) {
-      Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final static field " << PrettyField(field)
-                               << " from other class " << PrettyClass(method_->GetDeclaringClass());
-      return;
-    }
-    Class* field_class = field->GetType();
-    const RegType& field_type = reg_types_.FromClass(field_class);
-    Class* insn_class = insn_type.GetClass();
-    if (is_primitive) {
-      // Primitive field assignability rules are weaker than regular assignability rules
-      bool instruction_compatible;
-      bool value_compatible;
-      const RegType& value_type = work_line_->GetRegisterType(dec_insn.vA_);
-      if (field_type.IsIntegralTypes()) {
-        instruction_compatible = insn_type.IsIntegralTypes();
-        value_compatible = value_type.IsIntegralTypes();
-      } else if (field_type.IsFloat()) {
-        instruction_compatible = insn_type.IsInteger();  // no sput-float, so expect sput-int
-        value_compatible = value_type.IsFloatTypes();
-      } else if (field_type.IsLong()) {
-        instruction_compatible = insn_type.IsLong();
-        value_compatible = value_type.IsLongTypes();
-      } else if (field_type.IsDouble()) {
-        instruction_compatible = insn_type.IsLong();    // no sput-double, so expect sput-long
-        value_compatible = value_type.IsDoubleTypes();
-      } else {
-        instruction_compatible = false;  // reference field with primitive store
-        value_compatible = false;  // unused
-      }
-      if (!instruction_compatible) {
-        // This is a global failure rather than a class change failure as the instructions and
-        // the descriptors for the type should have been consistent within the same file at
-        // compile time
-        Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
-                                   << " to be of type " << PrettyClass(insn_class)
-                                   << " but found type " << PrettyClass(field_class) << " in sput";
-        return;
-      }
-      if (!value_compatible) {
-        Fail(VERIFY_ERROR_GENERIC) << "unexpected value in v" << dec_insn.vA_
-                                   << " of type " << value_type
-                                   << " but expected " << field_type
-                                   << " for store to " << PrettyField(field) << " in sput";
-        return;
-      }
-    } else {
-      if (!insn_class->IsAssignableFrom(field_class)) {
-        Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
-                                  << " to be compatible with type " << insn_type
-                                  << " but found type " << PrettyClass(field_class)
-                                  << " in sput-object";
-        return;
-      }
-      work_line_->VerifyRegisterType(dec_insn.vA_, field_type);
-    }
-  }
-}
-
 Field* DexVerifier::GetInstanceField(const RegType& obj_type, int field_idx) {
   Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, method_, false);
   if (field == NULL) {
@@ -3375,10 +3277,15 @@
   }
 }
 
-void DexVerifier::VerifyIGet(const Instruction::DecodedInstruction& dec_insn,
-                             const RegType& insn_type, bool is_primitive) {
-  const RegType& object_type = work_line_->GetRegisterType(dec_insn.vB_);
-  Field* field = GetInstanceField(object_type, dec_insn.vC_);
+void DexVerifier::VerifyISGet(const Instruction::DecodedInstruction& dec_insn,
+                              const RegType& insn_type, bool is_primitive, bool is_static) {
+  Field* field;
+  if (is_static) {
+    field = GetStaticField(dec_insn.vB_);
+  } else {
+    const RegType& object_type = work_line_->GetRegisterType(dec_insn.vB_);
+    field = GetInstanceField(object_type, dec_insn.vC_);
+  }
   if (field != NULL) {
     const RegType& field_type =
         reg_types_.FromDescriptor(field->GetDeclaringClass()->GetClassLoader(),
@@ -3395,7 +3302,7 @@
         // compile time
         Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
                                    << " to be of type '" << insn_type
-                                   << "' but found type '" << field_type << "' in iget";
+                                   << "' but found type '" << field_type << "' in get";
         return;
       }
     } else {
@@ -3403,7 +3310,7 @@
         Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
                                    << " to be compatible with type '" << insn_type
                                    << "' but found type '" << field_type
-                                   << "' in iget-object";
+                                   << "' in get-object";
         return;
       }
     }
@@ -3411,10 +3318,15 @@
   }
 }
 
-void DexVerifier::VerifyIPut(const Instruction::DecodedInstruction& dec_insn,
-                             const RegType& insn_type, bool is_primitive) {
-  const RegType& object_type = work_line_->GetRegisterType(dec_insn.vB_);
-  Field* field = GetInstanceField(object_type, dec_insn.vC_);
+void DexVerifier::VerifyISPut(const Instruction::DecodedInstruction& dec_insn,
+                              const RegType& insn_type, bool is_primitive, bool is_static) {
+  Field* field;
+  if (is_static) {
+    field = GetStaticField(dec_insn.vB_);
+  } else {
+    const RegType& object_type = work_line_->GetRegisterType(dec_insn.vB_);
+    field = GetInstanceField(object_type, dec_insn.vC_);
+  }
   if (field != NULL) {
     if (field->IsFinal() && field->GetDeclaringClass() != method_->GetDeclaringClass()) {
       Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field)
@@ -3433,13 +3345,13 @@
         instruction_compatible = insn_type.IsIntegralTypes();
         value_compatible = value_type.IsIntegralTypes();
       } else if (field_type.IsFloat()) {
-        instruction_compatible = insn_type.IsInteger();  // no iput-float, so expect iput-int
+        instruction_compatible = insn_type.IsInteger();  // no [is]put-float, so expect [is]put-int
         value_compatible = value_type.IsFloatTypes();
       } else if (field_type.IsLong()) {
         instruction_compatible = insn_type.IsLong();
         value_compatible = value_type.IsLongTypes();
       } else if (field_type.IsDouble()) {
-        instruction_compatible = insn_type.IsLong();  // no iput-double, so expect iput-long
+        instruction_compatible = insn_type.IsLong();  // no [is]put-double, so expect [is]put-long
         value_compatible = value_type.IsDoubleTypes();
       } else {
         instruction_compatible = false;  // reference field with primitive store
@@ -3452,14 +3364,14 @@
         Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
                                    << " to be of type '" << insn_type
                                    << "' but found type '" << field_type
-                                   << "' in iput";
+                                   << "' in put";
         return;
       }
       if (!value_compatible) {
         Fail(VERIFY_ERROR_GENERIC) << "unexpected value in v" << dec_insn.vA_
                                    << " of type " << value_type
                                    << " but expected " << field_type
-                                   << " for store to " << PrettyField(field) << " in iput";
+                                   << " for store to " << PrettyField(field) << " in put";
         return;
       }
     } else {
@@ -3467,7 +3379,7 @@
         Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
                                   << " to be compatible with type '" << insn_type
                                   << "' but found type '" << field_type
-                                  << "' in iput-object";
+                                  << "' in put-object";
         return;
       }
       work_line_->VerifyRegisterType(dec_insn.vA_, field_type);
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index e248ed4..d12e14f 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -1055,24 +1055,16 @@
   // Lookup instance field and fail for resolution violations
   Field* GetInstanceField(const RegType& obj_type, int field_idx);
 
-  // Perform verification of an iget instruction.
-  void VerifyIGet(const Instruction::DecodedInstruction& insn, const RegType& insn_type,
-                  bool is_primitive);
-
-  // Perform verification of an iput instruction.
-  void VerifyIPut(const Instruction::DecodedInstruction& insn, const RegType& insn_type,
-                  bool is_primitive);
-
   // Lookup static field and fail for resolution violations
   Field* GetStaticField(int field_idx);
 
-  // Perform verification of an sget instruction.
-  void VerifySGet(const Instruction::DecodedInstruction& insn, const RegType& insn_type,
-                  bool is_primitive);
+  // Perform verification of an iget or sget instruction.
+  void VerifyISGet(const Instruction::DecodedInstruction& insn, const RegType& insn_type,
+                   bool is_primitive, bool is_static);
 
-  // Perform verification of an sput instruction.
-  void VerifySPut(const Instruction::DecodedInstruction& insn, const RegType& insn_type,
-                  bool is_primitive);
+  // Perform verification of an iput or sput instruction.
+  void VerifyISPut(const Instruction::DecodedInstruction& insn, const RegType& insn_type,
+                   bool is_primitive, bool is_static);
 
   // Verify that the arguments in a filled-new-array instruction are valid.
   // "res_class" is the class refered to by dec_insn->vB_.