Initial implementation of throw+unwind+Frame.

Unit tests on Exception Handling pass.

Change-Id: I33505dacc6648e72e2ed80c2cca83643cfaef86b
diff --git a/src/thread.h b/src/thread.h
index 6677f7c..b6fad0f 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -113,6 +113,40 @@
   void* last_top_of_managed_stack;
 };
 
+// Iterator over managed frames up to the first native-to-managed transition
+class Frame {
+  Frame() : sp_(NULL) {}
+
+  const Method* GetMethod() const {
+    return *sp_;
+  }
+
+  bool HasNext() const {
+    return NextMethod() != NULL;
+  }
+
+  void Next();
+
+  void* GetPC() const;
+
+  const Method** GetSP() const {
+    return sp_;
+  }
+
+  // TODO: this is here for testing, remove when we have exception unit tests
+  // that use the real stack
+  void SetSP(const Method** sp) {
+    sp_ = sp;
+  }
+
+ private:
+  const Method* NextMethod() const;
+
+  friend class Thread;
+
+  const Method** sp_;
+};
+
 class Thread {
  public:
   enum State {
@@ -202,6 +236,16 @@
   }
 
   // TODO: Throwable*
+  Frame GetTopOfStack() const {
+    return top_of_managed_stack_;
+  }
+
+  // TODO: this is here for testing, remove when we have exception unit tests
+  // that use the real stack
+  void SetTopOfStack(void* stack) {
+    top_of_managed_stack_.SetSP(reinterpret_cast<const Method**>(stack));
+  }
+
   void SetException(Object* new_exception) {
     CHECK(new_exception != NULL);
     // TODO: CHECK(exception_ == NULL);
@@ -217,6 +261,13 @@
     exception_ = NULL;
   }
 
+  Frame FindExceptionHandler(void* throw_pc, void** handler_pc);
+
+  void* FindExceptionHandlerInMethod(const Method* method,
+                                     void* throw_pc,
+                                     const DexFile& dex_file,
+                                     ClassLinker* class_linker);
+
   // Offset of exception within Thread, used by generated code
   static ThreadOffset ExceptionOffset() {
     return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_));
@@ -242,10 +293,6 @@
 
   static bool Init();
 
-  Runtime* GetRuntime() const {
-    return runtime_;
-  }
-
   State GetState() const {
     return state_;
   }
@@ -275,7 +322,8 @@
 
   // Offset of top of managed stack address, used by generated code
   static ThreadOffset TopOfManagedStackOffset() {
-    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_));
+    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_) +
+                        OFFSETOF_MEMBER(Frame, sp_));
   }
 
   // Offset of top stack handle block within Thread, used by generated code
@@ -313,14 +361,14 @@
 
   // Linked list recording transitions from native to managed code
   void PushNativeToManagedRecord(NativeToManagedRecord* record) {
-    record->last_top_of_managed_stack = top_of_managed_stack_;
+    record->last_top_of_managed_stack = reinterpret_cast<void*>(top_of_managed_stack_.GetSP());
     record->link = native_to_managed_record_;
     native_to_managed_record_ = record;
-    top_of_managed_stack_ = NULL;
+    top_of_managed_stack_.SetSP(NULL);
   }
   void PopNativeToManagedRecord(const NativeToManagedRecord& record) {
     native_to_managed_record_ = record.link;
-    top_of_managed_stack_ = record.last_top_of_managed_stack;
+    top_of_managed_stack_.SetSP( reinterpret_cast<const Method**>(record.last_top_of_managed_stack) );
   }
 
   ClassLoader* GetClassLoaderOverride() {
@@ -334,7 +382,7 @@
  private:
   Thread()
       : id_(1234),
-        top_of_managed_stack_(NULL),
+        top_of_managed_stack_(),
         native_to_managed_record_(NULL),
         top_shb_(NULL),
         jni_env_(NULL),
@@ -358,7 +406,7 @@
   // Top of the managed stack, written out prior to the state transition from
   // kRunnable to kNative. Uses include to give the starting point for scanning
   // a managed stack when a thread is in native code.
-  void* top_of_managed_stack_;
+  Frame top_of_managed_stack_;
 
   // A linked list (of stack allocated records) recording transitions from
   // native to managed code.