thread.h revision dcc247493fd8fb243e335c3ec08e5e625896a47c
10e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro// Copyright 2011 Google Inc. All Rights Reserved.
20e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
30e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#ifndef ART_SRC_THREAD_H_
40e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#define ART_SRC_THREAD_H_
50e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
6b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <pthread.h>
7a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
8a09576416788b916095739e43a16917e7948f3a4Elliott Hughes#include <iosfwd>
9b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <list>
10b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
111f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "dex_file.h"
12578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "globals.h"
1369f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes#include "jni_internal.h"
14578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "logging.h"
15578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "macros.h"
16b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom#include "mem_map.h"
17578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "offsets.h"
18b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
190e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapironamespace art {
200e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
2169f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughesclass Array;
2237f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughesclass Class;
231f87008b165d26541d832ff805250afdc89c253dBrian Carlstromclass ClassLinker;
24edcc09c737b00462881f147602656739d029571eElliott Hughesclass ClassLoader;
25a40f9bc48afe3a9d38be2fa298fece13ed82ba28Brian Carlstromclass Method;
260e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Object;
27b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass Runtime;
280e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread;
29b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList;
30e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughesclass Throwable;
3155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liaoclass StackTraceElement;
321da522de18ac6e4c2913c3233529e9dd115059f8buzbeeclass StaticStorageBase;
331da522de18ac6e4c2913c3233529e9dd115059f8buzbee
3455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liaotemplate<class T> class ObjectArray;
354417536522fd2a9d8215d8672331984769c9520bShih-wei Liaotemplate<class T> class PrimitiveArray;
364417536522fd2a9d8215d8672331984769c9520bShih-wei Liaotypedef PrimitiveArray<int32_t> IntArray;
370e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Mutex {
390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
400e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  virtual ~Mutex() {}
410e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
42b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock();
430e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
44b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool TryLock();
450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
46b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock();
470e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
480e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  const char* GetName() { return name_; }
490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
500e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Thread* GetOwner() { return owner_; }
510e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
52b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static Mutex* Create(const char* name);
53b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
5479082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  // TODO: only needed because we lack a condition variable abstraction.
5579082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  pthread_mutex_t* GetImpl() { return &lock_impl_; }
560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
570e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
5818c0753c1659629021b4becdaa3f6ea81aecce35Elliott Hughes  explicit Mutex(const char* name) : name_(name), owner_(NULL) {}
5918c0753c1659629021b4becdaa3f6ea81aecce35Elliott Hughes
6079082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  void SetOwner(Thread* thread) { owner_ = thread; }
6179082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes
620e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  const char* name_;
630e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
640e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Thread* owner_;
650e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
66b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pthread_mutex_t lock_impl_;
67b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
680e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Mutex);
690e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
700e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
710e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass MutexLock {
720e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
730e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  explicit MutexLock(Mutex *mu) : mu_(mu) {
740e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    mu_->Lock();
750e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
760e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  ~MutexLock() { mu_->Unlock(); }
770e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
780e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Mutex* const mu_;
790e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(MutexLock);
800e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
810e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
82408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers// Stack allocated indirect reference table, allocated within the bridge frame
83408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers// between managed and native code.
84408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogersclass StackIndirectReferenceTable {
85b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public:
86408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Number of references contained within this SIRT
87b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t NumberOfReferences() {
88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return number_of_references_;
89b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
90b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
91408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Link to previous SIRT or NULL
92408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  StackIndirectReferenceTable* Link() {
93b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return link_;
94b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
95b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
96408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  Object** References() {
97408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    return references_;
98a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  }
99a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
100408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Offset of length within SIRT, used by generated code
101b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t NumberOfReferencesOffset() {
102408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    return OFFSETOF_MEMBER(StackIndirectReferenceTable, number_of_references_);
103b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
104b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
105408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Offset of link within SIRT, used by generated code
106b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t LinkOffset() {
107408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    return OFFSETOF_MEMBER(StackIndirectReferenceTable, link_);
108b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
109b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
110b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private:
111408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  StackIndirectReferenceTable() {}
112b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
113b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t number_of_references_;
114408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  StackIndirectReferenceTable* link_;
115b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
116a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  // Fake array, really allocated and filled in by jni_compiler.
117408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  Object* references_[0];
118a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
119408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  DISALLOW_COPY_AND_ASSIGN(StackIndirectReferenceTable);
120b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
121b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1226de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogersstruct NativeToManagedRecord {
1236de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  NativeToManagedRecord* link;
1246de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  void* last_top_of_managed_stack;
1256de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers};
1266de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers
1271a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao// Iterator over managed frames up to the first native-to-managed transition
1281a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaoclass Frame {
1299b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao public:
1301a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  Frame() : sp_(NULL) {}
1311a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1320cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Method* GetMethod() const {
133a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    return (sp_ != NULL) ? *sp_ : NULL;
1341a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
1351a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1361a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  bool HasNext() const {
1371a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return NextMethod() != NULL;
1381a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
1391a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1401a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  void Next();
1411a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
14255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  uintptr_t GetPC() const;
1431a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1440cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Method** GetSP() const {
1451a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return sp_;
1461a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
1471a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1481a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  // TODO: this is here for testing, remove when we have exception unit tests
1491a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  // that use the real stack
1500cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  void SetSP(Method** sp) {
1511a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    sp_ = sp;
1521a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
1531a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1541a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao private:
1550cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Method* NextMethod() const;
1561a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1571a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  friend class Thread;
1581a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1590cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Method** sp_;
1601a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao};
1611a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1620e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread {
1630e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
164b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  enum State {
165b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kUnknown = -1,
166b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kNew,
167b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kRunnable,
168b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kBlocked,
169b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kWaiting,
170b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTimedWaiting,
171b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    kNative,
172b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTerminated,
173b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
174b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
175c143c55718342519db5398e41dda31422cf16c79buzbee
17661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const size_t kDefaultStackSize = 64 * KB;
17761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
178c143c55718342519db5398e41dda31422cf16c79buzbee  // Runtime support function pointers
1794a3164faefd255b1c1e911e7ad7c3d57749caaf6buzbee  void (*pDebugMe)(Method*, uint32_t);
180c143c55718342519db5398e41dda31422cf16c79buzbee  void* (*pMemcpy)(void*, const void*, size_t);
1815433072f589b61413e042eddf76e8190a048f71dbuzbee  uint64_t (*pShlLong)(uint64_t, uint32_t);
1825433072f589b61413e042eddf76e8190a048f71dbuzbee  uint64_t (*pShrLong)(uint64_t, uint32_t);
1835433072f589b61413e042eddf76e8190a048f71dbuzbee  uint64_t (*pUshrLong)(uint64_t, uint32_t);
184c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pI2f)(int);
185c143c55718342519db5398e41dda31422cf16c79buzbee  int (*pF2iz)(float);
186c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pD2f)(double);
187c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pF2d)(float);
188c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pI2d)(int);
189c143c55718342519db5398e41dda31422cf16c79buzbee  int (*pD2iz)(double);
190c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pL2f)(long);
191c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pL2d)(long);
1921b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  long long (*pF2l)(float);
1931b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  long long (*pD2l)(double);
194c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFadd)(float, float);
195c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFsub)(float, float);
196c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFdiv)(float, float);
197c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFmul)(float, float);
198c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFmodf)(float, float);
199c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pDadd)(double, double);
200c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pDsub)(double, double);
201c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pDdiv)(double, double);
202c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pDmul)(double, double);
203c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pFmod)(double, double);
204c143c55718342519db5398e41dda31422cf16c79buzbee  int (*pIdivmod)(int, int);
205c143c55718342519db5398e41dda31422cf16c79buzbee  int (*pIdiv)(int, int);
206439c4fa0db980fb19e4a585723a64a3461e4c278buzbee  long long (*pLmul)(long long, long long);
207c143c55718342519db5398e41dda31422cf16c79buzbee  long long (*pLdivmod)(long long, long long);
208dfd3d70e58c37b5d56eded3a4469082d8bb26ee0buzbee  Array* (*pAllocFromCode)(uint32_t, Method*, int32_t);
2091da522de18ac6e4c2913c3233529e9dd115059f8buzbee  Array* (*pCheckAndAllocFromCode)(uint32_t, Method*, int32_t);
2101f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom  Object* (*pAllocObjectFromCode)(uint32_t, Method*);
211e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  uint32_t (*pGet32Static)(uint32_t, const Method*);
212e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  void (*pSet32Static)(uint32_t, const Method*, uint32_t);
213e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  uint64_t (*pGet64Static)(uint32_t, const Method*);
214e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  void (*pSet64Static)(uint32_t, const Method*, uint64_t);
215e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  Object* (*pGetObjStatic)(uint32_t, const Method*);
216e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  void (*pSetObjStatic)(uint32_t, const Method*, Object*);
2170f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes  void (*pCanPutArrayElementFromCode)(const Class*, const Class*);
2181b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  int (*pInstanceofNonTrivialFromCode) (const Class*, const Class*);
2191b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  Method* (*pFindInterfaceMethodInCache)(Class*, uint32_t, const Method*, struct DvmDex*);
2201b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  bool (*pUnlockObjectFromCode)(Thread*, Object*);
2211b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  void (*pLockObjectFromCode)(Thread*, Object*);
2221b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  void (*pThrowException)(Thread*, Throwable*);
2231b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  void (*pHandleFillArrayDataFromCode)(Array*, const uint16_t*);
2241b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  Class* (*pInitializeTypeFromCode)(uint32_t, Method*);
225561227c80077bbb4147f778043f1a836af6b9248buzbee  void (*pResolveMethodFromCode)(Method*, uint32_t);
2264a3164faefd255b1c1e911e7ad7c3d57749caaf6buzbee  void (*pInvokeInterfaceTrampoline)(void*, void*, void*, void*);
2271da522de18ac6e4c2913c3233529e9dd115059f8buzbee  StaticStorageBase* (*pInitializeStaticStorage)(uint32_t, const Method*);
228c143c55718342519db5398e41dda31422cf16c79buzbee
2299b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao  class StackVisitor {
2309b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao   public:
2310cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    virtual ~StackVisitor() {}
2329b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao    virtual bool VisitFrame(const Frame& frame) = 0;
2339b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao  };
2349b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao
23561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread.
236b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom  static Thread* Create(const Runtime* runtime);
23761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
23861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread from the calling thread.
239dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  static Thread* Attach(const Runtime* runtime, const char* name, bool as_daemon);
240b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
241b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static Thread* Current() {
242d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    void* thread = pthread_getspecific(Thread::pthread_key_self_);
243d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    return reinterpret_cast<Thread*>(thread);
2440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
2450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
246a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  void Dump(std::ostream& os) const;
247a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
2480cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  State GetState() const {
2490cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    return state_;
2500cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2510cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
2520cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  State SetState(State new_state) {
2530cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    State old_state = state_;
2540cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    state_ = new_state;
2550cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    return old_state;
2560cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2570cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
2580cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  bool CanAccessDirectReferences() const {
259a59d1793b89d0fd62c7544c94da4b6e5dac95ad5Elliott Hughes    // TODO: when we have a moving collector, we'll need: return state_ == kRunnable;
260a59d1793b89d0fd62c7544c94da4b6e5dac95ad5Elliott Hughes    return true;
2610cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2620cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
263dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  uint32_t GetThinLockId() const {
264dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    return thin_lock_id_;
265b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
266b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
267d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  pid_t GetTid() const {
268d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes    return tid_;
269d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  }
270e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes
271e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  pthread_t GetImpl() const {
272e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes    return handle_;
2730e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
2740e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
2750cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  // Returns the Method* for the current method.
2760cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  // This is used by the JNI implementation for logging and diagnostic purposes.
2770cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  const Method* GetCurrentMethod() const {
2780cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    return top_of_managed_stack_.GetMethod();
2790cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2800cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
2810e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  bool IsExceptionPending() const {
282b20a554613609dc372073d2ebd9fbc3925a429f5Elliott Hughes    return exception_ != NULL;
2830e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
2840e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
285e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  Throwable* GetException() const {
2860cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    DCHECK(CanAccessDirectReferences());
2870e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    return exception_;
2880e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
2890e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
2900cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  void SetException(Throwable* new_exception) {
2910cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    DCHECK(CanAccessDirectReferences());
2920cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    CHECK(new_exception != NULL);
2930cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    // TODO: CHECK(exception_ == NULL);
2940cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    exception_ = new_exception;  // TODO
2950cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2960cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
2970cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  void ClearException() {
2980cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    exception_ = NULL;
299a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  }
300a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
3011a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  Frame GetTopOfStack() const {
3021a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return top_of_managed_stack_;
3031a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
3041a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
3051a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  // TODO: this is here for testing, remove when we have exception unit tests
3061a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  // that use the real stack
3071a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  void SetTopOfStack(void* stack) {
3080cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    top_of_managed_stack_.SetSP(reinterpret_cast<Method**>(stack));
3090e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
3100e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
311e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  void ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...)
312a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes      __attribute__ ((format(printf, 3, 4)));
313a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes
31479082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  // This exception is special, because we need to pre-allocate an instance.
31579082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  void ThrowOutOfMemoryError();
31679082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes
3171a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  Frame FindExceptionHandler(void* throw_pc, void** handler_pc);
3181a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
3191a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  void* FindExceptionHandlerInMethod(const Method* method,
3201a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                     void* throw_pc,
3211a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                     const DexFile& dex_file,
3221a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                     ClassLinker* class_linker);
323668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao  static ThreadOffset SelfOffset() {
324668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao    return ThreadOffset(OFFSETOF_MEMBER(Thread, self_));
325668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao  }
3261a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
327dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  // Offset of exception_ within Thread, used by generated code
32845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionOffset() {
32945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_));
33045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
33145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
332dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  // Offset of thin_lock_id_ within Thread, used by generated code
333c143c55718342519db5398e41dda31422cf16c79buzbee  static ThreadOffset IdOffset() {
334dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes    return ThreadOffset(OFFSETOF_MEMBER(Thread, thin_lock_id_));
335c143c55718342519db5398e41dda31422cf16c79buzbee  }
336c143c55718342519db5398e41dda31422cf16c79buzbee
337c143c55718342519db5398e41dda31422cf16c79buzbee  // Offset of card_table within Thread, used by generated code
338c143c55718342519db5398e41dda31422cf16c79buzbee  static ThreadOffset CardTableOffset() {
339c143c55718342519db5398e41dda31422cf16c79buzbee    return ThreadOffset(OFFSETOF_MEMBER(Thread, card_table_));
340c143c55718342519db5398e41dda31422cf16c79buzbee  }
341c143c55718342519db5398e41dda31422cf16c79buzbee
342b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetName(const char* name);
343b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
344b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Suspend();
345b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
346b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool IsSuspended();
347b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
348b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Resume();
349b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
350c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  static bool Startup();
351c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  static void Shutdown();
352b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
35345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountOffset() {
35445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_));
35545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
35645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
357b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of state within Thread, used by generated code
358b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset StateOffset() {
359b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, state_));
360b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
361b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
362b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // JNI methods
36369f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes  JNIEnvExt* GetJniEnv() const {
364b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return jni_env_;
365b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
366b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
367b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of JNI environment within Thread, used by generated code
368b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset JniEnvOffset() {
369b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, jni_env_));
370b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
371b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
37245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of top of managed stack address, used by generated code
37345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset TopOfManagedStackOffset() {
3741a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_) +
3751a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                        OFFSETOF_MEMBER(Frame, sp_));
37645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
37745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
378408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Offset of top stack indirect reference table within Thread, used by
379408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // generated code
380408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  static ThreadOffset TopSirtOffset() {
381408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_sirt_));
382b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
383b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
384408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Number of references allocated in SIRTs on this thread
385408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  size_t NumSirtReferences();
386a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
387408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Is the given obj in this thread's stack indirect reference table?
388408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  bool SirtContains(jobject obj);
389408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers
390408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Convert a jobject into a Object*
391408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  Object* DecodeJObject(jobject obj);
392b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
39345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of exception_entry_point_ within Thread, used by generated code
39445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionEntryPointOffset() {
39545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_entry_point_));
39645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
39745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
39845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterExceptionEntryPoint(void (*handler)(Method**)) {
39945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    exception_entry_point_ = handler;
40045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
40145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
40245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of suspend_count_entry_point_ within Thread, used by generated code
40345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountEntryPointOffset() {
40445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_entry_point_));
40545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
40645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
40745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterSuspendCountEntryPoint(void (*handler)(Method**)) {
40845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    suspend_count_entry_point_ = handler;
40945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
41045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
41145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Increasing the suspend count, will cause the thread to run to safepoint
41245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void IncrementSuspendCount() { suspend_count_++; }
41345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void DecrementSuspendCount() { suspend_count_--; }
41445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
4156de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  // Linked list recording transitions from native to managed code
4166de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  void PushNativeToManagedRecord(NativeToManagedRecord* record) {
4171a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    record->last_top_of_managed_stack = reinterpret_cast<void*>(top_of_managed_stack_.GetSP());
4186de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    record->link = native_to_managed_record_;
4196de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    native_to_managed_record_ = record;
4201a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    top_of_managed_stack_.SetSP(NULL);
4216de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  }
4226de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  void PopNativeToManagedRecord(const NativeToManagedRecord& record) {
4236de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    native_to_managed_record_ = record.link;
4240cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    top_of_managed_stack_.SetSP(reinterpret_cast<Method**>(record.last_top_of_managed_stack));
4256de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  }
4266de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers
427bffb15585b8fd43d3ca534ddbb85e7f591595951Brian Carlstrom  const ClassLoader* GetClassLoaderOverride() {
4280cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    // TODO: need to place the class_loader_override_ in a handle
4290cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    // DCHECK(CanAccessDirectReferences());
430c143c55718342519db5398e41dda31422cf16c79buzbee    return class_loader_override_;
431c143c55718342519db5398e41dda31422cf16c79buzbee  }
432c143c55718342519db5398e41dda31422cf16c79buzbee
433bffb15585b8fd43d3ca534ddbb85e7f591595951Brian Carlstrom  void SetClassLoaderOverride(const ClassLoader* class_loader_override) {
434c143c55718342519db5398e41dda31422cf16c79buzbee    class_loader_override_ = class_loader_override;
435c143c55718342519db5398e41dda31422cf16c79buzbee  }
436c143c55718342519db5398e41dda31422cf16c79buzbee
4374417536522fd2a9d8215d8672331984769c9520bShih-wei Liao  // Allocate stack trace
4389b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao  ObjectArray<StackTraceElement>* AllocStackTrace();
43955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao
440410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  void VisitRoots(Heap::RootVisitor* visitor, void* arg) const;
441410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
4420e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
443dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  Thread();
444c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  ~Thread();
4450cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  friend class Runtime;  // For ~Thread.
4460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
447d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  void DumpState(std::ostream& os) const;
448d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  void DumpStack(std::ostream& os) const;
449d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
450b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void InitCpu();
4513ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee  void InitFunctionPointers();
452b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
4539b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao  void WalkStack(StackVisitor* visitor);
4544417536522fd2a9d8215d8672331984769c9520bShih-wei Liao
455dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  // Thin lock thread id. This is a small integer used by the thin lock implementation.
456dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  // This is not to be confused with the native thread's tid, nor is it the value returned
457dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  // by java.lang.Thread.getId --- this is a distinct value, used only for locking. One
458dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  // important difference between this id and the ids visible to managed code is that these
459dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  // ones get reused (to ensure that they fit in the number of bits available).
460dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  uint32_t thin_lock_id_;
461b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
462d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  // System thread id.
463d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  pid_t tid_;
464d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
465d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  // Native thread handle.
466d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  pthread_t handle_;
467d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
468dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  bool is_daemon_;
469dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
470dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  // Our managed peer (an instance of java.lang.Thread).
471dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes  Object* peer_;
472dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes
473c143c55718342519db5398e41dda31422cf16c79buzbee  // FIXME: placeholder for the gc cardTable
474c143c55718342519db5398e41dda31422cf16c79buzbee  uint32_t card_table_;
475c143c55718342519db5398e41dda31422cf16c79buzbee
47645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Top of the managed stack, written out prior to the state transition from
47745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // kRunnable to kNative. Uses include to give the starting point for scanning
47845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // a managed stack when a thread is in native code.
4791a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  Frame top_of_managed_stack_;
48045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
4816de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  // A linked list (of stack allocated records) recording transitions from
4826de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  // native to managed code.
4836de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  NativeToManagedRecord* native_to_managed_record_;
4846de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers
485408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Top of linked list of stack indirect reference tables or NULL for none
486408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  StackIndirectReferenceTable* top_sirt_;
487b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
488b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Every thread may have an associated JNI environment
48969f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes  JNIEnvExt* jni_env_;
490b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
491b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  State state_;
492b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
49369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Initialized to "this". On certain architectures (such as x86) reading
49469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // off of Thread::Current is easy but getting the address of Thread::Current
49569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // is hard. This field can be read off of Thread::Current to give the address.
49669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Thread* self_;
49769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
49869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* runtime_;
49969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
50069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The pending exception or NULL.
501e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  Throwable* exception_;
5020e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
50345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // A non-zero value is used to tell the current thread to enter a safe point
50445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // at the next poll.
50545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  int suspend_count_;
50645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
507edcc09c737b00462881f147602656739d029571eElliott Hughes  // Needed to get the right ClassLoader in JNI_OnLoad, but also
508edcc09c737b00462881f147602656739d029571eElliott Hughes  // useful for testing.
509bffb15585b8fd43d3ca534ddbb85e7f591595951Brian Carlstrom  const ClassLoader* class_loader_override_;
510c143c55718342519db5398e41dda31422cf16c79buzbee
51169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // TLS key used to retrieve the VM thread object.
512b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static pthread_key_t pthread_key_self_;
513b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
51445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when exception_ is set
51545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*exception_entry_point_)(Method** frame);
51645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
51745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when suspend_count_ is non-zero
51845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*suspend_count_entry_point_)(Method** frame);
51945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
5200e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Thread);
5210e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
522330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread);
523b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state);
5240e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
525b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList {
526b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
52761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMaxId = 0xFFFF;
52861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kInvalidId = 0;
52961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMainId = 1;
53061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
53161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static ThreadList* Create();
532b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
53361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  ~ThreadList();
534b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
535d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  void Dump(std::ostream& os);
536d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
537b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Register(Thread* thread);
538b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
539b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unregister(Thread* thread);
540b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
541c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  bool Contains(Thread* thread);
542c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
543b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock() {
544b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Lock();
545b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
546b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
547b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock() {
548b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Unlock();
549b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
550b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
551410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  void VisitRoots(Heap::RootVisitor* visitor, void* arg) const;
552410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
553b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
554b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList();
555b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
556b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  std::list<Thread*> list_;
557b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
558b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  Mutex* lock_;
559b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
560b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadList);
561b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
562b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
563b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadListLock {
564b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
565b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadListLock(ThreadList* thread_list, Thread* current_thread)
566b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      : thread_list_(thread_list) {
567b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread == NULL) {  // try to get it from TLS
568b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread = Thread::Current();
569b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
570b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    Thread::State old_state;
571b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
572ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes      old_state = current_thread->SetState(Thread::kWaiting);  // TODO: VMWAIT
573b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    } else {
574b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      // happens during VM shutdown
575b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = Thread::kUnknown;  // TODO: something else
576b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
577b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Lock();
578b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
579b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(old_state);
580b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
581b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
582b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
583b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ~ThreadListLock() {
584b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Unlock();
585b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
586b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
587b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
588b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList* thread_list_;
589b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
590b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadListLock);
591b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
592b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
593ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughesclass ScopedThreadStateChange {
594ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes public:
595ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  ScopedThreadStateChange(Thread* thread, Thread::State new_state) : thread_(thread) {
596ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes    old_thread_state_ = thread_->SetState(new_state);
597ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  }
598ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
599ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  ~ScopedThreadStateChange() {
600ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes    thread_->SetState(old_thread_state_);
601ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  }
602ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
603ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes private:
604ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  Thread* thread_;
605ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  Thread::State old_thread_state_;
606ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
607ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes};
608ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
6090e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}  // namespace art
6100e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
6110e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#endif  // ART_SRC_THREAD_H_
612