Interning image strings
Change-Id: I7e93b3975fe43d91d00b8185b65e8e0fd67ff6f4
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 570d797..a2e05c5 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -58,13 +58,13 @@
ClassLinker* ClassLinker::Create(const std::vector<const DexFile*>& boot_class_path,
const std::vector<const DexFile*>& class_path,
- InternTable* intern_table, Space* space) {
+ InternTable* intern_table, bool image) {
CHECK_NE(boot_class_path.size(), 0U);
UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
- if (space == NULL) {
- class_linker->Init(boot_class_path, class_path);
+ if (image) {
+ class_linker->InitFromImage(boot_class_path, class_path);
} else {
- class_linker->Init(boot_class_path, class_path, space);
+ class_linker->Init(boot_class_path, class_path);
}
// TODO: check for failure during initialization
return class_linker.release();
@@ -115,16 +115,11 @@
java_lang_String->SetStatus(Class::kStatusResolved);
// Backfill Class descriptors missing until this point
- // TODO: intern these strings
- java_lang_Class->SetDescriptor(
- String::AllocFromModifiedUtf8("Ljava/lang/Class;"));
- java_lang_Object->SetDescriptor(
- String::AllocFromModifiedUtf8("Ljava/lang/Object;"));
- object_array_class->SetDescriptor(
- String::AllocFromModifiedUtf8("[Ljava/lang/Object;"));
- java_lang_String->SetDescriptor(
- String::AllocFromModifiedUtf8("Ljava/lang/String;"));
- char_array_class->SetDescriptor(String::AllocFromModifiedUtf8("[C"));
+ java_lang_Class->SetDescriptor(intern_table_->InternStrong("Ljava/lang/Class;"));
+ java_lang_Object->SetDescriptor(intern_table_->InternStrong("Ljava/lang/Object;"));
+ object_array_class->SetDescriptor(intern_table_->InternStrong("[Ljava/lang/Object;"));
+ java_lang_String->SetDescriptor(intern_table_->InternStrong("Ljava/lang/String;"));
+ char_array_class->SetDescriptor(intern_table_->InternStrong("[C"));
// Create storage for root classes, save away our work so far (requires
// descriptors)
@@ -156,7 +151,7 @@
// Create int array type for AllocDexCache (done in AppendToBootClassPath)
Class* int_array_class = AllocClass(java_lang_Class, sizeof(Class));
int_array_class->SetArrayRank(1);
- int_array_class->SetDescriptor(String::AllocFromModifiedUtf8("[I"));
+ int_array_class->SetDescriptor(intern_table_->InternStrong("[I"));
int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
IntArray::SetArrayClass(int_array_class);
SetClassRoot(kIntArrayClass, int_array_class);
@@ -179,14 +174,15 @@
// Field and Method are necessary so that FindClass can link members
Class* java_lang_reflect_Field = AllocClass(java_lang_Class, sizeof(FieldClass));
CHECK(java_lang_reflect_Field != NULL);
- java_lang_reflect_Field->SetDescriptor(String::AllocFromModifiedUtf8("Ljava/lang/reflect/Field;"));
+ java_lang_reflect_Field->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Field;"));
java_lang_reflect_Field->SetObjectSize(sizeof(Field));
SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
java_lang_reflect_Field->SetStatus(Class::kStatusResolved);
Field::SetClass(java_lang_reflect_Field);
Class* java_lang_reflect_Method = AllocClass(java_lang_Class, sizeof(MethodClass));
- java_lang_reflect_Method->SetDescriptor(String::AllocFromModifiedUtf8("Ljava/lang/reflect/Method;"));
+ java_lang_reflect_Method->SetDescriptor(
+ intern_table_->InternStrong("Ljava/lang/reflect/Method;"));
CHECK(java_lang_reflect_Method != NULL);
java_lang_reflect_Method->SetObjectSize(sizeof(Method));
SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method);
@@ -358,7 +354,7 @@
init_done_ = true;
}
-struct ClassLinker::InitCallbackState {
+struct ClassLinker::InitFromImageCallbackState {
ClassLinker* class_linker;
Class* class_roots[kClassRootsMax];
@@ -370,15 +366,14 @@
Set dex_caches;
};
-void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path,
- const std::vector<const DexFile*>& class_path,
- Space* space) {
+void ClassLinker::InitFromImage(const std::vector<const DexFile*>& boot_class_path,
+ const std::vector<const DexFile*>& class_path) {
CHECK(!init_done_);
HeapBitmap* heap_bitmap = Heap::GetLiveBits();
DCHECK(heap_bitmap != NULL);
- InitCallbackState state;
+ InitFromImageCallbackState state;
state.class_linker = this;
for (size_t i = 0; i < kClassRootsMax; i++) {
ClassRoot class_root = static_cast<ClassRoot>(i);
@@ -386,7 +381,7 @@
}
// reinit clases_ table
- heap_bitmap->Walk(InitCallback, &state);
+ heap_bitmap->Walk(InitFromImageCallback, &state);
// reinit class_roots_
Class* object_array_class = state.class_roots[kObjectArrayClass];
@@ -396,21 +391,13 @@
SetClassRoot(class_root, state.class_roots[class_root]);
}
- // reinit intern table
- // TODO: remove interned_array, make all strings in image interned (and remove space argument)
- 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_->RegisterStrong(string);
- }
-
// reinit array_interfaces_ from any array class instance, they should all be ==
array_interfaces_ = GetClassRoot(kObjectArrayClass)->GetInterfaces();
DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->GetInterfaces());
// 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
+ typedef InitFromImageCallbackState::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();
@@ -454,11 +441,15 @@
FinishInit();
}
-void ClassLinker::InitCallback(Object* obj, void *arg) {
+void ClassLinker::InitFromImageCallback(Object* obj, void *arg) {
DCHECK(obj != NULL);
DCHECK(arg != NULL);
- InitCallbackState* state = reinterpret_cast<InitCallbackState*>(arg);
+ InitFromImageCallbackState* state = reinterpret_cast<InitFromImageCallbackState*>(arg);
+ if (obj->IsString()) {
+ state->class_linker->intern_table_->RegisterStrong(obj->AsString());
+ return;
+ }
if (!obj->IsClass()) {
return;
}
@@ -484,7 +475,7 @@
}
// check if this is a root, if so, register it
- typedef InitCallbackState::Table::const_iterator It; // TODO: C++0x auto
+ typedef InitFromImageCallbackState::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;
@@ -531,7 +522,7 @@
DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) {
DexCache* dex_cache = down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::LengthAsArray()));
- dex_cache->Init(String::AllocFromModifiedUtf8(dex_file.GetLocation().c_str()),
+ dex_cache->Init(intern_table_->InternStrong(dex_file.GetLocation().c_str()),
AllocObjectArray<String>(dex_file.NumStringIds()),
AllocObjectArray<Class>(dex_file.NumTypeIds()),
AllocObjectArray<Method>(dex_file.NumMethodIds()),
@@ -760,7 +751,7 @@
if (klass->GetDescriptor() != NULL) {
DCHECK(klass->GetDescriptor()->Equals(descriptor));
} else {
- klass->SetDescriptor(String::AllocFromModifiedUtf8(descriptor));
+ klass->SetDescriptor(intern_table_->InternStrong(descriptor));
}
uint32_t access_flags = dex_class_def.access_flags_;
// Make sure there aren't any "bonus" flags set, since we use them for runtime
@@ -778,7 +769,7 @@
size_t num_direct_methods = header.direct_methods_size_;
size_t num_virtual_methods = header.virtual_methods_size_;
- klass->SetSourceFile(String::AllocFromModifiedUtf8(dex_file.dexGetSourceFile(dex_class_def)));
+ klass->SetSourceFile(intern_table_->InternStrong(dex_file.dexGetSourceFile(dex_class_def)));
// Load class interfaces.
LoadInterfaces(dex_file, dex_class_def, klass);
@@ -885,12 +876,12 @@
{
int32_t utf16_length;
std::string utf8(dex_file.CreateMethodDescriptor(method_id.proto_idx_, &utf16_length));
- dst->SetSignature(String::AllocFromModifiedUtf8(utf16_length, utf8.c_str()));
+ dst->SetSignature(intern_table_->InternStrong(utf16_length, utf8.c_str()));
}
dst->SetProtoIdx(method_id.proto_idx_);
dst->SetCodeItemOffset(src.code_off_);
const char* shorty = dex_file.GetShorty(method_id.proto_idx_);
- dst->SetShorty(String::AllocFromModifiedUtf8(shorty));
+ dst->SetShorty(intern_table_->InternStrong(shorty));
dst->SetAccessFlags(src.access_flags_);
dst->SetReturnTypeIdx(dex_file.GetProtoId(method_id.proto_idx_).return_type_idx_);
@@ -965,7 +956,7 @@
Class* klass = AllocClass(sizeof(Class));
CHECK(klass != NULL);
klass->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
- klass->SetDescriptor(String::AllocFromModifiedUtf8(descriptor));
+ klass->SetDescriptor(intern_table_->InternStrong(descriptor));
klass->SetPrimitiveType(type);
klass->SetStatus(Class::kStatusInitialized);
bool success = InsertClass(descriptor, klass);
@@ -1078,7 +1069,7 @@
if (new_class->GetDescriptor() != NULL) {
DCHECK(new_class->GetDescriptor()->Equals(descriptor));
} else {
- new_class->SetDescriptor(String::AllocFromModifiedUtf8(descriptor.ToString().c_str()));
+ new_class->SetDescriptor(intern_table_->InternStrong(descriptor.ToString().c_str()));
}
Class* java_lang_Object = GetClassRoot(kJavaLangObject);
new_class->SetSuperClass(java_lang_Object);
diff --git a/src/class_linker.h b/src/class_linker.h
index fa0c789..b250593 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -24,10 +24,10 @@
class ClassLinker {
public:
- // Initializes the class linker using DexFile and an optional boot Space.
+ // Initializes the class linker using DexFiles and an optional an image.
static ClassLinker* Create(const std::vector<const DexFile*>& boot_class_path,
const std::vector<const DexFile*>& class_path,
- InternTable* intern_table, Space* boot_space);
+ InternTable* intern_table, bool image);
~ClassLinker();
@@ -153,12 +153,11 @@
void Init(const std::vector<const DexFile*>& boot_class_path_,
const std::vector<const DexFile*>& class_path_);
- // Initialize class linker from pre-initialized space.
- void Init(const std::vector<const DexFile*>& boot_class_path_,
- const std::vector<const DexFile*>& class_path_,
- Space* space);
- static void InitCallback(Object* obj, void *arg);
- struct InitCallbackState;
+ // Initialize class linker from pre-initialized image.
+ void InitFromImage(const std::vector<const DexFile*>& boot_class_path_,
+ const std::vector<const DexFile*>& class_path_);
+ static void InitFromImageCallback(Object* obj, void *arg);
+ struct InitFromImageCallbackState;
void FinishInit();
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index aaec17b..2161949 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -106,7 +106,7 @@
// Skip past "this"
sReg++;
}
- String* shorty = cUnit->method->GetShorty();
+ const String* shorty = cUnit->method->GetShorty();
for (int i = 1; i < shorty->GetLength(); i++) {
char arg = shorty->CharAt(i);
// Is it wide?
diff --git a/src/image.h b/src/image.h
index 00f72ba..02d15de 100644
--- a/src/image.h
+++ b/src/image.h
@@ -15,8 +15,7 @@
public:
ImageHeader() {}
- ImageHeader(uint32_t base_addr, uint32_t intern_addr)
- : base_addr_(base_addr), intern_addr_(intern_addr) {
+ ImageHeader(uint32_t base_addr) : base_addr_(base_addr) {
memcpy(magic_, kImageMagic, sizeof(kImageMagic));
memcpy(version_, kImageVersion, sizeof(kImageVersion));
}
@@ -35,10 +34,6 @@
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];
@@ -48,10 +43,6 @@
// required base address for mapping the image.
uint32_t base_addr_;
-
- // absolute address of an Object[] of Strings to InternTable::RegisterStrong.
- // TODO: remove after interning all Strings in image
- uint32_t intern_addr_;
};
} // namespace art
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 859da86..c265838 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -57,41 +57,6 @@
return true;
}
-namespace {
-
-struct InternTableVisitorState {
- int index;
- ObjectArray<const Object>* interned_array;
-};
-
-void InternTableVisitor(const Object* obj, void* arg) {
- InternTableVisitorState* state = reinterpret_cast<InternTableVisitorState*>(arg);
- state->interned_array->Set(state->index++, obj);
-}
-
-ObjectArray<const Object>* CreateInternedArray() {
- // build a Object[] of the interned strings for reinit
- // TODO: avoid creating this future garbage
- Runtime* runtime = Runtime::Current();
- ClassLinker* class_linker = runtime->GetClassLinker();
- const InternTable& intern_table = *runtime->GetInternTable();
- size_t size = intern_table.Size();
- CHECK_NE(0U, size);
-
- Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;");
- ObjectArray<const Object>* interned_array = ObjectArray<const 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);
@@ -99,9 +64,28 @@
if (!image_writer->InSourceSpace(obj)) {
return;
}
- image_writer->SetImageOffset(obj, image_writer->image_top_);
- image_writer->image_top_ += RoundUp(obj->SizeOf(), 8); // 64-bit alignment
- DCHECK_LT(image_writer->image_top_, image_writer->image_->GetLength());
+
+ // if it is a string, we want to intern it if its not interned.
+ if (obj->IsString()) {
+ // we must be an interned string that was forward referenced and already assigned
+ if (IsImageOffsetAssigned(obj)) {
+ DCHECK_EQ(obj, obj->AsString()->Intern());
+ return;
+ }
+ String* interned = obj->AsString()->Intern();
+ if (obj != interned) {
+ if (!IsImageOffsetAssigned(interned)) {
+ // interned obj is after us, allocate its location early
+ image_writer->AssignImageOffset(interned);
+ }
+ // point those looking for this object to the interned version.
+ SetImageOffset(obj, GetImageOffset(interned));
+ return;
+ }
+ // else (obj == interned), nothing to do but fall through to the normal case
+ }
+
+ image_writer->AssignImageOffset(obj);
// sniff out the DexCaches on this pass for use on the next pass
if (obj->IsClass()) {
@@ -116,22 +100,18 @@
}
void ImageWriter::CalculateNewObjectOffsets() {
- ObjectArray<const Object>* interned_array = CreateInternedArray();
-
HeapBitmap* heap_bitmap = Heap::GetLiveBits();
DCHECK(heap_bitmap != NULL);
DCHECK_EQ(0U, image_top_);
- // leave space for the header, but do not write it yet, we need to
- // know where interned_array is going to end up
+ // leave space for the header, but do not write it yet
image_top_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment
heap_bitmap->Walk(CalculateNewObjectOffsetsCallback, this); // TODO: add Space-limited Walk
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)));
+ // return to write header at start of image
+ ImageHeader image_header(reinterpret_cast<uint32_t>(image_base_));
memcpy(image_->GetAddress(), &image_header, sizeof(image_header));
// Note that top_ is left at end of used space
diff --git a/src/image_writer.h b/src/image_writer.h
index 9dac31a..a5d3d6a 100644
--- a/src/image_writer.h
+++ b/src/image_writer.h
@@ -29,12 +29,25 @@
bool Init();
// we use the lock word to store the offset of the object in the image
- static void SetImageOffset(Object* object, size_t offset) {
+ void AssignImageOffset(Object* object) {
DCHECK(object != NULL);
DCHECK(object->GetMonitor() == NULL); // should be no lock
+ SetImageOffset(object, image_top_);
+ image_top_ += RoundUp(object->SizeOf(), 8); // 64-bit alignment
+ DCHECK_LT(image_top_, image_->GetLength());
+ }
+ static void SetImageOffset(Object* object, size_t offset) {
+ DCHECK(object != NULL);
+ // should be no lock (but it might be forward referenced interned string)
+ DCHECK(object->GetMonitor() == NULL || object->IsString());
DCHECK_NE(0U, offset);
object->SetMonitor(reinterpret_cast<Monitor*>(offset));
}
+ static size_t IsImageOffsetAssigned(const Object* object) {
+ DCHECK(object != NULL);
+ size_t offset = reinterpret_cast<size_t>(object->GetMonitor());
+ return offset != 0U;
+ }
static size_t GetImageOffset(const Object* object) {
DCHECK(object != NULL);
size_t offset = reinterpret_cast<size_t>(object->GetMonitor());
diff --git a/src/intern_table.cc b/src/intern_table.cc
index 41c1b2a..aa27ace 100644
--- a/src/intern_table.cc
+++ b/src/intern_table.cc
@@ -24,11 +24,11 @@
// Note: we deliberately don't visit the weak_interns_ table.
}
-const String* InternTable::Lookup(Table& table, const String* s, uint32_t hash_code) {
+String* InternTable::Lookup(Table& table, String* s, uint32_t hash_code) {
intern_table_lock_.AssertHeld();
typedef Table::const_iterator It; // TODO: C++0x auto
for (It it = table.find(hash_code), end = table.end(); it != end; ++it) {
- const String* existing_string = it->second;
+ String* existing_string = it->second;
if (existing_string->Equals(s)) {
return existing_string;
}
@@ -36,13 +36,13 @@
return NULL;
}
-const String* InternTable::Insert(Table& table, const String* s, uint32_t hash_code) {
+String* InternTable::Insert(Table& table, String* s, uint32_t hash_code) {
intern_table_lock_.AssertHeld();
table.insert(std::make_pair(hash_code, s));
return s;
}
-void InternTable::RegisterStrong(const String* s) {
+void InternTable::RegisterStrong(String* s) {
MutexLock mu(intern_table_lock_);
Insert(strong_interns_, s, s->GetHashCode());
}
@@ -58,7 +58,7 @@
}
}
-const String* InternTable::Insert(const String* s, bool is_strong) {
+String* InternTable::Insert(String* s, bool is_strong) {
MutexLock mu(intern_table_lock_);
DCHECK(s != NULL);
@@ -66,13 +66,13 @@
if (is_strong) {
// Check the strong table for a match.
- const String* strong = Lookup(strong_interns_, s, hash_code);
+ String* strong = Lookup(strong_interns_, s, hash_code);
if (strong != NULL) {
return strong;
}
// There is no match in the strong table, check the weak table.
- const String* weak = Lookup(weak_interns_, s, hash_code);
+ String* weak = Lookup(weak_interns_, s, hash_code);
if (weak != NULL) {
// A match was found in the weak table. Promote to the strong table.
Remove(weak_interns_, weak, hash_code);
@@ -84,12 +84,12 @@
}
// Check the strong table for a match.
- const String* strong = Lookup(strong_interns_, s, hash_code);
+ String* strong = Lookup(strong_interns_, s, hash_code);
if (strong != NULL) {
return strong;
}
// Check the weak table for a match.
- const String* weak = Lookup(weak_interns_, s, hash_code);
+ String* weak = Lookup(weak_interns_, s, hash_code);
if (weak != NULL) {
return weak;
}
@@ -97,15 +97,23 @@
return Insert(weak_interns_, s, hash_code);
}
-const String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) {
+String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) {
return Insert(String::AllocFromModifiedUtf8(utf16_length, utf8_data), true);
}
-const String* InternTable::InternWeak(const String* s) {
+String* InternTable::InternStrong(const char* utf8_data) {
+ return Insert(String::AllocFromModifiedUtf8(utf8_data), true);
+}
+
+String* InternTable::InternStrong(String* s) {
+ return Insert(s, true);
+}
+
+String* InternTable::InternWeak(String* s) {
return Insert(s, false);
}
-bool InternTable::ContainsWeak(const String* s) {
+bool InternTable::ContainsWeak(String* s) {
MutexLock mu(intern_table_lock_);
const String* found = Lookup(weak_interns_, s, s->GetHashCode());
return found == s;
diff --git a/src/intern_table.h b/src/intern_table.h
index fe84347..c814a1b 100644
--- a/src/intern_table.h
+++ b/src/intern_table.h
@@ -26,14 +26,20 @@
InternTable();
// Interns a potentially new string in the 'strong' table. (See above.)
- const String* InternStrong(int32_t utf16_length, const char* utf8_data);
+ String* InternStrong(int32_t utf16_length, const char* utf8_data);
+
+ // Interns a potentially new string in the 'strong' table. (See above.)
+ String* InternStrong(const char* utf8_data);
+
+ // Interns a potentially new string in the 'strong' table. (See above.)
+ String* InternStrong(String* s);
// Interns a potentially new string in the 'weak' table. (See above.)
- const String* InternWeak(const String* s);
+ String* InternWeak(String* s);
// Register a String trusting that it is safe to intern.
// Used when reinitializing InternTable from an image.
- void RegisterStrong(const String* s);
+ void RegisterStrong(String* s);
// Removes all weak interns for which the predicate functor 'p' returns true.
// (We use an explicit Predicate type rather than a template to keep implementation
@@ -44,19 +50,19 @@
};
void RemoveWeakIf(const Predicate& p);
- bool ContainsWeak(const String* s);
+ bool ContainsWeak(String* s);
size_t Size() const;
void VisitRoots(Heap::RootVisitor* visitor, void* arg) const;
private:
- typedef std::tr1::unordered_multimap<int32_t, const String*> Table;
+ typedef std::tr1::unordered_multimap<int32_t, String*> Table;
- const String* Insert(const String* s, bool is_strong);
+ String* Insert(String* s, bool is_strong);
- const String* Lookup(Table& table, const String* s, uint32_t hash_code);
- const String* Insert(Table& table, const String* s, uint32_t hash_code);
+ String* Lookup(Table& table, String* s, uint32_t hash_code);
+ String* Insert(Table& table, String* s, uint32_t hash_code);
void Remove(Table& table, const String* s, uint32_t hash_code);
mutable Mutex intern_table_lock_;
diff --git a/src/intern_table_test.cc b/src/intern_table_test.cc
index 0362b05..3f9fab0 100644
--- a/src/intern_table_test.cc
+++ b/src/intern_table_test.cc
@@ -90,9 +90,9 @@
{
// Strongs are never weak.
InternTable t;
- const String* foo_1 = t.InternStrong(3, "foo");
+ String* foo_1 = t.InternStrong(3, "foo");
EXPECT_FALSE(t.ContainsWeak(foo_1));
- const String* foo_2 = t.InternStrong(3, "foo");
+ String* foo_2 = t.InternStrong(3, "foo");
EXPECT_FALSE(t.ContainsWeak(foo_2));
EXPECT_EQ(foo_1, foo_2);
}
@@ -100,9 +100,9 @@
{
// Weaks are always weak.
InternTable t;
- const String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
+ String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
EXPECT_TRUE(t.ContainsWeak(foo_1));
- const String* foo_2 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
+ String* foo_2 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
EXPECT_TRUE(t.ContainsWeak(foo_2));
EXPECT_EQ(foo_1, foo_2);
}
@@ -110,9 +110,9 @@
{
// A weak can be promoted to a strong.
InternTable t;
- const String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
+ String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
EXPECT_TRUE(t.ContainsWeak(foo_1));
- const String* foo_2 = t.InternStrong(3, "foo");
+ String* foo_2 = t.InternStrong(3, "foo");
EXPECT_FALSE(t.ContainsWeak(foo_2));
EXPECT_EQ(foo_1, foo_2);
}
@@ -120,9 +120,9 @@
{
// Interning a weak after a strong gets you the strong.
InternTable t;
- const String* foo_1 = t.InternStrong(3, "foo");
+ String* foo_1 = t.InternStrong(3, "foo");
EXPECT_FALSE(t.ContainsWeak(foo_1));
- const String* foo_2 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
+ String* foo_2 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
EXPECT_FALSE(t.ContainsWeak(foo_2));
EXPECT_EQ(foo_1, foo_2);
}
diff --git a/src/java_lang_String.cc b/src/java_lang_String.cc
index fbabd43..9aa5221 100644
--- a/src/java_lang_String.cc
+++ b/src/java_lang_String.cc
@@ -148,8 +148,8 @@
}
jstring String_intern(JNIEnv* env, jobject javaThis) {
- const String* s = Decode<String*>(env, javaThis);
- const String* result = s->Intern();
+ String* s = Decode<String*>(env, javaThis);
+ String* result = s->Intern();
return AddLocalReference<jstring>(env, result);
}
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 0f464d2..0129fc5 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -144,7 +144,7 @@
byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, va_list ap) {
size_t num_bytes = method->NumArgArrayBytes();
UniquePtr<byte[]> arg_array(new byte[num_bytes]);
- String* shorty = method->GetShorty();
+ const String* shorty = method->GetShorty();
for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
switch (shorty->CharAt(i)) {
case 'Z':
@@ -181,7 +181,7 @@
byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, jvalue* args) {
size_t num_bytes = method->NumArgArrayBytes();
UniquePtr<byte[]> arg_array(new byte[num_bytes]);
- String* shorty = method->GetShorty();
+ const String* shorty = method->GetShorty();
for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
switch (shorty->CharAt(i)) {
case 'Z':
diff --git a/src/object.cc b/src/object.cc
index 3696374..d78eb24 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -359,7 +359,7 @@
}
size_t Method::NumArgArrayBytes() const {
- String* shorty = GetShorty();
+ const String* shorty = GetShorty();
size_t num_bytes = 0;
for (int i = 1; i < shorty->GetLength(); ++i) {
char ch = shorty->CharAt(i);
@@ -385,7 +385,7 @@
// The number of reference arguments to this method including implicit this
// pointer
size_t Method::NumReferenceArgs() const {
- String* shorty = GetShorty();
+ const String* shorty = GetShorty();
size_t result = IsStatic() ? 0 : 1; // The implicit this pointer.
for (int i = 1; i < shorty->GetLength(); i++) {
char ch = shorty->CharAt(i);
@@ -398,7 +398,7 @@
// The number of long or double arguments
size_t Method::NumLongOrDoubleArgs() const {
- String* shorty = GetShorty();
+ const String* shorty = GetShorty();
size_t result = 0;
for (int i = 1; i < shorty->GetLength(); i++) {
char ch = shorty->CharAt(i);
@@ -981,7 +981,7 @@
java_lang_String_ = NULL;
}
-const String* String::Intern() const {
+String* String::Intern() {
return Runtime::Current()->GetInternTable()->InternWeak(this);
}
diff --git a/src/object.h b/src/object.h
index 70a9b33..959abcb 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1940,16 +1940,9 @@
klass, false);
}
- String* GetSourceFile() const {
- DCHECK(IsLoaded());
- return GetFieldPtr<String*>(
- OFFSET_OF_OBJECT_MEMBER(Class, source_file_), false);
- }
+ String* GetSourceFile() const;
- void SetSourceFile(String* new_source_file) {
- SetFieldPtr<String*>(OFFSET_OF_OBJECT_MEMBER(Class, source_file_),
- new_source_file, false);
- }
+ void SetSourceFile(String* new_source_file);
private:
bool Implements(const Class* klass) const;
@@ -2419,7 +2412,7 @@
uint16_t CharAt(int32_t index) const;
- const String* Intern() const;
+ String* Intern();
static String* AllocFromUtf16(int32_t utf16_length,
const uint16_t* utf16_data_in,
@@ -2589,6 +2582,15 @@
new_descriptor, false);
}
+inline String* Class::GetSourceFile() const {
+ DCHECK(IsLoaded());
+ return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, source_file_), false);
+}
+
+inline void Class::SetSourceFile(String* new_source_file) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, source_file_), new_source_file, false);
+}
+
inline uint32_t Method::GetAccessFlags() const {
DCHECK(GetDeclaringClass()->IsLoaded());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, access_flags_), false);