Expose functionality needed for linking.

Change-Id: I5abdee1d89510b9e4c2eeb5cdab45951b5e5305c
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 2b6500e..8a78789 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -76,9 +76,10 @@
   klass->class_loader_ = NULL;  // TODO
   klass->dex_file_ = this;
   klass->primitive_type_ = Class::kPrimNot;
-  klass->status_ = Class::kClassIdx;
+  klass->status_ = Class::kStatusIdx;
 
   klass->super_ = reinterpret_cast<Class*>(class_def.superclass_idx_);
+  klass->super_idx_ = class_def.superclass_idx_;
 
   klass->num_sfields_ = header.static_fields_size_;
   klass->num_ifields_ = header.instance_fields_size_;
diff --git a/src/object.cc b/src/object.cc
index a4f41b7..bc7cc86 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -4,8 +4,44 @@
 #include "src/object.h"
 #include "src/logging.h"
 
+#include <string.h>
+
 namespace art {
 
+bool Class::IsInSamePackage(const char* descriptor1, const char* descriptor2) {
+  size_t i = 0;
+  while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
+    ++i;
+  }
+  if (strrchr(descriptor1 + i, '/') != NULL ||
+      strrchr(descriptor2 + i, '/') != NULL ) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+bool Class::IsInSamePackage(const Class* that) const {
+  const Class* klass1 = this;
+  const Class* klass2 = that;
+  if (klass1 == klass2) {
+    return true;
+  }
+  // Class loaders must match.
+  if (klass1->class_loader_ != klass2->class_loader_) {
+    return false;
+  }
+  // Arrays are in the same package when their element classes are.
+  if (klass1->IsArray()) {
+    klass1 = klass1->array_element_class_;
+  }
+  if (klass2->IsArray()) {
+    klass2 = klass2->array_element_class_;
+  }
+  // Compare the package part of the descriptor string.
+  return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
+}
+
 uint32_t Method::NumArgRegisters() {
   CHECK(shorty_ != NULL);
   uint32_t num_registers = 0;
diff --git a/src/object.h b/src/object.h
index 89ccf49..fb68419 100644
--- a/src/object.h
+++ b/src/object.h
@@ -86,21 +86,66 @@
 class Class : public Object {
  public:
   enum ClassStatus {
-    kClassError = -1,
-    kClassNotReady = 0,
-    kClassIdx = 1,  // loaded, DEX idx in super or ifaces
-    kClassLoaded = 2,  // DEX idx values resolved
-    kClassResolved = 3,  // part of linking
-    kClassVerifying = 4,  // in the process of being verified
-    kClassVerified = 5,  // logically part of linking; done pre-init
-    kClassInitializing = 6,  // class init in progress
-    kClassInitialized = 7,  // ready to go
+    kStatusError = -1,
+    kStatusNotReady = 0,
+    kStatusIdx = 1,  // loaded, DEX idx in super or ifaces
+    kStatusLoaded = 2,  // DEX idx values resolved
+    kStatusResolved = 3,  // part of linking
+    kStatusVerifying = 4,  // in the process of being verified
+    kStatusVerified = 5,  // logically part of linking; done pre-init
+    kStatusInitializing = 6,  // class init in progress
+    kStatusInitialized = 7,  // ready to go
   };
 
   enum PrimitiveType {
     kPrimNot = -1
   };
 
+  // Returns true if this class is in the same packages as that class.
+  bool IsInSamePackage(const Class* that) const;
+
+  static bool IsInSamePackage(const char* descriptor1, const char* descriptor2);
+
+  // Returns true if this class represents an array class.
+  bool IsArray() const {
+    return descriptor_[0] == '[';  // TODO: avoid parsing the descriptor
+  }
+
+  // Returns true if the class is an interface.
+  bool IsInterface() const {
+    return (access_flags_ & kAccInterface) != 0;
+  }
+
+  // Returns true if the class is declared public.
+  bool IsPublic() const {
+    return (access_flags_ & kAccPublic) != 0;
+  }
+
+  // Returns true if the class is declared final.
+  bool IsFinal() const {
+    return (access_flags_ & kAccFinal) != 0;
+  }
+
+  // Returns true if the class is abstract.
+  bool IsAbstract() const {
+    return (access_flags_ & kAccAbstract) != 0;
+  }
+
+  // Returns true if the class is an annotation.
+  bool IsAnnotation() const {
+    return (access_flags_ & kAccAnnotation) != 0;
+  }
+
+  // Returns true if the class is a primitive type.
+  bool IsPrimitive() const {
+    return primitive_type_ != kPrimNot;
+  }
+
+  // Returns true if this class can access that class.
+  bool CanAccess(const Class* that) const {
+    return that->IsPublic() && this->IsInSamePackage(that);
+  }
+
   // Returns the size in bytes of a class object instance with the
   // given number of static fields.
   static size_t Size(size_t num_sfields) {
@@ -115,11 +160,10 @@
     return num_vmethods_;
   }
 
-
  public: // TODO: private
   // leave space for instance data; we could access fields directly if
   // we freeze the definition of java/lang/Class
-#define CLASS_FIELD_SLOTS   4
+#define CLASS_FIELD_SLOTS 4
   uint32_t instance_data_[CLASS_FIELD_SLOTS];
 #undef CLASS_FIELD_SLOTS
 
@@ -169,6 +213,7 @@
   // The superclass, or NULL if this is java.lang.Object or a
   // primitive type.
   Class* super_;  // TODO: make an instance field
+  uint32_t super_idx_;
 
   // defining class loader, or NULL for the "bootstrap" system loader
   Object* class_loader_;  // TODO: make an instance field
@@ -179,7 +224,7 @@
   //InitiatingLoaderList initiating_loader_list_;
 
   // array of interfaces this class implements directly
-  int interface_count_;
+  uint32_t interface_count_;
   Class** interfaces_;
 
   // static, private, and <init> methods
diff --git a/src/object_test.cc b/src/object_test.cc
new file mode 100644
index 0000000..d6d22c3
--- /dev/null
+++ b/src/object_test.cc
@@ -0,0 +1,25 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: cshapiro@google.com (Carl Shapiro)
+
+#include "src/object.h"
+
+#include <stdio.h>
+#include "gtest/gtest.h"
+
+namespace art {
+
+TEST(Object, IsInSamePackage) {
+  // Matches
+  EXPECT_TRUE(Class::IsInSamePackage("Ljava/lang/Object;",
+                                     "Ljava/lang/Class"));
+  EXPECT_TRUE(Class::IsInSamePackage("LFoo;",
+                                     "LBar;"));
+
+  // Mismatches
+  EXPECT_FALSE(Class::IsInSamePackage("Ljava/lang/Object;",
+                                      "Ljava/io/File;"));
+  EXPECT_FALSE(Class::IsInSamePackage("Ljava/lang/Object;",
+                                      "Ljava/lang/reflect/Method;"));
+}
+
+}  // namespace art