Add class loading infrastructure.
Change-Id: I94bdabcefdf1030ee1827d9219eaf60e4dc818ca
diff --git a/Android.aexec.host.mk b/Android.aexec.host.mk
index 44ecf77..7a59db0 100644
--- a/Android.aexec.host.mk
+++ b/Android.aexec.host.mk
@@ -23,6 +23,8 @@
include $(LOCAL_PATH)/Android.common.mk
LOCAL_SRC_FILES := $(AEXEC_LOCAL_SRC_FILES)
+LOCAL_C_INCLUDES :=
+
LOCAL_SHARED_LIBRARIES := \
libart
diff --git a/Android.aexec.mk b/Android.aexec.mk
index dd5bf58..a1707cc 100644
--- a/Android.aexec.mk
+++ b/Android.aexec.mk
@@ -23,13 +23,11 @@
include $(LOCAL_PATH)/Android.common.mk
LOCAL_SRC_FILES := $(AEXEC_LOCAL_SRC_FILES)
+include external/stlport/libstlport.mk
+LOCAL_C_INCLUDES +=
+
LOCAL_SHARED_LIBRARIES := \
libart \
libstlport
-LOCAL_C_INCLUDES := \
- external/stlport/stlport \
- bionic \
- bionic/libstdc++/include
-
include $(BUILD_EXECUTABLE)
diff --git a/Android.common.mk b/Android.common.mk
index 916a1f9..cc870d4 100644
--- a/Android.common.mk
+++ b/Android.common.mk
@@ -16,14 +16,36 @@
LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := \
+ -O0 \
+ -ggdb3 \
+ -Wall \
+ -Werror \
+ -Wextra \
+ -Wno-unused-parameter \
+ -Wno-deprecated \
+ -Wstrict-aliasing=2 \
+ -fno-align-jumps \
+ -fstrict-aliasing
+
+ifeq ($(TARGET_ARCH),arm)
+LOCAL_CFLAGS +=
+endif
+
+ifeq ($(TARGET_ARCH),x86)
+LOCAL_CFLAGS +=
+endif
+
AEXEC_LOCAL_SRC_FILES := \
src/main.cc
LIBART_LOCAL_SRC_FILES := \
- src/art.cc \
src/assembler.cc \
+ src/dex_file.cc \
src/dex_instruction.cc \
- src/memory_region.cc
+ src/memory_region.cc \
+ src/raw_dex_file.cc \
+ src/runtime.cc
ifeq ($(LIBART_TARGET_ARCH),arm)
LIBART_LOCAL_SRC_FILES += \
@@ -36,7 +58,9 @@
endif
TEST_LOCAL_SRC_FILES := \
- src/dex_instruction_visitor_test.cc
+ src/dex_file_test.cc \
+ src/dex_instruction_visitor_test.cc \
+ src/raw_dex_file_test.cc
ifeq ($(TEST_TARGET_ARCH),arm)
TEST_LOCAL_SRC_FILES +=
diff --git a/Android.libart.host.mk b/Android.libart.host.mk
index edb6869..3fc14a4 100644
--- a/Android.libart.host.mk
+++ b/Android.libart.host.mk
@@ -24,18 +24,8 @@
include $(LOCAL_PATH)/Android.common.mk
LOCAL_SRC_FILES := $(LIBART_LOCAL_SRC_FILES)
-LOCAL_CFLAGS := \
- -g3 \
- -Wall \
- -Wextra \
- -Wno-unused-parameter \
- -Wstrict-aliasing=2 \
- -fno-align-jumps \
- -fstrict-aliasing
-
LOCAL_C_INCLUDES := \
- dalvik \
- libcore/include
+ dalvik
LOCAL_WHOLE_STATIC_LIBRARIES := \
libcutils \
diff --git a/Android.libart.mk b/Android.libart.mk
index 6e86e98..4c02aae 100644
--- a/Android.libart.mk
+++ b/Android.libart.mk
@@ -24,37 +24,17 @@
include $(LOCAL_PATH)/Android.common.mk
LOCAL_SRC_FILES := $(LIBART_LOCAL_SRC_FILES)
-LOCAL_CFLAGS := \
- -g3
- -Wall \
- -Wextra \
- -Wno-unused-parameter \
- -Wstrict-aliasing=2 \
- -fno-align-jumps \
- -fstrict-aliasing
-
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_CFLAGS +=
-endif
-
-ifeq ($(TARGET_ARCH),x86)
-LOCAL_CFLAGS +=
-endif
-
-LOCAL_C_INCLUDES := \
- external/stlport/stlport \
- bionic/ \
- bionic/libstdc++/include \
- dalvik \
- libcore/include
+include external/stlport/libstlport.mk
+LOCAL_C_INCLUDES += \
+ dalvik
LOCAL_STATIC_LIBRARIES := \
- libdex
+ libcutils \
+ libdex \
+ liblog \
+ libz
LOCAL_SHARED_LIBRARIES := \
- libstlport \
- liblog \
- libcutils \
- libz
+ libstlport
include $(BUILD_SHARED_LIBRARY)
diff --git a/Android.test.host.mk b/Android.test.host.mk
index 2d7fedd..dc5a053 100644
--- a/Android.test.host.mk
+++ b/Android.test.host.mk
@@ -22,12 +22,12 @@
TEST_TARGET_ARCH := $(HOST_ARCH)
include $(LOCAL_PATH)/Android.common.mk
local_cpp_extension := $(LOCAL_CPP_EXTENSION)
+local_cflags := $(LOCAL_CFLAGS)
local_shared_libraries := \
libart
local_c_includes := \
- dalvik \
external/gtest/include
local_whole_static_libraries := \
@@ -40,6 +40,7 @@
$(eval LOCAL_MODULE := $(notdir $(file:%.cc=%))) \
$(eval LOCAL_MODULE_TAGS := $(local_module_tags)) \
$(eval LOCAL_SRC_FILES := $(file)) \
+ $(eval LOCAL_CFLAGS := $(local_cflags)) \
$(eval LOCAL_C_INCLUDES := $(local_c_includes)) \
$(eval LOCAL_WHOLE_STATIC_LIBRARIES := $(local_whole_static_libraries)) \
$(eval LOCAL_SHARED_LIBRARIES := $(local_shared_libraries)) \
diff --git a/Android.test.mk b/Android.test.mk
index dc3a229..4c679ac 100644
--- a/Android.test.mk
+++ b/Android.test.mk
@@ -22,16 +22,13 @@
TEST_TARGET_ARCH := $(TARGET_ARCH)
include $(LOCAL_PATH)/Android.common.mk
local_cpp_extension := $(LOCAL_CPP_EXTENSION)
+local_cflags := $(LOCAL_CFLAGS)
local_shared_libraries := \
libart \
libstlport
local_c_includes := \
- external/stlport/stlport \
- bionic \
- bionic/libstdc++/include \
- dalvik \
external/gtest/include
local_static_libraries := \
@@ -44,7 +41,9 @@
$(eval LOCAL_MODULE := $(notdir $(file:%.cc=%))) \
$(eval LOCAL_MODULE_TAGS := $(local_module_tags)) \
$(eval LOCAL_SRC_FILES := $(file)) \
- $(eval LOCAL_C_INCLUDES := $(local_c_includes)) \
+ $(eval LOCAL_CFLAGS := $(local_cflags)) \
+ $(eval include external/stlport/libstlport.mk) \
+ $(eval LOCAL_C_INCLUDES += $(local_c_includes)) \
$(eval LOCAL_STATIC_LIBRARIES := $(local_static_libraries)) \
$(eval LOCAL_SHARED_LIBRARIES := $(local_shared_libraries)) \
$(eval include $(BUILD_EXECUTABLE)) \
diff --git a/src/art.cc b/src/art.cc
deleted file mode 100644
index 08ae34d..0000000
--- a/src/art.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-#include "art.h"
-
-namespace art {
-
-bool Art::Startup() {
- return true;
-}
-
-void Art::Shutdown() {
-}
-
-} // namespace art
diff --git a/src/art.h b/src/art.h
deleted file mode 100644
index b02c1a5..0000000
--- a/src/art.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-#ifndef ART_SRC_ART_H_
-#define ART_SRC_ART_H_
-
-namespace art {
-
-class Art {
- public:
- static bool Startup();
- static void Shutdown();
-};
-
-} // namespace art
-
-namespace r = art;
-
-#endif // ART_SRC_ART_H_
diff --git a/src/dex_file.cc b/src/dex_file.cc
new file mode 100644
index 0000000..a89baaf
--- /dev/null
+++ b/src/dex_file.cc
@@ -0,0 +1,128 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "src/dex_file.h"
+#include "src/heap.h"
+#include "src/globals.h"
+#include "src/logging.h"
+#include "src/object.h"
+#include "src/raw_dex_file.h"
+
+namespace art {
+
+DexFile* DexFile::Open(const char* filename) {
+ RawDexFile* raw = RawDexFile::Open(filename);
+ if (raw == NULL) {
+ return NULL;
+ }
+ DexFile* dex_file = new DexFile(raw);
+ dex_file->Init();
+ return dex_file;
+}
+
+DexFile::~DexFile() {
+ delete raw_;
+ delete[] strings_;
+ delete[] classes_;
+ delete[] methods_;
+ delete[] fields_;
+}
+
+void DexFile::Init() {
+ num_strings_ = raw_->NumStringIds();
+ strings_ = new String*[num_strings_];
+
+ num_classes_ = raw_->NumTypeIds();
+ classes_ = new Class*[num_classes_];
+
+ num_methods_ = raw_->NumMethodIds();
+ methods_ = new Method*[num_methods_];
+
+ num_fields_ = raw_->NumFieldIds();
+ fields_ = new Field*[num_fields_];
+}
+
+Class* DexFile::LoadClass(const char* descriptor) {
+ const RawDexFile::ClassDef* class_def = raw_->FindClassDef(descriptor);
+ if (class_def == NULL) {
+ return NULL;
+ } else {
+ return LoadClass(*class_def);
+ }
+}
+
+Class* DexFile::LoadClass(const RawDexFile::ClassDef& class_def) {
+ const byte* class_data = raw_->GetClassData(class_def);
+ RawDexFile::ClassDataHeader header;
+ raw_->DecodeClassDataHeader(&header, class_data);
+
+ const char* descriptor = raw_->GetClassDescriptor(class_def);
+ CHECK(descriptor != NULL);
+
+ // Allocate storage for the new class object.
+ size_t size = Class::Size(header.static_fields_size_);
+ Class* klass = Heap::AllocClass(size);
+ CHECK(klass != NULL);
+
+ //klass->klass_ = NULL; // TODO
+ klass->descriptor_ = descriptor;
+ klass->access_flags_ = class_def.access_flags_;
+ klass->class_loader_ = NULL; // TODO
+ klass->dex_file_ = this;
+ klass->primitive_type_ = Class::kPrimNot;
+ klass->status_ = Class::kClassIdx;
+
+ klass->super_ = reinterpret_cast<Class*>(class_def.superclass_idx_);
+
+ // Load class interfaces.
+ LoadClassInterfaces(class_def, klass);
+
+ // Load static fields.
+ if (header.static_fields_size_ != 0) {
+ for (size_t i = 0; i < header.static_fields_size_; ++i) {
+ // TODO
+ }
+ }
+
+ // Load instance fields.
+ if (header.instance_fields_size_ != 0) {
+ for (size_t i = 0; i < header.instance_fields_size_; ++i) {
+ // TODO
+ }
+ }
+
+ // Load direct methods.
+
+ // Load virtual methods.
+
+ return klass;
+}
+
+void DexFile::LoadClassInterfaces(const RawDexFile::ClassDef& class_def,
+ Class* klass) {
+ const RawDexFile::TypeList* list = raw_->GetInterfacesList(class_def);
+ if (list != NULL) {
+ klass->interface_count_ = list->Size();
+ klass->interfaces_ = new Class*[list->Size()];
+ for (size_t i = 0; i < list->Size(); ++i) {
+ const RawDexFile::TypeItem& type_item = list->GetTypeItem(i);
+ klass->interfaces_[i] = reinterpret_cast<Class*>(type_item.type_idx_);
+ }
+ }
+}
+
+void DexFile::LoadSFields(Class* klass, const RawDexFile::Field* src,
+ Field* dst) {
+
+}
+
+void DexFile::LoadIFields(Class* klass, const RawDexFile::Field* src,
+ Field* dst) {
+}
+
+void DexFile::LoadMethod(Class* klass, const RawDexFile::Method* src,
+ Method* dst) {
+}
+
+
+
+} // namespace art
diff --git a/src/dex_file.h b/src/dex_file.h
new file mode 100644
index 0000000..3cd1a57
--- /dev/null
+++ b/src/dex_file.h
@@ -0,0 +1,77 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_DEX_FILE_H_
+#define ART_SRC_DEX_FILE_H_
+
+#include "src/globals.h"
+#include "src/macros.h"
+#include "src/object.h"
+#include "src/raw_dex_file.h"
+
+namespace art {
+
+class DexFile {
+ public:
+ // Opens a dex file. Returns NULL on failure.
+ static DexFile* Open(const char* filename);
+
+ // Close and deallocate.
+ ~DexFile();
+
+ size_t NumTypes() {
+ return num_classes_;
+ }
+
+ size_t NumMethods() {
+ return num_methods_;
+ }
+
+ Class* LoadClass(const char* descriptor);
+
+ Class* LoadClass(const RawDexFile::ClassDef& class_def);
+
+ private:
+ DexFile(RawDexFile* raw) : raw_(raw) {};
+
+ void Init();
+
+ void LoadClassInterfaces(const RawDexFile::ClassDef& class_def,
+ Class *klass);
+
+ void LoadSFields(Class* klass, const RawDexFile::Field* src,
+ Field* dst);
+
+ void LoadIFields(Class* klass, const RawDexFile::Field* src,
+ Field* dst);
+
+ void LoadMethod(Class* klass, const RawDexFile::Method* src,
+ Method* dst);
+
+ // Table of contents for interned String objects.
+ String** strings_;
+ size_t num_strings_;
+
+ // Table of contents for Class objects.
+ Class** classes_;
+ size_t num_classes_;
+
+ // Table of contents for methods.
+ Method** methods_;
+ size_t num_methods_;
+
+ // Table of contents for fields.
+ Field** fields_;
+ size_t num_fields_;
+
+ // The size of the DEX file, in bytes.
+ size_t length_;
+
+ // The underlying dex file.
+ RawDexFile* raw_;
+
+ DISALLOW_COPY_AND_ASSIGN(DexFile);
+};
+
+} // namespace art
+
+#endif // ART_SRC_DEX_FILE_H_
diff --git a/src/dex_file_test.cc b/src/dex_file_test.cc
new file mode 100644
index 0000000..ff80e46
--- /dev/null
+++ b/src/dex_file_test.cc
@@ -0,0 +1,35 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "src/dex_file.h"
+#include "src/scoped_ptr.h"
+
+#include <stdio.h>
+#include "gtest/gtest.h"
+
+namespace art {
+
+static const char* filename =
+ "/usr/local/google/work/dalvik-dev-git/Nested.dex";
+
+TEST(DexFile, Open) {
+ scoped_ptr<DexFile> dex(DexFile::Open(filename));
+ ASSERT_TRUE(dex != NULL);
+}
+
+TEST(DexFile, LoadNonexistent) {
+ scoped_ptr<DexFile> dex(DexFile::Open(filename));
+ ASSERT_TRUE(dex != NULL);
+
+ Class* klass = dex->LoadClass("NoSuchClass");
+ ASSERT_TRUE(klass == NULL);
+}
+
+TEST(DexFile, Load) {
+ scoped_ptr<DexFile> dex(DexFile::Open(filename));
+ ASSERT_TRUE(dex != NULL);
+
+ Class* klass = dex->LoadClass("LNested;");
+ ASSERT_TRUE(klass != NULL);
+}
+
+} // namespace art
diff --git a/src/dex_instruction_visitor_test.cc b/src/dex_instruction_visitor_test.cc
index 239e1eb..768fc50 100644
--- a/src/dex_instruction_visitor_test.cc
+++ b/src/dex_instruction_visitor_test.cc
@@ -1,6 +1,7 @@
// Copyright 2011 Google Inc. All Rights Reserved.
#include "src/dex_instruction_visitor.h"
+#include "src/scoped_ptr.h"
#include <iostream>
#include "gtest/gtest.h"
@@ -10,7 +11,7 @@
class TestVisitor : public DexInstructionVisitor<TestVisitor> {};
TEST(Instruction, Init) {
- TestVisitor visitor;
+ scoped_ptr<TestVisitor> visitor(new TestVisitor);
}
class CountVisitor : public DexInstructionVisitor<CountVisitor> {
diff --git a/src/globals.h b/src/globals.h
index 92d0cf7..1904203 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -3,6 +3,7 @@
#ifndef ART_SRC_GLOBALS_H_
#define ART_SRC_GLOBALS_H_
+#include <stddef.h>
#include <stdint.h>
namespace art {
diff --git a/src/heap.h b/src/heap.h
new file mode 100644
index 0000000..2673932
--- /dev/null
+++ b/src/heap.h
@@ -0,0 +1,22 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: cshapiro@google.com (Carl Shapiro)
+
+#ifndef ART_SRC_HEAP_H_
+#define ART_SRC_HEAP_H_
+
+#include "src/globals.h"
+#include "src/object.h"
+
+namespace art {
+
+class Heap {
+ public:
+ static Class* AllocClass(size_t size) {
+ byte* raw = new byte[size];
+ return reinterpret_cast<Class*>(raw);
+ }
+};
+
+} // namespace art
+
+#endif // ART_SRC_HEAP_H_
diff --git a/src/leb128.h b/src/leb128.h
new file mode 100644
index 0000000..aa8b895
--- /dev/null
+++ b/src/leb128.h
@@ -0,0 +1,76 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_LEB128_H_
+#define ART_SRC_LEB128_H_
+
+#include "src/globals.h"
+
+namespace art {
+
+// Reads an unsigned LEB128 value, updating the given pointer to point
+// just past the end of the read value. This function tolerates
+// non-zero high-order bits in the fifth encoded byte.
+static inline uint32_t DecodeUnsignedLeb128(const byte** data) {
+ const byte* ptr = *data;
+ int result = *(ptr++);
+ if (result > 0x7f) {
+ int cur = *(ptr++);
+ result = (result & 0x7f) | ((cur & 0x7f) << 7);
+ if (cur > 0x7f) {
+ cur = *(ptr++);
+ result |= (cur & 0x7f) << 14;
+ if (cur > 0x7f) {
+ cur = *(ptr++);
+ result |= (cur & 0x7f) << 21;
+ if (cur > 0x7f) {
+ // Note: We don't check to see if cur is out of range here,
+ // meaning we tolerate garbage in the four high-order bits.
+ cur = *(ptr++);
+ result |= cur << 28;
+ }
+ }
+ }
+ }
+ *data = ptr;
+ return (uint32_t)result;
+}
+
+// Reads a signed LEB128 value, updating the given pointer to point
+// just past the end of the read value. This function tolerates
+// non-zero high-order bits in the fifth encoded byte.
+static inline int32_t DecodeSignedLeb128(const byte** data) {
+ const byte* ptr = *data;
+ int32_t result = *(ptr++);
+ if (result <= 0x7f) {
+ result = (result << 25) >> 25;
+ } else {
+ int cur = *(ptr++);
+ result = (result & 0x7f) | ((cur & 0x7f) << 7);
+ if (cur <= 0x7f) {
+ result = (result << 18) >> 18;
+ } else {
+ cur = *(ptr++);
+ result |= (cur & 0x7f) << 14;
+ if (cur <= 0x7f) {
+ result = (result << 11) >> 11;
+ } else {
+ cur = *(ptr++);
+ result |= (cur & 0x7f) << 21;
+ if (cur <= 0x7f) {
+ result = (result << 4) >> 4;
+ } else {
+ // Note: We don't check to see if cur is out of range here,
+ // meaning we tolerate garbage in the four high-order bits.
+ cur = *(ptr++);
+ result |= cur << 28;
+ }
+ }
+ }
+ }
+ *data = ptr;
+ return result;
+}
+
+} // namespace art
+
+#endif // ART_SRC_LEB128_H_
diff --git a/src/logging.h b/src/logging.h
index ccab249..e1b99d6 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -74,6 +74,7 @@
#endif
#define LOG_INFO LogMessage(__FILE__, __LINE__)
+#define LOG_WARN LOG_INFO // TODO
#define LOG_FATAL LogMessageFatal(__FILE__, __LINE__)
#define LOG(severity) LOG_ ## severity.stream()
#define LG LOG(INFO)
diff --git a/src/object.h b/src/object.h
new file mode 100644
index 0000000..b7d3a50
--- /dev/null
+++ b/src/object.h
@@ -0,0 +1,214 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_OBJECT_H_
+#define ART_SRC_OBJECT_H_
+
+#include "src/globals.h"
+
+namespace art {
+
+class Array;
+class Class;
+class DexFile;
+class IField;
+class InterfaceEntry;
+class Monitor;
+class Method;
+class SField;
+
+class Object {
+ Class* klass_;
+ Monitor* lock_;
+};
+
+class Field {
+ Class* klass_;
+};
+
+// Instance fields.
+class IField : Field {
+ // TODO
+};
+
+// Static fields.
+class SField : Field {
+ // TODO
+};
+
+// Class objects.
+class Class : 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
+ };
+
+ enum PrimitiveType {
+ kPrimNot = -1
+ };
+
+ // 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) {
+ return OFFSETOF_MEMBER(Class, sfields_) + sizeof(SField) * num_sfields;
+ }
+
+ 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
+ uint32_t instance_data_[CLASS_FIELD_SLOTS];
+#undef CLASS_FIELD_SLOTS
+
+ // UTF-8 descriptor for the class from constant pool
+ // ("Ljava/lang/Class;"), or on heap if generated ("[C")
+ const char* descriptor_;
+
+ // Proxy classes have their descriptor allocated on the native heap.
+ // When this field is non-NULL it must be explicitly freed.
+ char* descriptor_alloc_;
+
+ // access flags; low 16 bits are defined by VM spec
+ uint32_t access_flags_;
+
+ // VM-unique class serial number, nonzero, set very early
+ //uint32_t serial_number_;
+
+ // DexFile from which we came; needed to resolve constant pool entries
+ // (will be NULL for VM-generated, e.g. arrays and primitive classes)
+ DexFile* dex_file_;
+
+ // state of class initialization
+ ClassStatus status_;
+
+ // if class verify fails, we must return same error on subsequent tries
+ Class* verify_error_class_;
+
+ // threadId, used to check for recursive <clinit> invocation
+ uint32_t clinit_thread_id_;
+
+ // Total object size; used when allocating storage on gc heap. (For
+ // interfaces and abstract classes this will be zero.)
+ uint32_t object_size_;
+
+ // For array classes, the class object for base element, for
+ // instanceof/checkcast (for String[][][], this will be String).
+ // Otherwise, NULL.
+ Class* array_element_class_;
+
+ // For array classes, the number of array dimensions, e.g. int[][]
+ // is 2. Otherwise 0.
+ int32_t array_rank_;
+
+ // primitive type index, or PRIM_NOT (-1); set for generated prim classes
+ PrimitiveType primitive_type_;
+
+ // The superclass, or NULL if this is java.lang.Object or a
+ // primitive type.
+ Class* super_;
+
+ // defining class loader, or NULL for the "bootstrap" system loader
+ Object* class_loader_;
+
+ // initiating class loader list
+ // NOTE: for classes with low serialNumber, these are unused, and the
+ // values are kept in a table in gDvm.
+ //InitiatingLoaderList initiating_loader_list_;
+
+ // array of interfaces this class implements directly
+ int interface_count_;
+ Class** interfaces_;
+
+ // static, private, and <init> methods
+ int direct_method_count_;
+ Method* direct_methods_;
+
+ // virtual methods defined in this class; invoked through vtable
+ int virtual_method_count_;
+ Method* virtual_methods_;
+
+ // Virtual method table (vtable), for use by "invoke-virtual". The
+ // vtable from the superclass is copied in, and virtual methods from
+ // our class either replace those from the super or are appended.
+ int32_t vtable_count_;
+ Method** vtable_;
+
+ // Interface table (iftable), one entry per interface supported by
+ // this class. That means one entry for each interface we support
+ // directly, indirectly via superclass, or indirectly via
+ // superinterface. This will be null if neither we nor our
+ // superclass implement any interfaces.
+ //
+ // Why we need this: given "class Foo implements Face", declare
+ // "Face faceObj = new Foo()". Invoke faceObj.blah(), where "blah"
+ // is part of the Face interface. We can't easily use a single
+ // vtable.
+ //
+ // For every interface a concrete class implements, we create a list
+ // of virtualMethod indices for the methods in the interface.
+ int iftable_count_;
+ InterfaceEntry* iftable_;
+
+ // The interface vtable indices for iftable get stored here. By
+ // placing them all in a single pool for each class that implements
+ // interfaces, we decrease the number of allocations.
+ int ifvipool_count;
+ int* ifvipool_;
+
+ // instance fields
+ //
+ // These describe the layout of the contents of a
+ // DataObject-compatible Object. Note that only the fields directly
+ // declared by this class are listed in ifields; fields declared by
+ // a superclass are listed in the superclass's ClassObject.ifields.
+ //
+ // All instance fields that refer to objects are guaranteed to be at
+ // the beginning of the field list. ifieldRefCount specifies the
+ // number of reference fields.
+ int ifield_count_;
+ int ifield_ref_count_; // number of fields that are object refs
+ IField* ifields_;
+
+ // bitmap of offsets of ifields
+ uint32_t ref_offsets_;
+
+ // source file name, if known. Otherwise, NULL.
+ const char* source_file_;
+
+ // Static fields
+ uint16_t num_sfields_;
+ SField sfields_[]; // MUST be last item
+};
+
+class String : Object {
+ public:
+ Array* array_;
+
+ uint32_t hash_code_;
+
+ uint32_t offset_;
+
+ uint32_t count_;
+};
+
+class Array : Object {
+ public:
+ // The number of array elements.
+ uint32_t length_;
+};
+
+class Method {
+ public:
+ Class* klass;
+};
+
+} // namespace art
+
+#endif // ART_SRC_OBJECT_H_
diff --git a/src/raw_dex_file.cc b/src/raw_dex_file.cc
new file mode 100644
index 0000000..9f09177
--- /dev/null
+++ b/src/raw_dex_file.cc
@@ -0,0 +1,121 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "src/raw_dex_file.h"
+#include "src/globals.h"
+#include "src/logging.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <map>
+
+namespace art {
+
+const byte RawDexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
+const byte RawDexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
+
+RawDexFile* RawDexFile::Open(const char* filename) {
+ CHECK(filename != NULL);
+ int fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ LG << "open: " << strerror(errno); // TODO: PLOG
+ return NULL;
+ }
+ struct stat sbuf;
+ memset(&sbuf, 0, sizeof(sbuf));
+ if (fstat(fd, &sbuf) == -1) {
+ LG << "fstat: " << strerror(errno); // TODO: PLOG
+ close(fd);
+ return NULL;
+ }
+ size_t length = sbuf.st_size;
+ void* addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
+ if (addr == MAP_FAILED) {
+ LG << "mmap: " << strerror(errno); // TODO: PLOG
+ close(fd);
+ return NULL;
+ }
+ close(fd);
+ RawDexFile* raw = new RawDexFile(reinterpret_cast<byte*>(addr), length);
+ raw->Init();
+ return raw;
+}
+
+RawDexFile::~RawDexFile() {
+ CHECK(base_ != NULL);
+ const void* addr = reinterpret_cast<const void*>(base_);
+ if (munmap(const_cast<void*>(addr), length_) == -1) {
+ LG << "munmap: " << strerror(errno); // TODO: PLOG
+ }
+}
+
+bool RawDexFile::Init() {
+ InitMembers();
+ if (!IsMagicValid()) {
+ return false;
+ }
+ InitIndex();
+ return true;
+}
+
+void RawDexFile::InitMembers() {
+ const byte* b = base_;
+ header_ = reinterpret_cast<const Header*>(b);
+ const Header* h = header_;
+ string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
+ type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
+ field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
+ method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
+ proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
+ class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
+}
+
+bool RawDexFile::IsMagicValid() {
+ return CheckMagic(header_->magic);
+}
+
+bool RawDexFile::CheckMagic(const byte* magic) {
+ CHECK(magic != NULL);
+ if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
+ LOG(WARN) << "Unrecognized magic number:"
+ << " " << magic[0]
+ << " " << magic[1]
+ << " " << magic[2]
+ << " " << magic[3];
+ return false;
+ }
+ const byte* version = &magic[sizeof(kDexMagic)];
+ if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
+ LOG(WARN) << "Unrecognized version number:"
+ << " " << version[0]
+ << " " << version[1]
+ << " " << version[2]
+ << " " << version[3];
+ return false;
+ }
+ return true;
+}
+
+void RawDexFile::InitIndex() {
+ CHECK_EQ(index_.size(), 0);
+ for (size_t i = 0; i < NumClassDefs(); ++i) {
+ const ClassDef& class_def = GetClassDef(i);
+ const char* descriptor = GetClassDescriptor(class_def);
+ index_[descriptor] = &class_def;
+ }
+}
+
+const RawDexFile::ClassDef* RawDexFile::FindClassDef(const char* descriptor) {
+ CHECK(descriptor != NULL);
+ Index::iterator it = index_.find(descriptor);
+ if (it == index_.end()) {
+ return NULL;
+ } else {
+ return it->second;
+ }
+}
+
+} // namespace art
diff --git a/src/raw_dex_file.h b/src/raw_dex_file.h
new file mode 100644
index 0000000..3cd7c88
--- /dev/null
+++ b/src/raw_dex_file.h
@@ -0,0 +1,345 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_RAW_DEX_FILE_H_
+#define ART_SRC_RAW_DEX_FILE_H_
+
+#include "src/globals.h"
+#include "src/leb128.h"
+#include "src/logging.h"
+#include "src/strutil.h"
+
+#include <map>
+
+namespace art {
+
+class RawDexFile {
+ public:
+ static const byte kDexMagic[];
+ static const byte kDexMagicVersion[];
+ static const size_t kSha1DigestSize = 20;
+
+ // Raw header_item.
+ struct Header {
+ uint8_t magic[8];
+ uint32_t checksum;
+ uint8_t signature[kSha1DigestSize];
+ uint32_t file_size_; // length of entire file
+ uint32_t header_size_; // offset to start of next section
+ uint32_t endian_tag_;
+ uint32_t link_size_;
+ uint32_t link_off_;
+ uint32_t map_off_;
+ uint32_t string_ids_size_;
+ uint32_t string_ids_off_;
+ uint32_t type_ids_size_;
+ uint32_t type_ids_off_;
+ uint32_t proto_ids_size_;
+ uint32_t proto_ids_off_;
+ uint32_t field_ids_size_;
+ uint32_t field_ids_off_;
+ uint32_t method_ids_size_;
+ uint32_t method_ids_off_;
+ uint32_t class_defs_size_;
+ uint32_t class_defs_off_;
+ uint32_t data_size_;
+ uint32_t data_off_;
+ };
+
+ // Raw string_id_item.
+ struct StringId {
+ uint32_t string_data_off_; // offset in bytes from the base address
+ };
+
+ // Raw type_id_item.
+ struct TypeId {
+ uint32_t descriptor_idx_; // index into string_ids
+ };
+
+ // Raw field_id_item.
+ struct FieldId {
+ uint32_t class_idx_; // index into typeIds list for defining class
+ uint32_t type_idx_; // index into typeIds for field type
+ uint32_t name_idx_; // index into stringIds for field name
+ };
+
+ // Raw method_id_item.
+ struct MethodId {
+ uint32_t class_idx_; // index into typeIds list for defining class
+ uint32_t proto_idx_; // index into protoIds for method prototype
+ uint32_t name_idx_; // index into stringIds for method name
+ };
+
+ // Raw proto_id_item.
+ struct ProtoId {
+ uint32_t shorty_idx_; // index into string_ids for shorty descriptor
+ uint32_t return_type_idx_; // index into type_ids list for return type
+ uint32_t parameters_off_; // file offset to type_list for parameter types
+ };
+
+ // Raw class_def_item.
+ struct ClassDef {
+ uint32_t class_idx_; // index into typeIds for this class
+ uint32_t access_flags_;
+ uint32_t superclass_idx_; // index into typeIds for superclass
+ uint32_t interfaces_off_; // file offset to TypeList
+ uint32_t source_file_idx_; // index into stringIds for source file name
+ uint32_t annotations_off_; // file offset to annotations_directory_item
+ uint32_t class_data_off_; // file offset to class_data_item
+ uint32_t static_values_off_; // file offset to EncodedArray
+ };
+
+ // Raw type_item.
+ struct TypeItem {
+ uint16_t type_idx_; // index into type_ids section
+ };
+
+ // Raw type_list.
+ class TypeList {
+ public:
+ uint32_t Size() const {
+ return size_;
+ }
+
+ const TypeItem& GetTypeItem(uint32_t idx) const {
+ CHECK_LT(idx, this->size_);
+ return this->list_[idx];
+ }
+
+ private:
+ uint32_t size_; // size of the list, in entries
+ TypeItem list_[1]; // elements of the list
+ };
+
+ // Raw code_item.
+ struct Code {
+ uint16_t registers_size_;
+ uint16_t ins_size_;
+ uint16_t outs_size_;
+ uint16_t tries_size_;
+ uint32_t debug_info_off_; // file offset to debug info stream
+ uint32_t insns_size_; // size of the insns array, in 2 byte code units
+ uint16_t insns_[1];
+ };
+
+ // Partially decoded form of class_data_item.
+ struct ClassDataHeader {
+ uint32_t static_fields_size_; // the number of static fields
+ uint32_t instance_fields_size_; // the number of instance fields
+ uint32_t direct_methods_size_; // the number of direct methods
+ uint32_t virtual_methods_size_; // the number of virtual methods
+ };
+
+ // Decoded form of encoded_field.
+ struct Field {
+ uint32_t field_idx_; // index into the field_ids list for the identity of this field
+ uint32_t access_flags_; // access flags for the field
+ };
+
+ // Decoded form of encoded_method.
+ struct Method {
+ uint32_t method_idx_;
+ uint32_t access_flags_;
+ uint32_t code_off_;
+ };
+
+ // Opens a .dex file.
+ static RawDexFile* Open(const char* filename);
+
+ // Closes a .dex file.
+ ~RawDexFile();
+
+ // Looks up a class definition by its class descriptor.
+ const ClassDef* FindClassDef(const char* descriptor);
+
+ // Returns the number of string identifiers in the .dex file.
+ size_t NumStringIds() const {
+ CHECK(header_ != NULL);
+ return header_->string_ids_size_;
+ }
+
+ // Returns the number of type identifiers in the .dex file.
+ size_t NumTypeIds() const {
+ CHECK(header_ != NULL);
+ return header_->type_ids_size_;
+ }
+
+ // Returns the number of prototype identifiers in the .dex file.
+ size_t NumProtoIds() const {
+ CHECK(header_ != NULL);
+ return header_->proto_ids_size_;
+ }
+
+ // Returns the number of field identifiers in the .dex file.
+ size_t NumFieldIds() const {
+ CHECK(header_ != NULL);
+ return header_->field_ids_size_;
+ }
+
+ // Returns the number of method identifiers in the .dex file.
+ size_t NumMethodIds() const {
+ CHECK(header_ != NULL);
+ return header_->method_ids_size_;
+ }
+
+ // Returns the number of class definitions in the .dex file.
+ size_t NumClassDefs() const {
+ CHECK(header_ != NULL);
+ return header_->class_defs_size_;
+ }
+
+ // Returns a pointer to the memory mapped class data.
+ const byte* GetClassData(const ClassDef& class_def) const {
+ if (class_def.class_data_off_ == 0) {
+ LG << "class_def.class_data_off_ == 0";
+ return NULL;
+ }
+ return base_ + class_def.class_data_off_;
+ }
+
+ // Decodes the header section from the raw class data bytes.
+ void DecodeClassDataHeader(ClassDataHeader* header, const byte* class_data) {
+ CHECK(header != NULL);
+ memset(header, 0, sizeof(ClassDataHeader));
+ if (header != NULL) {
+ header->static_fields_size_ = DecodeUnsignedLeb128(&class_data);
+ header->instance_fields_size_ = DecodeUnsignedLeb128(&class_data);
+ header->direct_methods_size_ = DecodeUnsignedLeb128(&class_data);
+ header->virtual_methods_size_ = DecodeUnsignedLeb128(&class_data);
+ }
+ }
+
+ // Returns the class descriptor string of a class definition.
+ const char* GetClassDescriptor(const ClassDef& class_def) const {
+ return dexStringByTypeIdx(class_def.class_idx_);
+ }
+
+ // Returns the StringId at the specified index.
+ const StringId& GetStringId(uint32_t idx) const {
+ CHECK_LT(idx, NumStringIds());
+ return string_ids_[idx];
+ }
+
+ // Returns the TypeId at the specified index.
+ const TypeId& GetTypeId(uint32_t idx) const {
+ CHECK_LT(idx, NumTypeIds());
+ return type_ids_[idx];
+ }
+
+ // Returns the FieldId at the specified index.
+ const FieldId& GetFieldId(uint32_t idx) const {
+ CHECK_LT(idx, NumFieldIds());
+ return field_ids_[idx];
+ }
+
+ // Returns the MethodId at the specified index.
+ const MethodId& GetMethodId(uint32_t idx) const {
+ CHECK_LT(idx, NumMethodIds());
+ return method_ids_[idx];
+ }
+
+ // Returns the ProtoId at the specified index.
+ const ProtoId& GetProtoId(uint32_t idx) const {
+ CHECK_LT(idx, NumProtoIds());
+ return proto_ids_[idx];
+ }
+
+ // Returns the ClassDef at the specified index.
+ const ClassDef& GetClassDef(uint32_t idx) const {
+ CHECK_LT(idx, NumClassDefs());
+ return class_defs_[idx];
+ }
+
+ const TypeList* GetInterfacesList(const ClassDef& class_def) {
+ if (class_def.interfaces_off_ == 0) {
+ return NULL;
+ } else {
+ const byte* addr = base_ + class_def.interfaces_off_;
+ return reinterpret_cast<const TypeList*>(addr);
+ }
+ }
+
+ // From libdex...
+
+ // Returns a pointer to the UTF-8 string data referred to by the
+ // given string_id.
+ const char* dexGetStringData(const StringId& string_id) const {
+ const byte* ptr = base_ + string_id.string_data_off_;
+ // Skip the uleb128 length.
+ while (*(ptr++) > 0x7f) /* empty */ ;
+ return (const char*) ptr;
+ }
+
+ // return the UTF-8 encoded string with the specified string_id index
+ const char* dexStringById(uint32_t idx) const {
+ const StringId& string_id = GetStringId(idx);
+ return dexGetStringData(string_id);
+ }
+
+ // Get the descriptor string associated with a given type index.
+ const char* dexStringByTypeIdx(uint32_t idx) const {
+ const TypeId& type_id = GetTypeId(idx);
+ return dexStringById(type_id.descriptor_idx_);
+ }
+
+ private:
+ RawDexFile(const byte* addr, size_t length)
+ : base_(addr),
+ length_(length),
+ header_(0),
+ string_ids_(0),
+ type_ids_(0),
+ field_ids_(0),
+ method_ids_(0),
+ proto_ids_(0),
+ class_defs_(0) {}
+
+ // Top-level initializer that calls other Init methods.
+ bool Init();
+
+ // Caches pointers into to the various file sections.
+ void InitMembers();
+
+ // Builds the index of descriptors to class definitions.
+ void InitIndex();
+
+ // Returns true if the byte string equals the magic value.
+ bool CheckMagic(const byte* magic);
+
+ // Returns true if the header magic is of the expected value.
+ bool IsMagicValid();
+
+ // The index of descriptors to class definitions.
+ typedef std::map<const char*, const RawDexFile::ClassDef*, CStringLt> Index;
+ Index index_;
+
+ // The base address of the memory mapping.
+ const byte* base_;
+
+ // The length of the memory mapping in bytes.
+ const size_t length_;
+
+ // Points to the header section.
+ const Header* header_;
+
+ // Points to the base of the string identifier list.
+ const StringId* string_ids_;
+
+ // Points to the base of the type identifier list.
+ const TypeId* type_ids_;
+
+ // Points to the base of the field identifier list.
+ const FieldId* field_ids_;
+
+ // Points to the base of the method identifier list.
+ const MethodId* method_ids_;
+
+ // Points to the base of the prototype identifier list.
+ const ProtoId* proto_ids_;
+
+ // Points to the base of the class definition list.
+ const ClassDef* class_defs_;
+};
+
+} // namespace art
+
+#endif // ART_SRC_RAW_DEX_FILE_H_
diff --git a/src/raw_dex_file_test.cc b/src/raw_dex_file_test.cc
new file mode 100644
index 0000000..6347c44
--- /dev/null
+++ b/src/raw_dex_file_test.cc
@@ -0,0 +1,33 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "src/raw_dex_file.h"
+
+#include <stdio.h>
+#include "gtest/gtest.h"
+
+namespace art {
+
+static const char* filename =
+ "/usr/local/google/work/dalvik-dev-git/Nested.dex";
+
+TEST(RawDexFile, Open) {
+ RawDexFile* raw = RawDexFile::Open(filename);
+ ASSERT_TRUE(raw != NULL);
+ delete raw;
+}
+
+TEST(RawDexFile, ClassDefs) {
+ RawDexFile* raw = RawDexFile::Open(filename);
+ ASSERT_TRUE(raw != NULL);
+ EXPECT_EQ(2U, raw->NumClassDefs());
+
+ const RawDexFile::ClassDef& c0 = raw->GetClassDef(0);
+ EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c0));
+
+ const RawDexFile::ClassDef& c1 = raw->GetClassDef(1);
+ EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
+
+ delete raw;
+}
+
+} // namespace art
diff --git a/src/runtime.cc b/src/runtime.cc
new file mode 100644
index 0000000..f627a46
--- /dev/null
+++ b/src/runtime.cc
@@ -0,0 +1,14 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "src/runtime.h"
+
+namespace art {
+
+bool Runtime::Startup() {
+ return true;
+}
+
+void Runtime::Shutdown() {
+}
+
+} // namespace art
diff --git a/src/runtime.h b/src/runtime.h
new file mode 100644
index 0000000..2afd9f0
--- /dev/null
+++ b/src/runtime.h
@@ -0,0 +1,20 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_RUNTIME_H_
+#define ART_SRC_RUNTIME_H_
+
+namespace art {
+
+class Runtime {
+ public:
+ static bool Startup();
+ static void Shutdown();
+
+ static void Compile(const char* filename);
+};
+
+} // namespace art
+
+namespace r = art;
+
+#endif // ART_SRC_RUNTIME_H_
diff --git a/src/scoped_ptr.h b/src/scoped_ptr.h
new file mode 100644
index 0000000..19c8166
--- /dev/null
+++ b/src/scoped_ptr.h
@@ -0,0 +1,378 @@
+// Copyright 2010 Google
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ART_SRC_SCOPED_PTR_H_
+#define ART_SRC_SCOPED_PTR_H_
+
+// This is an implementation designed to match the anticipated future TR2
+// implementation of the scoped_ptr class, and its closely-related brethren,
+// scoped_array, scoped_ptr_malloc, and make_scoped_ptr.
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <algorithm>
+#include <cstddef>
+
+namespace art {
+
+template <class C> class scoped_ptr;
+template <class C, class Free> class scoped_ptr_malloc;
+template <class C> class scoped_array;
+
+template <class C>
+scoped_ptr<C> make_scoped_ptr(C * param);
+
+// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
+// automatically deletes the pointer it holds (if any).
+// That is, scoped_ptr<T> owns the T object that it points to.
+// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
+//
+// The size of a scoped_ptr is small:
+// sizeof(scoped_ptr<C>) == sizeof(C*)
+template <class C>
+class scoped_ptr {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // Constructor. Defaults to intializing with NULL.
+ // There is no way to create an uninitialized scoped_ptr.
+ // The input parameter must be allocated with new.
+ explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
+
+ // Destructor. If there is a C object, delete it.
+ // We don't need to test ptr_ == NULL because C++ does that for us.
+ ~scoped_ptr() {
+ enum { type_must_be_complete = sizeof(C) };
+ delete ptr_;
+ }
+
+ // Reset. Deletes the current owned object, if any.
+ // Then takes ownership of a new object, if given.
+ // this->reset(this->get()) works.
+ void reset(C* p = NULL) {
+ if (p != ptr_) {
+ enum { type_must_be_complete = sizeof(C) };
+ delete ptr_;
+ ptr_ = p;
+ }
+ }
+
+ // Accessors to get the owned object.
+ // operator* and operator-> will assert() if there is no current object.
+ C& operator*() const {
+ assert(ptr_ != NULL);
+ return *ptr_;
+ }
+ C* operator->() const {
+ assert(ptr_ != NULL);
+ return ptr_;
+ }
+ C* get() const { return ptr_; }
+
+ // Comparison operators.
+ // These return whether two scoped_ptr refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(C* p) const { return ptr_ == p; }
+ bool operator!=(C* p) const { return ptr_ != p; }
+
+ // Swap two scoped pointers.
+ void swap(scoped_ptr& p2) {
+ C* tmp = ptr_;
+ ptr_ = p2.ptr_;
+ p2.ptr_ = tmp;
+ }
+
+ // Release a pointer.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ C* release() {
+ C* retVal = ptr_;
+ ptr_ = NULL;
+ return retVal;
+ }
+
+ private:
+ C* ptr_;
+
+ // friend class that can access copy ctor (although if it actually
+ // calls a copy ctor, there will be a problem) see below
+ friend scoped_ptr<C> make_scoped_ptr<C>(C *p);
+
+ // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't
+ // make sense, and if C2 == C, it still doesn't make sense because you should
+ // never have the same object owned by two different scoped_ptrs.
+ template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
+ template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
+
+ DISALLOW_COPY_AND_ASSIGN(scoped_ptr);
+};
+
+// Free functions
+template <class C>
+void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) {
+ p1.swap(p2);
+}
+
+template <class C>
+bool operator==(C* p1, const scoped_ptr<C>& p2) {
+ return p1 == p2.get();
+}
+
+template <class C>
+bool operator!=(C* p1, const scoped_ptr<C>& p2) {
+ return p1 != p2.get();
+}
+
+template <class C>
+scoped_ptr<C> make_scoped_ptr(C *p) {
+ // This does nothing but to return a scoped_ptr of the type that the passed
+ // pointer is of. (This eliminates the need to specify the name of T when
+ // making a scoped_ptr that is used anonymously/temporarily.) From an
+ // access control point of view, we construct an unnamed scoped_ptr here
+ // which we return and thus copy-construct. Hence, we need to have access
+ // to scoped_ptr::scoped_ptr(scoped_ptr const &). However, it is guaranteed
+ // that we never actually call the copy constructor, which is a good thing
+ // as we would call the temporary's object destructor (and thus delete p)
+ // if we actually did copy some object, here.
+ return scoped_ptr<C>(p);
+}
+
+// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
+// with new [] and the destructor deletes objects with delete [].
+//
+// As with scoped_ptr<C>, a scoped_array<C> either points to an object
+// or is NULL. A scoped_array<C> owns the object that it points to.
+//
+// Size: sizeof(scoped_array<C>) == sizeof(C*)
+template <class C>
+class scoped_array {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // Constructor. Defaults to intializing with NULL.
+ // There is no way to create an uninitialized scoped_array.
+ // The input parameter must be allocated with new [].
+ explicit scoped_array(C* p = NULL) : array_(p) { }
+
+ // Destructor. If there is a C object, delete it.
+ // We don't need to test ptr_ == NULL because C++ does that for us.
+ ~scoped_array() {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ }
+
+ // Reset. Deletes the current owned object, if any.
+ // Then takes ownership of a new object, if given.
+ // this->reset(this->get()) works.
+ void reset(C* p = NULL) {
+ if (p != array_) {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ array_ = p;
+ }
+ }
+
+ // Get one element of the current object.
+ // Will assert() if there is no current object, or index i is negative.
+ C& operator[](std::ptrdiff_t i) const {
+ assert(i >= 0);
+ assert(array_ != NULL);
+ return array_[i];
+ }
+
+ // Get a pointer to the zeroth element of the current object.
+ // If there is no current object, return NULL.
+ C* get() const {
+ return array_;
+ }
+
+ // Comparison operators.
+ // These return whether two scoped_array refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(C* p) const { return array_ == p; }
+ bool operator!=(C* p) const { return array_ != p; }
+
+ // Swap two scoped arrays.
+ void swap(scoped_array& p2) {
+ C* tmp = array_;
+ array_ = p2.array_;
+ p2.array_ = tmp;
+ }
+
+ // Release an array.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ C* release() {
+ C* retVal = array_;
+ array_ = NULL;
+ return retVal;
+ }
+
+ private:
+ C* array_;
+
+ // Forbid comparison of different scoped_array types.
+ template <class C2> bool operator==(scoped_array<C2> const& p2) const;
+ template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
+
+ DISALLOW_COPY_AND_ASSIGN(scoped_array);
+};
+
+// Free functions
+template <class C>
+void swap(scoped_array<C>& p1, scoped_array<C>& p2) {
+ p1.swap(p2);
+}
+
+template <class C>
+bool operator==(C* p1, const scoped_array<C>& p2) {
+ return p1 == p2.get();
+}
+
+template <class C>
+bool operator!=(C* p1, const scoped_array<C>& p2) {
+ return p1 != p2.get();
+}
+
+// This class wraps the c library function free() in a class that can be
+// passed as a template argument to scoped_ptr_malloc below.
+class ScopedPtrMallocFree {
+ public:
+ inline void operator()(void* x) const {
+ free(x);
+ }
+};
+
+// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
+// second template argument, the functor used to free the object.
+
+template<class C, class FreeProc = ScopedPtrMallocFree>
+class scoped_ptr_malloc {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // Constructor. Defaults to intializing with NULL.
+ // There is no way to create an uninitialized scoped_ptr.
+ // The input parameter must be allocated with an allocator that matches the
+ // Free functor. For the default Free functor, this is malloc, calloc, or
+ // realloc.
+ explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {}
+
+ // Destructor. If there is a C object, call the Free functor.
+ ~scoped_ptr_malloc() {
+ free_(ptr_);
+ }
+
+ // Reset. Calls the Free functor on the current owned object, if any.
+ // Then takes ownership of a new object, if given.
+ // this->reset(this->get()) works.
+ void reset(C* p = NULL) {
+ if (ptr_ != p) {
+ free_(ptr_);
+ ptr_ = p;
+ }
+ }
+
+ // Get the current object.
+ // operator* and operator-> will cause an assert() failure if there is
+ // no current object.
+ C& operator*() const {
+ assert(ptr_ != NULL);
+ return *ptr_;
+ }
+
+ C* operator->() const {
+ assert(ptr_ != NULL);
+ return ptr_;
+ }
+
+ C* get() const {
+ return ptr_;
+ }
+
+ // Comparison operators.
+ // These return whether a scoped_ptr_malloc and a plain pointer refer
+ // to the same object, not just to two different but equal objects.
+ // For compatibility wwith the boost-derived implementation, these
+ // take non-const arguments.
+ bool operator==(C* p) const {
+ return ptr_ == p;
+ }
+
+ bool operator!=(C* p) const {
+ return ptr_ != p;
+ }
+
+ // Swap two scoped pointers.
+ void swap(scoped_ptr_malloc & b) {
+ C* tmp = b.ptr_;
+ b.ptr_ = ptr_;
+ ptr_ = tmp;
+ }
+
+ // Release a pointer.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ C* release() {
+ C* tmp = ptr_;
+ ptr_ = NULL;
+ return tmp;
+ }
+
+ private:
+ C* ptr_;
+
+ // no reason to use these: each scoped_ptr_malloc should have its own object
+ template <class C2, class GP>
+ bool operator==(scoped_ptr_malloc<C2, GP> const& p) const;
+ template <class C2, class GP>
+ bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const;
+
+ static FreeProc const free_;
+
+ DISALLOW_COPY_AND_ASSIGN(scoped_ptr_malloc);
+};
+
+template<class C, class FP>
+FP const scoped_ptr_malloc<C, FP>::free_ = FP();
+
+template<class C, class FP> inline
+void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) {
+ a.swap(b);
+}
+
+template<class C, class FP> inline
+bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) {
+ return p == b.get();
+}
+
+template<class C, class FP> inline
+bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) {
+ return p != b.get();
+}
+} // namespace art
+
+#endif // ART_SRC_SCOPED_PTR_H_
diff --git a/src/strutil.h b/src/strutil.h
new file mode 100644
index 0000000..c9c6caa
--- /dev/null
+++ b/src/strutil.h
@@ -0,0 +1,26 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_STRUTIL_H_
+#define ART_SRC_STRUTIL_H_
+
+#include <string.h>
+
+namespace art {
+
+// Key comparison function for C strings.
+struct CStringLt {
+ bool operator()(const char* s1, const char* s2) const {
+ return strcmp(s1, s2) < 0;
+ }
+};
+
+// Key equality function for C strings.
+struct CStringEq {
+ bool operator()(const char* s1, const char* s2) const {
+ return strcmp(s1, s2) == 0;
+ }
+};
+
+} // namespace art
+
+#endif // ART_SRC_STRUTIL_H_
diff --git a/src/utils.h b/src/utils.h
index a8bf3e7..bf8896d 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -60,6 +60,18 @@
}
// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
+// figure 3-3, page 48, where the function is called clp2.
+static inline uint32_t RoundUpToPowerOfTwo(uint32_t x) {
+ x = x - 1;
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >> 16);
+ return x + 1;
+}
+
+// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
// figure 5-2, page 66, where the function is called pop.
static inline int CountOneBits(uint32_t x) {
x = x - ((x >> 1) & 0x55555555);