summaryrefslogtreecommitdiffstats
path: root/runtime/entrypoints/entrypoint_utils.h
diff options
context:
space:
mode:
authorHiroshi Yamauchi <yamauchi@google.com>2014-01-15 11:46:48 -0800
committerHiroshi Yamauchi <yamauchi@google.com>2014-01-23 15:29:12 -0800
commitbe1ca55db3362f5b100c4c65da5342fd299520bb (patch)
treeb9df6f5562d884698ed15f21764a704bb51e359e /runtime/entrypoints/entrypoint_utils.h
parent9d8918fe97c235fdc6eb2c7f2d50a6673ab50329 (diff)
downloadart-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.h79
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.
}