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.