diff options
| -rw-r--r-- | build/Android.common.mk | 2 | ||||
| -rw-r--r-- | src/class_linker.cc | 34 | ||||
| -rw-r--r-- | src/class_linker.h | 42 | ||||
| -rw-r--r-- | src/class_linker_test.cc | 5 | ||||
| -rw-r--r-- | src/dex_file.cc | 4 | ||||
| -rw-r--r-- | src/heap.h | 2 | ||||
| -rw-r--r-- | src/intern_table.cc | 40 | ||||
| -rw-r--r-- | src/intern_table.h | 27 | ||||
| -rw-r--r-- | src/intern_table_test.cc | 31 | ||||
| -rw-r--r-- | src/object.h | 156 | ||||
| -rw-r--r-- | src/object_test.cc | 21 | ||||
| -rw-r--r-- | src/unordered_map.h | 37 | ||||
| -rw-r--r-- | src/zip_archive.cc | 2 | ||||
| -rw-r--r-- | src/zip_archive.h | 5 |
14 files changed, 296 insertions, 112 deletions
diff --git a/build/Android.common.mk b/build/Android.common.mk index 64f0de411a..3932b7443d 100644 --- a/build/Android.common.mk +++ b/build/Android.common.mk @@ -41,6 +41,7 @@ LIBART_COMMON_SRC_FILES := \ src/dex_instruction.cc \ src/dex_verifier.cc \ src/heap.cc \ + src/intern_table.cc \ src/jni_compiler.cc \ src/jni_internal.cc \ src/mark_stack.cc \ @@ -83,6 +84,7 @@ TEST_COMMON_SRC_FILES := \ src/dex_cache_test.cc \ src/dex_file_test.cc \ src/dex_instruction_visitor_test.cc \ + src/intern_table_test.cc \ src/jni_compiler_test.cc.arm \ src/object_test.cc \ src/runtime_test.cc \ diff --git a/src/class_linker.cc b/src/class_linker.cc index 1bfa00929a..89c96b4fe8 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -186,19 +186,22 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { init_done_ = true; } -void ClassLinker::VisitRoots(RootVistor* root_visitor, void* arg) { +void ClassLinker::VisitRoots(Heap::RootVistor* root_visitor, void* arg) { root_visitor(class_roots_, arg); for (size_t i = 0; i < dex_caches_.size(); i++) { root_visitor(dex_caches_[i], arg); } - // TODO: acquire classes_lock_ - typedef Table::const_iterator It; // TODO: C++0x auto - for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) { - root_visitor(it->second, arg); + { + MutexLock mu(classes_lock_); + typedef Table::const_iterator It; // TODO: C++0x auto + for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) { + root_visitor(it->second, arg); + } } - // TODO: release classes_lock_ + + intern_table_.VisitRoots(root_visitor, arg); root_visitor(array_interfaces_, arg); } @@ -461,7 +464,7 @@ void ClassLinker::LoadField(const DexFile& dex_file, Field* dst) { const DexFile::FieldId& field_id = dex_file.GetFieldId(src.field_idx_); dst->klass_ = klass; - dst->java_name_ = ResolveString(klass, field_id.name_idx_, dex_file); + dst->name_ = ResolveString(klass, field_id.name_idx_, dex_file); dst->descriptor_.set(dex_file.dexStringByTypeIdx(field_id.type_idx_)); dst->access_flags_ = src.access_flags_; } @@ -472,7 +475,7 @@ void ClassLinker::LoadMethod(const DexFile& dex_file, Method* dst) { const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_); dst->klass_ = klass; - dst->java_name_ = ResolveString(klass, method_id.name_idx_, dex_file); + dst->name_ = ResolveString(klass, method_id.name_idx_, dex_file); { int32_t utf16_length; scoped_ptr<char> utf8(dex_file.CreateMethodDescriptor(method_id.proto_idx_, @@ -736,15 +739,14 @@ Class* ClassLinker::FindPrimitiveClass(char type) { } bool ClassLinker::InsertClass(Class* klass) { - // TODO: acquire classes_lock_ + MutexLock mu(classes_lock_); const StringPiece& key = klass->GetDescriptor(); Table::iterator it = classes_.insert(std::make_pair(key, klass)); return ((*it).second == klass); - // TODO: release classes_lock_ } Class* ClassLinker::LookupClass(const StringPiece& descriptor, ClassLoader* class_loader) { - // TODO: acquire classes_lock_ + MutexLock mu(classes_lock_); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = classes_.find(descriptor), end = classes_.end(); it != end; ++it) { Class* klass = it->second; @@ -753,7 +755,6 @@ Class* ClassLinker::LookupClass(const StringPiece& descriptor, ClassLoader* clas } } return NULL; - // TODO: release classes_lock_ } bool ClassLinker::InitializeClass(Class* klass) { @@ -963,7 +964,7 @@ bool ClassLinker::HasSameDescriptorClasses(const char* descriptor, bool ClassLinker::InitializeSuperClass(Class* klass) { CHECK(klass != NULL); - // TODO: assert klass lock is acquired + MutexLock mu(classes_lock_); if (!klass->IsInterface() && klass->HasSuperClass()) { Class* super_class = klass->GetSuperClass(); if (super_class->GetStatus() != Class::kStatusInitialized) { @@ -1536,10 +1537,9 @@ String* ClassLinker::ResolveString(const Class* referring, const DexFile::StringId& string_id = dex_file.GetStringId(string_idx); int32_t utf16_length = dex_file.GetStringLength(string_id); const char* utf8_data = dex_file.GetStringData(string_id); - String* new_string = String::AllocFromModifiedUtf8(utf16_length, utf8_data); - // TODO: intern the new string - referring->GetDexCache()->SetResolvedString(string_idx, new_string); - return new_string; + String* string = intern_table_.Intern(utf16_length, utf8_data); + referring->GetDexCache()->SetResolvedString(string_idx, string); + return string; } } // namespace art diff --git a/src/class_linker.h b/src/class_linker.h index 70d268d131..15bd054287 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -7,11 +7,14 @@ #include <utility> #include <vector> +#include "dex_file.h" #include "heap.h" +#include "intern_table.h" #include "macros.h" -#include "dex_file.h" -#include "thread.h" #include "object.h" +#include "thread.h" +#include "unordered_map.h" + #include "gtest/gtest.h" namespace art { @@ -34,24 +37,14 @@ class ClassLinker { bool InitializeClass(Class* klass); - Class* LookupClass(const StringPiece& descriptor, ClassLoader* class_loader); - - Class* ResolveClass(const Class* referring, - uint32_t class_idx, - const DexFile& dex_file); - - String* ResolveString(const Class* referring, - uint32_t string_idx, - const DexFile& dex_file); - void RegisterDexFile(const DexFile* dex_file); - // TODO replace with heap interface - typedef void (RootVistor)(Object* root, void* arg); - void VisitRoots(RootVistor* root_visitor, void* arg); + void VisitRoots(Heap::RootVistor* root_visitor, void* arg); private: - ClassLinker() {} + ClassLinker() { + classes_lock_ = Mutex::Create("ClassLinker::Lock"); + } void Init(const std::vector<DexFile*>& boot_class_path_); @@ -104,6 +97,16 @@ class ClassLinker { Class* klass, Method* dst); + Class* ResolveClass(const Class* referring, + uint32_t class_idx, + const DexFile& dex_file); + + String* ResolveString(const Class* referring, + uint32_t string_idx, + const DexFile& dex_file); + + Class* LookupClass(const StringPiece& descriptor, ClassLoader* class_loader); + // Inserts a class into the class table. Returns true if the class // was inserted. bool InsertClass(Class* klass); @@ -149,14 +152,11 @@ class ClassLinker { // multimap from String::descriptor_ to Class* instances. Results // should be compared for a matching Class::descriptor_ and // Class::class_loader_. - // TODO: unordered_multimap - typedef std::multimap<const StringPiece, Class*> Table; - + typedef std::tr1::unordered_multimap<StringPiece, Class*> Table; Table classes_; - Mutex* classes_lock_; - // TODO: classpath + InternTable intern_table_; // indexes into class_roots_ enum ClassRoot { diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc index a9c3e50b69..5e48921afa 100644 --- a/src/class_linker_test.cc +++ b/src/class_linker_test.cc @@ -4,6 +4,7 @@ #include "class_linker.h" #include "dex_file.h" #include "heap.h" + #include "gtest/gtest.h" namespace art { @@ -142,11 +143,13 @@ class ClassLinkerTest : public RuntimeTest { for (size_t i = 0; i < klass->NumInstanceFields(); i++) { InstanceField* field = klass->GetInstanceField(i); EXPECT_TRUE(field != NULL); + EXPECT_FALSE(field->IsStatic()); } for (size_t i = 0; i < klass->NumStaticFields(); i++) { StaticField* field = klass->GetStaticField(i); EXPECT_TRUE(field != NULL); + EXPECT_TRUE(field->IsStatic()); } // Confirm that all instances fields are packed together at the start @@ -367,4 +370,4 @@ TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) { EXPECT_NE(MyClass_1, MyClass_2); } -} // namespace art +}// namespace art diff --git a/src/dex_file.cc b/src/dex_file.cc index 35e98db020..90893cb155 100644 --- a/src/dex_file.cc +++ b/src/dex_file.cc @@ -34,7 +34,9 @@ DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor, return ClassPathEntry(dex_file, dex_class_def); } } - return ClassPathEntry(NULL, NULL); + // TODO remove reinterpret_cast when issue with -std=gnu++0x host issue resolved + return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL), + reinterpret_cast<const DexFile::ClassDef*>(NULL)); } DexFile::Closer::~Closer() {} diff --git a/src/heap.h b/src/heap.h index 1059fd7664..f8a5d235b3 100644 --- a/src/heap.h +++ b/src/heap.h @@ -23,6 +23,8 @@ class Heap { static const size_t kMaximumSize = 64 * MB; + typedef void (RootVistor)(Object* root, void* arg); + static bool Init() { return Init(kStartupSize, kMaximumSize); } diff --git a/src/intern_table.cc b/src/intern_table.cc new file mode 100644 index 0000000000..31749fd7ea --- /dev/null +++ b/src/intern_table.cc @@ -0,0 +1,40 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +#include "intern_table.h" + +#include "scoped_ptr.h" + +namespace art { + +InternTable::InternTable() { + intern_table_lock_ = Mutex::Create("InternTable::Lock"); +} + +void InternTable::VisitRoots(Heap::RootVistor* root_visitor, void* arg) { + 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); + } +} + +String* InternTable::Intern(int32_t utf16_length, const char* utf8_data_in) { + scoped_ptr<uint16_t> utf16_data_out(new uint16_t[utf16_length]); + String::ConvertModifiedUtf8ToUtf16(utf16_data_out.get(), utf8_data_in); + int32_t hash_code = String::ComputeUtf16Hash(utf16_data_out.get(), utf16_length); + { + MutexLock mu(intern_table_lock_); + typedef Table::const_iterator It; // TODO: C++0x auto + for (It it = intern_table_.find(hash_code), end = intern_table_.end(); it != end; ++it) { + String* string = it->second; + if (string->Equals(utf16_data_out.get(), 0, utf16_length)) { + return string; + } + } + String* new_string = String::AllocFromUtf16(utf16_length, utf16_data_out.get(), hash_code); + intern_table_.insert(std::make_pair(hash_code, new_string)); + return new_string; + } +} + +} // namespace art diff --git a/src/intern_table.h b/src/intern_table.h new file mode 100644 index 0000000000..61da28b211 --- /dev/null +++ b/src/intern_table.h @@ -0,0 +1,27 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +#ifndef ART_SRC_INTERN_TABLE_H_ +#define ART_SRC_INTERN_TABLE_H_ + +#include "unordered_map.h" + +#include "heap.h" +#include "object.h" + +namespace art { + +class InternTable { + public: + InternTable(); + String* Intern(int32_t utf16_length, const char* utf8_data); + void VisitRoots(Heap::RootVistor* root_visitor, void* arg); + + private: + typedef std::tr1::unordered_multimap<int32_t, String*> Table; + Table intern_table_; + Mutex* intern_table_lock_; +}; + +} // namespace art + +#endif // ART_SRC_CLASS_LINKER_H_ diff --git a/src/intern_table_test.cc b/src/intern_table_test.cc new file mode 100644 index 0000000000..daae8410fb --- /dev/null +++ b/src/intern_table_test.cc @@ -0,0 +1,31 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +#include "intern_table.h" + +#include "common_test.h" +#include "object.h" + +#include "gtest/gtest.h" + +namespace art { + +class InternTableTest : public RuntimeTest {}; + +TEST_F(InternTableTest, Intern) { + InternTable intern_table; + String* foo_1 = intern_table.Intern(3, "foo"); + String* foo_2 = intern_table.Intern(3, "foo"); + String* foo_3 = String::AllocFromAscii("foo"); + String* bar = intern_table.Intern(3, "bar"); + EXPECT_TRUE(foo_1->Equals("foo")); + EXPECT_TRUE(foo_2->Equals("foo")); + EXPECT_TRUE(foo_3->Equals("foo")); + EXPECT_TRUE(foo_1 != NULL); + EXPECT_TRUE(foo_2 != NULL); + EXPECT_EQ(foo_1, foo_2); + EXPECT_NE(foo_1, bar); + EXPECT_NE(foo_2, bar); + EXPECT_NE(foo_3, bar); +} + +} // namespace art diff --git a/src/object.h b/src/object.h index 0e0728dece..6871dfb75e 100644 --- a/src/object.h +++ b/src/object.h @@ -25,7 +25,11 @@ class Method; class Object; class String; template<class T> class ObjectArray; +template<class T> class PrimitiveArray; class StaticField; +typedef PrimitiveArray<uint16_t> CharArray; +typedef PrimitiveArray<uint32_t> IntArray; +typedef PrimitiveArray<uint64_t> LongArray; union JValue { uint8_t z; @@ -258,7 +262,11 @@ class Field : public AccessibleObject { } const String* GetName() const { - return java_name_; + return name_; + } + + bool IsStatic() const { + return (access_flags_ & kAccStatic) != 0; } char GetType() const { // TODO: return type @@ -275,15 +283,13 @@ class Field : public AccessibleObject { Class* java_declaring_class_; Object* java_generic_type_; uint32_t java_generic_types_are_initialized_; - String* java_name_; + String* name_; uint32_t java_slot_; Class* java_type_; // The class in which this field is declared. Class* declaring_class_; - StringPiece name_; - // e.g. "I", "[C", "Landroid/os/Debug;" StringPiece descriptor_; @@ -380,7 +386,7 @@ class Method : public AccessibleObject { public: // Returns the method name, e.g. "<init>" or "eatLunch" const String* GetName() const { - return java_name_; + return name_; } const String* GetDescriptor() const { @@ -447,7 +453,7 @@ class Method : public AccessibleObject { Object* java_generic_parameter_types_; Object* java_generic_return_type_; Class* java_return_type_; - String* java_name_; + String* name_; ObjectArray<Class>* java_parameter_types_; uint32_t java_generic_types_are_initialized_; uint32_t java_slot_; @@ -544,9 +550,6 @@ class Method : public AccessibleObject { uint16_t num_outs_; uint16_t num_ins_; - // method name, e.g. "<init>" or "eatLunch" - StringPiece name_; - // The method descriptor. This represents the parameters a method // takes and value it returns. This string is a list of the type // descriptors for the parameters enclosed in parenthesis followed @@ -596,18 +599,10 @@ class Array : public Object { void SetLength(uint32_t length) { length_ = length; } - const void* GetData() const { - return &elements_; - } - void* GetData() { - return &elements_; - } private: // The number of array elements. uint32_t length_; - // Location of first element. - uint32_t elements_[0]; Array(); }; @@ -621,15 +616,19 @@ class ObjectArray : public Array { sizeof(uint32_t))); } + T* const * GetData() const { + return reinterpret_cast<T* const *>(&elements_); + } + T** GetData() { + return reinterpret_cast<T**>(&elements_); + } T* Get(uint32_t i) const { CHECK_LT(i, GetLength()); - Object* const * data = reinterpret_cast<Object* const *>(GetData()); - return down_cast<T*>(data[i]); + return GetData()[i]; } void Set(uint32_t i, T* object) { CHECK_LT(i, GetLength()); - T** data = reinterpret_cast<T**>(GetData()); - data[i] = object; + GetData()[i] = object; } static void Copy(ObjectArray<T>* src, int src_pos, ObjectArray<T>* dst, int dst_pos, size_t length) { for (size_t i = 0; i < length; i++) { @@ -644,6 +643,8 @@ class ObjectArray : public Array { private: ObjectArray(); + // Location of first element. + T* elements_[0]; }; // ClassLoader objects. @@ -1055,6 +1056,10 @@ class Class : public Object { // source file name, if known. Otherwise, NULL. const char* source_file_; + ObjectArray<Object>* static_references_; + IntArray* static_32bit_primitives_; + LongArray* static_64bit_primitives_; + // Static fields ObjectArray<StaticField>* sfields_; @@ -1075,34 +1080,37 @@ class DataObject : public Object { DataObject(); }; -class CharArray : public Array { +template<class T> +class PrimitiveArray : public Array { public: - static CharArray* Alloc(Class* char_array_class, size_t length) { - return down_cast<CharArray*>(Array::Alloc(char_array_class, - length, - sizeof(uint16_t))); + static PrimitiveArray<T>* Alloc(Class* element_class, size_t length) { + return down_cast<PrimitiveArray<T>*>(Array::Alloc(element_class, + length, + sizeof(T))); } - uint16_t* GetChars() { - return reinterpret_cast<uint16_t*>(GetData()); + const T* GetData() const { + return reinterpret_cast<const T*>(&elements_); } - const uint16_t* GetChars() const { - return reinterpret_cast<const uint16_t*>(GetData()); + T* GetData() { + return reinterpret_cast<T*>(&elements_); } - uint16_t GetChar(uint32_t i) const { + T Get(T i) const { CHECK_LT(i, GetLength()); - return GetChars()[i]; + return GetData()[i]; } - void SetChar(uint32_t i, uint16_t ch) { + void Set(uint32_t i, T value) { CHECK_LT(i, GetLength()); - GetChars()[i] = ch; + GetData()[i] = value; } private: - CharArray(); + PrimitiveArray(); + // Location of first element. + T elements_[0]; }; class String : public Object { @@ -1111,33 +1119,33 @@ class String : public Object { return array_; } - uint32_t GetHashCode() const { + int32_t GetHashCode() const { return hash_code_; } - uint32_t GetOffset() const { + int32_t GetOffset() const { + DCHECK_LE(0, offset_); return offset_; } - uint32_t GetLength() const { + int32_t GetLength() const { + DCHECK_LE(0, count_); return count_; } - uint16_t CharAt(uint32_t index) const { - return GetCharArray()->GetChar(index + GetOffset()); + uint16_t CharAt(int32_t index) const { + return GetCharArray()->Get(index + GetOffset()); } - static String* AllocFromUtf16(Class* java_lang_String, - Class* char_array, - int32_t utf16_length, - uint16_t* utf16_data_in) { - String* string = Alloc(java_lang_String, char_array, utf16_length); - uint16_t* utf16_data_out = string->array_->GetChars(); + static String* AllocFromUtf16(int32_t utf16_length, + uint16_t* utf16_data_in, + int32_t hash_code) { + String* string = Alloc(GetJavaLangString(), GetCharArrayClass(), utf16_length); // TODO use 16-bit wide memset variant for (int i = 0; i < utf16_length; i++ ) { - utf16_data_out[i] = utf16_data_in[i]; + string->array_->Set(i, utf16_data_in[i]); } - string->hash_code_ = ComputeUtf16Hash(utf16_data_out, utf16_length); + string->ComputeHashCode(); return string; } @@ -1146,26 +1154,25 @@ class String : public Object { int32_t utf16_length, const char* utf8_data_in) { String* string = Alloc(java_lang_String, char_array, utf16_length); - uint16_t* utf16_data_out = string->array_->GetChars(); + uint16_t* utf16_data_out = string->array_->GetData(); ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in); - string->hash_code_ = ComputeUtf16Hash(utf16_data_out, utf16_length); + string->ComputeHashCode(); return string; } // Creates a String of the given ASCII characters. It is an error to call this // using non-ASCII characters as this function assumes one char per byte. static String* AllocFromAscii(const char* ascii_data_in) { - DCHECK(java_lang_String_ != NULL); - DCHECK(char_array_ != NULL); - return AllocFromModifiedUtf8(java_lang_String_, - char_array_, + return AllocFromModifiedUtf8(GetJavaLangString(), + GetCharArrayClass(), strlen(ascii_data_in), ascii_data_in); } static String* AllocFromModifiedUtf8(int32_t utf16_length, const char* utf8_data_in) { - return AllocFromModifiedUtf8(java_lang_String_, char_array_, utf16_length, utf8_data_in); + return AllocFromModifiedUtf8(GetJavaLangString(), GetCharArrayClass(), + utf16_length, utf8_data_in); } static void InitClasses(Class* java_lang_String, Class* char_array); @@ -1248,18 +1255,21 @@ class String : public Object { return len; } - // The java/lang/String.computeHashCode() algorithm static int32_t ComputeUtf16Hash(const uint16_t* string_data, size_t string_length) { int32_t hash = 0; while (string_length--) { - hash = hash * 31 + *string_data++; + hash = hash * 31 + *string_data++; } return hash; } + void ComputeHashCode() { + hash_code_ = ComputeUtf16Hash(array_->GetData(), count_); + } + bool Equals(const char* modified_utf8) const { - for (size_t i = 0; i < GetLength(); ++i) { + for (int32_t i = 0; i < GetLength(); ++i) { uint16_t ch = GetUtf16FromUtf8(&modified_utf8); if (ch == '\0' || ch != CharAt(i)) { return false; @@ -1274,10 +1284,11 @@ class String : public Object { } bool Equals(const String* that) const { + // TODO short circuit on hash_code_ if (this->GetLength() != that->GetLength()) { return false; } - for (size_t i = 0; i < that->GetLength(); ++i) { + for (int32_t i = 0; i < that->GetLength(); ++i) { if (this->CharAt(i) != that->CharAt(i)) { return false; } @@ -1285,15 +1296,36 @@ class String : public Object { return true; } + bool Equals(const uint16_t* that_chars, int32_t that_offset, int32_t that_length) const { + if (this->GetLength() != that_length) { + return false; + } + for (int32_t i = 0; i < that_length; ++i) { + if (this->CharAt(i) != that_chars[that_offset + i]) { + return false; + } + } + return true; + } + private: // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". CharArray* array_; - uint32_t hash_code_; + int32_t hash_code_; + + int32_t offset_; - uint32_t offset_; + int32_t count_; - uint32_t count_; + static Class* GetJavaLangString() { + DCHECK(java_lang_String_ != NULL); + return java_lang_String_; + } + static Class* GetCharArrayClass() { + DCHECK(char_array_ != NULL); + return char_array_; + } static Class* java_lang_String_; static Class* char_array_; diff --git a/src/object_test.cc b/src/object_test.cc index 18e8e77644..e5bdd35bf9 100644 --- a/src/object_test.cc +++ b/src/object_test.cc @@ -16,12 +16,12 @@ namespace art { class ObjectTest : public RuntimeTest { protected: - void AssertString(size_t length, + void AssertString(int32_t length, const char* utf8_in, const char* utf16_expected_le, - uint32_t hash_expected) { + int32_t hash_expected) { uint16_t utf16_expected[length]; - for (size_t i = 0; i < length; i++) { + for (int32_t i = 0; i < length; i++) { uint16_t ch = (((utf16_expected_le[i*2 + 0] & 0xff) << 8) | ((utf16_expected_le[i*2 + 1] & 0xff) << 0)); utf16_expected[i] = ch; @@ -30,11 +30,11 @@ class ObjectTest : public RuntimeTest { String* string = String::AllocFromModifiedUtf8(length, utf8_in); ASSERT_EQ(length, string->GetLength()); ASSERT_TRUE(string->GetCharArray() != NULL); - ASSERT_TRUE(string->GetCharArray()->GetChars() != NULL); + ASSERT_TRUE(string->GetCharArray()->GetData() != NULL); // strlen is necessary because the 1-character string "\0" is interpreted as "" - ASSERT_TRUE(string->Equals(utf8_in) || length != strlen(utf8_in)); - for (size_t i = 0; i < length; i++) { - EXPECT_EQ(utf16_expected[i], string->GetCharArray()->GetChar(i)); + ASSERT_TRUE(string->Equals(utf8_in) || length != static_cast<int32_t>(strlen(utf8_in))); + for (int32_t i = 0; i < length; i++) { + EXPECT_EQ(utf16_expected[i], string->CharAt(i)); } EXPECT_EQ(hash_expected, string->GetHashCode()); } @@ -162,4 +162,11 @@ TEST_F(ObjectTest, DescriptorCompare) { EXPECT_TRUE(m4_2->HasSameNameAndDescriptor(m4_1)); } + +TEST_F(ObjectTest, StringHashCode) { + EXPECT_EQ(0, String::AllocFromAscii("")->GetHashCode()); + EXPECT_EQ(65, String::AllocFromAscii("A")->GetHashCode()); + EXPECT_EQ(64578, String::AllocFromAscii("ABC")->GetHashCode()); +} + } // namespace art diff --git a/src/unordered_map.h b/src/unordered_map.h new file mode 100644 index 0000000000..66613c6a01 --- /dev/null +++ b/src/unordered_map.h @@ -0,0 +1,37 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +#ifndef ART_SRC_CLASS_UNORDERED_MAP_H_ +#define ART_SRC_CLASS_UNORDERED_MAP_H_ + +#include "stringpiece.h" + +#ifdef __ANDROID__ +#include <unordered_map> +#else +#include <tr1/unordered_map> +#endif + +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 + +#endif // ART_SRC_CLASS_UNORDERED_MAP_H_ diff --git a/src/zip_archive.cc b/src/zip_archive.cc index 09dc3d4322..a615321243 100644 --- a/src/zip_archive.cc +++ b/src/zip_archive.cc @@ -310,7 +310,7 @@ ZipArchive* ZipArchive::Open(const std::string& filename) { ZipEntry* ZipArchive::Find(const char* name) { DCHECK(name != NULL); - std::map<StringPiece, const uint8_t*>::const_iterator it = dir_entries_.find(name); + DirEntries::const_iterator it = dir_entries_.find(name); if (it == dir_entries_.end()) { return NULL; } diff --git a/src/zip_archive.h b/src/zip_archive.h index 9eb29486d6..858afe09f2 100644 --- a/src/zip_archive.h +++ b/src/zip_archive.h @@ -26,6 +26,7 @@ #include "logging.h" #include "scoped_ptr.h" #include "stringpiece.h" +#include "unordered_map.h" namespace art { @@ -183,8 +184,8 @@ class ZipArchive { uint16_t num_entries_; off_t dir_offset_; scoped_ptr<MemMap> dir_map_; - // TODO: unordered map - std::map<StringPiece, const uint8_t*> dir_entries_; + typedef std::tr1::unordered_map<StringPiece, const uint8_t*> DirEntries; + DirEntries dir_entries_; friend class ZipEntry; }; |