diff options
| -rw-r--r-- | src/calling_convention.cc | 2 | ||||
| -rw-r--r-- | src/casts.h | 2 | ||||
| -rw-r--r-- | src/class_linker.cc | 263 | ||||
| -rw-r--r-- | src/class_linker.h | 62 | ||||
| -rw-r--r-- | src/class_linker_test.cc | 28 | ||||
| -rw-r--r-- | src/common_test.h | 4 | ||||
| -rw-r--r-- | src/dex_cache.cc | 12 | ||||
| -rw-r--r-- | src/dex_cache.h | 26 | ||||
| -rw-r--r-- | src/dex_cache_test.cc | 14 | ||||
| -rw-r--r-- | src/dex_file.cc | 10 | ||||
| -rw-r--r-- | src/dex_file.h | 31 | ||||
| -rw-r--r-- | src/dex_file_test.cc | 8 | ||||
| -rw-r--r-- | src/exception_test.cc | 2 | ||||
| -rw-r--r-- | src/heap.cc | 3 | ||||
| -rw-r--r-- | src/heap.h | 7 | ||||
| -rw-r--r-- | src/image.h | 13 | ||||
| -rw-r--r-- | src/image_test.cc | 35 | ||||
| -rw-r--r-- | src/image_writer.cc | 70 | ||||
| -rw-r--r-- | src/image_writer.h | 2 | ||||
| -rw-r--r-- | src/intern_table.cc | 14 | ||||
| -rw-r--r-- | src/intern_table.h | 10 | ||||
| -rw-r--r-- | src/jni_compiler_test.cc | 2 | ||||
| -rw-r--r-- | src/jni_internal_test.cc | 26 | ||||
| -rw-r--r-- | src/object.cc | 8 | ||||
| -rw-r--r-- | src/object.h | 57 | ||||
| -rw-r--r-- | src/object_test.cc | 10 | ||||
| -rw-r--r-- | src/runtime.cc | 2 | ||||
| -rw-r--r-- | src/space.cc | 3 | ||||
| -rw-r--r-- | src/space.h | 13 | ||||
| -rw-r--r-- | src/stringpiece.h | 15 | ||||
| -rw-r--r-- | src/unordered_map.h | 30 | ||||
| -rw-r--r-- | src/zip_archive.h | 2 |
32 files changed, 598 insertions, 188 deletions
diff --git a/src/calling_convention.cc b/src/calling_convention.cc index d14857b4c3..32e3ee2a4b 100644 --- a/src/calling_convention.cc +++ b/src/calling_convention.cc @@ -24,7 +24,7 @@ bool ManagedRuntimeCallingConvention::HasNext() { void ManagedRuntimeCallingConvention::Next() { CHECK(HasNext()); - if (IsCurrentUserArg() && + if (IsCurrentUserArg() && GetMethod()->IsParamALongOrDouble(itr_args_)) { itr_longs_and_doubles_++; itr_slots_++; diff --git a/src/casts.h b/src/casts.h index a5e31c4cc7..461df21fa8 100644 --- a/src/casts.h +++ b/src/casts.h @@ -59,7 +59,7 @@ inline To down_cast(From* f) { // so we only accept pointers implicit_cast<From*, To>(0); } - // + // // assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only! return static_cast<To>(f); } diff --git a/src/class_linker.cc b/src/class_linker.cc index 55aaff4888..2e4aa9ed42 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -14,25 +14,59 @@ #include "object.h" #include "dex_file.h" #include "scoped_ptr.h" +#include "space.h" #include "thread.h" #include "utils.h" namespace art { -ClassLinker* ClassLinker::Create(const std::vector<DexFile*>& boot_class_path) { +const char* ClassLinker::class_roots_descriptors_[kClassRootsMax] = { + "Ljava/lang/Class;", + "Ljava/lang/Object;", + "[Ljava/lang/Object;", + "Ljava/lang/String;", + "Ljava/lang/reflect/Field;", + "Ljava/lang/reflect/Method;", + "Ljava/lang/ClassLoader;", + "Ldalvik/system/BaseDexClassLoader;", + "Ldalvik/system/PathClassLoader;", + "Z", + "B", + "C", + "D", + "F", + "I", + "J", + "S", + "V", + "[Z", + "[B", + "[C", + "[D", + "[F", + "[I", + "[J", + "[S", +}; + +ClassLinker* ClassLinker::Create(const std::vector<DexFile*>& boot_class_path, Space* space) { scoped_ptr<ClassLinker> class_linker(new ClassLinker); - class_linker->Init(boot_class_path); + if (space == NULL) { + class_linker->Init(boot_class_path); + } else { + class_linker->Init(boot_class_path, space); + } // TODO: check for failure during initialization return class_linker.release(); } + void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { CHECK(!init_done_); // java_lang_Class comes first, its needed for AllocClass Class* java_lang_Class = down_cast<Class*>(Heap::AllocObject(NULL, sizeof(Class))); CHECK(java_lang_Class != NULL); - // java_lang_Class->descriptor_ = "Ljava/lang/Class;"; // XXX bdc can these be created later? java_lang_Class->object_size_ = sizeof(Class); java_lang_Class->klass_ = java_lang_Class; // AllocClass(Class*) can now be used @@ -40,7 +74,6 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { // java_lang_Object comes next so that object_array_class can be created Class* java_lang_Object = AllocClass(java_lang_Class); CHECK(java_lang_Object != NULL); - // java_lang_Object->descriptor_ = "Ljava/lang/Object;"; // XXX bdc can these be created later? // backfill Object as the super class of Class java_lang_Class->super_class_ = java_lang_Object; // mark as non-primitive for object_array_class @@ -49,19 +82,16 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { // object_array_class is for root_classes to provide the storage for these classes Class* object_array_class = AllocClass(java_lang_Class); CHECK(object_array_class != NULL); - // object_array_class->descriptor_ = "[Ljava/lang/Object;"; // XXX bdc can these be created later? object_array_class->component_type_ = java_lang_Object; // String and char[] are necessary so that FindClass can assign names to members Class* java_lang_String = AllocClass(java_lang_Class); CHECK(java_lang_String != NULL); - // java_lang_String->descriptor_ = "Ljava/lang/String;"; // XXX can these be created later? CHECK_LT(java_lang_String->object_size_, sizeof(String)); java_lang_String->object_size_ = sizeof(String); - String::InitClass(java_lang_String); + String::SetClass(java_lang_String); Class* char_array_class = AllocClass(java_lang_Class); CHECK(char_array_class != NULL); - // char_array_class->descriptor_ = "[C"; // XXX can these be created later? CharArray::SetArrayClass(char_array_class); // Now String::Alloc* can be used @@ -96,15 +126,15 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { // create storage for root classes, save away our work so far class_roots_ = ObjectArray<Class>::Alloc(object_array_class, kClassRootsMax); - class_roots_->Set(kJavaLangClass, java_lang_Class); - class_roots_->Set(kJavaLangObject, java_lang_Object); - class_roots_->Set(kObjectArrayClass, object_array_class); - class_roots_->Set(kJavaLangString, java_lang_String); - class_roots_->Set(kCharArrayClass, char_array_class); - class_roots_->Set(kIntArrayClass, int_array_class); - class_roots_->Set(kLongArrayClass, long_array_class); - class_roots_->Set(kJavaLangReflectField, java_lang_reflect_Field); - class_roots_->Set(kJavaLangReflectMethod, java_lang_reflect_Method); + SetClassRoot(kJavaLangClass, java_lang_Class); + SetClassRoot(kJavaLangObject, java_lang_Object); + SetClassRoot(kObjectArrayClass, object_array_class); + SetClassRoot(kJavaLangString, java_lang_String); + SetClassRoot(kCharArrayClass, char_array_class); + SetClassRoot(kIntArrayClass, int_array_class); + SetClassRoot(kLongArrayClass, long_array_class); + SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field); + SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method); // now that these are registered, we can use AllocClass() and AllocObjectArray // setup boot_class_path_ now that we can use AllocObjectArray to @@ -143,15 +173,15 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { CHECK(java_lang_ClassLoader != NULL); CHECK_LT(java_lang_ClassLoader->object_size_, sizeof(ClassLoader)); java_lang_ClassLoader->object_size_ = sizeof(ClassLoader); - class_roots_->Set(kJavaLangClassLoader, java_lang_ClassLoader); + SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader); Class* dalvik_system_BaseDexClassLoader = FindSystemClass("Ldalvik/system/BaseDexClassLoader;"); CHECK(dalvik_system_BaseDexClassLoader != NULL); CHECK_EQ(dalvik_system_BaseDexClassLoader->object_size_, sizeof(BaseDexClassLoader)); - class_roots_->Set(kDalvikSystemBaseDexClassLoader, dalvik_system_BaseDexClassLoader); + SetClassRoot(kDalvikSystemBaseDexClassLoader, dalvik_system_BaseDexClassLoader); Class* dalvik_system_PathClassLoader = FindSystemClass("Ldalvik/system/PathClassLoader;"); CHECK(dalvik_system_PathClassLoader != NULL); CHECK_EQ(dalvik_system_PathClassLoader->object_size_, sizeof(PathClassLoader)); - class_roots_->Set(kDalvikSystemPathClassLoader, dalvik_system_PathClassLoader); + SetClassRoot(kDalvikSystemPathClassLoader, dalvik_system_PathClassLoader); // Setup a single, global copy of "interfaces" and "iftable" for // reuse across array classes @@ -181,15 +211,15 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { CHECK_EQ(java_io_Serializable, object_array_class->GetInterface(1)); // Setup the primitive type classes. - class_roots_->Set(kPrimitiveBoolean, CreatePrimitiveClass("Z")); - class_roots_->Set(kPrimitiveByte, CreatePrimitiveClass("B")); - class_roots_->Set(kPrimitiveChar, CreatePrimitiveClass("C")); - class_roots_->Set(kPrimitiveDouble, CreatePrimitiveClass("D")); - class_roots_->Set(kPrimitiveFloat, CreatePrimitiveClass("F")); - class_roots_->Set(kPrimitiveInt, CreatePrimitiveClass("I")); - class_roots_->Set(kPrimitiveLong, CreatePrimitiveClass("J")); - class_roots_->Set(kPrimitiveShort, CreatePrimitiveClass("S")); - class_roots_->Set(kPrimitiveVoid, CreatePrimitiveClass("V")); + SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z")); + SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B")); + SetClassRoot(kPrimitiveChar, CreatePrimitiveClass("C")); + SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D")); + SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F")); + SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I")); + SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J")); + SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S")); + SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V")); // now we can use FindSystemClass for anything, including for "[C" // run char[], int[] and long[] through FindClass to complete initialization @@ -202,20 +232,29 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { // Initialize all the other primitive array types for PrimitiveArray::Alloc. // These are easy because everything we need has already been set up. - class_roots_->Set(kBooleanArrayClass, FindSystemClass("[Z")); - class_roots_->Set(kByteArrayClass, FindSystemClass("[B")); - class_roots_->Set(kDoubleArrayClass, FindSystemClass("[D")); - class_roots_->Set(kFloatArrayClass, FindSystemClass("[F")); - class_roots_->Set(kShortArrayClass, FindSystemClass("[S")); + SetClassRoot(kBooleanArrayClass, FindSystemClass("[Z")); + SetClassRoot(kByteArrayClass, FindSystemClass("[B")); + SetClassRoot(kDoubleArrayClass, FindSystemClass("[D")); + SetClassRoot(kFloatArrayClass, FindSystemClass("[F")); + SetClassRoot(kShortArrayClass, FindSystemClass("[S")); BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); - // ensure all class_roots_ were initialized + FinishInit(); +} + +void ClassLinker::FinishInit() { + // ensure all class_roots_ are initialized for (size_t i = 0; i < kClassRootsMax; i++) { - CHECK(GetClassRoot(static_cast<ClassRoot>(i))); + ClassRoot class_root = static_cast<ClassRoot>(i); + Class* klass = GetClassRoot(class_root); + CHECK(klass != NULL); + DCHECK(klass->IsArray() || klass->IsPrimitive() || klass->dex_cache_ != NULL); + // note SetClassRoot does additional validation. + // if possible add new checks there to catch errors early } // disable the slow paths in FindClass and CreatePrimitiveClass now @@ -223,7 +262,125 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { init_done_ = true; } -void ClassLinker::VisitRoots(Heap::RootVistor* root_visitor, void* arg) { +struct ClassLinker::InitCallbackState { + ClassLinker* class_linker; + + Class* class_roots[kClassRootsMax]; + + typedef std::tr1::unordered_map<std::string, ClassRoot> Table; + Table descriptor_to_class_root; + + struct DexCacheHash { + size_t operator()(art::DexCache* const& obj) const { + return reinterpret_cast<size_t>(&obj); + } + }; + typedef std::tr1::unordered_set<DexCache*, DexCacheHash> Set; + Set dex_caches; +}; + +void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path, Space* space) { + CHECK(!init_done_); + + HeapBitmap* heap_bitmap = Heap::GetLiveBits(); + DCHECK(heap_bitmap != NULL); + + InitCallbackState state; + state.class_linker = this; + for (size_t i = 0; i < kClassRootsMax; i++) { + ClassRoot class_root = static_cast<ClassRoot>(i); + state.descriptor_to_class_root[GetClassRootDescriptor(class_root)] = class_root; + } + + // reinit clases_ table + heap_bitmap->Walk(InitCallback, &state); + + // reinit class_roots_ + Class* object_array_class = state.class_roots[kObjectArrayClass]; + class_roots_ = ObjectArray<Class>::Alloc(object_array_class, kClassRootsMax); + for (size_t i = 0; i < kClassRootsMax; i++) { + ClassRoot class_root = static_cast<ClassRoot>(i); + SetClassRoot(class_root, state.class_roots[class_root]); + } + + // reinit intern_table_ + ObjectArray<Object>* interned_array = space->GetImageHeader().GetInternedArray(); + for (int32_t i = 0; i < interned_array->GetLength(); i++) { + String* string = interned_array->Get(i)->AsString(); + intern_table_.Register(string); + } + + // reinit array_interfaces_ from any array class instance, they should all be == + array_interfaces_ = GetClassRoot(kObjectArrayClass)->interfaces_; + DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->interfaces_); + + // build a map from location to DexCache to match up with DexFile::GetLocation + std::tr1::unordered_map<std::string, DexCache*> location_to_dex_cache; + typedef InitCallbackState::Set::const_iterator It; // TODO: C++0x auto + for (It it = state.dex_caches.begin(), end = state.dex_caches.end(); it != end; ++it) { + DexCache* dex_cache = *it; + std::string location = dex_cache->GetLocation()->ToModifiedUtf8(); + location_to_dex_cache[location] = dex_cache; + } + + // reinit boot_class_path with DexFile arguments and found DexCaches + for (size_t i = 0; i != boot_class_path.size(); ++i) { + DexFile* dex_file = boot_class_path[i]; + DexCache* dex_cache = location_to_dex_cache[dex_file->GetLocation()]; + AppendToBootClassPath(dex_file, dex_cache); + } + + String::SetClass(GetClassRoot(kJavaLangString)); + BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); + ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); + CharArray::SetArrayClass(GetClassRoot(kCharArrayClass)); + DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); + FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); + IntArray::SetArrayClass(GetClassRoot(kIntArrayClass)); + LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); + ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); + + FinishInit(); +} + +void ClassLinker::InitCallback(Object *obj, void *arg) { + DCHECK(obj != NULL); + DCHECK(arg != NULL); + InitCallbackState* state = reinterpret_cast<InitCallbackState*>(arg); + + if (!obj->IsClass()) { + return; + } + Class* klass = obj->AsClass(); + CHECK(klass->class_loader_ == NULL); + + std::string descriptor = klass->GetDescriptor()->ToModifiedUtf8(); + + // restore class to ClassLinker::classes_ table + state->class_linker->InsertClass(descriptor, klass); + + // note DexCache to match with DexFile later + DexCache* dex_cache = klass->GetDexCache(); + if (dex_cache != NULL) { + state->dex_caches.insert(dex_cache); + } else { + DCHECK(klass->IsArray() || klass->IsPrimitive()); + } + + // check if this is a root, if so, register it + typedef InitCallbackState::Table::const_iterator It; // TODO: C++0x auto + It it = state->descriptor_to_class_root.find(descriptor); + if (it != state->descriptor_to_class_root.end()) { + ClassRoot class_root = it->second; + state->class_roots[class_root] = klass; + } +} + +// Keep in sync with InitCallback. Anything we visit, we need to +// reinit references to when reinitializing a ClassLinker from a +// mapped image. +void ClassLinker::VisitRoots(Heap::RootVistor* root_visitor, void* arg) const { + root_visitor(class_roots_, arg); for (size_t i = 0; i < dex_caches_.size(); i++) { @@ -243,8 +400,14 @@ void ClassLinker::VisitRoots(Heap::RootVistor* root_visitor, void* arg) { root_visitor(array_interfaces_, arg); } -DexCache* ClassLinker::AllocDexCache() { - return down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::kMax)); +DexCache* ClassLinker::AllocDexCache(const DexFile* dex_file) { + DexCache* dex_cache = down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::kMax)); + dex_cache->Init(String::AllocFromModifiedUtf8(dex_file->GetLocation().c_str()), + AllocObjectArray<String>(dex_file->NumStringIds()), + AllocObjectArray<Class>(dex_file->NumTypeIds()), + AllocObjectArray<Method>(dex_file->NumMethodIds()), + AllocObjectArray<Field>(dex_file->NumFieldIds())); + return dex_cache; } Class* ClassLinker::AllocClass(Class* java_lang_Class) { @@ -537,21 +700,27 @@ void ClassLinker::LoadMethod(const DexFile& dex_file, } } -void ClassLinker::AppendToBootClassPath(DexFile* dex_file) { +void ClassLinker::AppendToBootClassPath(const DexFile* dex_file) { CHECK(dex_file != NULL); + AppendToBootClassPath(dex_file, AllocDexCache(dex_file)); +} + +void ClassLinker::AppendToBootClassPath(const DexFile* dex_file, DexCache* dex_cache) { + CHECK(dex_file != NULL); + CHECK(dex_cache != NULL); boot_class_path_.push_back(dex_file); - RegisterDexFile(dex_file); + RegisterDexFile(dex_file, dex_cache); } void ClassLinker::RegisterDexFile(const DexFile* dex_file) { CHECK(dex_file != NULL); - dex_files_.push_back(dex_file); - DexCache* dex_cache = AllocDexCache(); + RegisterDexFile(dex_file, AllocDexCache(dex_file)); +} + +void ClassLinker::RegisterDexFile(const DexFile* dex_file, DexCache* dex_cache) { + CHECK(dex_file != NULL); CHECK(dex_cache != NULL); - dex_cache->Init(AllocObjectArray<String>(dex_file->NumStringIds()), - AllocObjectArray<Class>(dex_file->NumTypeIds()), - AllocObjectArray<Method>(dex_file->NumMethodIds()), - AllocObjectArray<Field>(dex_file->NumFieldIds())); + dex_files_.push_back(dex_file); dex_caches_.push_back(dex_cache); } diff --git a/src/class_linker.h b/src/class_linker.h index bc7a780e13..ad293833cf 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -14,6 +14,7 @@ #include "object.h" #include "thread.h" #include "unordered_map.h" +#include "unordered_set.h" #include "gtest/gtest.h" @@ -21,11 +22,20 @@ namespace art { class ClassLinker { public: - // Initializes the class linker. - static ClassLinker* Create(const std::vector<DexFile*>& boot_class_path); + // Initializes the class linker using DexFile and an optional boot Space. + static ClassLinker* Create(const std::vector<DexFile*>& boot_class_path, Space* boot_space); ~ClassLinker() { delete classes_lock_; + String::ResetClass(); + BooleanArray::ResetArrayClass(); + ByteArray::ResetArrayClass(); + CharArray::ResetArrayClass(); + DoubleArray::ResetArrayClass(); + FloatArray::ResetArrayClass(); + IntArray::ResetArrayClass(); + LongArray::ResetArrayClass(); + ShortArray::ResetArrayClass(); } // Finds a class by its descriptor name. @@ -43,17 +53,31 @@ class ClassLinker { bool EnsureInitialized(Class* c); void RegisterDexFile(const DexFile* dex_file); + void RegisterDexFile(const DexFile* dex_file, DexCache* dex_cache); - void VisitRoots(Heap::RootVistor* root_visitor, void* arg); + const InternTable& GetInternTable() { + return intern_table_; + } + + void VisitRoots(Heap::RootVistor* root_visitor, void* arg) const; private: ClassLinker() : classes_lock_(Mutex::Create("ClassLinker::Lock")), + class_roots_(NULL), init_done_(false) { } + // Initialize class linker from DexFile instances. void Init(const std::vector<DexFile*>& boot_class_path_); + // Initialize class linker from pre-initialized space. + void Init(const std::vector<DexFile*>& boot_class_path_, Space* space); + static void InitCallback(Object *obj, void *arg); + struct InitCallbackState; + + void FinishInit(); + bool InitializeClass(Class* klass); // For early bootstrapping by Init @@ -63,12 +87,12 @@ class ClassLinker { // values that are known to the ClassLinker such as // kObjectArrayClass and kJavaLangString etc. Class* AllocClass(); - DexCache* AllocDexCache(); + DexCache* AllocDexCache(const DexFile* dex_file); Field* AllocField(); Method* AllocMethod(); template <class T> ObjectArray<T>* AllocObjectArray(size_t length) { - return ObjectArray<T>::Alloc(class_roots_->Get(kObjectArrayClass), length); + return ObjectArray<T>::Alloc(GetClassRoot(kObjectArrayClass), length); } PathClassLoader* AllocPathClassLoader(std::vector<const DexFile*> dex_files); @@ -81,7 +105,8 @@ class ClassLinker { DexCache* FindDexCache(const DexFile* dex_file) const; - void AppendToBootClassPath(DexFile* dex_file); + void AppendToBootClassPath(const DexFile* dex_file); + void AppendToBootClassPath(const DexFile* dex_file, DexCache* dex_cache); void LoadClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, @@ -165,7 +190,8 @@ class ClassLinker { InternTable intern_table_; - // indexes into class_roots_ + // indexes into class_roots_. + // needs to be kept in sync with class_roots_descriptors_. enum ClassRoot { kJavaLangClass, kJavaLangObject, @@ -198,11 +224,33 @@ class ClassLinker { ObjectArray<Class>* class_roots_; Class* GetClassRoot(ClassRoot class_root) { + DCHECK(class_roots_ != NULL); Class* klass = class_roots_->Get(class_root); DCHECK(klass != NULL); return klass; } + void SetClassRoot(ClassRoot class_root, Class* klass) { + DCHECK(!init_done_); + + DCHECK(klass != NULL); + DCHECK(klass->class_loader_ == NULL); + DCHECK(klass->descriptor_ != NULL); + DCHECK(klass->descriptor_->Equals(GetClassRootDescriptor(class_root))); + + DCHECK(class_roots_ != NULL); + DCHECK(class_roots_->Get(class_root) == NULL); + class_roots_->Set(class_root, klass); + } + + static const char* class_roots_descriptors_[kClassRootsMax]; + + const char* GetClassRootDescriptor(ClassRoot class_root) { + const char* descriptor = class_roots_descriptors_[class_root]; + CHECK(descriptor != NULL); + return descriptor; + } + ObjectArray<Class>* array_interfaces_; InterfaceEntry* array_iftable_; diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc index 42a773ca07..88ddd07a68 100644 --- a/src/class_linker_test.cc +++ b/src/class_linker_test.cc @@ -134,11 +134,15 @@ class ClassLinkerTest : public CommonTest { Method* method = klass->GetDirectMethod(i); EXPECT_TRUE(method != NULL); EXPECT_EQ(klass, method->GetDeclaringClass()); + EXPECT_TRUE(method->GetName() != NULL); + EXPECT_TRUE(method->GetSignature() != NULL); } for (size_t i = 0; i < klass->NumVirtualMethods(); i++) { Method* method = klass->GetVirtualMethod(i); EXPECT_TRUE(method != NULL); + EXPECT_TRUE(method->GetName() != NULL); + EXPECT_TRUE(method->GetSignature() != NULL); } for (size_t i = 0; i < klass->NumInstanceFields(); i++) { @@ -146,6 +150,8 @@ class ClassLinkerTest : public CommonTest { EXPECT_TRUE(field != NULL); EXPECT_FALSE(field->IsStatic()); EXPECT_EQ(klass, field->GetDeclaringClass()); + EXPECT_TRUE(field->GetName() != NULL); + EXPECT_TRUE(field->GetDescriptor() != NULL); } for (size_t i = 0; i < klass->NumStaticFields(); i++) { @@ -153,22 +159,20 @@ class ClassLinkerTest : public CommonTest { EXPECT_TRUE(field != NULL); EXPECT_TRUE(field->IsStatic()); EXPECT_EQ(klass, field->GetDeclaringClass()); - } + EXPECT_TRUE(field->GetName() != NULL); + EXPECT_TRUE(field->GetDescriptor() != NULL); + } // Confirm that all instances fields are packed together at the start EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields()); for (size_t i = 0; i < klass->NumReferenceInstanceFields(); i++) { Field* field = klass->GetInstanceField(i); - ASSERT_TRUE(field != NULL); - ASSERT_TRUE(field->GetDescriptor() != NULL); Class* field_type = class_linker_->FindClass(field->GetDescriptor(), class_loader); ASSERT_TRUE(field_type != NULL); EXPECT_FALSE(field_type->IsPrimitive()); } for (size_t i = klass->NumReferenceInstanceFields(); i < klass->NumInstanceFields(); i++) { Field* field = klass->GetInstanceField(i); - ASSERT_TRUE(field != NULL); - ASSERT_TRUE(field->GetDescriptor() != NULL); Class* field_type = class_linker_->FindClass(field->GetDescriptor(), class_loader); ASSERT_TRUE(field_type != NULL); EXPECT_TRUE(field_type->IsPrimitive()); @@ -207,7 +211,7 @@ TEST_F(ClassLinkerTest, FindClassNonexistent) { } TEST_F(ClassLinkerTest, FindClassNested) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kNestedDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kNestedDex, "kNestedDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); Class* outer = class_linker_->FindClass("LNested;", class_loader); @@ -262,7 +266,7 @@ TEST_F(ClassLinkerTest, FindClass) { EXPECT_EQ(0U, JavaLangObject->NumInterfaces()); - scoped_ptr<DexFile> dex(OpenDexFileBase64(kMyClassDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kMyClassDex, "kMyClassDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); EXPECT_TRUE(linker->FindSystemClass("LMyClass;") == NULL); Class* MyClass = linker->FindClass("LMyClass;", class_loader); @@ -378,8 +382,8 @@ TEST_F(ClassLinkerTest, ValidatePrimitiveArrayElementsOffset) { } TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) { - scoped_ptr<DexFile> dex_1(OpenDexFileBase64(kMyClassDex)); - scoped_ptr<DexFile> dex_2(OpenDexFileBase64(kMyClassDex)); + scoped_ptr<DexFile> dex_1(OpenDexFileBase64(kMyClassDex, "kMyClassDex")); + scoped_ptr<DexFile> dex_2(OpenDexFileBase64(kMyClassDex, "kMyClassDex")); PathClassLoader* class_loader_1 = AllocPathClassLoader(dex_1.get()); PathClassLoader* class_loader_2 = AllocPathClassLoader(dex_2.get()); Class* MyClass_1 = class_linker_->FindClass("LMyClass;", class_loader_1); @@ -391,7 +395,7 @@ TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) { TEST_F(ClassLinkerTest, StaticFields) { // TODO: uncomment expectations of initial values when InitializeClass works - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStatics)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStatics, "kStatics")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); Class* statics = class_linker_->FindClass("LStatics;", class_loader); // class_linker_->InitializeClass(statics); // TODO: uncomment this @@ -441,7 +445,7 @@ TEST_F(ClassLinkerTest, StaticFields) { Field* s8 = statics->GetStaticField(8); EXPECT_EQ('L', s8->GetType()); -// EXPECT_TRUE(down_cast<String*>(s8->GetObject())->Equals("android")); // TODO: uncomment this +// EXPECT_TRUE(s8->GetObject()->AsString()->Equals("android")); // TODO: uncomment this s8->SetObject(String::AllocFromModifiedUtf8("robot")); Field* s9 = statics->GetStaticField(9); @@ -457,7 +461,7 @@ TEST_F(ClassLinkerTest, StaticFields) { EXPECT_EQ(0x34567890abcdef12LL, s5->GetLong()); EXPECT_EQ(0.75, s6->GetFloat()); EXPECT_EQ(16777219, s7->GetDouble()); - EXPECT_TRUE(down_cast<String*>(s8->GetObject())->Equals("robot")); + EXPECT_TRUE(s8->GetObject()->AsString()->Equals("robot")); } } // namespace art diff --git a/src/common_test.h b/src/common_test.h index 14a68a2de0..685e627297 100644 --- a/src/common_test.h +++ b/src/common_test.h @@ -277,12 +277,12 @@ static const char kStaticLeafMethodsDex[] = "AAwAAADgAAAABQAAAA4AAABwAQAABgAAAAEAAADgAQAAASAAAA0AAAAAAgAAARAAAAsAAAA4AwAA" "AiAAABYAAACuAwAAAyAAAA0AAABXBAAAACAAAAEAAAC3BAAAABAAAAEAAAD0BAAA"; -static inline DexFile* OpenDexFileBase64(const char* base64) { +static inline DexFile* OpenDexFileBase64(const char* base64, const std::string& location) { CHECK(base64 != NULL); size_t length; byte* dex_bytes = DecodeBase64(base64, &length); CHECK(dex_bytes != NULL); - DexFile* dex_file = DexFile::OpenPtr(dex_bytes, length); + DexFile* dex_file = DexFile::OpenPtr(dex_bytes, length, location); CHECK(dex_file != NULL); return dex_file; } diff --git a/src/dex_cache.cc b/src/dex_cache.cc index 8ab4130971..3bd04eb301 100644 --- a/src/dex_cache.cc +++ b/src/dex_cache.cc @@ -8,14 +8,16 @@ namespace art { -void DexCache::Init(ObjectArray<String>* strings, +void DexCache::Init(String* location, + ObjectArray<String>* strings, ObjectArray<Class>* classes, ObjectArray<Method>* methods, ObjectArray<Field>* fields) { - Set(kStrings, strings); - Set(kClasses, classes); - Set(kMethods, methods); - Set(kFields, fields); + Set(kLocation, location); + Set(kStrings, strings); + Set(kClasses, classes); + Set(kMethods, methods); + Set(kFields, fields); } } // namespace art diff --git a/src/dex_cache.h b/src/dex_cache.h index 5f3c54fb5d..534a29b319 100644 --- a/src/dex_cache.h +++ b/src/dex_cache.h @@ -19,18 +19,24 @@ class DexCache : public ObjectArray<Object> { public: enum ArrayIndexes { - kStrings = 0, - kClasses = 1, - kMethods = 2, - kFields = 3, - kMax = 4, + kLocation = 0, + kStrings = 1, + kClasses = 2, + kMethods = 3, + kFields = 4, + kMax = 5, }; - void Init(ObjectArray<String>* strings, + void Init(String* location, + ObjectArray<String>* strings, ObjectArray<Class>* classes, ObjectArray<Method>* methods, ObjectArray<Field>* fields); + String* GetLocation() const { + return Get(kLocation)->AsString(); + } + size_t NumStrings() const { return GetStrings()->GetLength(); } @@ -81,16 +87,16 @@ class DexCache : public ObjectArray<Object> { private: ObjectArray<String>* GetStrings() const { - return static_cast<ObjectArray<String>*>(Get(kStrings)); + return static_cast<ObjectArray<String>*>(Get(kStrings)); } ObjectArray<Class>* GetClasses() const { - return static_cast<ObjectArray<Class>*>(Get(kClasses)); + return static_cast<ObjectArray<Class>*>(Get(kClasses)); } ObjectArray<Method>* GetMethods() const { - return static_cast<ObjectArray<Method>*>(Get(kMethods)); + return static_cast<ObjectArray<Method>*>(Get(kMethods)); } ObjectArray<Field>* GetFields() const { - return static_cast<ObjectArray<Field>*>(Get(kFields)); + return static_cast<ObjectArray<Field>*>(Get(kFields)); } DexCache(); }; diff --git a/src/dex_cache_test.cc b/src/dex_cache_test.cc index cb682a08df..674ec0f80e 100644 --- a/src/dex_cache_test.cc +++ b/src/dex_cache_test.cc @@ -16,16 +16,12 @@ class DexCacheTest : public CommonTest {}; TEST_F(DexCacheTest, Open) { - DexCache* dex_cache = class_linker_->AllocDexCache(); + DexCache* dex_cache = class_linker_->AllocDexCache(java_lang_dex_file_.get()); ASSERT_TRUE(dex_cache != NULL); - dex_cache->Init(class_linker_->AllocObjectArray<String>(1), - class_linker_->AllocObjectArray<Class>(2), - class_linker_->AllocObjectArray<Method>(3), - class_linker_->AllocObjectArray<Field>(4)); - EXPECT_EQ(1U, dex_cache->NumStrings()); - EXPECT_EQ(2U, dex_cache->NumClasses()); - EXPECT_EQ(3U, dex_cache->NumMethods()); - EXPECT_EQ(4U, dex_cache->NumFields()); + EXPECT_EQ(java_lang_dex_file_->NumStringIds(), dex_cache->NumStrings()); + EXPECT_EQ(java_lang_dex_file_->NumTypeIds(), dex_cache->NumClasses()); + EXPECT_EQ(java_lang_dex_file_->NumMethodIds(), dex_cache->NumMethods()); + EXPECT_EQ(java_lang_dex_file_->NumFieldIds(), dex_cache->NumFields()); } } // namespace art diff --git a/src/dex_file.cc b/src/dex_file.cc index b9ae7e3b1a..14c62f1312 100644 --- a/src/dex_file.cc +++ b/src/dex_file.cc @@ -77,7 +77,7 @@ DexFile* DexFile::OpenFile(const std::string& filename) { close(fd); byte* dex_file = reinterpret_cast<byte*>(addr); Closer* closer = new MmapCloser(addr, length); - return Open(dex_file, length, closer); + return Open(dex_file, length, filename, closer); } static const char* kClassesDex = "classes.dex"; @@ -294,15 +294,15 @@ DexFile* DexFile::OpenZip(const std::string& filename) { // NOTREACHED } -DexFile* DexFile::OpenPtr(byte* ptr, size_t length) { +DexFile* DexFile::OpenPtr(byte* ptr, size_t length, const std::string& location) { CHECK(ptr != NULL); DexFile::Closer* closer = new PtrCloser(ptr); - return Open(ptr, length, closer); + return Open(ptr, length, location, closer); } DexFile* DexFile::Open(const byte* dex_bytes, size_t length, - Closer* closer) { - scoped_ptr<DexFile> dex_file(new DexFile(dex_bytes, length, closer)); + const std::string& location, Closer* closer) { + scoped_ptr<DexFile> dex_file(new DexFile(dex_bytes, length, location, closer)); if (!dex_file->Init()) { return NULL; } else { diff --git a/src/dex_file.h b/src/dex_file.h index 2de46f8d2d..b3f9bdd39a 100644 --- a/src/dex_file.h +++ b/src/dex_file.h @@ -288,13 +288,21 @@ class DexFile { // Opens a .jar, .zip, or .apk file from the file system. static DexFile* OpenZip(const std::string& filename); - // Opens a .dex file from a new allocated pointer - static DexFile* OpenPtr(byte* ptr, size_t length); + // Opens a .dex file from a new allocated pointer. location is used + // to identify the source, for example "/system/framework/core.jar" + // or "contrived-test-42". When initializing a ClassLinker from an + // image, the location is used to match DexCaches the image to their + // corresponding DexFiles.N + static DexFile* OpenPtr(byte* ptr, size_t length, const std::string& location); // Closes a .dex file. virtual ~DexFile(); - const Header& GetHeader() { + const std::string& GetLocation() const { + return location_; + } + + const Header& GetHeader() const { CHECK(header_ != NULL); return *header_; } @@ -640,11 +648,12 @@ class DexFile { }; // Opens a .dex file at a the given address. - static DexFile* Open(const byte* dex_file, size_t length, Closer* closer); + static DexFile* Open(const byte* dex_file, size_t length, const std::string& location, Closer* closer); - DexFile(const byte* addr, size_t length, Closer* closer) + DexFile(const byte* addr, size_t length, const std::string& location, Closer* closer) : base_(addr), length_(length), + location_(location), closer_(closer), header_(0), string_ids_(0), @@ -652,7 +661,11 @@ class DexFile { field_ids_(0), method_ids_(0), proto_ids_(0), - class_defs_(0) {} + class_defs_(0) { + CHECK(addr != NULL); + CHECK_GT(length, 0U); + CHECK(closer != NULL); + } // Top-level initializer that calls other Init methods. bool Init(); @@ -679,6 +692,12 @@ class DexFile { // The size of the underlying memory allocation in bytes. size_t length_; + // Typically the dex file name when availble, alternatively some identifying string. + // + // The ClassLinker will use this to match DexFiles the boot class + // path to DexCache::GetLocation when loading from an image. + const std::string location_; + // Helper object to free the underlying allocation. scoped_ptr<Closer> closer_; diff --git a/src/dex_file_test.cc b/src/dex_file_test.cc index 616e1c418e..9eb5f73b35 100644 --- a/src/dex_file_test.cc +++ b/src/dex_file_test.cc @@ -10,12 +10,12 @@ namespace art { TEST(DexFileTest, Open) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kNestedDex)); + scoped_ptr<const DexFile> dex(OpenDexFileBase64(kNestedDex, "kNestedDex")); ASSERT_TRUE(dex != NULL); } TEST(DexFileTest, Header) { - scoped_ptr<DexFile> raw(OpenDexFileBase64(kNestedDex)); + scoped_ptr<const DexFile> raw(OpenDexFileBase64(kNestedDex, "kNestedDex")); ASSERT_TRUE(raw != NULL); const DexFile::Header& header = raw->GetHeader(); @@ -43,7 +43,7 @@ TEST(DexFileTest, Header) { } TEST(DexFileTest, ClassDefs) { - scoped_ptr<DexFile> raw(OpenDexFileBase64(kNestedDex)); + scoped_ptr<const DexFile> raw(OpenDexFileBase64(kNestedDex, "kNestedDex")); ASSERT_TRUE(raw != NULL); EXPECT_EQ(2U, raw->NumClassDefs()); @@ -55,7 +55,7 @@ TEST(DexFileTest, ClassDefs) { } TEST(DexFileTest, CreateMethodDescriptor) { - scoped_ptr<DexFile> raw(OpenDexFileBase64(kCreateMethodDescriptorDex)); + scoped_ptr<const DexFile> raw(OpenDexFileBase64(kCreateMethodDescriptorDex, "kCreateMethodDescriptorDex")); ASSERT_TRUE(raw != NULL); EXPECT_EQ(1U, raw->NumClassDefs()); diff --git a/src/exception_test.cc b/src/exception_test.cc index e2f97c0a9c..a9673effae 100644 --- a/src/exception_test.cc +++ b/src/exception_test.cc @@ -64,7 +64,7 @@ class ExceptionTest : public CommonTest { }; TEST_F(ExceptionTest, MyClass_F_G) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kMyClassExceptionHandleDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kMyClassExceptionHandleDex, "kMyClassExceptionHandleDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); Class* klass = class_linker_->FindClass("Ljava/lang/MyClass;", class_loader); ASSERT_TRUE(klass != NULL); diff --git a/src/heap.cc b/src/heap.cc index 643d056b59..7369804541 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -15,6 +15,8 @@ namespace art { std::vector<Space*> Heap::spaces_; +Space* Heap::boot_space_ = NULL; + Space* Heap::alloc_space_ = NULL; size_t Heap::maximum_size_ = 0; @@ -79,6 +81,7 @@ bool Heap::Init(size_t initial_size, size_t maximum_size, const char* boot_image // Make objects in boot_space live (after live_bitmap_ is set) if (boot_image_file_name != NULL) { + boot_space_ = boot_space; RecordImageAllocations(boot_space); } diff --git a/src/heap.h b/src/heap.h index 0cf0b5747a..4d453667fa 100644 --- a/src/heap.h +++ b/src/heap.h @@ -47,6 +47,10 @@ class Heap { return spaces_; } + static Space* GetBootSpace() { + return boot_space_; + } + static HeapBitmap* GetLiveBits() { return live_bitmap_; } @@ -72,6 +76,9 @@ class Heap { static std::vector<Space*> spaces_; + // Space loaded from an image + static Space* boot_space_; + // default Space for allocations static Space* alloc_space_; diff --git a/src/image.h b/src/image.h index c4123e8c6c..c567880f0f 100644 --- a/src/image.h +++ b/src/image.h @@ -6,6 +6,7 @@ #include <string.h> #include "globals.h" +#include "object.h" namespace art { @@ -14,7 +15,8 @@ class ImageHeader { public: ImageHeader() {} - ImageHeader(uint32_t base_addr) : base_addr_(base_addr) { + ImageHeader(uint32_t base_addr, uint32_t intern_addr) + : base_addr_(base_addr), intern_addr_(intern_addr) { memcpy(magic_, kImageMagic, sizeof(kImageMagic)); memcpy(version_, kImageVersion, sizeof(kImageVersion)); } @@ -33,13 +35,22 @@ class ImageHeader { return reinterpret_cast<byte*>(base_addr_); } + ObjectArray<Object>* GetInternedArray() const { + return reinterpret_cast<ObjectArray<Object>*>(intern_addr_); + } + private: static const byte kImageMagic[4]; static const byte kImageVersion[4]; byte magic_[4]; byte version_[4]; + + // required base address for mapping the image. uint32_t base_addr_; + + // absolute address of an Object[] of Strings to InternTable::Register + uint32_t intern_addr_; }; } // namespace art diff --git a/src/image_test.cc b/src/image_test.cc index c68b600389..8c00e895ad 100644 --- a/src/image_test.cc +++ b/src/image_test.cc @@ -31,7 +31,16 @@ std::string ReadFileToString(const char* file_name) { } TEST_F(ImageTest, WriteRead) { + + // TODO: move the touching of classes and GC to the ImageWriter proper + for (size_t i = 0; i < java_lang_dex_file_->NumClassDefs(); i++) { + const DexFile::ClassDef class_def = java_lang_dex_file_->GetClassDef(i); + const char* descriptor = java_lang_dex_file_->GetClassDescriptor(class_def); + Class* klass = class_linker_->FindSystemClass(descriptor); + ASSERT_TRUE(klass != NULL) << descriptor; + } // TODO: Heap::CollectGarbage before writing + const std::vector<Space*>& spaces = Heap::GetSpaces(); // can't currently deal with writing a space that might have pointers between spaces ASSERT_EQ(1U, spaces.size()); @@ -52,7 +61,7 @@ TEST_F(ImageTest, WriteRead) { ASSERT_GE(sizeof(image_header) + space->Size(), static_cast<size_t>(file->Length())); } - // tear down old runtime and make a new one + // tear down old runtime before making a new one, clearing out misc state delete runtime_.release(); // don't reuse java_lang_dex_file_ so we make sure we don't get @@ -74,27 +83,27 @@ TEST_F(ImageTest, WriteRead) { runtime_.reset(Runtime::Create(options, false)); ASSERT_TRUE(runtime_ != NULL); class_linker_ = runtime_->GetClassLinker(); - - if (true) { - const char* maps_file = "/proc/self/maps"; - std::string contents = ReadFileToString(maps_file); - LG << maps_file << ":\n" << contents; - } ASSERT_EQ(2U, Heap::GetSpaces().size()); Space* boot_space = Heap::GetSpaces()[0]; ASSERT_TRUE(boot_space != NULL); - // TODO: need to rebuild ClassLinker::classes_ and ::intern_table_ - // byte* boot_base = boot_space->GetBase(); - // byte* boot_limit = boot_space->GetLimit(); + // enable to display maps to debug boot_base and boot_limit checking problems below + if (false) { + const char* maps_file = "/proc/self/maps"; + std::string contents = ReadFileToString(maps_file); + LG << maps_file << ":\n" << contents; + } + + byte* boot_base = boot_space->GetBase(); + byte* boot_limit = boot_space->GetLimit(); for (size_t i = 0; i < dex->NumClassDefs(); i++) { const DexFile::ClassDef class_def = dex->GetClassDef(i); const char* descriptor = dex->GetClassDescriptor(class_def); Class* klass = class_linker_->FindSystemClass(descriptor); - EXPECT_TRUE(klass != NULL); - // EXPECT_LT(boot_base, reinterpret_cast<byte*>(klass)); - // EXPECT_LT(reinterpret_cast<byte*>(klass), boot_limit); + EXPECT_TRUE(klass != NULL) << descriptor; + EXPECT_LT(boot_base, reinterpret_cast<byte*>(klass)) << descriptor; + EXPECT_LT(reinterpret_cast<byte*>(klass), boot_limit) << descriptor; } } diff --git a/src/image_writer.cc b/src/image_writer.cc index 4335a90323..1c7acffd11 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -6,10 +6,12 @@ #include <vector> #include "dex_cache.h" +#include "class_linker.h" #include "file.h" #include "globals.h" #include "heap.h" #include "image.h" +#include "intern_table.h" #include "logging.h" #include "object.h" #include "space.h" @@ -43,6 +45,40 @@ bool ImageWriter::Init(Space* space) { return true; } +namespace { + +struct InternTableVisitorState { + int index; + ObjectArray<Object>* interned_array; +}; + +void InternTableVisitor(Object* obj, void* arg) { + InternTableVisitorState* state = reinterpret_cast<InternTableVisitorState*>(arg); + state->interned_array->Set(state->index++, obj); +} + +ObjectArray<Object>* CreateInternedArray() { + // build a Object[] of the interned strings for reinit + // TODO: avoid creating this future garbage + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + const InternTable& intern_table = class_linker->GetInternTable(); + size_t size = intern_table.Size(); + CHECK_NE(0U, size); + + Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;"); + ObjectArray<Object>* interned_array = ObjectArray<Object>::Alloc(object_array_class, size); + + InternTableVisitorState state; + state.index = 0; + state.interned_array = interned_array; + + intern_table.VisitRoots(InternTableVisitor, &state); + + return interned_array; +} + +} // namespace + void ImageWriter::CalculateNewObjectOffsetsCallback(Object *obj, void *arg) { DCHECK(obj != NULL); DCHECK(arg != NULL); @@ -53,14 +89,24 @@ void ImageWriter::CalculateNewObjectOffsetsCallback(Object *obj, void *arg) { } void ImageWriter::CalculateNewObjectOffsets() { + ObjectArray<Object>* interned_array = CreateInternedArray(); + HeapBitmap* heap_bitmap = Heap::GetLiveBits(); DCHECK(heap_bitmap != NULL); DCHECK_EQ(0U, image_top_); - ImageHeader image_header(reinterpret_cast<uint32_t>(image_base_)); - memcpy(image_->GetAddress(), &image_header, sizeof(image_header)); - image_top_ += RoundUp(sizeof(image_header), 8); // 64-bit-alignment + + // leave space for the header, but do not write it yet, we need to + // know where interned_array is going to end up + image_top_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment + heap_bitmap->Walk(CalculateNewObjectOffsetsCallback, this); DCHECK_LT(image_top_, image_->GetLength()); + + // return to write header at start of image with future location of interned_array + ImageHeader image_header(reinterpret_cast<uint32_t>(image_base_), + reinterpret_cast<uint32_t>(GetImageAddress(interned_array))); + memcpy(image_->GetAddress(), &image_header, sizeof(image_header)); + // Note that top_ is left at end of used space } @@ -92,6 +138,10 @@ void ImageWriter::FixupObject(Object* orig, Object* copy) { // TODO: special case init of pointers to malloc data (or removal of these pointers) if (orig->IsClass()) { FixupClass(orig->AsClass(), down_cast<Class*>(copy)); + } else if (orig->IsMethod()) { + FixupMethod(orig->AsMethod(), down_cast<Method*>(copy)); + } else if (orig->IsField()) { + FixupField(orig->AsField(), down_cast<Field*>(copy)); } else if (orig->IsObjectArray()) { FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy)); } else { @@ -117,6 +167,20 @@ void ImageWriter::FixupClass(Class* orig, Class* copy) { copy->static_references_ = down_cast<ObjectArray<Object>*>(GetImageAddress(orig->static_references_)); } +// TODO: remove this slow path +void ImageWriter::FixupMethod(Method* orig, Method* copy) { + FixupInstanceFields(orig, copy); + // TODO: remove need for this by adding "signature" to java.lang.reflect.Method + copy->signature_ = down_cast<String*>(GetImageAddress(orig->signature_)); + DCHECK(copy->signature_ != NULL); + // TODO: convert shorty_ to heap allocated storage +} + +void ImageWriter::FixupField(Field* orig, Field* copy) { + FixupInstanceFields(orig, copy); + // TODO: convert descriptor_ to heap allocated storage +} + void ImageWriter::FixupObjectArray(ObjectArray<Object>* orig, ObjectArray<Object>* copy) { for (int32_t i = 0; i < orig->GetLength(); ++i) { const Object* element = orig->Get(i); diff --git a/src/image_writer.h b/src/image_writer.h index 8ae8f7db48..8e9ac103cd 100644 --- a/src/image_writer.h +++ b/src/image_writer.h @@ -51,6 +51,8 @@ class ImageWriter { void CopyAndFixupObjects(); static void CopyAndFixupObjectsCallback(Object *obj, void *arg); void FixupClass(Class* orig, Class* copy); + void FixupMethod(Method* orig, Method* copy); + void FixupField(Field* orig, Field* copy); void FixupObject(Object* orig, Object* copy); void FixupObjectArray(ObjectArray<Object>* orig, ObjectArray<Object>* copy); void FixupInstanceFields(Object* orig, Object* copy); diff --git a/src/intern_table.cc b/src/intern_table.cc index 3ef591796e..e070573530 100644 --- a/src/intern_table.cc +++ b/src/intern_table.cc @@ -14,11 +14,15 @@ InternTable::~InternTable() { delete intern_table_lock_; } -void InternTable::VisitRoots(Heap::RootVistor* root_visitor, void* arg) { +size_t InternTable::Size() const { + return intern_table_.size(); +} + +void InternTable::VisitRoots(Heap::RootVistor* root_visitor, void* arg) const { MutexLock mu(intern_table_lock_); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = intern_table_.begin(), end = intern_table_.end(); it != end; ++it) { - root_visitor(it->second, arg); + root_visitor(it->second, arg); } } @@ -36,9 +40,13 @@ String* InternTable::Intern(int32_t utf16_length, const char* utf8_data_in) { } } String* new_string = String::AllocFromUtf16(utf16_length, utf16_data_out.get(), hash_code); - intern_table_.insert(std::make_pair(hash_code, new_string)); + Register(new_string); return new_string; } } +void InternTable::Register(String* string) { + intern_table_.insert(std::make_pair(string->GetHashCode(), string)); +} + } // namespace art diff --git a/src/intern_table.h b/src/intern_table.h index 0a1554df88..46e0e0553f 100644 --- a/src/intern_table.h +++ b/src/intern_table.h @@ -14,8 +14,16 @@ class InternTable { public: InternTable(); ~InternTable(); + + // intern a potentially new string String* Intern(int32_t utf16_length, const char* utf8_data); - void VisitRoots(Heap::RootVistor* root_visitor, void* arg); + + // register a String trusting that it is safe to intern. + // used when reinitializing InternTable from an image. + void Register(String* string); + + size_t Size() const; + void VisitRoots(Heap::RootVistor* root_visitor, void* arg) const; private: typedef std::tr1::unordered_multimap<int32_t, String*> Table; diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc index 8a5155f7a5..cb48e7635c 100644 --- a/src/jni_compiler_test.cc +++ b/src/jni_compiler_test.cc @@ -21,7 +21,7 @@ class JniCompilerTest : public CommonTest { protected: virtual void SetUp() { CommonTest::SetUp(); - dex_.reset(OpenDexFileBase64(kMyClassNativesDex)); + dex_.reset(OpenDexFileBase64(kMyClassNativesDex, "kMyClassNativesDex")); class_loader_ = AllocPathClassLoader(dex_.get()); } diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc index 6c5d6f2741..b9e8f19286 100644 --- a/src/jni_internal_test.cc +++ b/src/jni_internal_test.cc @@ -456,7 +456,7 @@ void FreeStub(Method* method, size_t length) { #if defined(__arm__) TEST_F(JniInternalTest, StaticMainMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kMainDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kMainDex, "kMainDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -484,7 +484,7 @@ TEST_F(JniInternalTest, StaticMainMethod) { } TEST_F(JniInternalTest, StaticNopMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -511,7 +511,7 @@ TEST_F(JniInternalTest, StaticNopMethod) { } TEST_F(JniInternalTest, StaticIdentityByteMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -559,7 +559,7 @@ TEST_F(JniInternalTest, StaticIdentityByteMethod) { } TEST_F(JniInternalTest, StaticIdentityIntMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -607,7 +607,7 @@ TEST_F(JniInternalTest, StaticIdentityIntMethod) { } TEST_F(JniInternalTest, StaticIdentityDoubleMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -656,7 +656,7 @@ TEST_F(JniInternalTest, StaticIdentityDoubleMethod) { } TEST_F(JniInternalTest, StaticSumIntIntMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -716,7 +716,7 @@ TEST_F(JniInternalTest, StaticSumIntIntMethod) { } TEST_F(JniInternalTest, StaticSumIntIntIntMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -783,7 +783,7 @@ TEST_F(JniInternalTest, StaticSumIntIntIntMethod) { } TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -856,7 +856,7 @@ TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) { } TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -936,7 +936,7 @@ TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) { } TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -997,7 +997,7 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) { } TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -1051,7 +1051,7 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) { } TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); @@ -1110,7 +1110,7 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) { } TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex, "kStaticLeafMethodsDex")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); ASSERT_TRUE(class_loader != NULL); diff --git a/src/object.cc b/src/object.cc index bfa200ad47..3200e4d051 100644 --- a/src/object.cc +++ b/src/object.cc @@ -526,9 +526,15 @@ template class PrimitiveArray<int16_t>; // ShortArray // TODO: get global references for these Class* String::java_lang_String_ = NULL; -void String::InitClass(Class* java_lang_String) { +void String::SetClass(Class* java_lang_String) { + CHECK(java_lang_String_ == NULL); + CHECK(java_lang_String != NULL); java_lang_String_ = java_lang_String; } +void String::ResetClass() { + CHECK(java_lang_String_ != NULL); + java_lang_String_ = NULL; +} static const char* kClassStatusNames[] = { "Error", diff --git a/src/object.h b/src/object.h index ca09d07899..e246deac08 100644 --- a/src/object.h +++ b/src/object.h @@ -239,6 +239,27 @@ class Object { return down_cast<const Array*>(this); } + bool IsString() const; + + String* AsString() { + DCHECK(IsString()); + return down_cast<String*>(this); + } + + bool IsMethod() const; + + Method* AsMethod() { + DCHECK(IsMethod()); + return down_cast<Method*>(this); + } + + bool IsField() const; + + Field* AsField() { + DCHECK(IsField()); + return down_cast<Field*>(this); + } + public: Class* klass_; @@ -285,10 +306,12 @@ class AccessibleObject : public Object { class Field : public AccessibleObject { public: Class* GetDeclaringClass() const { + DCHECK(declaring_class_ != NULL); return declaring_class_; } const String* GetName() const { + DCHECK(name_ != NULL); return name_; } @@ -364,14 +387,17 @@ class Method : public AccessibleObject { // Returns the method name, e.g. "<init>" or "eatLunch" const String* GetName() const { + DCHECK(name_ != NULL); return name_; } const String* GetSignature() const { + DCHECK(signature_ != NULL); return signature_; } Class* GetDeclaringClass() const { + DCHECK(declaring_class_ != NULL); return declaring_class_; } @@ -1177,7 +1203,8 @@ inline bool Object::InstanceOf(const Class* klass) const { } inline bool Object::IsClass() const { - return klass_ == klass_->klass_; + Class* java_lang_Class = klass_->klass_; + return klass_ == java_lang_Class; } inline bool Object::IsObjectArray() const { @@ -1188,6 +1215,18 @@ inline bool Object::IsArray() const { return klass_->IsArray(); } +inline bool Object::IsField() const { + Class* java_lang_Class = klass_->klass_; + Class* java_lang_reflect_Field = java_lang_Class->GetInstanceField(0)->klass_; + return klass_ == java_lang_reflect_Field; +} + +inline bool Object::IsMethod() const { + Class* java_lang_Class = klass_->klass_; + Class* java_lang_reflect_Method = java_lang_Class->GetDirectMethod(0)->klass_; + return klass_ == java_lang_reflect_Method; +} + inline size_t Object::SizeOf() const { if (IsArray()) { return AsArray()->SizeOf(); @@ -1236,10 +1275,16 @@ class PrimitiveArray : public Array { } static void SetArrayClass(Class* array_class) { + CHECK(array_class_ == NULL); CHECK(array_class != NULL); array_class_ = array_class; } + static void ResetArrayClass() { + CHECK(array_class_ != NULL); + array_class_ = NULL; + } + private: // Location of first element. T elements_[0]; @@ -1281,7 +1326,7 @@ class String : public Object { } static String* AllocFromUtf16(int32_t utf16_length, - uint16_t* utf16_data_in, + const uint16_t* utf16_data_in, int32_t hash_code) { String* string = Alloc(GetJavaLangString(), utf16_length); @@ -1307,7 +1352,8 @@ class String : public Object { return string; } - static void InitClass(Class* java_lang_String); + static void SetClass(Class* java_lang_String); + static void ResetClass(); static String* Alloc(Class* java_lang_String, int32_t utf16_length) { @@ -1489,6 +1535,11 @@ class String : public Object { DISALLOW_IMPLICIT_CONSTRUCTORS(String); }; +inline bool Object::IsString() const { + // TODO use "klass_ == String::GetJavaLangString()" instead? + return klass_ == klass_->descriptor_->klass_; +} + inline size_t Class::GetTypeSize(String* descriptor) { switch (descriptor->CharAt(0)) { case 'B': return 1; // byte diff --git a/src/object_test.cc b/src/object_test.cc index c517459b1b..aa3cf8665c 100644 --- a/src/object_test.cc +++ b/src/object_test.cc @@ -208,9 +208,9 @@ TEST_F(ObjectTest, StringEquals) { TEST_F(ObjectTest, DescriptorCompare) { ClassLinker* linker = class_linker_; - scoped_ptr<DexFile> proto1_dex_file(OpenDexFileBase64(kProtoCompareDex)); + scoped_ptr<DexFile> proto1_dex_file(OpenDexFileBase64(kProtoCompareDex, "kProtoCompareDex")); PathClassLoader* class_loader_1 = AllocPathClassLoader(proto1_dex_file.get()); - scoped_ptr<DexFile> proto2_dex_file(OpenDexFileBase64(kProtoCompare2Dex)); + scoped_ptr<DexFile> proto2_dex_file(OpenDexFileBase64(kProtoCompare2Dex, "kProtoCompare2Dex")); PathClassLoader* class_loader_2 = AllocPathClassLoader(proto2_dex_file.get()); Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1); @@ -257,7 +257,7 @@ TEST_F(ObjectTest, StringHashCode) { } TEST_F(ObjectTest, InstanceOf) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kXandY)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kXandY, "kXandY")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); Class* X = class_linker_->FindClass("LX;", class_loader); Class* Y = class_linker_->FindClass("LY;", class_loader); @@ -284,7 +284,7 @@ TEST_F(ObjectTest, InstanceOf) { } TEST_F(ObjectTest, IsAssignableFrom) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kXandY)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kXandY, "kXandY")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); Class* X = class_linker_->FindClass("LX;", class_loader); Class* Y = class_linker_->FindClass("LY;", class_loader); @@ -296,7 +296,7 @@ TEST_F(ObjectTest, IsAssignableFrom) { } TEST_F(ObjectTest, IsAssignableFromArray) { - scoped_ptr<DexFile> dex(OpenDexFileBase64(kXandY)); + scoped_ptr<DexFile> dex(OpenDexFileBase64(kXandY, "kXandY")); PathClassLoader* class_loader = AllocPathClassLoader(dex.get()); Class* X = class_linker_->FindClass("LX;", class_loader); Class* Y = class_linker_->FindClass("LY;", class_loader); diff --git a/src/runtime.cc b/src/runtime.cc index 864b257c3c..476297b5cf 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -352,7 +352,7 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { Thread* current_thread = Thread::Attach(this); thread_list_->Register(current_thread); - class_linker_ = ClassLinker::Create(options->boot_class_path_); + class_linker_ = ClassLinker::Create(options->boot_class_path_, Heap::GetBootSpace()); return true; } diff --git a/src/space.cc b/src/space.cc index 8048f29198..c636e3809f 100644 --- a/src/space.cc +++ b/src/space.cc @@ -100,6 +100,9 @@ bool Space::Init(const char* image_file_name) { return false; } CHECK_EQ(image_header.GetBaseAddr(), map->GetAddress()); + image_header_ = reinterpret_cast<ImageHeader*>(map->GetAddress()); + DCHECK_EQ(0, memcmp(&image_header, image_header_, sizeof(ImageHeader))); + Init(map.release()); return true; } diff --git a/src/space.h b/src/space.h index 57f676def3..24bcefadd2 100644 --- a/src/space.h +++ b/src/space.h @@ -4,6 +4,7 @@ #define ART_SRC_SPACE_H_ #include "globals.h" +#include "image.h" #include "macros.h" #include "mem_map.h" #include "scoped_ptr.h" @@ -47,6 +48,11 @@ class Space { return limit_ - base_; } + const ImageHeader& GetImageHeader() const { + CHECK(image_header_ != NULL); + return *image_header_; + } + size_t AllocationSize(const Object* obj); bool IsCondemned() const { @@ -60,7 +66,7 @@ class Space { // create a Space from an existing memory mapping, taking ownership of the address space. static Space* Create(MemMap* mem_map); - Space() : mspace_(NULL), maximum_size_(0), base_(0), limit_(0) {} + Space() : mspace_(NULL), maximum_size_(0), image_header_(NULL), base_(0), limit_(0) {} // Initializes the space and underlying storage. bool Init(size_t initial_size, size_t maximum_size, byte* requested_base); @@ -75,10 +81,13 @@ class Space { static void DontNeed(void* start, void* end, void* num_bytes); - // TODO: have a Space subclass for methods that depend on mspace_ and maximum_size_ + // TODO: have a Space subclass for non-image Spaces with mspace_ and maximum_size_ void* mspace_; size_t maximum_size_; + // TODO: have a Space subclass for image Spaces with image_header_ + ImageHeader* image_header_; + scoped_ptr<MemMap> mem_map_; byte* base_; diff --git a/src/stringpiece.h b/src/stringpiece.h index 249b0413e8..1338ed97cc 100644 --- a/src/stringpiece.h +++ b/src/stringpiece.h @@ -200,6 +200,21 @@ inline bool operator>=(const art::StringPiece& x, const art::StringPiece& y) { extern std::ostream& operator<<(std::ostream& o, const art::StringPiece& piece); +// BEGIN android-added +struct StringPieceHash { + size_t operator()(const art::StringPiece& string_piece) const { + size_t string_size = string_piece.size(); + const char* string_data = string_piece.data(); + // this is the java.lang.String hashcode for convenience, not interoperability + size_t hash = 0; + while (string_size--) { + hash = hash * 31 + *string_data++; + } + return hash; + } +}; +// END android-added + } // namespace art #endif // ART_SRC_STRINGPIECE_H_ diff --git a/src/unordered_map.h b/src/unordered_map.h index caa859d7d6..4f55d77cfd 100644 --- a/src/unordered_map.h +++ b/src/unordered_map.h @@ -11,34 +11,4 @@ #include <tr1/unordered_map> #endif -//TODO: move out to stringpiece.h? -namespace std { -#ifndef __ANDROID__ -namespace tr1 { -#endif -template<> -struct hash<art::StringPiece> { - public: - size_t operator()(const art::StringPiece& string_piece) const { - size_t string_size = string_piece.size(); - const char* string_data = string_piece.data(); - // this is the java.lang.String hashcode for convenience, not interoperability - size_t hash = 0; - while (string_size--) { - hash = hash * 31 + *string_data++; - } - return hash; - } -}; -#ifndef __ANDROID__ -} // namespace tr1 -#endif -} // namespace std - -#ifdef __ANDROID__ -typedef std::hash<art::StringPiece> StringPieceHash; -#else -typedef std::tr1::hash<art::StringPiece> StringPieceHash; -#endif - #endif // ART_SRC_CLASS_UNORDERED_MAP_H_ diff --git a/src/zip_archive.h b/src/zip_archive.h index 8001fa357f..26cb438c24 100644 --- a/src/zip_archive.h +++ b/src/zip_archive.h @@ -119,7 +119,7 @@ class ZipArchive { uint16_t num_entries_; off_t dir_offset_; scoped_ptr<MemMap> dir_map_; - typedef std::tr1::unordered_map<StringPiece, const byte*> DirEntries; + typedef std::tr1::unordered_map<StringPiece, const byte*, StringPieceHash> DirEntries; DirEntries dir_entries_; friend class ZipEntry; |