thread.cc revision 9b576b4ed1dbe035952f3106d8f4b6993125ed6f
1b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro// Copyright 2011 Google Inc. All Rights Reserved. 2b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 3578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h" 4b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 5b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <pthread.h> 6b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <sys/mman.h> 7b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <algorithm> 8eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes#include <cerrno> 9b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <list> 10b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 11a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes#include "class_linker.h" 12408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers#include "heap.h" 13c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h" 14a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes#include "object.h" 15578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h" 16578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "utils.h" 175433072f589b61413e042eddf76e8190a048f71dbuzbee#include "runtime_support.h" 18b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 19b557353b22c728eecbd1c68593b482622c7782a8Carl Shapironamespace art { 20b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 21e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes/* desktop Linux needs a little help with gettid() */ 22e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#if !defined(HAVE_ANDROID_OS) 23e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#define __KERNEL__ 24e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes# include <linux/unistd.h> 25e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#ifdef _syscall0 26e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes_syscall0(pid_t, gettid) 27e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#else 28e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughespid_t gettid() { return syscall(__NR_gettid);} 29e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#endif 30e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#undef __KERNEL__ 31e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#endif 32e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes 33b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiropthread_key_t Thread::pthread_key_self_; 34b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 353ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid Thread::InitFunctionPointers() { 365433072f589b61413e042eddf76e8190a048f71dbuzbee#if defined(__arm__) 375433072f589b61413e042eddf76e8190a048f71dbuzbee pShlLong = art_shl_long; 385433072f589b61413e042eddf76e8190a048f71dbuzbee pShrLong = art_shr_long; 395433072f589b61413e042eddf76e8190a048f71dbuzbee pUshrLong = art_ushr_long; 407b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pIdiv = __aeabi_idiv; 417b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pIdivmod = __aeabi_idivmod; 427b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pI2f = __aeabi_i2f; 437b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pF2iz = __aeabi_f2iz; 447b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pD2f = __aeabi_d2f; 457b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pF2d = __aeabi_f2d; 467b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pD2iz = __aeabi_d2iz; 477b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pL2f = __aeabi_l2f; 487b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pL2d = __aeabi_l2d; 497b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFadd = __aeabi_fadd; 507b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFsub = __aeabi_fsub; 517b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFdiv = __aeabi_fdiv; 527b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFmul = __aeabi_fmul; 537b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFmodf = fmodf; 547b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pDadd = __aeabi_dadd; 557b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pDsub = __aeabi_dsub; 567b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pDdiv = __aeabi_ddiv; 577b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pDmul = __aeabi_dmul; 587b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFmod = fmod; 597b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pArtF2l = artF2L; 607b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pArtD2l = artD2L; 617b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pLdivmod = __aeabi_ldivmod; 62439c4fa0db980fb19e4a585723a64a3461e4c278buzbee pLmul = __aeabi_lmul; 635433072f589b61413e042eddf76e8190a048f71dbuzbee#endif 64dfd3d70e58c37b5d56eded3a4469082d8bb26ee0buzbee pAllocFromCode = Array::AllocFromCode; 65dfd3d70e58c37b5d56eded3a4469082d8bb26ee0buzbee pNewInstanceFromCode = Class::NewInstanceFromCode; 663ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee pMemcpy = memcpy; 67e6d6196822952a9ccbb6ac2a97f4e3ae5e59705bbuzbee pArtHandleFillArrayDataNoThrow = artHandleFillArrayDataNoThrow; 68e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pGet32Static = Field::Get32StaticFromCode; 69e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pSet32Static = Field::Set32StaticFromCode; 70e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pGet64Static = Field::Get64StaticFromCode; 71e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pSet64Static = Field::Set64StaticFromCode; 72e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pGetObjStatic = Field::GetObjStaticFromCode; 73e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pSetObjStatic = Field::SetObjStaticFromCode; 743ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee#if 0 753ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtUnlockObject)(struct Thread*, struct Object*); 763ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtCanPutArrayElementNoThrow)(const struct ClassObject*, 773ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee const struct ClassObject*); 783ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pArtInstanceofNonTrivialNoThrow) 793ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee (const struct ClassObject*, const struct ClassObject*); 803ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pArtInstanceofNonTrivial) (const struct ClassObject*, 813ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee const struct ClassObject*); 823ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeestruct Method* (Thread::*pArtFindInterfaceMethodInCache)(ClassObject*, uint32_t, 833ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee const struct Method*, struct DvmDex*); 843ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtUnlockObjectNoThrow)(struct Thread*, struct Object*); 853ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid (Thread::*pArtLockObjectNoThrow)(struct Thread*, struct Object*); 863ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeestruct Object* (Thread::*pArtAllocObjectNoThrow)(struct ClassObject*, int); 873ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid (Thread::*pArtThrowException)(struct Thread*, struct Object*); 883ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtHandleFillArrayDataNoThrow)(struct ArrayObject*, const uint16_t*); 893ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee#endif 903ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee} 913ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee 92b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroMutex* Mutex::Create(const char* name) { 93b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro Mutex* mu = new Mutex(name); 94b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_init(&mu->lock_impl_, NULL); 95b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers CHECK_EQ(0, result); 96b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return mu; 97b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 98b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 99b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid Mutex::Lock() { 100b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_lock(&lock_impl_); 101b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK_EQ(result, 0); 102b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro SetOwner(Thread::Current()); 103b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 104b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 105b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirobool Mutex::TryLock() { 106b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_lock(&lock_impl_); 107b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (result == EBUSY) { 108b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return false; 109b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } else { 110b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK_EQ(result, 0); 111b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro SetOwner(Thread::Current()); 112b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return true; 113b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 114b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 115b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 116b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid Mutex::Unlock() { 117b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK(GetOwner() == Thread::Current()); 118b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_unlock(&lock_impl_); 119b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK_EQ(result, 0); 120f4c21c9f6440c3980c47a297519f758796dbc039Elliott Hughes SetOwner(NULL); 121b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 122b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 1231a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid Frame::Next() { 1241a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* next_sp = reinterpret_cast<byte*>(sp_) + 125d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao GetMethod()->GetFrameSizeInBytes(); 1261a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao sp_ = reinterpret_cast<const Method**>(next_sp); 1271a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 1281a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 12955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liaouintptr_t Frame::GetPC() const { 1301a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* pc_addr = reinterpret_cast<byte*>(sp_) + 131d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao GetMethod()->GetReturnPcOffsetInBytes(); 13255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao return *reinterpret_cast<uintptr_t*>(pc_addr); 1331a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 1341a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 1351a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaoconst Method* Frame::NextMethod() const { 1361a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* next_sp = reinterpret_cast<byte*>(sp_) + 137d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao GetMethod()->GetFrameSizeInBytes(); 1389b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao return *reinterpret_cast<const Method**>(next_sp); 1391a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 1401a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 14161e019d291583029c01b61b93bea750f2b663c37Carl Shapirovoid* ThreadStart(void *arg) { 14253b61314370c49354ed6f8d616d6a9a182410fc1Elliott Hughes UNIMPLEMENTED(FATAL); 143b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return NULL; 144b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 145b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 146b765be0d656c3073402693aeaf64e95a0e49f218Brian CarlstromThread* Thread::Create(const Runtime* runtime) { 147b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom size_t stack_size = runtime->GetStackSize(); 14861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 14961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro Thread* new_thread = new Thread; 150176f59cd8997a0491ea5ccdea8e9dfff85dd32d6Ian Rogers new_thread->InitCpu(); 15161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 15261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro pthread_attr_t attr; 153e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_attr_init(&attr); 154e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 155e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_attr_init failed"; 156e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 15761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 158e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 159e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 160e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_attr_setdetachstate(PTHREAD_CREATE_DETACHED) failed"; 161e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 16261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 163e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_attr_setstacksize(&attr, stack_size); 164e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 165e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_attr_setstacksize(" << stack_size << ") failed"; 166e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 16761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 168e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_create(&new_thread->handle_, &attr, ThreadStart, new_thread); 169e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 170e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_create failed"; 171e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 172e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes 173e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_attr_destroy(&attr); 174e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 175e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_attr_destroy failed"; 176e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 17761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 17861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro return new_thread; 17961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 18061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 181515a5bc89282d6f910cae4d5852bb77124a47825Elliott HughesThread* Thread::Attach(const Runtime* runtime) { 18261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro Thread* thread = new Thread; 183176f59cd8997a0491ea5ccdea8e9dfff85dd32d6Ian Rogers thread->InitCpu(); 18461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 18561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro thread->handle_ = pthread_self(); 18661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 18761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro thread->state_ = kRunnable; 18861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 189a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes errno = pthread_setspecific(Thread::pthread_key_self_, thread); 190a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes if (errno != 0) { 191c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes PLOG(FATAL) << "pthread_setspecific failed"; 192a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes } 193a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes 1947577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes thread->jni_env_ = new JNIEnvExt(thread, runtime->GetJavaVM()); 195330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes 19661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro return thread; 19761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 19861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 199e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughespid_t Thread::GetTid() const { 200e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes return gettid(); 201e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes} 202e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes 203b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirostatic void ThreadExitCheck(void* arg) { 204b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro LG << "Thread exit check"; 205b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 206b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 207c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesbool Thread::Startup() { 208b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Allocate a TLS slot. 209c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes errno = pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck); 210c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (errno != 0) { 211eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes PLOG(WARNING) << "pthread_key_create failed"; 212b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return false; 213b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 214b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 215b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Double-check the TLS slot allocation. 216b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (pthread_getspecific(pthread_key_self_) != NULL) { 217eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes LOG(WARNING) << "newly-created pthread TLS slot is not NULL"; 218b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return false; 219b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 220b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 221b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // TODO: initialize other locks and condition variables 222b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 223b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return true; 224b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 225b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 226c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Thread::Shutdown() { 227c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes errno = pthread_key_delete(Thread::pthread_key_self_); 228c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (errno != 0) { 229c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes PLOG(WARNING) << "pthread_key_delete failed"; 230c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes } 231c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 232c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 233c1674ed06662420213441ff2b818f2f71f9098dcElliott HughesThread::~Thread() { 234c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes delete jni_env_; 235c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 236c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 237408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogerssize_t Thread::NumSirtReferences() { 238a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers size_t count = 0; 239408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) { 240a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers count += cur->NumberOfReferences(); 241a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 242a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return count; 243a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 244a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 245408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogersbool Thread::SirtContains(jobject obj) { 246408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Object** sirt_entry = reinterpret_cast<Object**>(obj); 247408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) { 248a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers size_t num_refs = cur->NumberOfReferences(); 249408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // A SIRT should always have a jobject/jclass as a native method is passed 250408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // in a this pointer or a class 251408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers DCHECK_GT(num_refs, 0u); 252408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if ((&cur->References()[0] >= sirt_entry) && 253408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers (sirt_entry <= (&cur->References()[num_refs-1]))) { 254a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return true; 255a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 256a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 257a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return false; 258a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 259a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 260408f79aeb676251ba35667a64e86c20638d7cb0bIan RogersObject* Thread::DecodeJObject(jobject obj) { 261408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // TODO: Only allowed to hold Object* when in the runnable state 262408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // DCHECK(state_ == kRunnable); 263408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (obj == NULL) { 264408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return NULL; 265408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 266408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectRef ref = reinterpret_cast<IndirectRef>(obj); 267408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectRefKind kind = GetIndirectRefKind(ref); 268408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Object* result; 269408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers switch (kind) { 270408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kLocal: 271408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 27269f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes IndirectReferenceTable& locals = jni_env_->locals; 273408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = locals.Get(ref); 274408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 275408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 276408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kGlobal: 277408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 278408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers JavaVMExt* vm = Runtime::Current()->GetJavaVM(); 279408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectReferenceTable& globals = vm->globals; 280408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers MutexLock mu(vm->globals_lock); 281408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = globals.Get(ref); 282408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 283408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 284408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kWeakGlobal: 285408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 286408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers JavaVMExt* vm = Runtime::Current()->GetJavaVM(); 287408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectReferenceTable& weak_globals = vm->weak_globals; 288408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers MutexLock mu(vm->weak_globals_lock); 289408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = weak_globals.Get(ref); 290408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (result == kClearedJniWeakGlobal) { 291408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // This is a special case where it's okay to return NULL. 292408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return NULL; 293408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 294408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 295408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 296408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kSirtOrInvalid: 297408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers default: 298408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // TODO: make stack indirect reference table lookup more efficient 299408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Check if this is a local reference in the SIRT 300408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (SirtContains(obj)) { 301408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = *reinterpret_cast<Object**>(obj); // Read from SIRT 302408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } else if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO 303408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Assume an invalid local reference is actually a direct pointer. 304408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = reinterpret_cast<Object*>(obj); 305408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } else { 306408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers LOG(FATAL) << "Invalid indirect reference " << obj; 307408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = reinterpret_cast<Object*>(kInvalidIndirectRefObject); 308408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 309408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 310408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers 311408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (result == NULL) { 312408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": " 313408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers << obj; 314408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 315408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Heap::VerifyObject(result); 316408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return result; 317408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers} 318408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers 3199b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liaoclass CountStackDepthVisitor : public Thread::StackVisitor { 3209b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao public: 3219b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao CountStackDepthVisitor() : depth(0) {} 3229b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao virtual bool VisitFrame(const Frame&) { 3239b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao ++depth; 3249b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao return true; 3259b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 3269b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 3279b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao int GetDepth() const { 3289b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao return depth; 3299b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 3309b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 3319b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao private: 3329b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao uint32_t depth; 3339b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao}; 3349b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 3359b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liaoclass BuildStackTraceVisitor : public Thread::StackVisitor { 3369b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao public: 3379b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao BuildStackTraceVisitor(int depth) : count(0) { 3389b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao method_trace = Runtime::Current()->GetClassLinker()->AllocObjectArray<const Method>(depth); 3399b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao pc_trace = IntArray::Alloc(depth); 3409b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 3419b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 3429b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao virtual ~BuildStackTraceVisitor() {} 3439b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 3449b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao virtual bool VisitFrame(const Frame& frame) { 3459b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao method_trace->Set(count, frame.GetMethod()); 3469b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao pc_trace->Set(count, frame.GetPC()); 3479b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao ++count; 3489b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao return true; 3499b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 3509b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 3519b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao const Method* GetMethod(uint32_t i) { 3529b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao DCHECK(i < count); 3539b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao return method_trace->Get(i); 3549b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 3559b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 3569b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao uintptr_t GetPC(uint32_t i) { 3579b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao DCHECK(i < count); 3589b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao return pc_trace->Get(i); 3599b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 3609b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 3619b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao private: 3629b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao uint32_t count; 3639b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao ObjectArray<const Method>* method_trace; 3649b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao IntArray* pc_trace; 3659b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao}; 3669b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 3679b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liaovoid Thread::WalkStack(StackVisitor* visitor) { 36855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao Frame frame = Thread::Current()->GetTopOfStack(); 3699b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao // TODO: enable this CHECK after native_to_managed_record_ is initialized during startup. 3709b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao // CHECK(native_to_managed_record_ != NULL); 3719b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao NativeToManagedRecord* record = native_to_managed_record_; 3724417536522fd2a9d8215d8672331984769c9520bShih-wei Liao 3739b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao while (frame.GetSP()) { 3749b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao for ( ; frame.GetMethod() != 0; frame.Next()) { 3759b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao visitor->VisitFrame(frame); 3769b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 3779b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao if (record == NULL) { 3789b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao break; 3799b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 3809b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao frame.SetSP(reinterpret_cast<const art::Method**>(record->last_top_of_managed_stack)); // last_tos should return Frame instead of sp? 3819b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao record = record->link; 38255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao } 38355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao} 38455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 3859b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei LiaoObjectArray<StackTraceElement>* Thread::AllocStackTrace() { 38655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 3874417536522fd2a9d8215d8672331984769c9520bShih-wei Liao 3889b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao CountStackDepthVisitor count_visitor; 3899b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao WalkStack(&count_visitor); 3909b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao int32_t depth = count_visitor.GetDepth(); 3914417536522fd2a9d8215d8672331984769c9520bShih-wei Liao 3929b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao BuildStackTraceVisitor build_trace_visitor(depth); 3939b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao WalkStack(&build_trace_visitor); 3944417536522fd2a9d8215d8672331984769c9520bShih-wei Liao 3959b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao ObjectArray<StackTraceElement>* java_traces = class_linker->AllocStackTraceElementArray(depth); 39655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 3979b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao for (int32_t i = 0; i < depth; ++i) { 39855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao // Prepare parameter for StackTraceElement(String cls, String method, String file, int line) 3999b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao const Method* method = build_trace_visitor.GetMethod(i); 40055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao const Class* klass = method->GetDeclaringClass(); 40155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao const DexFile& dex_file = class_linker->FindDexFile(klass->GetDexCache()); 4024417536522fd2a9d8215d8672331984769c9520bShih-wei Liao String* readable_descriptor = String::AllocFromModifiedUtf8( 4034417536522fd2a9d8215d8672331984769c9520bShih-wei Liao PrettyDescriptor(klass->GetDescriptor()).c_str() 4044417536522fd2a9d8215d8672331984769c9520bShih-wei Liao ); 40555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 40655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao StackTraceElement* obj = 40755df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao StackTraceElement::Alloc(readable_descriptor, 4084417536522fd2a9d8215d8672331984769c9520bShih-wei Liao method->GetName(), 4094417536522fd2a9d8215d8672331984769c9520bShih-wei Liao String::AllocFromModifiedUtf8(klass->source_file_), 4104417536522fd2a9d8215d8672331984769c9520bShih-wei Liao dex_file.GetLineNumFromPC(method, 4119b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao method->ToDexPC(build_trace_visitor.GetPC(i)))); 41255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao java_traces->Set(i, obj); 41355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao } 41455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao return java_traces; 41555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao} 41655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 417e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughesvoid Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) { 41837f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes std::string msg; 419a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_list args; 420a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_start(args, fmt); 42137f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes StringAppendV(&msg, fmt, args); 422a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_end(args); 42337f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes 424e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception". 425e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK(exception_class_descriptor[0] == 'L'); 426e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes std::string descriptor(exception_class_descriptor + 1); 427e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK(descriptor[descriptor.length() - 1] == ';'); 428e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes descriptor.erase(descriptor.length() - 1); 429e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes 430e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes JNIEnv* env = GetJniEnv(); 431e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes jclass exception_class = env->FindClass(descriptor.c_str()); 432e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\""; 433e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes int rc = env->ThrowNew(exception_class, msg.c_str()); 434e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK_EQ(rc, JNI_OK); 435a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes} 436a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 43779082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughesvoid Thread::ThrowOutOfMemoryError() { 43879082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes UNIMPLEMENTED(FATAL); 43979082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes} 44079082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes 4411a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei LiaoFrame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) { 4421a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 4431a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DCHECK(class_linker != NULL); 4441a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 4451a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao Frame cur_frame = GetTopOfStack(); 4461a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao for (int unwind_depth = 0; ; unwind_depth++) { 4471a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const Method* cur_method = cur_frame.GetMethod(); 4481a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache(); 4491a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const DexFile& dex_file = class_linker->FindDexFile(dex_cache); 4501a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 4511a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao void* handler_addr = FindExceptionHandlerInMethod(cur_method, 4521a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao throw_pc, 4531a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao dex_file, 4541a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao class_linker); 4551a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (handler_addr) { 4561a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao *handler_pc = handler_addr; 4571a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return cur_frame; 4581a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 4591a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao // Check if we are at the last frame 4601a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (cur_frame.HasNext()) { 4611a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao cur_frame.Next(); 4621a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 4631a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao // Either at the top of stack or next frame is native. 4641a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao break; 4651a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 4661a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 4671a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 4681a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao *handler_pc = NULL; 4691a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return Frame(); 4701a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 4711a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 4721a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid* Thread::FindExceptionHandlerInMethod(const Method* method, 4731a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao void* throw_pc, 4741a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const DexFile& dex_file, 4751a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao ClassLinker* class_linker) { 476e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes Throwable* exception_obj = exception_; 4771a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao exception_ = NULL; 4781a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 4791a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao intptr_t dex_pc = -1; 4801a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_); 4811a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DexFile::CatchHandlerIterator iter; 4821a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao for (iter = dex_file.dexFindCatchHandler(*code_item, 4831a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc))); 4841a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao !iter.HasNext(); 4851a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao iter.Next()) { 4861a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_)); 4871a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DCHECK(klass != NULL); 4881a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (exception_obj->InstanceOf(klass)) { 4891a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao dex_pc = iter.Get().address_; 4901a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao break; 4911a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 4921a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 4931a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 4941a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao exception_ = exception_obj; 4951a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (iter.HasNext()) { 4961a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return NULL; 4971a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 4981a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return reinterpret_cast<void*>( method->ToNativePC(dex_pc) ); 4991a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 5001a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 5011a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 502b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstatic const char* kStateNames[] = { 503b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "New", 504b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Runnable", 505b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Blocked", 506b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Waiting", 507b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "TimedWaiting", 508b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Native", 509b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Terminated", 510b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 511b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state) { 512b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers if (state >= Thread::kNew && state <= Thread::kTerminated) { 513b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers os << kStateNames[state-Thread::kNew]; 514b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } else { 515b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers os << "State[" << static_cast<int>(state) << "]"; 516b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 517b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return os; 518b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 519b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 520330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread) { 521330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes os << "Thread[" << &thread 522e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",pthread_t=" << thread.GetImpl() 523e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",tid=" << thread.GetTid() 524e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",id=" << thread.GetId() 525e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",state=" << thread.GetState() << "]"; 526330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes return os; 527330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes} 528330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes 52961e019d291583029c01b61b93bea750f2b663c37Carl ShapiroThreadList* ThreadList::Create() { 53061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro return new ThreadList; 53161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 53261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 533b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroThreadList::ThreadList() { 534b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro lock_ = Mutex::Create("ThreadList::Lock"); 535b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 536b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 537b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroThreadList::~ThreadList() { 538c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (Contains(Thread::Current())) { 539c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes Runtime::Current()->DetachCurrentThread(); 540c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes } 541c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 542c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes // All threads should have exited and unregistered when we 543b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // reach this point. This means that all daemon threads had been 544b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // shutdown cleanly. 545c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes // TODO: dump ThreadList if non-empty. 546c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes CHECK_EQ(list_.size(), 0U); 547c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 548b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro delete lock_; 549b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro lock_ = NULL; 550b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 551b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 552c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesbool ThreadList::Contains(Thread* thread) { 553c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes return find(list_.begin(), list_.end(), thread) != list_.end(); 554c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 555c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 556b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid ThreadList::Register(Thread* thread) { 557b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro MutexLock mu(lock_); 558c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes CHECK(!Contains(thread)); 559b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro list_.push_front(thread); 560b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 561b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 562b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid ThreadList::Unregister(Thread* thread) { 563b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro MutexLock mu(lock_); 564c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes CHECK(Contains(thread)); 565b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro list_.remove(thread); 566b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 567b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 568b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} // namespace 569