diff options
author | Ian Rogers <irogers@google.com> | 2013-10-18 15:42:20 -0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2013-10-20 14:55:26 -0700 |
commit | 1eb512d33f94d1dd7ea38263307ba0f7a0dfa653 (patch) | |
tree | b4d4d9b16013ab90fb4b40d23013d7ef44bb5852 /runtime | |
parent | b917ea1a62aa0ab8eca3f689ef64b5be34e11abb (diff) | |
download | art-1eb512d33f94d1dd7ea38263307ba0f7a0dfa653.zip art-1eb512d33f94d1dd7ea38263307ba0f7a0dfa653.tar.gz art-1eb512d33f94d1dd7ea38263307ba0f7a0dfa653.tar.bz2 |
Fast JNI support.
Use a modifier to signal a native method is a fast JNI method. If the
modifier is set then don't perform runnable transitions.
Change-Id: I7835b4d837bfdd1cb8e2d54b919c0d5e6cf90499
Diffstat (limited to 'runtime')
29 files changed, 236 insertions, 202 deletions
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc index 83d3a58..16364fc 100644 --- a/runtime/entrypoints/jni/jni_entrypoints.cc +++ b/runtime/entrypoints/jni/jni_entrypoints.cc @@ -41,7 +41,7 @@ extern "C" void* artFindNativeMethod() { return NULL; } else { // Register so that future calls don't come here - method->RegisterNative(self, native_code); + method->RegisterNative(self, native_code, false); return native_code; } } @@ -115,7 +115,7 @@ extern "C" const void* artWorkAroundAppJniBugs(Thread* self, intptr_t* sp) const void* code = reinterpret_cast<const void*>(jni_method->GetNativeGcMap()); if (UNLIKELY(code == NULL)) { code = GetJniDlsymLookupStub(); - jni_method->RegisterNative(self, code); + jni_method->RegisterNative(self, code, false); } return code; } diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h index e9964ad..c8a85a0 100644 --- a/runtime/entrypoints/quick/quick_entrypoints.h +++ b/runtime/entrypoints/quick/quick_entrypoints.h @@ -142,22 +142,23 @@ struct PACKED(4) QuickEntryPoints { // JNI entrypoints. -extern uint32_t JniMethodStart(Thread* self) UNLOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR; +// TODO: NO_THREAD_SAFETY_ANALYSIS due to different control paths depending on fast JNI. +extern uint32_t JniMethodStart(Thread* self) NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self) - UNLOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR; + NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self) - SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR; + NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject locked, Thread* self) - SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR; + NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, Thread* self) - SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR; + NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result, uint32_t saved_local_ref_cookie, jobject locked, Thread* self) - SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR; + NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; } // namespace art diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc index 27ae59b..59da7a0 100644 --- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc @@ -30,10 +30,14 @@ namespace art { // Called on entry to JNI, transition out of Runnable and release share of mutator_lock_. extern uint32_t JniMethodStart(Thread* self) { JNIEnvExt* env = self->GetJniEnv(); - DCHECK(env != NULL); + DCHECK(env != nullptr); uint32_t saved_local_ref_cookie = env->local_ref_cookie; env->local_ref_cookie = env->locals.GetSegmentState(); - self->TransitionFromRunnableToSuspended(kNative); + mirror::ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame(); + if (!native_method->IsFastNative()) { + // When not fast JNI we transition out of runnable. + self->TransitionFromRunnableToSuspended(kNative); + } return saved_local_ref_cookie; } @@ -42,6 +46,20 @@ extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self) { return JniMethodStart(self); } +// TODO: NO_THREAD_SAFETY_ANALYSIS due to different control paths depending on fast JNI. +static void GoToRunnable(Thread* self) NO_THREAD_SAFETY_ANALYSIS { + mirror::ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame(); + bool is_fast = native_method->IsFastNative(); + if (!is_fast) { + self->TransitionFromSuspendedToRunnable(); + } else if (UNLIKELY(self->TestAllFlags())) { + // In fast JNI mode we never transitioned out of runnable. Perform a suspend check if there + // is a flag raised. + DCHECK(Locks::mutator_lock_->IsSharedHeld(self)); + CheckSuspend(self); + } +} + static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) { JNIEnvExt* env = self->GetJniEnv(); env->locals.SetSegmentState(env->local_ref_cookie); @@ -50,21 +68,21 @@ static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) { } extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self) { - self->TransitionFromSuspendedToRunnable(); + GoToRunnable(self); PopLocalReferences(saved_local_ref_cookie, self); } extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject locked, Thread* self) { - self->TransitionFromSuspendedToRunnable(); + GoToRunnable(self); UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. PopLocalReferences(saved_local_ref_cookie, self); } extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, Thread* self) { - self->TransitionFromSuspendedToRunnable(); + GoToRunnable(self); mirror::Object* o = self->DecodeJObject(result); // Must decode before pop. PopLocalReferences(saved_local_ref_cookie, self); // Process result. @@ -80,7 +98,7 @@ extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_ extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result, uint32_t saved_local_ref_cookie, jobject locked, Thread* self) { - self->TransitionFromSuspendedToRunnable(); + GoToRunnable(self); UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. mirror::Object* o = self->DecodeJObject(result); PopLocalReferences(saved_local_ref_cookie, self); diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index ed90242..d26e28c 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -2044,24 +2044,22 @@ bool Heap::IsGCRequestPending() const { return concurrent_start_bytes_ != std::numeric_limits<size_t>::max(); } -void Heap::RegisterNativeAllocation(int bytes) { +void Heap::RegisterNativeAllocation(JNIEnv* env, int bytes) { // Total number of native bytes allocated. native_bytes_allocated_.fetch_add(bytes); - Thread* self = Thread::Current(); if (static_cast<size_t>(native_bytes_allocated_) > native_footprint_gc_watermark_) { // The second watermark is higher than the gc watermark. If you hit this it means you are // allocating native objects faster than the GC can keep up with. if (static_cast<size_t>(native_bytes_allocated_) > native_footprint_limit_) { - JNIEnv* env = self->GetJniEnv(); // Can't do this in WellKnownClasses::Init since System is not properly set up at that // point. - if (WellKnownClasses::java_lang_System_runFinalization == NULL) { + if (UNLIKELY(WellKnownClasses::java_lang_System_runFinalization == NULL)) { DCHECK(WellKnownClasses::java_lang_System != NULL); WellKnownClasses::java_lang_System_runFinalization = CacheMethod(env, WellKnownClasses::java_lang_System, true, "runFinalization", "()V"); - assert(WellKnownClasses::java_lang_System_runFinalization != NULL); + CHECK(WellKnownClasses::java_lang_System_runFinalization != NULL); } - if (WaitForConcurrentGcToComplete(self) != collector::kGcTypeNone) { + if (WaitForConcurrentGcToComplete(ThreadForEnv(env)) != collector::kGcTypeNone) { // Just finished a GC, attempt to run finalizers. env->CallStaticVoidMethod(WellKnownClasses::java_lang_System, WellKnownClasses::java_lang_System_runFinalization); @@ -2080,20 +2078,22 @@ void Heap::RegisterNativeAllocation(int bytes) { UpdateMaxNativeFootprint(); } else { if (!IsGCRequestPending()) { - RequestConcurrentGC(self); + RequestConcurrentGC(ThreadForEnv(env)); } } } } -void Heap::RegisterNativeFree(int bytes) { +void Heap::RegisterNativeFree(JNIEnv* env, int bytes) { int expected_size, new_size; do { expected_size = native_bytes_allocated_.load(); new_size = expected_size - bytes; - if (new_size < 0) { - ThrowRuntimeException("attempted to free %d native bytes with only %d native bytes registered as allocated", - bytes, expected_size); + if (UNLIKELY(new_size < 0)) { + ScopedObjectAccess soa(env); + env->ThrowNew(WellKnownClasses::java_lang_RuntimeException, + StringPrintf("Attempted to free %d native bytes with only %d native bytes " + "registered as allocated", bytes, expected_size).c_str()); break; } } while (!native_bytes_allocated_.compare_and_swap(expected_size, new_size)); diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index ffd3034..1c2b7ef 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -146,9 +146,8 @@ class Heap { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void ThrowOutOfMemoryError(size_t byte_count, bool large_object_allocation); - void RegisterNativeAllocation(int bytes) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void RegisterNativeFree(int bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void RegisterNativeAllocation(JNIEnv* env, int bytes); + void RegisterNativeFree(JNIEnv* env, int bytes); // The given reference is believed to be to an object in the Java heap, check the soundness of it. void VerifyObjectImpl(const mirror::Object* o); diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 29fc7a4..ec717c1 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -2357,9 +2357,9 @@ class JNI { for (jint i = 0; i < method_count; ++i) { const char* name = methods[i].name; const char* sig = methods[i].signature; - + bool is_fast = false; if (*sig == '!') { - // TODO: fast jni. it's too noisy to log all these. + is_fast = true; ++sig; } @@ -2382,7 +2382,7 @@ class JNI { VLOG(jni) << "[Registering JNI native method " << PrettyMethod(m) << "]"; - m->RegisterNative(soa.Self(), methods[i].fnPtr); + m->RegisterNative(soa.Self(), methods[i].fnPtr, is_fast); } return JNI_OK; } @@ -3107,8 +3107,8 @@ void JavaVMExt::DumpReferenceTables(std::ostream& os) { } bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_loader, - std::string& detail) { - detail.clear(); + std::string* detail) { + detail->clear(); // See if we've already loaded this library. If we have, and the class loader // matches, return successfully without doing anything. @@ -3126,7 +3126,7 @@ bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_lo // The library will be associated with class_loader. The JNI // spec says we can't load the same library into more than one // class loader. - StringAppendF(&detail, "Shared library \"%s\" already opened by " + StringAppendF(detail, "Shared library \"%s\" already opened by " "ClassLoader %p; can't open in ClassLoader %p", path.c_str(), library->GetClassLoader(), class_loader); LOG(WARNING) << detail; @@ -3135,7 +3135,7 @@ bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_lo VLOG(jni) << "[Shared library \"" << path << "\" already loaded in " << "ClassLoader " << class_loader << "]"; if (!library->CheckOnLoadResult()) { - StringAppendF(&detail, "JNI_OnLoad failed on a previous attempt " + StringAppendF(detail, "JNI_OnLoad failed on a previous attempt " "to load \"%s\"", path.c_str()); return false; } @@ -3162,7 +3162,7 @@ bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_lo VLOG(jni) << "[Call to dlopen(\"" << path << "\", RTLD_LAZY) returned " << handle << "]"; if (handle == NULL) { - detail = dlerror(); + *detail = dlerror(); LOG(ERROR) << "dlopen(\"" << path << "\", RTLD_LAZY) failed: " << detail; return false; } @@ -3212,9 +3212,9 @@ bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_lo self->SetClassLoaderOverride(old_class_loader); if (version == JNI_ERR) { - StringAppendF(&detail, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str()); + StringAppendF(detail, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str()); } else if (IsBadJniVersion(version)) { - StringAppendF(&detail, "Bad JNI version returned from JNI_OnLoad in \"%s\": %d", + StringAppendF(detail, "Bad JNI version returned from JNI_OnLoad in \"%s\": %d", path.c_str(), version); // It's unwise to call dlclose() here, but we can mark it // as bad and ensure that future load attempts will fail. diff --git a/runtime/jni_internal.h b/runtime/jni_internal.h index c73ed48..888d5e5 100644 --- a/runtime/jni_internal.h +++ b/runtime/jni_internal.h @@ -73,7 +73,7 @@ class JavaVMExt : public JavaVM { * human-readable description of the error. */ bool LoadNativeLibrary(const std::string& path, mirror::ClassLoader* class_loader, - std::string& detail) + std::string* detail) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); /** diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index cd05f41..f5c0e9f 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -306,11 +306,15 @@ bool ArtMethod::IsRegistered() const { } extern "C" void art_work_around_app_jni_bugs(JNIEnv*, jobject); -void ArtMethod::RegisterNative(Thread* self, const void* native_method) { +void ArtMethod::RegisterNative(Thread* self, const void* native_method, bool is_fast) { DCHECK(Thread::Current() == self); CHECK(IsNative()) << PrettyMethod(this); + CHECK(!IsFastNative()) << PrettyMethod(this); CHECK(native_method != NULL) << PrettyMethod(this); if (!self->GetJniEnv()->vm->work_around_app_jni_bugs) { + if (is_fast) { + SetAccessFlags(GetAccessFlags() | kAccFastNative); + } SetNativeMethod(native_method); } else { // We've been asked to associate this method with the given native method but are working @@ -328,9 +332,9 @@ void ArtMethod::RegisterNative(Thread* self, const void* native_method) { } void ArtMethod::UnregisterNative(Thread* self) { - CHECK(IsNative()) << PrettyMethod(this); + CHECK(IsNative() && !IsFastNative()) << PrettyMethod(this); // restore stub to lookup native pointer via dlsym - RegisterNative(self, GetJniDlsymLookupStub()); + RegisterNative(self, GetJniDlsymLookupStub(), false); } void ArtMethod::SetNativeMethod(const void* native_method) { diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index 5d4a6ea..0520893 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -112,6 +112,10 @@ class MANAGED ArtMethod : public Object { return (GetAccessFlags() & kAccNative) != 0; } + bool IsFastNative() const { + return (GetAccessFlags() & kAccFastNative) != 0; + } + bool IsAbstract() const { return (GetAccessFlags() & kAccAbstract) != 0; } @@ -307,7 +311,7 @@ class MANAGED ArtMethod : public Object { bool IsRegistered() const; - void RegisterNative(Thread* self, const void* native_method) + void RegisterNative(Thread* self, const void* native_method, bool is_fast) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void UnregisterNative(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 2b0b1e1..319ca4a 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -661,7 +661,9 @@ static void SetPreverifiedFlagOnMethods(mirror::ObjectArray<mirror::ArtMethod>* for (int32_t index = 0, end = methods->GetLength(); index < end; ++index) { mirror::ArtMethod* method = methods->GetWithoutChecks(index); DCHECK(method != NULL); - method->SetPreverified(); + if (!method->IsNative() && !method->IsAbstract()) { + method->SetPreverified(); + } } } } diff --git a/runtime/modifiers.h b/runtime/modifiers.h index 34f4af8..4e365be 100644 --- a/runtime/modifiers.h +++ b/runtime/modifiers.h @@ -46,6 +46,7 @@ static const uint32_t kAccConstructor = 0x00010000; // method (dex only) <init> static const uint32_t kAccDeclaredSynchronized = 0x00020000; // method (dex only) static const uint32_t kAccClassIsProxy = 0x00040000; // class (dex only) static const uint32_t kAccPreverified = 0x00080000; // method (dex only) +static const uint32_t kAccFastNative = 0x0080000; // method (dex only) // Special runtime-only flags. // Note: if only kAccClassIsReference is set, we have a soft reference. diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index 823013a..4e17b79 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -95,7 +95,6 @@ static jint DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceNam return 0; } ScopedObjectAccess soa(env); - uint32_t dex_location_checksum; if (!DexFile::GetChecksum(dex_location, &dex_location_checksum)) { LOG(WARNING) << "Failed to compute checksum: " << dex_location; @@ -123,9 +122,10 @@ static jint DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceNam return static_cast<jint>(reinterpret_cast<uintptr_t>(dex_file)); } -static const DexFile* toDexFile(int dex_file_address) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +static const DexFile* toDexFile(int dex_file_address, JNIEnv* env) { const DexFile* dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(dex_file_address)); - if (dex_file == NULL) { + if (UNLIKELY(dex_file == nullptr)) { + ScopedObjectAccess soa(env); ThrowNullPointerException(NULL, "dex_file == null"); } return dex_file; @@ -133,11 +133,8 @@ static const DexFile* toDexFile(int dex_file_address) SHARED_LOCKS_REQUIRED(Lock static void DexFile_closeDexFile(JNIEnv* env, jclass, jint cookie) { const DexFile* dex_file; - { - ScopedObjectAccess soa(env); - dex_file = toDexFile(cookie); - } - if (dex_file == NULL) { + dex_file = toDexFile(cookie, env); + if (dex_file == nullptr) { return; } if (Runtime::Current()->GetClassLinker()->IsDexFileRegistered(*dex_file)) { @@ -148,8 +145,7 @@ static void DexFile_closeDexFile(JNIEnv* env, jclass, jint cookie) { static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, jobject javaLoader, jint cookie) { - ScopedObjectAccess soa(env); - const DexFile* dex_file = toDexFile(cookie); + const DexFile* dex_file = toDexFile(cookie, env); if (dex_file == NULL) { VLOG(class_linker) << "Failed to find dex_file"; return NULL; @@ -165,6 +161,7 @@ static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, j VLOG(class_linker) << "Failed to find dex_class_def"; return NULL; } + ScopedObjectAccess soa(env); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); class_linker->RegisterDexFile(*dex_file); mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(javaLoader); @@ -176,12 +173,9 @@ static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, j static jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jint cookie) { const DexFile* dex_file; - { - ScopedObjectAccess soa(env); - dex_file = toDexFile(cookie); - } - if (dex_file == NULL) { - return NULL; + dex_file = toDexFile(cookie, env); + if (dex_file == nullptr) { + return nullptr; } std::vector<std::string> class_names; diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index dad6eff..9ad2585 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -28,6 +28,7 @@ #include "mirror/object.h" #include "mirror/object-inl.h" #include "object_utils.h" +#include "scoped_fast_native_object_access.h" #include "scoped_thread_state_change.h" #include "thread.h" #include "thread_list.h" @@ -50,7 +51,7 @@ static void VMRuntime_disableJitCompilation(JNIEnv*, jobject) { } static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass, jint length) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); #ifdef MOVING_GARBAGE_COLLECTOR // TODO: right now, we don't have a copying collector, so there's no need // to do anything special here, but we ought to pass the non-movability @@ -81,7 +82,7 @@ static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) { if (javaArray == NULL) { // Most likely allocation failed return 0; } - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Array* array = soa.Decode<mirror::Array*>(javaArray); if (!array->IsArrayInstance()) { ThrowIllegalArgumentException(NULL, "not an array"); @@ -147,21 +148,21 @@ static void VMRuntime_setTargetSdkVersion(JNIEnv* env, jobject, jint targetSdkVe } static void VMRuntime_registerNativeAllocation(JNIEnv* env, jobject, jint bytes) { - ScopedObjectAccess soa(env); - if (bytes < 0) { + if (UNLIKELY(bytes < 0)) { + ScopedObjectAccess soa(env); ThrowRuntimeException("allocation size negative %d", bytes); return; } - Runtime::Current()->GetHeap()->RegisterNativeAllocation(bytes); + Runtime::Current()->GetHeap()->RegisterNativeAllocation(env, bytes); } static void VMRuntime_registerNativeFree(JNIEnv* env, jobject, jint bytes) { - ScopedObjectAccess soa(env); - if (bytes < 0) { + if (UNLIKELY(bytes < 0)) { + ScopedObjectAccess soa(env); ThrowRuntimeException("allocation size negative %d", bytes); return; } - Runtime::Current()->GetHeap()->RegisterNativeFree(bytes); + Runtime::Current()->GetHeap()->RegisterNativeFree(env, bytes); } static void VMRuntime_trimHeap(JNIEnv*, jobject) { @@ -189,12 +190,12 @@ static void VMRuntime_trimHeap(JNIEnv*, jobject) { } static void VMRuntime_concurrentGC(JNIEnv* env, jobject) { - Thread* self = static_cast<JNIEnvExt*>(env)->self; + Thread* self = ThreadForEnv(env); Runtime::Current()->GetHeap()->ConcurrentGC(self); } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(VMRuntime, addressOf, "(Ljava/lang/Object;)J"), + NATIVE_METHOD(VMRuntime, addressOf, "!(Ljava/lang/Object;)J"), NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"), NATIVE_METHOD(VMRuntime, classPath, "()Ljava/lang/String;"), NATIVE_METHOD(VMRuntime, clearGrowthLimit, "()V"), @@ -203,7 +204,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(VMRuntime, getTargetHeapUtilization, "()F"), NATIVE_METHOD(VMRuntime, isDebuggerActive, "()Z"), NATIVE_METHOD(VMRuntime, nativeSetTargetHeapUtilization, "(F)V"), - NATIVE_METHOD(VMRuntime, newNonMovableArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"), + NATIVE_METHOD(VMRuntime, newNonMovableArray, "!(Ljava/lang/Class;I)Ljava/lang/Object;"), NATIVE_METHOD(VMRuntime, properties, "()[Ljava/lang/String;"), NATIVE_METHOD(VMRuntime, setTargetSdkVersion, "(I)V"), NATIVE_METHOD(VMRuntime, registerNativeAllocation, "(I)V"), diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc index 5508270..f915365 100644 --- a/runtime/native/dalvik_system_VMStack.cc +++ b/runtime/native/dalvik_system_VMStack.cc @@ -20,6 +20,7 @@ #include "mirror/class-inl.h" #include "mirror/class_loader.h" #include "mirror/object-inl.h" +#include "scoped_fast_native_object_access.h" #include "scoped_thread_state_change.h" #include "thread_list.h" @@ -66,7 +67,7 @@ static jint VMStack_fillStackTraceElements(JNIEnv* env, jclass, jobject javaThre // Returns the defining class loader of the caller's caller. static jobject VMStack_getCallingClassLoader(JNIEnv* env, jclass) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); NthCallerVisitor visitor(soa.Self(), 2); visitor.WalkStack(); return soa.AddLocalReference<jobject>(visitor.caller->GetDeclaringClass()->GetClassLoader()); @@ -93,7 +94,7 @@ static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject ja mirror::Object* system; mirror::Object* class_loader; }; - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* bootstrap = soa.Decode<mirror::Object*>(javaBootstrap); mirror::Object* system = soa.Decode<mirror::Object*>(javaSystem); ClosestUserClassLoaderVisitor visitor(soa.Self(), bootstrap, system); @@ -103,7 +104,7 @@ static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject ja // Returns the class of the caller's caller's caller. static jclass VMStack_getStackClass2(JNIEnv* env, jclass) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); NthCallerVisitor visitor(soa.Self(), 3); visitor.WalkStack(); return soa.AddLocalReference<jclass>(visitor.caller->GetDeclaringClass()); @@ -119,9 +120,9 @@ static jobjectArray VMStack_getThreadStackTrace(JNIEnv* env, jclass, jobject jav static JNINativeMethod gMethods[] = { NATIVE_METHOD(VMStack, fillStackTraceElements, "(Ljava/lang/Thread;[Ljava/lang/StackTraceElement;)I"), - NATIVE_METHOD(VMStack, getCallingClassLoader, "()Ljava/lang/ClassLoader;"), - NATIVE_METHOD(VMStack, getClosestUserClassLoader, "(Ljava/lang/ClassLoader;Ljava/lang/ClassLoader;)Ljava/lang/ClassLoader;"), - NATIVE_METHOD(VMStack, getStackClass2, "()Ljava/lang/Class;"), + NATIVE_METHOD(VMStack, getCallingClassLoader, "!()Ljava/lang/ClassLoader;"), + NATIVE_METHOD(VMStack, getClosestUserClassLoader, "!(Ljava/lang/ClassLoader;Ljava/lang/ClassLoader;)Ljava/lang/ClassLoader;"), + NATIVE_METHOD(VMStack, getStackClass2, "!()Ljava/lang/Class;"), NATIVE_METHOD(VMStack, getThreadStackTrace, "(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;"), }; diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index d3011cb..3591611 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -24,13 +24,14 @@ #include "mirror/proxy.h" #include "object_utils.h" #include "scoped_thread_state_change.h" +#include "scoped_fast_native_object_access.h" #include "ScopedLocalRef.h" #include "ScopedUtfChars.h" #include "well_known_classes.h" namespace art { -static mirror::Class* DecodeClass(const ScopedObjectAccess& soa, jobject java_class) +static mirror::Class* DecodeClass(const ScopedFastNativeObjectAccess& soa, jobject java_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { mirror::Class* c = soa.Decode<mirror::Class*>(java_class); DCHECK(c != NULL); @@ -79,13 +80,13 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean } static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Class* c = DecodeClass(soa, javaThis); return soa.AddLocalReference<jstring>(c->ComputeName()); } static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::SynthesizedProxyClass* c = down_cast<mirror::SynthesizedProxyClass*>(DecodeClass(soa, javaThis)); return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self())); @@ -93,8 +94,8 @@ static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) { static JNINativeMethod gMethods[] = { NATIVE_METHOD(Class, classForName, "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"), - NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"), - NATIVE_METHOD(Class, getProxyInterfaces, "()[Ljava/lang/Class;"), + NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"), + NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"), }; void register_java_lang_Class(JNIEnv* env) { diff --git a/runtime/native/java_lang_DexCache.cc b/runtime/native/java_lang_DexCache.cc index 9b83206..51cd5b8 100644 --- a/runtime/native/java_lang_DexCache.cc +++ b/runtime/native/java_lang_DexCache.cc @@ -17,13 +17,13 @@ #include "dex_file.h" #include "mirror/dex_cache.h" #include "mirror/object-inl.h" -#include "scoped_thread_state_change.h" +#include "scoped_fast_native_object_access.h" #include "well_known_classes.h" namespace art { static jobject DexCache_getDexNative(JNIEnv* env, jobject javaDexCache) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache); // Should only be called while holding the lock on the dex cache. DCHECK_EQ(dex_cache->GetLockOwnerThreadId(), soa.Self()->GetThreadId()); @@ -46,7 +46,7 @@ static jobject DexCache_getDexNative(JNIEnv* env, jobject javaDexCache) { } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(DexCache, getDexNative, "()Lcom/android/dex/Dex;"), + NATIVE_METHOD(DexCache, getDexNative, "!()Lcom/android/dex/Dex;"), }; void register_java_lang_DexCache(JNIEnv* env) { diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc index 5db7a33..4768f48 100644 --- a/runtime/native/java_lang_Object.cc +++ b/runtime/native/java_lang_Object.cc @@ -16,7 +16,7 @@ #include "jni_internal.h" #include "mirror/object-inl.h" -#include "scoped_thread_state_change.h" +#include "scoped_fast_native_object_access.h" // TODO: better support for overloading. #undef NATIVE_METHOD @@ -26,41 +26,41 @@ namespace art { static jobject Object_internalClone(JNIEnv* env, jobject java_this) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(java_this); return soa.AddLocalReference<jobject>(o->Clone(soa.Self())); } static void Object_notify(JNIEnv* env, jobject java_this) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(java_this); o->Notify(soa.Self()); } static void Object_notifyAll(JNIEnv* env, jobject java_this) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(java_this); o->NotifyAll(soa.Self()); } static void Object_wait(JNIEnv* env, jobject java_this) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(java_this); o->Wait(soa.Self()); } static void Object_waitJI(JNIEnv* env, jobject java_this, jlong ms, jint ns) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(java_this); o->Wait(soa.Self(), ms, ns); } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Object, internalClone, "()Ljava/lang/Object;", internalClone), - NATIVE_METHOD(Object, notify, "()V", notify), - NATIVE_METHOD(Object, notifyAll, "()V", notifyAll), - NATIVE_METHOD(Object, wait, "()V", wait), - NATIVE_METHOD(Object, wait, "(JI)V", waitJI), + NATIVE_METHOD(Object, internalClone, "!()Ljava/lang/Object;", internalClone), + NATIVE_METHOD(Object, notify, "!()V", notify), + NATIVE_METHOD(Object, notifyAll, "!()V", notifyAll), + NATIVE_METHOD(Object, wait, "!()V", wait), + NATIVE_METHOD(Object, wait, "!(JI)V", waitJI), }; void register_java_lang_Object(JNIEnv* env) { diff --git a/runtime/native/java_lang_Runtime.cc b/runtime/native/java_lang_Runtime.cc index 55575cf..e969fcf 100644 --- a/runtime/native/java_lang_Runtime.cc +++ b/runtime/native/java_lang_Runtime.cc @@ -41,7 +41,6 @@ static void Runtime_nativeExit(JNIEnv*, jclass, jint status) { } static jstring Runtime_nativeLoad(JNIEnv* env, jclass, jstring javaFilename, jobject javaLoader, jstring javaLdLibraryPath) { - ScopedObjectAccess soa(env); ScopedUtfChars filename(env, javaFilename); if (filename.c_str() == NULL) { return NULL; @@ -62,12 +61,15 @@ static jstring Runtime_nativeLoad(JNIEnv* env, jclass, jstring javaFilename, job } } - mirror::ClassLoader* classLoader = soa.Decode<mirror::ClassLoader*>(javaLoader); std::string detail; - JavaVMExt* vm = Runtime::Current()->GetJavaVM(); - bool success = vm->LoadNativeLibrary(filename.c_str(), classLoader, detail); - if (success) { - return NULL; + { + ScopedObjectAccess soa(env); + mirror::ClassLoader* classLoader = soa.Decode<mirror::ClassLoader*>(javaLoader); + JavaVMExt* vm = Runtime::Current()->GetJavaVM(); + bool success = vm->LoadNativeLibrary(filename.c_str(), classLoader, &detail); + if (success) { + return nullptr; + } } // Don't let a pending exception from JNI_OnLoad cause a CheckJNI issue with NewStringUTF. diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc index 3e9c3f3..c401d50 100644 --- a/runtime/native/java_lang_String.cc +++ b/runtime/native/java_lang_String.cc @@ -17,13 +17,14 @@ #include "common_throws.h" #include "jni_internal.h" #include "mirror/string.h" +#include "scoped_fast_native_object_access.h" #include "scoped_thread_state_change.h" #include "ScopedLocalRef.h" namespace art { static jint String_compareTo(JNIEnv* env, jobject javaThis, jobject javaRhs) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); if (UNLIKELY(javaRhs == NULL)) { ThrowNullPointerException(NULL, "rhs == null"); return -1; @@ -33,7 +34,7 @@ static jint String_compareTo(JNIEnv* env, jobject javaThis, jobject javaRhs) { } static jint String_fastIndexOf(JNIEnv* env, jobject java_this, jint ch, jint start) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); // This method does not handle supplementary characters. They're dealt with in managed code. DCHECK_LE(ch, 0xffff); @@ -42,16 +43,16 @@ static jint String_fastIndexOf(JNIEnv* env, jobject java_this, jint ch, jint sta } static jstring String_intern(JNIEnv* env, jobject javaThis) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::String* s = soa.Decode<mirror::String*>(javaThis); mirror::String* result = s->Intern(); return soa.AddLocalReference<jstring>(result); } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(String, compareTo, "(Ljava/lang/String;)I"), - NATIVE_METHOD(String, fastIndexOf, "(II)I"), - NATIVE_METHOD(String, intern, "()Ljava/lang/String;"), + NATIVE_METHOD(String, compareTo, "!(Ljava/lang/String;)I"), + NATIVE_METHOD(String, fastIndexOf, "!(II)I"), + NATIVE_METHOD(String, intern, "!()Ljava/lang/String;"), }; void register_java_lang_String(JNIEnv* env) { diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc index 100f5a9..6674db2 100644 --- a/runtime/native/java_lang_System.cc +++ b/runtime/native/java_lang_System.cc @@ -22,7 +22,7 @@ #include "mirror/class-inl.h" #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" -#include "scoped_thread_state_change.h" +#include "scoped_fast_native_object_access.h" /* * We make guarantees about the atomicity of accesses to primitive @@ -179,7 +179,7 @@ static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror:: } static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); // Null pointer checks. if (UNLIKELY(javaSrc == NULL)) { @@ -317,7 +317,7 @@ static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, } static void System_arraycopyCharUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); DCHECK(javaSrc != NULL); DCHECK(javaDst != NULL); mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc); @@ -339,15 +339,15 @@ static void System_arraycopyCharUnchecked(JNIEnv* env, jclass, jobject javaSrc, } static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(javaObject); return static_cast<jint>(o->IdentityHashCode()); } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(System, arraycopy, "(Ljava/lang/Object;ILjava/lang/Object;II)V"), - NATIVE_METHOD(System, arraycopyCharUnchecked, "([CI[CII)V"), - NATIVE_METHOD(System, identityHashCode, "(Ljava/lang/Object;)I"), + NATIVE_METHOD(System, arraycopy, "!(Ljava/lang/Object;ILjava/lang/Object;II)V"), + NATIVE_METHOD(System, arraycopyCharUnchecked, "!([CI[CII)V"), + NATIVE_METHOD(System, identityHashCode, "!(Ljava/lang/Object;)I"), }; void register_java_lang_System(JNIEnv* env) { diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc index a9de086..5b34cfb 100644 --- a/runtime/native/java_lang_Thread.cc +++ b/runtime/native/java_lang_Thread.cc @@ -19,6 +19,7 @@ #include "jni_internal.h" #include "monitor.h" #include "mirror/object.h" +#include "scoped_fast_native_object_access.h" #include "scoped_thread_state_change.h" #include "ScopedUtfChars.h" #include "thread.h" @@ -27,7 +28,7 @@ namespace art { static jobject Thread_currentThread(JNIEnv* env, jclass) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); return soa.AddLocalReference<jobject>(soa.Self()->GetPeer()); } @@ -150,7 +151,7 @@ static void Thread_nativeSetPriority(JNIEnv* env, jobject java_thread, jint new_ } static void Thread_sleep(JNIEnv* env, jclass, jobject java_lock, jlong ms, jint ns) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* lock = soa.Decode<mirror::Object*>(java_lock); Monitor::Wait(Thread::Current(), lock, ms, ns, true, kSleeping); } @@ -166,7 +167,7 @@ static void Thread_yield(JNIEnv*, jobject) { } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Thread, currentThread, "()Ljava/lang/Thread;"), + NATIVE_METHOD(Thread, currentThread, "!()Ljava/lang/Thread;"), NATIVE_METHOD(Thread, interrupted, "()Z"), NATIVE_METHOD(Thread, isInterrupted, "()Z"), NATIVE_METHOD(Thread, nativeCreate, "(Ljava/lang/Thread;JZ)V"), @@ -175,7 +176,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Thread, nativeInterrupt, "()V"), NATIVE_METHOD(Thread, nativeSetName, "(Ljava/lang/String;)V"), NATIVE_METHOD(Thread, nativeSetPriority, "(I)V"), - NATIVE_METHOD(Thread, sleep, "(Ljava/lang/Object;JI)V"), + NATIVE_METHOD(Thread, sleep, "!(Ljava/lang/Object;JI)V"), NATIVE_METHOD(Thread, yield, "()V"), }; diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc index 45ec0ad..a2d6b18 100644 --- a/runtime/native/java_lang_reflect_Array.cc +++ b/runtime/native/java_lang_reflect_Array.cc @@ -21,13 +21,13 @@ #include "mirror/class-inl.h" #include "mirror/object-inl.h" #include "object_utils.h" -#include "scoped_thread_state_change.h" +#include "scoped_fast_native_object_access.h" #include "sirt_ref.h" namespace art { static jobject Array_createMultiArray(JNIEnv* env, jclass, jclass javaElementClass, jobject javaDimArray) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); DCHECK(javaElementClass != NULL); mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass); DCHECK(element_class->IsClass()); @@ -41,7 +41,7 @@ static jobject Array_createMultiArray(JNIEnv* env, jclass, jclass javaElementCla } static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementClass, jint length) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); DCHECK(javaElementClass != NULL); mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass); if (UNLIKELY(length < 0)) { @@ -63,8 +63,8 @@ static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementCl } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Array, createMultiArray, "(Ljava/lang/Class;[I)Ljava/lang/Object;"), - NATIVE_METHOD(Array, createObjectArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"), + NATIVE_METHOD(Array, createMultiArray, "!(Ljava/lang/Class;[I)Ljava/lang/Object;"), + NATIVE_METHOD(Array, createObjectArray, "!(Ljava/lang/Class;I)Ljava/lang/Object;"), }; void register_java_lang_reflect_Array(JNIEnv* env) { diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc index 85556ac..aa72755 100644 --- a/runtime/native/java_lang_reflect_Constructor.cc +++ b/runtime/native/java_lang_reflect_Constructor.cc @@ -35,6 +35,7 @@ namespace art { * with an interface, array, or primitive class. */ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) { + // TODO: ScopedFastNativeObjectAccess ScopedObjectAccess soa(env); jobject art_method = soa.Env()->GetObjectField( javaMethod, WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod); @@ -68,7 +69,7 @@ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectA } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Constructor, newInstance, "([Ljava/lang/Object;)Ljava/lang/Object;"), + NATIVE_METHOD(Constructor, newInstance, "!([Ljava/lang/Object;)Ljava/lang/Object;"), }; void register_java_lang_reflect_Constructor(JNIEnv* env) { diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc index 00f89b6..4d69a68 100644 --- a/runtime/native/java_lang_reflect_Field.cc +++ b/runtime/native/java_lang_reflect_Field.cc @@ -23,12 +23,12 @@ #include "mirror/class-inl.h" #include "object_utils.h" #include "reflection.h" -#include "scoped_thread_state_change.h" +#include "scoped_fast_native_object_access.h" namespace art { -static bool GetFieldValue(const ScopedObjectAccess& soa, mirror::Object* o, mirror::ArtField* f, - JValue& value, bool allow_references) +static bool GetFieldValue(const ScopedFastNativeObjectAccess& soa, mirror::Object* o, + mirror::ArtField* f, JValue& value, bool allow_references) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK_EQ(value.GetJ(), 0LL); if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(f->GetDeclaringClass(), @@ -77,8 +77,8 @@ static bool GetFieldValue(const ScopedObjectAccess& soa, mirror::Object* o, mirr return false; } -static bool CheckReceiver(const ScopedObjectAccess& soa, jobject j_rcvr, mirror::ArtField* f, - mirror::Object*& class_or_rcvr) +static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa, jobject j_rcvr, + mirror::ArtField* f, mirror::Object*& class_or_rcvr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (f->IsStatic()) { class_or_rcvr = f->GetDeclaringClass(); @@ -94,7 +94,7 @@ static bool CheckReceiver(const ScopedObjectAccess& soa, jobject j_rcvr, mirror: } static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField)); mirror::Object* o = NULL; if (!CheckReceiver(soa, javaObj, f, o)) { @@ -112,7 +112,7 @@ static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) { static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char dst_descriptor) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField)); mirror::Object* o = NULL; if (!CheckReceiver(soa, javaObj, f, o)) { @@ -221,7 +221,7 @@ static void SetFieldValue(mirror::Object* o, mirror::ArtField* f, const JValue& } static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField)); // Unbox the value, if necessary. @@ -242,7 +242,7 @@ static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject j static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor, const JValue& new_value) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField)); mirror::Object* o = NULL; if (!CheckReceiver(soa, javaObj, f, o)) { @@ -316,24 +316,24 @@ static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jsho } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Field, get, "(Ljava/lang/Object;)Ljava/lang/Object;"), - NATIVE_METHOD(Field, getBoolean, "(Ljava/lang/Object;)Z"), - NATIVE_METHOD(Field, getByte, "(Ljava/lang/Object;)B"), - NATIVE_METHOD(Field, getChar, "(Ljava/lang/Object;)C"), - NATIVE_METHOD(Field, getDouble, "(Ljava/lang/Object;)D"), - NATIVE_METHOD(Field, getFloat, "(Ljava/lang/Object;)F"), - NATIVE_METHOD(Field, getInt, "(Ljava/lang/Object;)I"), - NATIVE_METHOD(Field, getLong, "(Ljava/lang/Object;)J"), - NATIVE_METHOD(Field, getShort, "(Ljava/lang/Object;)S"), - NATIVE_METHOD(Field, set, "(Ljava/lang/Object;Ljava/lang/Object;)V"), - NATIVE_METHOD(Field, setBoolean, "(Ljava/lang/Object;Z)V"), - NATIVE_METHOD(Field, setByte, "(Ljava/lang/Object;B)V"), - NATIVE_METHOD(Field, setChar, "(Ljava/lang/Object;C)V"), - NATIVE_METHOD(Field, setDouble, "(Ljava/lang/Object;D)V"), - NATIVE_METHOD(Field, setFloat, "(Ljava/lang/Object;F)V"), - NATIVE_METHOD(Field, setInt, "(Ljava/lang/Object;I)V"), - NATIVE_METHOD(Field, setLong, "(Ljava/lang/Object;J)V"), - NATIVE_METHOD(Field, setShort, "(Ljava/lang/Object;S)V"), + NATIVE_METHOD(Field, get, "!(Ljava/lang/Object;)Ljava/lang/Object;"), + NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;)Z"), + NATIVE_METHOD(Field, getByte, "!(Ljava/lang/Object;)B"), + NATIVE_METHOD(Field, getChar, "!(Ljava/lang/Object;)C"), + NATIVE_METHOD(Field, getDouble, "!(Ljava/lang/Object;)D"), + NATIVE_METHOD(Field, getFloat, "!(Ljava/lang/Object;)F"), + NATIVE_METHOD(Field, getInt, "!(Ljava/lang/Object;)I"), + NATIVE_METHOD(Field, getLong, "!(Ljava/lang/Object;)J"), + NATIVE_METHOD(Field, getShort, "!(Ljava/lang/Object;)S"), + NATIVE_METHOD(Field, set, "!(Ljava/lang/Object;Ljava/lang/Object;)V"), + NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;Z)V"), + NATIVE_METHOD(Field, setByte, "!(Ljava/lang/Object;B)V"), + NATIVE_METHOD(Field, setChar, "!(Ljava/lang/Object;C)V"), + NATIVE_METHOD(Field, setDouble, "!(Ljava/lang/Object;D)V"), + NATIVE_METHOD(Field, setFloat, "!(Ljava/lang/Object;F)V"), + NATIVE_METHOD(Field, setInt, "!(Ljava/lang/Object;I)V"), + NATIVE_METHOD(Field, setLong, "!(Ljava/lang/Object;J)V"), + NATIVE_METHOD(Field, setShort, "!(Ljava/lang/Object;S)V"), }; void register_java_lang_reflect_Field(JNIEnv* env) { diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc index d7cd18d..163ae20 100644 --- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc +++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc @@ -16,21 +16,21 @@ #include "base/logging.h" #include "debugger.h" -#include "scoped_thread_state_change.h" +#include "scoped_fast_native_object_access.h" #include "ScopedPrimitiveArray.h" namespace art { static void DdmServer_nativeSendChunk(JNIEnv* env, jclass, jint type, jbyteArray javaData, jint offset, jint length) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); ScopedByteArrayRO data(env, javaData); DCHECK_LE(offset + length, static_cast<int32_t>(data.size())); Dbg::DdmSendChunk(type, length, reinterpret_cast<const uint8_t*>(&data[offset])); } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(DdmServer, nativeSendChunk, "(I[BII)V"), + NATIVE_METHOD(DdmServer, nativeSendChunk, "!(I[BII)V"), }; void register_org_apache_harmony_dalvik_ddmc_DdmServer(JNIEnv* env) { diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc index eece81a..2c6d281 100644 --- a/runtime/native/sun_misc_Unsafe.cc +++ b/runtime/native/sun_misc_Unsafe.cc @@ -19,12 +19,12 @@ #include "jni_internal.h" #include "mirror/object.h" #include "mirror/object-inl.h" -#include "scoped_thread_state_change.h" +#include "scoped_fast_native_object_access.h" namespace art { static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint expectedValue, jint newValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); byte* raw_addr = reinterpret_cast<byte*>(obj) + offset; volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr); @@ -34,7 +34,7 @@ static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, } static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); byte* raw_addr = reinterpret_cast<byte*>(obj) + offset; volatile int64_t* address = reinterpret_cast<volatile int64_t*>(raw_addr); @@ -44,7 +44,7 @@ static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, } static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaExpectedValue, jobject javaNewValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); mirror::Object* expectedValue = soa.Decode<mirror::Object*>(javaExpectedValue); mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); @@ -60,97 +60,97 @@ static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaOb } static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); return obj->GetField32(MemberOffset(offset), false); } static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); return obj->GetField32(MemberOffset(offset), true); } static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); obj->SetField32(MemberOffset(offset), newValue, false); } static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); obj->SetField32(MemberOffset(offset), newValue, true); } static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); ANDROID_MEMBAR_STORE(); obj->SetField32(MemberOffset(offset), newValue, false); } static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); return obj->GetField64(MemberOffset(offset), false); } static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); return obj->GetField64(MemberOffset(offset), true); } static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); obj->SetField64(MemberOffset(offset), newValue, false); } static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); obj->SetField64(MemberOffset(offset), newValue, true); } static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); ANDROID_MEMBAR_STORE(); obj->SetField64(MemberOffset(offset), newValue, false); } static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), true); return soa.AddLocalReference<jobject>(value); } static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), false); return soa.AddLocalReference<jobject>(value); } static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); obj->SetFieldObject(MemberOffset(offset), newValue, false); } static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); obj->SetFieldObject(MemberOffset(offset), newValue, true); } static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) { - ScopedObjectAccess soa(env); + ScopedFastNativeObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); ANDROID_MEMBAR_STORE(); @@ -158,24 +158,24 @@ static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"), - NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"), - NATIVE_METHOD(Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"), - NATIVE_METHOD(Unsafe, getIntVolatile, "(Ljava/lang/Object;J)I"), - NATIVE_METHOD(Unsafe, putIntVolatile, "(Ljava/lang/Object;JI)V"), - NATIVE_METHOD(Unsafe, getLongVolatile, "(Ljava/lang/Object;J)J"), - NATIVE_METHOD(Unsafe, putLongVolatile, "(Ljava/lang/Object;JJ)V"), - NATIVE_METHOD(Unsafe, getObjectVolatile, "(Ljava/lang/Object;J)Ljava/lang/Object;"), - NATIVE_METHOD(Unsafe, putObjectVolatile, "(Ljava/lang/Object;JLjava/lang/Object;)V"), - NATIVE_METHOD(Unsafe, getInt, "(Ljava/lang/Object;J)I"), - NATIVE_METHOD(Unsafe, putInt, "(Ljava/lang/Object;JI)V"), - NATIVE_METHOD(Unsafe, putOrderedInt, "(Ljava/lang/Object;JI)V"), - NATIVE_METHOD(Unsafe, getLong, "(Ljava/lang/Object;J)J"), - NATIVE_METHOD(Unsafe, putLong, "(Ljava/lang/Object;JJ)V"), - NATIVE_METHOD(Unsafe, putOrderedLong, "(Ljava/lang/Object;JJ)V"), - NATIVE_METHOD(Unsafe, getObject, "(Ljava/lang/Object;J)Ljava/lang/Object;"), - NATIVE_METHOD(Unsafe, putObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"), - NATIVE_METHOD(Unsafe, putOrderedObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"), + NATIVE_METHOD(Unsafe, compareAndSwapInt, "!(Ljava/lang/Object;JII)Z"), + NATIVE_METHOD(Unsafe, compareAndSwapLong, "!(Ljava/lang/Object;JJJ)Z"), + NATIVE_METHOD(Unsafe, compareAndSwapObject, "!(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"), + NATIVE_METHOD(Unsafe, getIntVolatile, "!(Ljava/lang/Object;J)I"), + NATIVE_METHOD(Unsafe, putIntVolatile, "!(Ljava/lang/Object;JI)V"), + NATIVE_METHOD(Unsafe, getLongVolatile, "!(Ljava/lang/Object;J)J"), + NATIVE_METHOD(Unsafe, putLongVolatile, "!(Ljava/lang/Object;JJ)V"), + NATIVE_METHOD(Unsafe, getObjectVolatile, "!(Ljava/lang/Object;J)Ljava/lang/Object;"), + NATIVE_METHOD(Unsafe, putObjectVolatile, "!(Ljava/lang/Object;JLjava/lang/Object;)V"), + NATIVE_METHOD(Unsafe, getInt, "!(Ljava/lang/Object;J)I"), + NATIVE_METHOD(Unsafe, putInt, "!(Ljava/lang/Object;JI)V"), + NATIVE_METHOD(Unsafe, putOrderedInt, "!(Ljava/lang/Object;JI)V"), + NATIVE_METHOD(Unsafe, getLong, "!(Ljava/lang/Object;J)J"), + NATIVE_METHOD(Unsafe, putLong, "!(Ljava/lang/Object;JJ)V"), + NATIVE_METHOD(Unsafe, putOrderedLong, "!(Ljava/lang/Object;JJ)V"), + NATIVE_METHOD(Unsafe, getObject, "!(Ljava/lang/Object;J)Ljava/lang/Object;"), + NATIVE_METHOD(Unsafe, putObject, "!(Ljava/lang/Object;JLjava/lang/Object;)V"), + NATIVE_METHOD(Unsafe, putOrderedObject, "!(Ljava/lang/Object;JLjava/lang/Object;)V"), }; void register_sun_misc_Unsafe(JNIEnv* env) { diff --git a/runtime/runtime.cc b/runtime/runtime.cc index bdedef4..f46b794 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -977,7 +977,7 @@ void Runtime::InitNativeMethods() { std::string mapped_name(StringPrintf(OS_SHARED_LIB_FORMAT_STR, "javacore")); std::string reason; self->TransitionFromSuspendedToRunnable(); - if (!instance_->java_vm_->LoadNativeLibrary(mapped_name, NULL, reason)) { + if (!instance_->java_vm_->LoadNativeLibrary(mapped_name, NULL, &reason)) { LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": " << reason; } self->TransitionFromRunnableToSuspended(kNative); diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h index d3f3a88..c39cdb2 100644 --- a/runtime/scoped_thread_state_change.h +++ b/runtime/scoped_thread_state_change.h @@ -18,7 +18,6 @@ #define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_ #include "base/casts.h" -#include "jni_internal.h" #include "thread-inl.h" namespace art { @@ -122,14 +121,14 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { explicit ScopedObjectAccessUnchecked(JNIEnv* env) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) ALWAYS_INLINE : ScopedThreadStateChange(ThreadForEnv(env), kRunnable), - env_(reinterpret_cast<JNIEnvExt*>(env)), vm_(env_->vm) { + env_(down_cast<JNIEnvExt*>(env)), vm_(env_->vm) { self_->VerifyStack(); } explicit ScopedObjectAccessUnchecked(Thread* self) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) : ScopedThreadStateChange(self, kRunnable), - env_(reinterpret_cast<JNIEnvExt*>(self->GetJniEnv())), + env_(down_cast<JNIEnvExt*>(self->GetJniEnv())), vm_(env_ != NULL ? env_->vm : NULL) { self_->VerifyStack(); } @@ -137,7 +136,7 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't // change into Runnable or acquire a share on the mutator_lock_. explicit ScopedObjectAccessUnchecked(JavaVM* vm) - : ScopedThreadStateChange(), env_(NULL), vm_(reinterpret_cast<JavaVMExt*>(vm)) {} + : ScopedThreadStateChange(), env_(NULL), vm_(down_cast<JavaVMExt*>(vm)) {} // Here purely to force inlining. ~ScopedObjectAccessUnchecked() ALWAYS_INLINE { @@ -162,6 +161,7 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { */ template<typename T> T AddLocalReference(mirror::Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + Locks::mutator_lock_->AssertSharedHeld(Self()); DCHECK_EQ(thread_state_, kRunnable); // Don't work with raw objects in non-runnable states. if (obj == NULL) { return NULL; @@ -245,11 +245,6 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { } private: - static Thread* ThreadForEnv(JNIEnv* env) { - JNIEnvExt* full_env(reinterpret_cast<JNIEnvExt*>(env)); - return full_env->self; - } - // The full JNIEnv. JNIEnvExt* const env_; // The full JavaVM. diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h index 7d28785..8449607 100644 --- a/runtime/thread-inl.h +++ b/runtime/thread-inl.h @@ -21,11 +21,19 @@ #include <pthread.h> +#include "base/casts.h" #include "base/mutex-inl.h" #include "cutils/atomic-inline.h" +#include "jni_internal.h" namespace art { +// Quickly access the current thread from a JNIEnv. +static inline Thread* ThreadForEnv(JNIEnv* env) { + JNIEnvExt* full_env(down_cast<JNIEnvExt*>(env)); + return full_env->self; +} + inline Thread* Thread::Current() { // We rely on Thread::Current returning NULL for a detached thread, so it's not obvious // that we can replace this with a direct %fs access on x86. |