summaryrefslogtreecommitdiffstats
path: root/runtime/entrypoints/entrypoint_utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/entrypoints/entrypoint_utils.h')
-rw-r--r--runtime/entrypoints/entrypoint_utils.h144
1 files changed, 69 insertions, 75 deletions
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 3b58a8d..747dd56 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -27,9 +27,11 @@
#include "mirror/art_method.h"
#include "mirror/array.h"
#include "mirror/class-inl.h"
+#include "mirror/object-inl.h"
#include "mirror/throwable.h"
+#include "locks.h"
#include "object_utils.h"
-
+#include "sirt_ref.h"
#include "thread.h"
namespace art {
@@ -40,130 +42,122 @@ namespace mirror {
class Object;
} // namespace mirror
-static inline bool CheckObjectAlloc(uint32_t type_idx, mirror::ArtMethod* method,
- Thread* self,
- bool access_check,
- mirror::Class** klass_ptr)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+// TODO: Fix no thread safety analysis when GCC can handle template specialization.
+template <const bool kAccessCheck>
+ALWAYS_INLINE static inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
+ mirror::ArtMethod* method,
+ Thread* self)
+ NO_THREAD_SAFETY_ANALYSIS {
mirror::Class* klass = method->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx);
- Runtime* runtime = Runtime::Current();
if (UNLIKELY(klass == NULL)) {
- klass = runtime->GetClassLinker()->ResolveType(type_idx, method);
+ klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
if (klass == NULL) {
DCHECK(self->IsExceptionPending());
- return false; // Failure
+ return nullptr; // Failure
}
}
- if (access_check) {
+ if (kAccessCheck) {
if (UNLIKELY(!klass->IsInstantiable())) {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
self->ThrowNewException(throw_location, "Ljava/lang/InstantiationError;",
PrettyDescriptor(klass).c_str());
- return false; // Failure
+ return nullptr; // Failure
}
mirror::Class* referrer = method->GetDeclaringClass();
if (UNLIKELY(!referrer->CanAccess(klass))) {
ThrowIllegalAccessErrorClass(referrer, klass);
- return false; // Failure
+ return nullptr; // Failure
}
}
- if (!klass->IsInitialized() &&
- !runtime->GetClassLinker()->EnsureInitialized(klass, true, true)) {
- DCHECK(self->IsExceptionPending());
- return false; // Failure
+ if (UNLIKELY(!klass->IsInitialized())) {
+ SirtRef<mirror::Class> sirt_klass(self, klass);
+ // The class initializer might cause a GC.
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(klass, true, true)) {
+ DCHECK(self->IsExceptionPending());
+ return nullptr; // Failure
+ }
+ return sirt_klass.get();
}
- *klass_ptr = klass;
- return true;
+ 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
// check.
-static inline mirror::Object* AllocObjectFromCode(uint32_t type_idx, mirror::ArtMethod* method,
- Thread* self,
- bool access_check)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::Class* klass;
- if (UNLIKELY(!CheckObjectAlloc(type_idx, method, self, access_check, &klass))) {
- return NULL;
- }
- return klass->Alloc<kMovingCollector, false>(self);
-}
-
-static inline mirror::Object* AllocObjectFromCodeInstrumented(uint32_t type_idx, mirror::ArtMethod* method,
- Thread* self,
- bool access_check)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::Class* klass;
- if (UNLIKELY(!CheckObjectAlloc(type_idx, method, self, access_check, &klass))) {
- return NULL;
- }
- return klass->Alloc<kMovingCollector, true>(self);
-}
-
-static inline bool CheckArrayAlloc(uint32_t type_idx, mirror::ArtMethod* method,
- int32_t component_count,
- bool access_check, mirror::Class** klass_ptr)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+// TODO: Fix NO_THREAD_SAFETY_ANALYSIS when GCC is smarter.
+template <bool kAccessCheck, bool kInstrumented>
+ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCode(uint32_t type_idx,
+ mirror::ArtMethod* method,
+ Thread* self,
+ gc::AllocatorType allocator_type)
+ NO_THREAD_SAFETY_ANALYSIS {
+ mirror::Class* klass = CheckObjectAlloc<kAccessCheck>(type_idx, method, self);
+ if (UNLIKELY(klass == nullptr)) {
+ return 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,
+ mirror::ArtMethod* method,
+ int32_t component_count)
+ NO_THREAD_SAFETY_ANALYSIS {
if (UNLIKELY(component_count < 0)) {
ThrowNegativeArraySizeException(component_count);
- return false; // Failure
+ return nullptr; // Failure
}
mirror::Class* klass = method->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx);
- if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
+ if (UNLIKELY(klass == nullptr)) { // Not in dex cache so try to resolve
klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
if (klass == NULL) { // Error
DCHECK(Thread::Current()->IsExceptionPending());
- return false; // Failure
+ return nullptr; // Failure
}
CHECK(klass->IsArrayClass()) << PrettyClass(klass);
}
- if (access_check) {
+ if (kAccessCheck) {
mirror::Class* referrer = method->GetDeclaringClass();
if (UNLIKELY(!referrer->CanAccess(klass))) {
ThrowIllegalAccessErrorClass(referrer, klass);
- return false; // Failure
+ return nullptr; // Failure
}
}
- *klass_ptr = klass;
- return true;
+ return klass;
}
// Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If
// it cannot be resolved, throw an error. If it can, use it to create an array.
// When verification/compiler hasn't been able to verify access, optionally perform an access
// check.
-static inline mirror::Array* AllocArrayFromCode(uint32_t type_idx, mirror::ArtMethod* method,
- int32_t component_count,
- Thread* self, bool access_check)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::Class* klass;
- if (UNLIKELY(!CheckArrayAlloc(type_idx, method, component_count, access_check, &klass))) {
- return NULL;
- }
- return mirror::Array::Alloc<kMovingCollector, false>(self, klass, component_count);
-}
-
-static inline mirror::Array* AllocArrayFromCodeInstrumented(uint32_t type_idx, mirror::ArtMethod* method,
- int32_t component_count,
- Thread* self, bool access_check)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::Class* klass;
- if (UNLIKELY(!CheckArrayAlloc(type_idx, method, component_count, access_check, &klass))) {
- return NULL;
+// TODO: Fix no thread safety analysis when GCC can handle template specialization.
+template <bool kAccessCheck, bool kInstrumented>
+ALWAYS_INLINE static inline mirror::Array* AllocArrayFromCode(uint32_t type_idx,
+ mirror::ArtMethod* method,
+ int32_t component_count,
+ Thread* self,
+ gc::AllocatorType allocator_type)
+ NO_THREAD_SAFETY_ANALYSIS {
+ mirror::Class* klass = CheckArrayAlloc<kAccessCheck>(type_idx, method, component_count);
+ if (UNLIKELY(klass == nullptr)) {
+ return nullptr;
}
- return mirror::Array::Alloc<kMovingCollector, true>(self, klass, component_count);
+ return mirror::Array::Alloc<kInstrumented>(self, klass, component_count, allocator_type);
}
extern mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::ArtMethod* method,
- int32_t component_count,
- Thread* self, bool access_check)
+ int32_t component_count, Thread* self,
+ bool access_check,
+ gc::AllocatorType allocator_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-extern mirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx, mirror::ArtMethod* method,
- int32_t component_count,
- Thread* self, bool access_check)
+extern mirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx,
+ mirror::ArtMethod* method,
+ int32_t component_count, Thread* self,
+ bool access_check,
+ gc::AllocatorType allocator_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Type of find field operation for fast and slow case.