Merge "Old tests run with new system." into dalvik-dev
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 67acf9d..1963985 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -546,8 +546,9 @@
     std::string location = dex_cache->GetLocation()->ToModifiedUtf8();
     location_to_dex_cache[location] = dex_cache;
   }
-  CHECK_EQ(boot_class_path.size() + class_path.size(),
-           location_to_dex_cache.size());
+  CHECK(boot_class_path.size() + class_path.size() == location_to_dex_cache.size())
+      << "(" << boot_class_path.size() << " + " << class_path.size()
+      << " != " << location_to_dex_cache.size() << ")";
 
   // reinit boot_class_path with DexFile arguments and found DexCaches
   for (size_t i = 0; i != boot_class_path.size(); ++i) {
diff --git a/src/common_test.h b/src/common_test.h
index b56090b..bbf2e2f 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -16,6 +16,7 @@
 #include "gtest/gtest.h"
 #include "heap.h"
 #include "runtime.h"
+#include "stl_util.h"
 #include "stringprintf.h"
 #include "thread.h"
 #include "unicode/uclean.h"
@@ -296,14 +297,7 @@
 // TODO: isn't gtest supposed to be able to print STL types for itself?
 template <typename T>
 std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
-  os << "[";
-  for (size_t i = 0; i < rhs.size(); ++i) {
-    os << rhs[i];
-    if (i < rhs.size() - 1) {
-      os << ", ";
-    }
-  }
-  os << "]";
+  os << ::art::ToString(rhs);
   return os;
 }
 
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 9e026be..80118d8 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -187,8 +187,7 @@
     oatFlushAllRegs(cUnit);
     if (SLOW_FIELD_PATH || field == NULL) {
         // Slow path
-        LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
-            << " unresolved at compile time";
+        warnIfUnresolved(cUnit, fieldIdx, field);
         int funcOffset = isObject ? OFFSETOF_MEMBER(Thread, pSetObjStatic)
                                   : OFFSETOF_MEMBER(Thread, pSet32Static);
         loadWordDisp(cUnit, rSELF, funcOffset, rLR);
@@ -252,8 +251,7 @@
     bool isVolatile = false;
 #endif
     if (SLOW_FIELD_PATH || field == NULL || isVolatile) {
-        LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
-            << " unresolved at compile time";
+        warnIfUnresolved(cUnit, fieldIdx, field);
         loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pSet64Static), rLR);
         loadConstant(cUnit, r0, mir->dalvikInsn.vB);
         loadCurrMethodDirect(cUnit, r1);
@@ -304,8 +302,7 @@
 #endif
     oatFlushAllRegs(cUnit);
     if (SLOW_FIELD_PATH || field == NULL || isVolatile) {
-        LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
-            << " unresolved at compile time";
+        warnIfUnresolved(cUnit, fieldIdx, field);
         loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pGet64Static), rLR);
         loadConstant(cUnit, r0, mir->dalvikInsn.vB);
         loadCurrMethodDirect(cUnit, r1);
@@ -354,9 +351,8 @@
                      (mir->dalvikInsn.opcode == OP_SGET_OBJECT_VOLATILE));
     oatFlushAllRegs(cUnit);
     if (SLOW_FIELD_PATH || field == NULL) {
-        LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
-            << " unresolved at compile time";
         // Slow path
+        warnIfUnresolved(cUnit, fieldIdx, field);
         int funcOffset = isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic)
                                   : OFFSETOF_MEMBER(Thread, pGet32Static);
         loadWordDisp(cUnit, rSELF, funcOffset, rLR);
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 173aa64..5ef7687 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -37,6 +37,15 @@
     return class_name + "." + field_name;
 }
 
+void warnIfUnresolved(CompilationUnit* cUnit, int fieldIdx, Field* field) {
+  if (field == NULL) {
+    LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
+              << " unresolved at compile time";
+  } else {
+    // We also use the slow path for wide volatile fields.
+  }
+}
+
 /*
  * Construct an s4 from two consecutive half-words of switch data.
  * This needs to check endianness because the DEX optimizer only swaps
@@ -403,12 +412,11 @@
  * Helper function for Iget/put when field not resolved at compile time.
  * Will trash call temps and return with the field offset in r0.
  */
-STATIC void getFieldOffset(CompilationUnit* cUnit, MIR* mir)
+STATIC void getFieldOffset(CompilationUnit* cUnit, MIR* mir, Field* fieldPtr)
 {
     int fieldIdx = mir->dalvikInsn.vC;
     oatFlushAllRegs(cUnit);
-    LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
-        << " unresolved at compile time";
+    warnIfUnresolved(cUnit, fieldIdx, fieldPtr);
     oatLockCallTemps(cUnit);  // Explicit register usage
     loadCurrMethodDirect(cUnit, r1);              // arg1 <= Method*
     loadWordDisp(cUnit, r1,
@@ -447,7 +455,7 @@
     RegLocation rlResult;
     RegisterClass regClass = oatRegClassBySize(size);
     if (SLOW_FIELD_PATH || fieldPtr == NULL) {
-        getFieldOffset(cUnit, mir);
+        getFieldOffset(cUnit, mir, fieldPtr);
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
@@ -481,7 +489,7 @@
         GetResolvedField(mir->dalvikInsn.vC);
     RegisterClass regClass = oatRegClassBySize(size);
     if (SLOW_FIELD_PATH || fieldPtr == NULL) {
-        getFieldOffset(cUnit, mir);
+        getFieldOffset(cUnit, mir, fieldPtr);
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlSrc = loadValue(cUnit, rlSrc, regClass);
@@ -525,7 +533,7 @@
     bool isVolatile = false;
 #endif
     if ((fieldPtr == NULL) || isVolatile) {
-        getFieldOffset(cUnit, mir);
+        getFieldOffset(cUnit, mir, fieldPtr);
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
@@ -563,7 +571,7 @@
     bool isVolatile = false;
 #endif
     if ((fieldPtr == NULL) || isVolatile) {
-        getFieldOffset(cUnit, mir);
+        getFieldOffset(cUnit, mir, fieldPtr);
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index d01d841..144ec22 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -251,6 +251,12 @@
   return result;
 }
 
+void ThrowNoSuchMethodError(ScopedJniThreadState& ts, Class* c, const char* name, const char* sig, const char* kind) {
+  std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
+  ts.Self()->ThrowNewException("Ljava/lang/NoSuchMethodError;",
+      "no %s method \"%s.%s%s\"", kind, class_descriptor.c_str(), name, sig);
+}
+
 jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
   Class* c = Decode<Class*>(ts, jni_class);
   if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
@@ -270,12 +276,7 @@
   }
 
   if (method == NULL || method->IsStatic() != is_static) {
-    std::string method_name(PrettyMethod(method));
-    // TODO: try searching for the opposite kind of method from is_static
-    // for better diagnostics?
-    ts.Self()->ThrowNewException("Ljava/lang/NoSuchMethodError;",
-        "no %s method %s", is_static ? "static" : "non-static",
-        method_name.c_str());
+    ThrowNoSuchMethodError(ts, c, name, sig, is_static ? "static" : "non-static");
     return NULL;
   }
 
@@ -2097,16 +2098,10 @@
         m = c->FindVirtualMethod(name, sig);
       }
       if (m == NULL) {
-        std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
-        ts.Self()->ThrowNewException("Ljava/lang/NoSuchMethodError;",
-            "no method \"%s.%s%s\"",
-            class_descriptor.c_str(), name, sig);
+        ThrowNoSuchMethodError(ts, c, name, sig, "static or non-static");
         return JNI_ERR;
       } else if (!m->IsNative()) {
-        std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
-        ts.Self()->ThrowNewException("Ljava/lang/NoSuchMethodError;",
-            "method \"%s.%s%s\" is not native",
-            class_descriptor.c_str(), name, sig);
+        ThrowNoSuchMethodError(ts, c, name, sig, "native");
         return JNI_ERR;
       }
 
diff --git a/src/object.cc b/src/object.cc
index 0e8e176..f8c9624 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -433,7 +433,7 @@
     // Do full linkage and set cache value for next call
     result = Runtime::Current()->GetClassLinker()->ResolveType(GetReturnTypeIdx(), this);
   }
-  CHECK(result != NULL);
+  CHECK(result != NULL) << PrettyMethod(this);
   return result;
 }
 
diff --git a/src/stl_util.h b/src/stl_util.h
index 5fcf089..d826510 100644
--- a/src/stl_util.h
+++ b/src/stl_util.h
@@ -3,6 +3,8 @@
 #ifndef ART_SRC_STL_UTIL_H_
 #define ART_SRC_STL_UTIL_H_
 
+#include <iostream>
+
 namespace art {
 
 // STLDeleteContainerPointers()
@@ -54,6 +56,20 @@
   v->clear();
 }
 
+template <class T>
+std::string ToString(const T& v) {
+  std::stringstream os;
+  os << "[";
+  for (size_t i = 0; i < v.size(); ++i) {
+    os << v[i];
+    if (i < v.size() - 1) {
+      os << ", ";
+    }
+  }
+  os << "]";
+  return os.str();
+}
+
 }  // namespace art
 
 #endif  // ART_SRC_STL_UTIL_H_