x86 JNI compiler and unit tests.

Change-Id: I4c2e10328961a2e8e27c90777fe2a93737b21143
diff --git a/src/thread.h b/src/thread.h
index a862e0a..ab0bacc 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -4,19 +4,23 @@
 #ifndef ART_SRC_THREAD_H_
 #define ART_SRC_THREAD_H_
 
-#include <list>
 #include <pthread.h>
+#include <list>
 
 #include "src/globals.h"
+#include "src/heap.h"
 #include "src/logging.h"
 #include "src/macros.h"
 #include "src/runtime.h"
 
+#include "jni.h"
+
 namespace art {
 
 class Heap;
 class Object;
 class Runtime;
+class StackHandleBlock;
 class Thread;
 class ThreadList;
 
@@ -62,6 +66,39 @@
   DISALLOW_COPY_AND_ASSIGN(MutexLock);
 };
 
+// Stack handle blocks are allocated within the bridge frame between managed
+// and native code.
+class StackHandleBlock {
+ public:
+  // Number of references contained within this SHB
+  size_t NumberOfReferences() {
+    return number_of_references_;
+  }
+
+  // Link to previous SHB or NULL
+  StackHandleBlock* Link() {
+    return link_;
+  }
+
+  // Offset of length within SHB, used by generated code
+  static size_t NumberOfReferencesOffset() {
+    return OFFSETOF_MEMBER(StackHandleBlock, number_of_references_);
+  }
+
+  // Offset of link within SHB, used by generated code
+  static size_t LinkOffset() {
+    return OFFSETOF_MEMBER(StackHandleBlock, link_);
+  }
+
+ private:
+  StackHandleBlock() {}
+
+  size_t number_of_references_;
+  StackHandleBlock* link_;
+
+  DISALLOW_COPY_AND_ASSIGN(StackHandleBlock);
+};
+
 class Thread {
  public:
   enum State {
@@ -71,6 +108,7 @@
     kBlocked,
     kWaiting,
     kTimedWaiting,
+    kNative,
     kTerminated,
   };
 
@@ -131,10 +169,63 @@
     state_ = new_state;
   }
 
+  // Offset of state within Thread, used by generated code
+  static ThreadOffset StateOffset() {
+    return ThreadOffset(OFFSETOF_MEMBER(Thread, state_));
+  }
+
+  Heap* GetHeap() {
+    return heap_;
+  }
+
+  // JNI methods
+  JNIEnv* GetJniEnv() const {
+    return jni_env_;
+  }
+
+  // Offset of JNI environment within Thread, used by generated code
+  static ThreadOffset JniEnvOffset() {
+    return ThreadOffset(OFFSETOF_MEMBER(Thread, jni_env_));
+  }
+
+  // Offset of top stack handle block within Thread, used by generated code
+  static ThreadOffset TopShbOffset() {
+    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_shb_));
+  }
+
+  // Number of references allocated in StackHandleBlocks on this thread
+  size_t NumShbHandles() {
+    size_t count = 0;
+    for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
+      count += cur->NumberOfReferences();
+    }
+    return count;
+  }
+
  private:
-  Thread() : id_(1234), exception_(NULL) {}
+  Thread() :
+    thread_id_(1234), top_shb_(NULL),
+    jni_env_(reinterpret_cast<JNIEnv*>(0xEBADC0DE)), exception_(NULL) {
+  }
   ~Thread() {}
 
+  void InitCpu();
+
+  // Initialized to "this". On certain architectures (such as x86) reading
+  // off of Thread::Current is easy but getting the address of Thread::Current
+  // is hard. This field can be read off of Thread::Current to give the address.
+  Thread* self_;
+
+  uint32_t thread_id_;
+
+  Heap* heap_;
+
+  // Top of linked list of stack handle blocks or NULL for none
+  StackHandleBlock* top_shb_;
+
+  // Every thread may have an associated JNI environment
+  JNIEnv* jni_env_;
+
   State state_;
 
   uint32_t id_;
@@ -152,6 +243,7 @@
 
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
+std::ostream& operator<<(std::ostream& os, const Thread::State& state);
 
 class ThreadList {
  public: