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