diff options
| -rw-r--r-- | runtime/class_linker.cc | 5 | ||||
| -rw-r--r-- | runtime/mirror/class.cc | 43 | ||||
| -rw-r--r-- | runtime/mirror/object.cc | 6 | ||||
| -rw-r--r-- | runtime/mirror/object.h | 9 |
4 files changed, 46 insertions, 17 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 1436810f36..ea02ab1c4f 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2563,8 +2563,9 @@ mirror::Class* ClassLinker::UpdateClass(const char* descriptor, mirror::Class* k for (auto it = class_table_.lower_bound(hash), end = class_table_.end(); it != end && it->first == hash; ++it) { - mirror::Class* entry = it->second; - if (entry == existing) { + mirror::Class** root = &it->second; + mirror::Class* klass = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(root); + if (klass == existing) { class_table_.erase(it); break; } diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index be05fb8a9b..b499a5d242 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -834,13 +834,42 @@ void Class::PopulateEmbeddedImtAndVTable() SHARED_LOCKS_REQUIRED(Locks::mutator_ } } +// The pre-fence visitor for Class::CopyOf(). +class CopyClassVisitor { + public: + explicit CopyClassVisitor(Thread* self, Handle<mirror::Class>* orig, + size_t new_length, size_t copy_bytes) + : self_(self), orig_(orig), new_length_(new_length), + copy_bytes_(copy_bytes) { + } + + void operator()(Object* obj, size_t usable_size) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + UNUSED(usable_size); + mirror::Class* new_class_obj = obj->AsClass(); + mirror::Object::CopyObject(self_, new_class_obj, orig_->Get(), copy_bytes_); + new_class_obj->SetStatus(Class::kStatusResolving, self_); + new_class_obj->PopulateEmbeddedImtAndVTable(); + new_class_obj->SetClassSize(new_length_); + } + + private: + Thread* const self_; + Handle<mirror::Class>* const orig_; + const size_t new_length_; + const size_t copy_bytes_; + DISALLOW_COPY_AND_ASSIGN(CopyClassVisitor); +}; + Class* Class::CopyOf(Thread* self, int32_t new_length) { DCHECK_GE(new_length, static_cast<int32_t>(sizeof(Class))); // We may get copied by a compacting GC. StackHandleScope<1> hs(self); Handle<mirror::Class> h_this(hs.NewHandle(this)); gc::Heap* heap = Runtime::Current()->GetHeap(); - InitializeClassVisitor visitor(new_length); + // The num_bytes (3rd param) is sizeof(Class) as opposed to SizeOf() + // to skip copying the tail part that we will overwrite here. + CopyClassVisitor visitor(self, &h_this, new_length, sizeof(Class)); mirror::Object* new_class = kMovingClasses ? heap->AllocObject<true>(self, java_lang_Class_, new_length, visitor) @@ -850,17 +879,7 @@ Class* Class::CopyOf(Thread* self, int32_t new_length) { return NULL; } - mirror::Class* new_class_obj = new_class->AsClass(); - memcpy(new_class_obj, h_this.Get(), sizeof(Class)); - - new_class_obj->SetStatus(kStatusResolving, self); - new_class_obj->PopulateEmbeddedImtAndVTable(); - // Correct some fields. - new_class_obj->SetLockWord(LockWord(), false); - new_class_obj->SetClassSize(new_length); - - Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(new_class_obj); - return new_class_obj; + return new_class->AsClass(); } } // namespace mirror diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index 5f88d54fe0..97d88cfb93 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -65,8 +65,8 @@ class CopyReferenceFieldsWithReadBarrierVisitor { Object* const dest_obj_; }; -static Object* CopyObject(Thread* self, mirror::Object* dest, mirror::Object* src, size_t num_bytes) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +Object* Object::CopyObject(Thread* self, mirror::Object* dest, mirror::Object* src, + size_t num_bytes) { // Copy instance data. We assume memcpy copies by words. // TODO: expose and use move32. byte* src_bytes = reinterpret_cast<byte*>(src); @@ -107,7 +107,7 @@ class CopyObjectVisitor { void operator()(Object* obj, size_t usable_size) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { UNUSED(usable_size); - CopyObject(self_, obj, orig_->Get(), num_bytes_); + Object::CopyObject(self_, obj, orig_->Get(), num_bytes_); } private: diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h index 4fae4704bf..a6b622719e 100644 --- a/runtime/mirror/object.h +++ b/runtime/mirror/object.h @@ -370,6 +370,13 @@ class MANAGED LOCKABLE Object { // Generate an identity hash code. static int32_t GenerateIdentityHashCode(); + // A utility function that copies an object in a read barrier and + // write barrier-aware way. This is internally used by Clone() and + // Class::CopyOf(). + static Object* CopyObject(Thread* self, mirror::Object* dest, mirror::Object* src, + size_t num_bytes) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // The Class representing the type of the object. HeapReference<Class> klass_; // Monitor and hash code information. @@ -386,6 +393,8 @@ class MANAGED LOCKABLE Object { friend class art::ImageWriter; friend class art::Monitor; friend struct art::ObjectOffsets; // for verifying offset information + friend class CopyObjectVisitor; // for CopyObject(). + friend class CopyClassVisitor; // for CopyObject(). DISALLOW_IMPLICIT_CONSTRUCTORS(Object); }; |