x86 JNI compiler and unit tests.

Change-Id: I4c2e10328961a2e8e27c90777fe2a93737b21143
diff --git a/src/object.cc b/src/object.cc
index c2c09ca..95e8b67 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -1,16 +1,17 @@
 // Copyright 2011 Google Inc. All Rights Reserved.
 
+#include "src/object.h"
+#include <algorithm>
+#include <string.h>
 #include "src/globals.h"
 #include "src/logging.h"
-#include "src/object.h"
 #include "src/dex_file.h"
 #include "src/raw_dex_file.h"
 
-#include <algorithm>
-
 namespace art {
 
-bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2) {
+bool Class::IsInSamePackage(const StringPiece& descriptor1,
+                            const StringPiece& descriptor2) {
   size_t i = 0;
   while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
     ++i;
@@ -24,10 +25,12 @@
 }
 
 #if 0
-bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2) {
+bool Class::IsInSamePackage(const StringPiece& descriptor1,
+                            const StringPiece& descriptor2) {
   size_t size = std::min(descriptor1.size(), descriptor2.size());
   std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos;
-  pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size, descriptor2.begin());
+  pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size,
+                      descriptor2.begin());
   return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos);
 }
 #endif
@@ -67,6 +70,79 @@
   return num_registers;
 }
 
+// The number of reference arguments to this method including implicit this
+// pointer
+size_t Method::NumReferenceArgs() const {
+  size_t result = IsStatic() ? 0 : 1;
+  for (int i = 1; i < shorty_.length(); i++) {
+    if ((shorty_[i] == 'L') || (shorty_[i] == '[')) {
+      result++;
+    }
+  }
+  return result;
+}
+
+// The number of long or double arguments
+size_t Method::NumLongOrDoubleArgs() const {
+  size_t result = 0;
+  for (int i = 1; i < shorty_.length(); i++) {
+    if ((shorty_[i] == 'D') || (shorty_[i] == 'J')) {
+      result++;
+    }
+  }
+  return result;
+}
+
+// The number of reference arguments to this method before the given parameter
+// index
+size_t Method::NumReferenceArgsBefore(unsigned int param) const {
+  CHECK_LT(param, NumArgs());
+  unsigned int result = IsStatic() ? 0 : 1;
+  for (unsigned int i = 1; (i < (unsigned int)shorty_.length()) &&
+                           (i < (param + 1)); i++) {
+    if ((shorty_[i] == 'L') || (shorty_[i] == '[')) {
+      result++;
+    }
+  }
+  return result;
+}
+
+// Is the given method parameter a reference?
+bool Method::IsParamAReference(unsigned int param) const {
+  CHECK_LT(param, NumArgs());
+  if (IsStatic()) {
+    param++;  // 0th argument must skip return value at start of the shorty
+  } else if (param == 0) {
+    return true;  // this argument
+  }
+  return ((shorty_[param] == 'L') || (shorty_[param] == '['));
+}
+
+// Is the given method parameter a long or double?
+bool Method::IsParamALongOrDouble(unsigned int param) const {
+  CHECK_LT(param, NumArgs());
+  if (IsStatic()) {
+    param++;  // 0th argument must skip return value at start of the shorty
+  }
+  return (shorty_[param] == 'J') || (shorty_[param] == 'D');
+}
+
+size_t Method::ParamSizeInBytes(unsigned int param) const {
+  CHECK_LT(param, NumArgs());
+  if (IsStatic()) {
+    param++;  // 0th argument must skip return value at start of the shorty
+  } else if (param == 0) {
+    return kPointerSize;  // this argument
+  }
+  switch (shorty_[param]) {
+    case '[': return kPointerSize;
+    case 'L': return kPointerSize;
+    case 'D': return 8;
+    case 'J': return 8;
+    default:  return 4;
+  }
+}
+
 bool Method::HasSameArgumentTypes(const Method* that) const {
   const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw();
   const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_);
@@ -111,6 +187,30 @@
   return (strcmp(type1, type2) == 0);
 }
 
+Method* Class::FindDirectMethod(const StringPiece& name) const {
+  Method* result = NULL;
+  for (size_t i = 0; i < NumDirectMethods(); i++) {
+    Method* method = GetDirectMethod(i);
+    if (method->GetName().compare(name) == 0) {
+      result = method;
+      break;
+    }
+  }
+  return result;
+}
+
+Method* Class::FindVirtualMethod(const StringPiece& name) const {
+  Method* result = NULL;
+  for (size_t i = 0; i < NumVirtualMethods(); i++) {
+    Method* method = GetVirtualMethod(i);
+    if (method->GetName().compare(name) == 0) {
+      result = method;
+      break;
+    }
+  }
+  return result;
+}
+
 Method* Class::FindDirectMethodLocally(const StringPiece& name,
                                        const StringPiece& descriptor) const {
   return NULL;  // TODO
@@ -131,7 +231,7 @@
   if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
     os << kClassStatusNames[rhs - 1];
   } else {
-    os << "Class::Status[" << int(rhs) << "]";
+    os << "Class::Status[" << static_cast<int>(rhs) << "]";
   }
   return os;
 }