ART: Templatize IsInt & IsUint

Ensure that things are used correctly.

Change-Id: I76f082b32dcee28bbfb4c519daa401ac595873b3
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 3592d2c..33456cf 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4812,7 +4812,7 @@
   if (klass->IsInterface()) {
     // No vtable.
     size_t count = klass->NumVirtualMethods();
-    if (!IsUint(16, count)) {
+    if (!IsUint<16>(count)) {
       ThrowClassFormatError(klass.Get(), "Too many methods on interface: %zd", count);
       return false;
     }
@@ -5033,7 +5033,7 @@
       local_method->SetMethodIndex(actual_count);
       ++actual_count;
     }
-    if (!IsUint(16, actual_count)) {
+    if (!IsUint<16>(actual_count)) {
       ThrowClassFormatError(klass.Get(), "Too many methods defined on class: %zd", actual_count);
       return false;
     }
@@ -5049,7 +5049,7 @@
     klass->SetVTable(vtable.Get());
   } else {
     CHECK_EQ(klass.Get(), GetClassRoot(kJavaLangObject));
-    if (!IsUint(16, num_virtual_methods)) {
+    if (!IsUint<16>(num_virtual_methods)) {
       ThrowClassFormatError(klass.Get(), "Too many methods: %d",
                             static_cast<int>(num_virtual_methods));
       return false;
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 94d62db..19a4bd0 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -1164,15 +1164,15 @@
     break;
   case kByte:
     jval_.i = ReadSignedInt(ptr_, value_arg);
-    CHECK(IsInt(8, jval_.i));
+    CHECK(IsInt<8>(jval_.i));
     break;
   case kShort:
     jval_.i = ReadSignedInt(ptr_, value_arg);
-    CHECK(IsInt(16, jval_.i));
+    CHECK(IsInt<16>(jval_.i));
     break;
   case kChar:
     jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
-    CHECK(IsUint(16, jval_.i));
+    CHECK(IsUint<16>(jval_.i));
     break;
   case kInt:
     jval_.i = ReadSignedInt(ptr_, value_arg);
diff --git a/runtime/utils.h b/runtime/utils.h
index 1c2576c..0fbc9df 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -22,6 +22,7 @@
 #include <limits>
 #include <memory>
 #include <string>
+#include <type_traits>
 #include <vector>
 
 #include "arch/instruction_set.h"
@@ -115,32 +116,45 @@
   return (-limit <= value) && (value < limit);
 }
 
-static inline bool IsInt32(int N, int32_t value) {
-  CHECK_LT(0, N);
-  CHECK_LT(static_cast<size_t>(N), 8 * sizeof(int32_t));
-  int32_t limit = static_cast<int32_t>(1) << (N - 1);
-  return (-limit <= value) && (value < limit);
+template <typename T>
+static constexpr T GetIntLimit(size_t bits) {
+  return
+      DCHECK_CONSTEXPR(bits > 0, "bits cannot be zero", 0)
+      DCHECK_CONSTEXPR(bits < kBitsPerByte * sizeof(T), "kBits must be < max.", 0)
+      static_cast<T>(1) << (bits - 1);
 }
 
-static inline bool IsInt64(int N, int64_t value) {
-  CHECK_LT(0, N);
-  CHECK_LT(static_cast<size_t>(N), 8 * sizeof(int64_t));
-  int64_t limit = static_cast<int64_t>(1) << (N - 1);
-  return (-limit <= value) && (value < limit);
+template <size_t kBits, typename T>
+static constexpr bool IsInt(T value) {
+  static_assert(kBits > 0, "kBits cannot be zero.");
+  static_assert(kBits <= kBitsPerByte * sizeof(T), "kBits must be <= max.");
+  static_assert(std::is_signed<T>::value, "Needs a signed type.");
+  // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
+  // trivially true.
+  return (kBits == kBitsPerByte * sizeof(T)) ?
+      true :
+      (-GetIntLimit<T>(kBits) <= value) && (value < GetIntLimit<T>(kBits));
 }
 
-static inline bool IsUint(int N, intptr_t value) {
-  CHECK_LT(0, N);
-  CHECK_LT(N, kBitsPerIntPtrT);
-  intptr_t limit = static_cast<intptr_t>(1) << N;
-  return (0 <= value) && (value < limit);
+template <size_t kBits, typename T>
+static constexpr bool IsUint(T value) {
+  static_assert(kBits > 0, "kBits cannot be zero.");
+  static_assert(kBits <= kBitsPerByte * sizeof(T), "kBits must be <= max.");
+  static_assert(std::is_integral<T>::value, "Needs an integral type.");
+  // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
+  // trivially true.
+  return (0 <= value) &&
+      (kBits == kBitsPerByte * sizeof(T) ||
+          (static_cast<typename std::make_unsigned<T>::type>(value) <=
+               GetIntLimit<typename std::make_unsigned<T>::type>(kBits + 1) - 1));
 }
 
-static inline bool IsAbsoluteUint(int N, intptr_t value) {
-  CHECK_LT(0, N);
-  CHECK_LT(N, kBitsPerIntPtrT);
-  if (value < 0) value = -value;
-  return IsUint(N, value);
+template <size_t kBits, typename T>
+static constexpr bool IsAbsoluteUint(T value) {
+  static_assert(kBits <= kBitsPerByte * sizeof(T), "kBits must be < max.");
+  return (kBits == kBitsPerByte * sizeof(T)) ?
+      true :
+      IsUint<kBits, T>(value < 0 ? -value : value);
 }
 
 static inline uint16_t Low16Bits(uint32_t value) {