diff options
Diffstat (limited to 'runtime/mirror/class.cc')
| -rw-r--r-- | runtime/mirror/class.cc | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 96b3345fab..b60c5731ae 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -100,9 +100,21 @@ void Class::SetStatus(Handle<Class> h_this, Status new_status, Thread* self) { } static_assert(sizeof(Status) == sizeof(uint32_t), "Size of status not equal to uint32"); if (Runtime::Current()->IsActiveTransaction()) { - h_this->SetField32Volatile<true>(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status); + h_this->SetField32Volatile<true>(StatusOffset(), new_status); } else { - h_this->SetField32Volatile<false>(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status); + h_this->SetField32Volatile<false>(StatusOffset(), new_status); + } + + // Setting the object size alloc fast path needs to be after the status write so that if the + // alloc path sees a valid object size, we would know that it's initialized as long as it has a + // load-acquire/fake dependency. + if (new_status == kStatusInitialized && !h_this->IsVariableSize()) { + uint32_t object_size = RoundUp(h_this->GetObjectSize(), kObjectAlignment); + if (h_this->IsFinalizable()) { + // Finalizable objects must always go slow path. + object_size = std::numeric_limits<int32_t>::max(); + } + h_this->SetObjectSizeAllocFastPath(object_size); } if (!class_linker_initialized) { @@ -1209,5 +1221,13 @@ int32_t Class::GetInnerClassFlags(Handle<Class> h_this, int32_t default_value) { return flags; } +void Class::SetObjectSizeAllocFastPath(uint32_t new_object_size) { + if (Runtime::Current()->IsActiveTransaction()) { + SetField32Volatile<true>(ObjectSizeAllocFastPathOffset(), new_object_size); + } else { + SetField32Volatile<false>(ObjectSizeAllocFastPathOffset(), new_object_size); + } +} + } // namespace mirror } // namespace art |