thread.cc revision 55df06be4369f5d8ab5eb61a5d22809255171036
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;
405433072f589b61413e042eddf76e8190a048f71dbuzbee#endif
413ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee  pArtAllocArrayByClass = Array::Alloc;
423ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee  pMemcpy = memcpy;
433ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee#if 0
443ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee//void* (Thread::*pMemcpy)(void*, const void*, size_t) /* = memcpy*/ ;
453ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pI2f)(int);
463ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pF2iz)(float);
473ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pD2f)(double);
483ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pF2d)(float);
493ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pI2d)(int);
503ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pD2iz)(double);
513ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pL2f)(long);
523ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pL2d)(long);
533ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeelong long (Thread::*pArtF2l)(float);
543ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeelong long (Thread::*pArtD2l)(double);
553ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFadd)(float, float);
563ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFsub)(float, float);
573ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFdiv)(float, float);
583ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFmul)(float, float);
593ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFmodf)(float, float);
603ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pDadd)(double, double);
613ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pDsub)(double, double);
623ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pDdiv)(double, double);
633ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pDmul)(double, double);
643ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pFmod)(double, double);
653ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pIdivmod)(int, int);
663ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pIdiv)(int, int);
673ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeelong long (Thread::*pLdivmod)(long long, long long);
683ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtUnlockObject)(struct Thread*, struct Object*);
693ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtCanPutArrayElementNoThrow)(const struct ClassObject*,
703ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee      const struct ClassObject*);
713ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pArtInstanceofNonTrivialNoThrow)
723ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee  (const struct ClassObject*, const struct ClassObject*);
733ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pArtInstanceofNonTrivial) (const struct ClassObject*,
743ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee     const struct ClassObject*);
753ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeestruct Method* (Thread::*pArtFindInterfaceMethodInCache)(ClassObject*, uint32_t,
763ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee      const struct Method*, struct DvmDex*);
773ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtUnlockObjectNoThrow)(struct Thread*, struct Object*);
783ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid (Thread::*pArtLockObjectNoThrow)(struct Thread*, struct Object*);
793ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeestruct Object* (Thread::*pArtAllocObjectNoThrow)(struct ClassObject*, int);
803ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid (Thread::*pArtThrowException)(struct Thread*, struct Object*);
813ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtHandleFillArrayDataNoThrow)(struct ArrayObject*, const uint16_t*);
823ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee#endif
833ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee}
843ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee
85b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroMutex* Mutex::Create(const char* name) {
86b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  Mutex* mu = new Mutex(name);
87b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  int result = pthread_mutex_init(&mu->lock_impl_, NULL);
88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  CHECK_EQ(0, result);
89b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  return mu;
90b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
91b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
92b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid Mutex::Lock() {
93b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  int result = pthread_mutex_lock(&lock_impl_);
94b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  CHECK_EQ(result, 0);
95b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  SetOwner(Thread::Current());
96b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
97b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
98b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirobool Mutex::TryLock() {
99b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  int result = pthread_mutex_lock(&lock_impl_);
100b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  if (result == EBUSY) {
101b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return false;
102b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  } else {
103b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    CHECK_EQ(result, 0);
104b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    SetOwner(Thread::Current());
105b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return true;
106b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
107b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
108b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
109b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid Mutex::Unlock() {
110b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  CHECK(GetOwner() == Thread::Current());
111b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  int result = pthread_mutex_unlock(&lock_impl_);
112b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  CHECK_EQ(result, 0);
113f4c21c9f6440c3980c47a297519f758796dbc039Elliott Hughes  SetOwner(NULL);
114b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
115b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
1161a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid Frame::Next() {
1171a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  byte* next_sp = reinterpret_cast<byte*>(sp_) +
118d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao      GetMethod()->GetFrameSizeInBytes();
1191a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  sp_ = reinterpret_cast<const Method**>(next_sp);
1201a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao}
1211a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
12255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liaouintptr_t Frame::GetPC() const {
1231a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  byte* pc_addr = reinterpret_cast<byte*>(sp_) +
124d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao      GetMethod()->GetReturnPcOffsetInBytes();
12555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  return *reinterpret_cast<uintptr_t*>(pc_addr);
1261a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao}
1271a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1281a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaoconst Method* Frame::NextMethod() const {
1291a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  byte* next_sp = reinterpret_cast<byte*>(sp_) +
130d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao      GetMethod()->GetFrameSizeInBytes();
1311a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  return reinterpret_cast<const Method*>(next_sp);
1321a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao}
1331a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
13461e019d291583029c01b61b93bea750f2b663c37Carl Shapirovoid* ThreadStart(void *arg) {
13553b61314370c49354ed6f8d616d6a9a182410fc1Elliott Hughes  UNIMPLEMENTED(FATAL);
136b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  return NULL;
137b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
138b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
139b765be0d656c3073402693aeaf64e95a0e49f218Brian CarlstromThread* Thread::Create(const Runtime* runtime) {
140b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom  size_t stack_size = runtime->GetStackSize();
14161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
14261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  Thread* new_thread = new Thread;
143176f59cd8997a0491ea5ccdea8e9dfff85dd32d6Ian Rogers  new_thread->InitCpu();
14461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
14561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  pthread_attr_t attr;
146e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  errno = pthread_attr_init(&attr);
147e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  if (errno != 0) {
148e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes    PLOG(FATAL) << "pthread_attr_init failed";
149e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  }
15061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
151e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  errno = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
152e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  if (errno != 0) {
153e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes    PLOG(FATAL) << "pthread_attr_setdetachstate(PTHREAD_CREATE_DETACHED) failed";
154e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  }
15561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
156e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  errno = pthread_attr_setstacksize(&attr, stack_size);
157e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  if (errno != 0) {
158e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes    PLOG(FATAL) << "pthread_attr_setstacksize(" << stack_size << ") failed";
159e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  }
16061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
161e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  errno = pthread_create(&new_thread->handle_, &attr, ThreadStart, new_thread);
162e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  if (errno != 0) {
163e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes    PLOG(FATAL) << "pthread_create failed";
164e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  }
165e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes
166e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  errno = pthread_attr_destroy(&attr);
167e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  if (errno != 0) {
168e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes    PLOG(FATAL) << "pthread_attr_destroy failed";
169e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  }
17061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
17161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  return new_thread;
17261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
17361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
174515a5bc89282d6f910cae4d5852bb77124a47825Elliott HughesThread* Thread::Attach(const Runtime* runtime) {
17561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  Thread* thread = new Thread;
176176f59cd8997a0491ea5ccdea8e9dfff85dd32d6Ian Rogers  thread->InitCpu();
17761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
17861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  thread->handle_ = pthread_self();
17961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
18061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  thread->state_ = kRunnable;
18161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
182a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes  errno = pthread_setspecific(Thread::pthread_key_self_, thread);
183a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes  if (errno != 0) {
184c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(FATAL) << "pthread_setspecific failed";
185a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes  }
186a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes
1877577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  thread->jni_env_ = new JNIEnvExt(thread, runtime->GetJavaVM());
188330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes
18961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  return thread;
19061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
19161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
192e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughespid_t Thread::GetTid() const {
193e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  return gettid();
194e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes}
195e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes
196b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirostatic void ThreadExitCheck(void* arg) {
197b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  LG << "Thread exit check";
198b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
199b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
200c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesbool Thread::Startup() {
201b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  // Allocate a TLS slot.
202c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  errno = pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck);
203c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (errno != 0) {
204eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes    PLOG(WARNING) << "pthread_key_create failed";
205b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return false;
206b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
207b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
208b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  // Double-check the TLS slot allocation.
209b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  if (pthread_getspecific(pthread_key_self_) != NULL) {
210eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes    LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
211b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return false;
212b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
213b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
214b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  // TODO: initialize other locks and condition variables
215b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
216b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  return true;
217b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
218b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
219c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Thread::Shutdown() {
220c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  errno = pthread_key_delete(Thread::pthread_key_self_);
221c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (errno != 0) {
222c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    PLOG(WARNING) << "pthread_key_delete failed";
223c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
224c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
225c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
226c1674ed06662420213441ff2b818f2f71f9098dcElliott HughesThread::~Thread() {
227c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  delete jni_env_;
228c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
229c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
230408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogerssize_t Thread::NumSirtReferences() {
231a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  size_t count = 0;
232408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
233a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers    count += cur->NumberOfReferences();
234a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  }
235a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  return count;
236a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers}
237a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
238408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogersbool Thread::SirtContains(jobject obj) {
239408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  Object** sirt_entry = reinterpret_cast<Object**>(obj);
240408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
241a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers    size_t num_refs = cur->NumberOfReferences();
242408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    // A SIRT should always have a jobject/jclass as a native method is passed
243408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    // in a this pointer or a class
244408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    DCHECK_GT(num_refs, 0u);
245408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    if ((&cur->References()[0] >= sirt_entry) &&
246408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers        (sirt_entry <= (&cur->References()[num_refs-1]))) {
247a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers      return true;
248a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers    }
249a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  }
250a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  return false;
251a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers}
252a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
253408f79aeb676251ba35667a64e86c20638d7cb0bIan RogersObject* Thread::DecodeJObject(jobject obj) {
254408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // TODO: Only allowed to hold Object* when in the runnable state
255408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // DCHECK(state_ == kRunnable);
256408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  if (obj == NULL) {
257408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    return NULL;
258408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  }
259408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
260408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  IndirectRefKind kind = GetIndirectRefKind(ref);
261408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  Object* result;
262408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  switch (kind) {
263408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  case kLocal:
264408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    {
26569f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes      IndirectReferenceTable& locals = jni_env_->locals;
266408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      result = locals.Get(ref);
267408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      break;
268408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    }
269408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  case kGlobal:
270408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    {
271408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      JavaVMExt* vm = Runtime::Current()->GetJavaVM();
272408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      IndirectReferenceTable& globals = vm->globals;
273408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      MutexLock mu(vm->globals_lock);
274408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      result = globals.Get(ref);
275408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      break;
276408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    }
277408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  case kWeakGlobal:
278408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    {
279408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      JavaVMExt* vm = Runtime::Current()->GetJavaVM();
280408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      IndirectReferenceTable& weak_globals = vm->weak_globals;
281408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      MutexLock mu(vm->weak_globals_lock);
282408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      result = weak_globals.Get(ref);
283408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      if (result == kClearedJniWeakGlobal) {
284408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers        // This is a special case where it's okay to return NULL.
285408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers        return NULL;
286408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      }
287408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      break;
288408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    }
289408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  case kSirtOrInvalid:
290408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  default:
291408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    // TODO: make stack indirect reference table lookup more efficient
292408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    // Check if this is a local reference in the SIRT
293408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    if (SirtContains(obj)) {
294408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      result = *reinterpret_cast<Object**>(obj); // Read from SIRT
295408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    } else if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
296408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      // Assume an invalid local reference is actually a direct pointer.
297408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      result = reinterpret_cast<Object*>(obj);
298408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    } else {
299408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      LOG(FATAL) << "Invalid indirect reference " << obj;
300408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers      result = reinterpret_cast<Object*>(kInvalidIndirectRefObject);
301408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    }
302408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  }
303408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers
304408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  if (result == NULL) {
305408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": "
306408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers               << obj;
307408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  }
308408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  Heap::VerifyObject(result);
309408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  return result;
310408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers}
311408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers
31255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao// TODO: Replaces trace.method and trace.pc with IntArray nad
31355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao// ObjectArray<Method>.
31455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei LiaoThread::InternalStackTrace* Thread::GetStackTrace(uint16_t length) {
31555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  Frame frame = Thread::Current()->GetTopOfStack();
31655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  InternalStackTrace *traces = new InternalStackTrace[length];
31755df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  for (uint16_t i = 0; i < length && frame.HasNext(); ++i, frame.Next()) {
31855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao    traces[i].method = frame.GetMethod();
31955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao    traces[i].pc = frame.GetPC();
32055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  }
32155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  return traces;
32255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao}
32355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao
32455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei LiaoObjectArray<StackTraceElement>* Thread::GetStackTraceElement(uint16_t length, InternalStackTrace *raw_trace) {
32555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
32655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  ObjectArray<StackTraceElement>* java_traces = class_linker->AllocStackTraceElementArray(length);
32755df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao
32855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  for (uint16_t i = 0; i < length; ++i) {
32955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao    // Prepare parameter for StackTraceElement(String cls, String method, String file, int line)
33055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao    const Method* method = raw_trace[i].method;
33155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao    const Class* klass = method->GetDeclaringClass();
33255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao    const DexFile& dex_file = class_linker->FindDexFile(klass->GetDexCache());
33355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao    String* readable_descriptor = String::AllocFromModifiedUtf8(PrettyDescriptor(klass->GetDescriptor()).c_str());
33455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao
33555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao    StackTraceElement* obj =
33655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao        StackTraceElement::Alloc(readable_descriptor,
33755df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao                                 method->GetName(), String::AllocFromModifiedUtf8(klass->source_file_),
33855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao                                 dex_file.GetLineNumFromPC(method, method->ToDexPC(raw_trace[i].pc)));
33955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao    java_traces->Set(i, obj);
34055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  }
34155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  return java_traces;
34255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao}
34355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao
344e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughesvoid Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) {
34537f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes  std::string msg;
346a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes  va_list args;
347a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes  va_start(args, fmt);
34837f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes  StringAppendV(&msg, fmt, args);
349a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes  va_end(args);
35037f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes
351e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception".
352e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  CHECK(exception_class_descriptor[0] == 'L');
353e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  std::string descriptor(exception_class_descriptor + 1);
354e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  CHECK(descriptor[descriptor.length() - 1] == ';');
355e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  descriptor.erase(descriptor.length() - 1);
356e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes
357e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  JNIEnv* env = GetJniEnv();
358e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  jclass exception_class = env->FindClass(descriptor.c_str());
359e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\"";
360e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  int rc = env->ThrowNew(exception_class, msg.c_str());
361e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  CHECK_EQ(rc, JNI_OK);
362a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes}
363a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes
36479082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughesvoid Thread::ThrowOutOfMemoryError() {
36579082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  UNIMPLEMENTED(FATAL);
36679082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes}
36779082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes
3681a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei LiaoFrame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) {
3691a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3701a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  DCHECK(class_linker != NULL);
3711a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
3721a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  Frame cur_frame = GetTopOfStack();
3731a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  for (int unwind_depth = 0; ; unwind_depth++) {
3741a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    const Method* cur_method = cur_frame.GetMethod();
3751a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache();
3761a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
3771a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
3781a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    void* handler_addr = FindExceptionHandlerInMethod(cur_method,
3791a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                                      throw_pc,
3801a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                                      dex_file,
3811a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                                      class_linker);
3821a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    if (handler_addr) {
3831a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao      *handler_pc = handler_addr;
3841a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao      return cur_frame;
3851a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    } else {
3861a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao      // Check if we are at the last frame
3871a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao      if (cur_frame.HasNext()) {
3881a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao        cur_frame.Next();
3891a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao      } else {
3901a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao        // Either at the top of stack or next frame is native.
3911a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao        break;
3921a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao      }
3931a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    }
3941a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
3951a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  *handler_pc = NULL;
3961a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  return Frame();
3971a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao}
3981a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
3991a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid* Thread::FindExceptionHandlerInMethod(const Method* method,
4001a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                           void* throw_pc,
4011a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                           const DexFile& dex_file,
4021a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                           ClassLinker* class_linker) {
403e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  Throwable* exception_obj = exception_;
4041a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  exception_ = NULL;
4051a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
4061a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  intptr_t dex_pc = -1;
4071a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_);
4081a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  DexFile::CatchHandlerIterator iter;
4091a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  for (iter = dex_file.dexFindCatchHandler(*code_item,
4101a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                           method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc)));
4111a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao       !iter.HasNext();
4121a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao       iter.Next()) {
4131a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_));
4141a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    DCHECK(klass != NULL);
4151a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    if (exception_obj->InstanceOf(klass)) {
4161a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao      dex_pc = iter.Get().address_;
4171a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao      break;
4181a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    }
4191a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
4201a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
4211a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  exception_ = exception_obj;
4221a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  if (iter.HasNext()) {
4231a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return NULL;
4241a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  } else {
4251a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return reinterpret_cast<void*>( method->ToNativePC(dex_pc) );
4261a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
4271a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao}
4281a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
429b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstatic const char* kStateNames[] = {
430b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  "New",
431b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  "Runnable",
432b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  "Blocked",
433b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  "Waiting",
434b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  "TimedWaiting",
435b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  "Native",
436b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  "Terminated",
437b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
438b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state) {
439b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  if (state >= Thread::kNew && state <= Thread::kTerminated) {
440b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    os << kStateNames[state-Thread::kNew];
441b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  } else {
442b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    os << "State[" << static_cast<int>(state) << "]";
443b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
444b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  return os;
445b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
446b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
447330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread) {
448330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes  os << "Thread[" << &thread
449e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes     << ",pthread_t=" << thread.GetImpl()
450e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes     << ",tid=" << thread.GetTid()
451e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes     << ",id=" << thread.GetId()
452e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes     << ",state=" << thread.GetState() << "]";
453330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes  return os;
454330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes}
455330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes
45661e019d291583029c01b61b93bea750f2b663c37Carl ShapiroThreadList* ThreadList::Create() {
45761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  return new ThreadList;
45861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro}
45961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
460b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroThreadList::ThreadList() {
461b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  lock_ = Mutex::Create("ThreadList::Lock");
462b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
463b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
464b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroThreadList::~ThreadList() {
465c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  if (Contains(Thread::Current())) {
466c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes    Runtime::Current()->DetachCurrentThread();
467c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  }
468c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
469c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // All threads should have exited and unregistered when we
470b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  // reach this point. This means that all daemon threads had been
471b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  // shutdown cleanly.
472c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  // TODO: dump ThreadList if non-empty.
473c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK_EQ(list_.size(), 0U);
474c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
475b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  delete lock_;
476b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  lock_ = NULL;
477b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
478b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
479c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesbool ThreadList::Contains(Thread* thread) {
480c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  return find(list_.begin(), list_.end(), thread) != list_.end();
481c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
482c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
483b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid ThreadList::Register(Thread* thread) {
484b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  MutexLock mu(lock_);
485c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK(!Contains(thread));
486b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  list_.push_front(thread);
487b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
488b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
489b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid ThreadList::Unregister(Thread* thread) {
490b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  MutexLock mu(lock_);
491c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  CHECK(Contains(thread));
492b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  list_.remove(thread);
493b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}
494b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
495b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}  // namespace
496