diff options
author | Hiroshi Yamauchi <yamauchi@google.com> | 2014-01-15 11:46:48 -0800 |
---|---|---|
committer | Hiroshi Yamauchi <yamauchi@google.com> | 2014-01-23 15:29:12 -0800 |
commit | be1ca55db3362f5b100c4c65da5342fd299520bb (patch) | |
tree | b9df6f5562d884698ed15f21764a704bb51e359e /runtime/entrypoints/entrypoint_utils.h | |
parent | 9d8918fe97c235fdc6eb2c7f2d50a6673ab50329 (diff) | |
download | art-be1ca55db3362f5b100c4c65da5342fd299520bb.zip art-be1ca55db3362f5b100c4c65da5342fd299520bb.tar.gz art-be1ca55db3362f5b100c4c65da5342fd299520bb.tar.bz2 |
Use direct class pointers at allocation sites in the compiled code.
- Rather than looking up a class from its type ID (and checking if
it's resolved/initialized, resolving/initializing if not), use
direct class pointers, if possible (boot-code-to-boot-class pointers
and app-code-to-boot-class pointers.)
- This results in a 1-2% speedup in Ritz MemAllocTest on Nexus 4.
- Embedding the object size (along with class pointers) caused a 1-2%
slowdown in MemAllocTest and isn't implemented in this change.
- TODO: do the same for array allocations.
- TODO: when/if an application gets its own image, implement
app-code-to-app-class pointers.
- Fix a -XX:gc bug.
cf. https://android-review.googlesource.com/79460/
- Add /tmp/android-data/dalvik-cache to the list of locations to
remove oat files in clean-oat-host.
cf. https://android-review.googlesource.com/79550
- Add back a dropped UNLIKELY in FindMethodFromCode().
cf. https://android-review.googlesource.com/74205
Bug: 9986565
Change-Id: I590b96bd21f7a7472f88e36752e675547559a5b1
Diffstat (limited to 'runtime/entrypoints/entrypoint_utils.h')
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.h | 79 |
1 files changed, 71 insertions, 8 deletions
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index 09be56e..5ee750f 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -74,21 +74,48 @@ ALWAYS_INLINE static inline mirror::Class* CheckObjectAlloc(uint32_t type_idx, } if (UNLIKELY(!klass->IsInitialized())) { SirtRef<mirror::Class> sirt_klass(self, klass); - // The class initializer might cause a GC. + // EnsureInitialized (the class initializer) might cause a GC. + // may cause us to suspend meaning that another thread may try to + // change the allocator while we are stuck in the entrypoints of + // an old allocator. Also, the class initialization may fail. To + // handle these cases we mark the slow path boolean as true so + // that the caller knows to check the allocator type to see if it + // has changed and to null-check the return value in case the + // initialization fails. + *slow_path = true; if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) { DCHECK(self->IsExceptionPending()); return nullptr; // Failure } - // TODO: EnsureInitialized may cause us to suspend meaning that another thread may try to - // change the allocator while we are stuck in the entrypoints of an old allocator. To handle - // this case we mark the slow path boolean as true so that the caller knows to check the - // allocator type to see if it has changed. - *slow_path = true; return sirt_klass.get(); } return klass; } +// TODO: Fix no thread safety analysis when annotalysis is smarter. +ALWAYS_INLINE static inline mirror::Class* CheckClassInitializedForObjectAlloc(mirror::Class* klass, + Thread* self, bool* slow_path) + NO_THREAD_SAFETY_ANALYSIS { + if (UNLIKELY(!klass->IsInitialized())) { + SirtRef<mirror::Class> sirt_class(self, klass); + // EnsureInitialized (the class initializer) might cause a GC. + // may cause us to suspend meaning that another thread may try to + // change the allocator while we are stuck in the entrypoints of + // an old allocator. Also, the class initialization may fail. To + // handle these cases we mark the slow path boolean as true so + // that the caller knows to check the allocator type to see if it + // has changed and to null-check the return value in case the + // initialization fails. + *slow_path = true; + if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_class, true, true)) { + DCHECK(self->IsExceptionPending()); + return nullptr; // Failure + } + return sirt_class.get(); + } + return klass; +} + // Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it // cannot be resolved, throw an error. If it can, use it to create an instance. // When verification/compiler hasn't been able to verify access, optionally perform an access @@ -112,6 +139,40 @@ ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCode(uint32_t type_id return klass->Alloc<kInstrumented>(self, allocator_type); } +// Given the context of a calling Method and a resolved class, create an instance. +// TODO: Fix NO_THREAD_SAFETY_ANALYSIS when GCC is smarter. +template <bool kInstrumented> +ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCodeResolved(mirror::Class* klass, + mirror::ArtMethod* method, + Thread* self, + gc::AllocatorType allocator_type) + NO_THREAD_SAFETY_ANALYSIS { + DCHECK(klass != nullptr); + bool slow_path = false; + klass = CheckClassInitializedForObjectAlloc(klass, self, &slow_path); + if (UNLIKELY(slow_path)) { + if (klass == nullptr) { + return nullptr; + } + gc::Heap* heap = Runtime::Current()->GetHeap(); + return klass->Alloc<kInstrumented>(self, heap->GetCurrentAllocator()); + } + return klass->Alloc<kInstrumented>(self, allocator_type); +} + +// Given the context of a calling Method and an initialized class, create an instance. +// TODO: Fix NO_THREAD_SAFETY_ANALYSIS when GCC is smarter. +template <bool kInstrumented> +ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCodeInitialized(mirror::Class* klass, + mirror::ArtMethod* method, + Thread* self, + gc::AllocatorType allocator_type) + NO_THREAD_SAFETY_ANALYSIS { + DCHECK(klass != nullptr); + return klass->Alloc<kInstrumented>(self, allocator_type); +} + + // TODO: Fix no thread safety analysis when GCC can handle template specialization. template <bool kAccessCheck> ALWAYS_INLINE static inline mirror::Class* CheckArrayAlloc(uint32_t type_idx, @@ -316,8 +377,10 @@ static inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror: } mirror::Class* methods_class = resolved_method->GetDeclaringClass(); mirror::Class* referring_class = referrer->GetDeclaringClass(); - if (!referring_class->CanAccessResolvedMethod<true, type>(methods_class, resolved_method, - method_idx)) { + bool can_access_resolved_method = + referring_class->CanAccessResolvedMethod<true, type>(methods_class, resolved_method, + method_idx); + if (UNLIKELY(!can_access_resolved_method)) { DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. } |