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