blob: cddb429f844279010586ef319f5b54ae177a1cdd [file] [log] [blame]
Carl Shapirob5573532011-07-12 18:22:59 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "thread.h"
Carl Shapirob5573532011-07-12 18:22:59 -07004
Ian Rogersb033c752011-07-20 12:22:35 -07005#include <pthread.h>
6#include <sys/mman.h>
Carl Shapirob5573532011-07-12 18:22:59 -07007#include <algorithm>
Elliott Hugheseb4f6142011-07-15 17:43:51 -07008#include <cerrno>
Carl Shapirob5573532011-07-12 18:22:59 -07009#include <list>
Carl Shapirob5573532011-07-12 18:22:59 -070010
Elliott Hughesa5b897e2011-08-16 11:33:06 -070011#include "class_linker.h"
Ian Rogers408f79a2011-08-23 18:22:33 -070012#include "heap.h"
Elliott Hughesc5f7c912011-08-18 14:00:42 -070013#include "jni_internal.h"
Elliott Hughesa5b897e2011-08-16 11:33:06 -070014#include "object.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070015#include "runtime.h"
16#include "utils.h"
buzbee54330722011-08-23 16:46:55 -070017#include "runtime_support.h"
Carl Shapirob5573532011-07-12 18:22:59 -070018
19namespace art {
20
Elliott Hughese27955c2011-08-26 15:21:24 -070021/* desktop Linux needs a little help with gettid() */
22#if !defined(HAVE_ANDROID_OS)
23#define __KERNEL__
24# include <linux/unistd.h>
25#ifdef _syscall0
26_syscall0(pid_t, gettid)
27#else
28pid_t gettid() { return syscall(__NR_gettid);}
29#endif
30#undef __KERNEL__
31#endif
32
Carl Shapirob5573532011-07-12 18:22:59 -070033pthread_key_t Thread::pthread_key_self_;
34
buzbee3ea4ec52011-08-22 17:37:19 -070035void Thread::InitFunctionPointers() {
buzbee54330722011-08-23 16:46:55 -070036#if defined(__arm__)
37 pShlLong = art_shl_long;
38 pShrLong = art_shr_long;
39 pUshrLong = art_ushr_long;
buzbee7b1b86d2011-08-26 18:59:10 -070040 pIdiv = __aeabi_idiv;
41 pIdivmod = __aeabi_idivmod;
42 pI2f = __aeabi_i2f;
43 pF2iz = __aeabi_f2iz;
44 pD2f = __aeabi_d2f;
45 pF2d = __aeabi_f2d;
46 pD2iz = __aeabi_d2iz;
47 pL2f = __aeabi_l2f;
48 pL2d = __aeabi_l2d;
49 pFadd = __aeabi_fadd;
50 pFsub = __aeabi_fsub;
51 pFdiv = __aeabi_fdiv;
52 pFmul = __aeabi_fmul;
53 pFmodf = fmodf;
54 pDadd = __aeabi_dadd;
55 pDsub = __aeabi_dsub;
56 pDdiv = __aeabi_ddiv;
57 pDmul = __aeabi_dmul;
58 pFmod = fmod;
59 pArtF2l = artF2L;
60 pArtD2l = artD2L;
61 pLdivmod = __aeabi_ldivmod;
buzbee439c4fa2011-08-27 15:59:07 -070062 pLmul = __aeabi_lmul;
buzbee54330722011-08-23 16:46:55 -070063#endif
buzbeedfd3d702011-08-28 12:56:51 -070064 pAllocFromCode = Array::AllocFromCode;
Brian Carlstrom1f870082011-08-23 16:02:11 -070065 pAllocObjectFromCode = Class::AllocObjectFromCode;
buzbee3ea4ec52011-08-22 17:37:19 -070066 pMemcpy = memcpy;
buzbeee6d61962011-08-27 11:58:19 -070067 pArtHandleFillArrayDataNoThrow = artHandleFillArrayDataNoThrow;
buzbeee1931742011-08-28 21:15:53 -070068 pGet32Static = Field::Get32StaticFromCode;
69 pSet32Static = Field::Set32StaticFromCode;
70 pGet64Static = Field::Get64StaticFromCode;
71 pSet64Static = Field::Set64StaticFromCode;
72 pGetObjStatic = Field::GetObjStaticFromCode;
73 pSetObjStatic = Field::SetObjStaticFromCode;
Elliott Hughesbf86d042011-08-31 17:53:14 -070074 pArtCanPutArrayElementNoThrow = Class::CanPutArrayElementNoThrow;
buzbee3ea4ec52011-08-22 17:37:19 -070075#if 0
Elliott Hughesbf86d042011-08-31 17:53:14 -070076bool (Thread::*pArtUnlockObject)(Thread*, Object*);
77int (Thread::*pArtInstanceofNonTrivialNoThrow)(const Class*, const Class*);
78int (Thread::*pArtInstanceofNonTrivial) (const Class*, const Class*);
79Method* (Thread::*pArtFindInterfaceMethodInCache)(Class*, uint32_t, const Method*, DvmDex*);
80bool (Thread::*pArtUnlockObjectNoThrow)(Thread*, Object*);
81void (Thread::*pArtLockObjectNoThrow)(Thread*, Object*);
82Object* (Thread::*pArtAllocObjectNoThrow)(Class*, int);
83void (Thread::*pArtThrowException)(Thread*, Object*);
84bool (Thread::*pArtHandleFillArrayDataNoThrow)(Array*, const uint16_t*);
buzbee3ea4ec52011-08-22 17:37:19 -070085#endif
86}
87
Carl Shapirob5573532011-07-12 18:22:59 -070088Mutex* Mutex::Create(const char* name) {
89 Mutex* mu = new Mutex(name);
90 int result = pthread_mutex_init(&mu->lock_impl_, NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070091 CHECK_EQ(0, result);
Carl Shapirob5573532011-07-12 18:22:59 -070092 return mu;
93}
94
95void Mutex::Lock() {
96 int result = pthread_mutex_lock(&lock_impl_);
97 CHECK_EQ(result, 0);
98 SetOwner(Thread::Current());
99}
100
101bool Mutex::TryLock() {
102 int result = pthread_mutex_lock(&lock_impl_);
103 if (result == EBUSY) {
104 return false;
105 } else {
106 CHECK_EQ(result, 0);
107 SetOwner(Thread::Current());
108 return true;
109 }
110}
111
112void Mutex::Unlock() {
113 CHECK(GetOwner() == Thread::Current());
114 int result = pthread_mutex_unlock(&lock_impl_);
115 CHECK_EQ(result, 0);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700116 SetOwner(NULL);
Carl Shapirob5573532011-07-12 18:22:59 -0700117}
118
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700119void Frame::Next() {
120 byte* next_sp = reinterpret_cast<byte*>(sp_) +
Shih-wei Liaod11af152011-08-23 16:02:11 -0700121 GetMethod()->GetFrameSizeInBytes();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700122 sp_ = reinterpret_cast<const Method**>(next_sp);
123}
124
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700125uintptr_t Frame::GetPC() const {
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700126 byte* pc_addr = reinterpret_cast<byte*>(sp_) +
Shih-wei Liaod11af152011-08-23 16:02:11 -0700127 GetMethod()->GetReturnPcOffsetInBytes();
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700128 return *reinterpret_cast<uintptr_t*>(pc_addr);
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700129}
130
131const Method* Frame::NextMethod() const {
132 byte* next_sp = reinterpret_cast<byte*>(sp_) +
Shih-wei Liaod11af152011-08-23 16:02:11 -0700133 GetMethod()->GetFrameSizeInBytes();
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700134 return *reinterpret_cast<const Method**>(next_sp);
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700135}
136
Carl Shapiro61e019d2011-07-14 16:53:09 -0700137void* ThreadStart(void *arg) {
Elliott Hughes53b61312011-08-12 18:28:20 -0700138 UNIMPLEMENTED(FATAL);
Carl Shapirob5573532011-07-12 18:22:59 -0700139 return NULL;
140}
141
Brian Carlstromb765be02011-08-17 23:54:10 -0700142Thread* Thread::Create(const Runtime* runtime) {
143 size_t stack_size = runtime->GetStackSize();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700144
145 Thread* new_thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -0700146 new_thread->InitCpu();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700147
148 pthread_attr_t attr;
Elliott Hughese27955c2011-08-26 15:21:24 -0700149 errno = pthread_attr_init(&attr);
150 if (errno != 0) {
151 PLOG(FATAL) << "pthread_attr_init failed";
152 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700153
Elliott Hughese27955c2011-08-26 15:21:24 -0700154 errno = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
155 if (errno != 0) {
156 PLOG(FATAL) << "pthread_attr_setdetachstate(PTHREAD_CREATE_DETACHED) failed";
157 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700158
Elliott Hughese27955c2011-08-26 15:21:24 -0700159 errno = pthread_attr_setstacksize(&attr, stack_size);
160 if (errno != 0) {
161 PLOG(FATAL) << "pthread_attr_setstacksize(" << stack_size << ") failed";
162 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700163
Elliott Hughese27955c2011-08-26 15:21:24 -0700164 errno = pthread_create(&new_thread->handle_, &attr, ThreadStart, new_thread);
165 if (errno != 0) {
166 PLOG(FATAL) << "pthread_create failed";
167 }
168
169 errno = pthread_attr_destroy(&attr);
170 if (errno != 0) {
171 PLOG(FATAL) << "pthread_attr_destroy failed";
172 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700173
174 return new_thread;
175}
176
Elliott Hughes515a5bc2011-08-17 11:08:34 -0700177Thread* Thread::Attach(const Runtime* runtime) {
Carl Shapiro61e019d2011-07-14 16:53:09 -0700178 Thread* thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -0700179 thread->InitCpu();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700180
181 thread->handle_ = pthread_self();
182
183 thread->state_ = kRunnable;
184
Elliott Hughesa5780da2011-07-17 11:39:39 -0700185 errno = pthread_setspecific(Thread::pthread_key_self_, thread);
186 if (errno != 0) {
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700187 PLOG(FATAL) << "pthread_setspecific failed";
Elliott Hughesa5780da2011-07-17 11:39:39 -0700188 }
189
Elliott Hughes75770752011-08-24 17:52:38 -0700190 thread->jni_env_ = new JNIEnvExt(thread, runtime->GetJavaVM());
Elliott Hughes330304d2011-08-12 14:28:05 -0700191
Carl Shapiro61e019d2011-07-14 16:53:09 -0700192 return thread;
193}
194
Elliott Hughese27955c2011-08-26 15:21:24 -0700195pid_t Thread::GetTid() const {
196 return gettid();
197}
198
Carl Shapirob5573532011-07-12 18:22:59 -0700199static void ThreadExitCheck(void* arg) {
200 LG << "Thread exit check";
201}
202
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700203bool Thread::Startup() {
Carl Shapirob5573532011-07-12 18:22:59 -0700204 // Allocate a TLS slot.
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700205 errno = pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck);
206 if (errno != 0) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700207 PLOG(WARNING) << "pthread_key_create failed";
Carl Shapirob5573532011-07-12 18:22:59 -0700208 return false;
209 }
210
211 // Double-check the TLS slot allocation.
212 if (pthread_getspecific(pthread_key_self_) != NULL) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700213 LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
Carl Shapirob5573532011-07-12 18:22:59 -0700214 return false;
215 }
216
217 // TODO: initialize other locks and condition variables
218
219 return true;
220}
221
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700222void Thread::Shutdown() {
223 errno = pthread_key_delete(Thread::pthread_key_self_);
224 if (errno != 0) {
225 PLOG(WARNING) << "pthread_key_delete failed";
226 }
227}
228
229Thread::~Thread() {
230 delete jni_env_;
231}
232
Ian Rogers408f79a2011-08-23 18:22:33 -0700233size_t Thread::NumSirtReferences() {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700234 size_t count = 0;
Ian Rogers408f79a2011-08-23 18:22:33 -0700235 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700236 count += cur->NumberOfReferences();
237 }
238 return count;
239}
240
Ian Rogers408f79a2011-08-23 18:22:33 -0700241bool Thread::SirtContains(jobject obj) {
242 Object** sirt_entry = reinterpret_cast<Object**>(obj);
243 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700244 size_t num_refs = cur->NumberOfReferences();
Ian Rogers408f79a2011-08-23 18:22:33 -0700245 // A SIRT should always have a jobject/jclass as a native method is passed
246 // in a this pointer or a class
247 DCHECK_GT(num_refs, 0u);
Shih-wei Liao2f0ce9d2011-09-01 02:07:58 -0700248 if ((&cur->References()[0] <= sirt_entry) &&
249 (sirt_entry <= (&cur->References()[num_refs - 1]))) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700250 return true;
251 }
252 }
253 return false;
254}
255
Ian Rogers408f79a2011-08-23 18:22:33 -0700256Object* Thread::DecodeJObject(jobject obj) {
257 // TODO: Only allowed to hold Object* when in the runnable state
258 // DCHECK(state_ == kRunnable);
259 if (obj == NULL) {
260 return NULL;
261 }
262 IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
263 IndirectRefKind kind = GetIndirectRefKind(ref);
264 Object* result;
265 switch (kind) {
266 case kLocal:
267 {
Elliott Hughes69f5bc62011-08-24 09:26:14 -0700268 IndirectReferenceTable& locals = jni_env_->locals;
Ian Rogers408f79a2011-08-23 18:22:33 -0700269 result = locals.Get(ref);
270 break;
271 }
272 case kGlobal:
273 {
274 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
275 IndirectReferenceTable& globals = vm->globals;
276 MutexLock mu(vm->globals_lock);
277 result = globals.Get(ref);
278 break;
279 }
280 case kWeakGlobal:
281 {
282 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
283 IndirectReferenceTable& weak_globals = vm->weak_globals;
284 MutexLock mu(vm->weak_globals_lock);
285 result = weak_globals.Get(ref);
286 if (result == kClearedJniWeakGlobal) {
287 // This is a special case where it's okay to return NULL.
288 return NULL;
289 }
290 break;
291 }
292 case kSirtOrInvalid:
293 default:
294 // TODO: make stack indirect reference table lookup more efficient
295 // Check if this is a local reference in the SIRT
296 if (SirtContains(obj)) {
297 result = *reinterpret_cast<Object**>(obj); // Read from SIRT
Elliott Hughesc5bfa8f2011-08-30 14:32:49 -0700298 } else if (jni_env_->work_around_app_jni_bugs) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700299 // Assume an invalid local reference is actually a direct pointer.
300 result = reinterpret_cast<Object*>(obj);
301 } else {
Elliott Hughesa2501992011-08-26 19:39:54 -0700302 result = kInvalidIndirectRefObject;
Ian Rogers408f79a2011-08-23 18:22:33 -0700303 }
304 }
305
306 if (result == NULL) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700307 LOG(ERROR) << "JNI ERROR (app bug): use of deleted " << kind << ": " << obj;
308 JniAbort(NULL);
309 } else {
310 if (result != kInvalidIndirectRefObject) {
311 Heap::VerifyObject(result);
312 }
Ian Rogers408f79a2011-08-23 18:22:33 -0700313 }
Ian Rogers408f79a2011-08-23 18:22:33 -0700314 return result;
315}
316
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700317class CountStackDepthVisitor : public Thread::StackVisitor {
318 public:
319 CountStackDepthVisitor() : depth(0) {}
320 virtual bool VisitFrame(const Frame&) {
321 ++depth;
322 return true;
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700323 }
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700324
325 int GetDepth() const {
326 return depth;
327 }
328
329 private:
330 uint32_t depth;
331};
332
333class BuildStackTraceVisitor : public Thread::StackVisitor {
334 public:
335 BuildStackTraceVisitor(int depth) : count(0) {
336 method_trace = Runtime::Current()->GetClassLinker()->AllocObjectArray<const Method>(depth);
337 pc_trace = IntArray::Alloc(depth);
338 }
339
340 virtual ~BuildStackTraceVisitor() {}
341
342 virtual bool VisitFrame(const Frame& frame) {
343 method_trace->Set(count, frame.GetMethod());
344 pc_trace->Set(count, frame.GetPC());
345 ++count;
346 return true;
347 }
348
349 const Method* GetMethod(uint32_t i) {
350 DCHECK(i < count);
351 return method_trace->Get(i);
352 }
353
354 uintptr_t GetPC(uint32_t i) {
355 DCHECK(i < count);
356 return pc_trace->Get(i);
357 }
358
359 private:
360 uint32_t count;
361 ObjectArray<const Method>* method_trace;
362 IntArray* pc_trace;
363};
364
365void Thread::WalkStack(StackVisitor* visitor) {
366 Frame frame = Thread::Current()->GetTopOfStack();
367 // TODO: enable this CHECK after native_to_managed_record_ is initialized during startup.
368 // CHECK(native_to_managed_record_ != NULL);
369 NativeToManagedRecord* record = native_to_managed_record_;
370
371 while (frame.GetSP()) {
372 for ( ; frame.GetMethod() != 0; frame.Next()) {
373 visitor->VisitFrame(frame);
374 }
375 if (record == NULL) {
376 break;
377 }
378 frame.SetSP(reinterpret_cast<const art::Method**>(record->last_top_of_managed_stack)); // last_tos should return Frame instead of sp?
379 record = record->link;
380 }
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700381}
382
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700383ObjectArray<StackTraceElement>* Thread::AllocStackTrace() {
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700384 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Shih-wei Liao44175362011-08-28 16:59:17 -0700385
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700386 CountStackDepthVisitor count_visitor;
387 WalkStack(&count_visitor);
388 int32_t depth = count_visitor.GetDepth();
Shih-wei Liao44175362011-08-28 16:59:17 -0700389
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700390 BuildStackTraceVisitor build_trace_visitor(depth);
391 WalkStack(&build_trace_visitor);
Shih-wei Liao44175362011-08-28 16:59:17 -0700392
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700393 ObjectArray<StackTraceElement>* java_traces = class_linker->AllocStackTraceElementArray(depth);
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700394
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700395 for (int32_t i = 0; i < depth; ++i) {
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700396 // Prepare parameter for StackTraceElement(String cls, String method, String file, int line)
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700397 const Method* method = build_trace_visitor.GetMethod(i);
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700398 const Class* klass = method->GetDeclaringClass();
399 const DexFile& dex_file = class_linker->FindDexFile(klass->GetDexCache());
Shih-wei Liao44175362011-08-28 16:59:17 -0700400 String* readable_descriptor = String::AllocFromModifiedUtf8(
401 PrettyDescriptor(klass->GetDescriptor()).c_str()
402 );
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700403
404 StackTraceElement* obj =
405 StackTraceElement::Alloc(readable_descriptor,
Shih-wei Liao44175362011-08-28 16:59:17 -0700406 method->GetName(),
407 String::AllocFromModifiedUtf8(klass->source_file_),
408 dex_file.GetLineNumFromPC(method,
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700409 method->ToDexPC(build_trace_visitor.GetPC(i))));
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700410 java_traces->Set(i, obj);
411 }
412 return java_traces;
413}
414
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700415void Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) {
Elliott Hughes37f7a402011-08-22 18:56:01 -0700416 std::string msg;
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700417 va_list args;
418 va_start(args, fmt);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700419 StringAppendV(&msg, fmt, args);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700420 va_end(args);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700421
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700422 // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception".
423 CHECK(exception_class_descriptor[0] == 'L');
424 std::string descriptor(exception_class_descriptor + 1);
425 CHECK(descriptor[descriptor.length() - 1] == ';');
426 descriptor.erase(descriptor.length() - 1);
427
428 JNIEnv* env = GetJniEnv();
429 jclass exception_class = env->FindClass(descriptor.c_str());
430 CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\"";
431 int rc = env->ThrowNew(exception_class, msg.c_str());
432 CHECK_EQ(rc, JNI_OK);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700433}
434
Elliott Hughes79082e32011-08-25 12:07:32 -0700435void Thread::ThrowOutOfMemoryError() {
436 UNIMPLEMENTED(FATAL);
437}
438
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700439Frame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) {
440 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
441 DCHECK(class_linker != NULL);
442
443 Frame cur_frame = GetTopOfStack();
444 for (int unwind_depth = 0; ; unwind_depth++) {
445 const Method* cur_method = cur_frame.GetMethod();
446 DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache();
447 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
448
449 void* handler_addr = FindExceptionHandlerInMethod(cur_method,
450 throw_pc,
451 dex_file,
452 class_linker);
453 if (handler_addr) {
454 *handler_pc = handler_addr;
455 return cur_frame;
456 } else {
457 // Check if we are at the last frame
458 if (cur_frame.HasNext()) {
459 cur_frame.Next();
460 } else {
461 // Either at the top of stack or next frame is native.
462 break;
463 }
464 }
465 }
466 *handler_pc = NULL;
467 return Frame();
468}
469
470void* Thread::FindExceptionHandlerInMethod(const Method* method,
471 void* throw_pc,
472 const DexFile& dex_file,
473 ClassLinker* class_linker) {
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700474 Throwable* exception_obj = exception_;
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700475 exception_ = NULL;
476
477 intptr_t dex_pc = -1;
478 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_);
479 DexFile::CatchHandlerIterator iter;
480 for (iter = dex_file.dexFindCatchHandler(*code_item,
481 method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc)));
482 !iter.HasNext();
483 iter.Next()) {
484 Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_));
485 DCHECK(klass != NULL);
486 if (exception_obj->InstanceOf(klass)) {
487 dex_pc = iter.Get().address_;
488 break;
489 }
490 }
491
492 exception_ = exception_obj;
493 if (iter.HasNext()) {
494 return NULL;
495 } else {
496 return reinterpret_cast<void*>( method->ToNativePC(dex_pc) );
497 }
498}
499
Ian Rogersb033c752011-07-20 12:22:35 -0700500static const char* kStateNames[] = {
501 "New",
502 "Runnable",
503 "Blocked",
504 "Waiting",
505 "TimedWaiting",
506 "Native",
507 "Terminated",
508};
509std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
510 if (state >= Thread::kNew && state <= Thread::kTerminated) {
511 os << kStateNames[state-Thread::kNew];
512 } else {
513 os << "State[" << static_cast<int>(state) << "]";
514 }
515 return os;
516}
517
Elliott Hughes330304d2011-08-12 14:28:05 -0700518std::ostream& operator<<(std::ostream& os, const Thread& thread) {
519 os << "Thread[" << &thread
Elliott Hughese27955c2011-08-26 15:21:24 -0700520 << ",pthread_t=" << thread.GetImpl()
521 << ",tid=" << thread.GetTid()
522 << ",id=" << thread.GetId()
523 << ",state=" << thread.GetState() << "]";
Elliott Hughes330304d2011-08-12 14:28:05 -0700524 return os;
525}
526
Carl Shapiro61e019d2011-07-14 16:53:09 -0700527ThreadList* ThreadList::Create() {
528 return new ThreadList;
529}
530
Carl Shapirob5573532011-07-12 18:22:59 -0700531ThreadList::ThreadList() {
532 lock_ = Mutex::Create("ThreadList::Lock");
533}
534
535ThreadList::~ThreadList() {
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700536 if (Contains(Thread::Current())) {
537 Runtime::Current()->DetachCurrentThread();
538 }
539
540 // All threads should have exited and unregistered when we
Carl Shapirob5573532011-07-12 18:22:59 -0700541 // reach this point. This means that all daemon threads had been
542 // shutdown cleanly.
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700543 // TODO: dump ThreadList if non-empty.
544 CHECK_EQ(list_.size(), 0U);
545
Carl Shapirob5573532011-07-12 18:22:59 -0700546 delete lock_;
547 lock_ = NULL;
548}
549
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700550bool ThreadList::Contains(Thread* thread) {
551 return find(list_.begin(), list_.end(), thread) != list_.end();
552}
553
Carl Shapirob5573532011-07-12 18:22:59 -0700554void ThreadList::Register(Thread* thread) {
555 MutexLock mu(lock_);
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700556 CHECK(!Contains(thread));
Carl Shapirob5573532011-07-12 18:22:59 -0700557 list_.push_front(thread);
558}
559
560void ThreadList::Unregister(Thread* thread) {
561 MutexLock mu(lock_);
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700562 CHECK(Contains(thread));
Carl Shapirob5573532011-07-12 18:22:59 -0700563 list_.remove(thread);
564}
565
Carl Shapirob5573532011-07-12 18:22:59 -0700566} // namespace