Implement Throwable::nativeFillInStackTrace and nativeGetStackTrace.

Refactor stack trace into compact internal form which is then used to
compute larger and more verbose StackTraceElement[] form. Fix some
potential problems with GC.

Change-Id: I4a4308c1ec5b82fd95b649d5ec0504b9607e688f
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index 216350b..880503f 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -14,6 +14,7 @@
 #include "jni_internal.h"
 #include "mem_map.h"
 #include "runtime.h"
+#include "scoped_jni_thread_state.h"
 #include "thread.h"
 
 namespace art {
@@ -413,12 +414,14 @@
 
 int gSuspendCounterHandler_calls;
 void SuspendCountHandler(Method** frame) {
+  // Check we came here in the native state then transition to runnable to work
+  // on the Object*
   EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
-  Thread::Current()->SetState(Thread::kRunnable);
+  ScopedJniThreadState ts(Thread::Current()->GetJniEnv());
+
   EXPECT_TRUE((*frame)->GetName()->Equals("fooI"));
   gSuspendCounterHandler_calls++;
   Thread::Current()->DecrementSuspendCount();
-  Thread::Current()->SetState(Thread::kNative);
 }
 
 TEST_F(JniCompilerTest, SuspendCountAcknowledgement) {
@@ -444,12 +447,14 @@
 
 int gExceptionHandler_calls;
 void ExceptionHandler(Method** frame) {
+  // Check we came here in the native state then transition to runnable to work
+  // on the Object*
   EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
-  Thread::Current()->SetState(Thread::kRunnable);
+  ScopedJniThreadState ts(Thread::Current()->GetJniEnv());
+
   EXPECT_TRUE((*frame)->GetName()->Equals("throwException"));
   gExceptionHandler_calls++;
   Thread::Current()->ClearException();
-  Thread::Current()->SetState(Thread::kNative);
 }
 
 void Java_MyClass_throwException(JNIEnv* env, jobject) {
@@ -480,19 +485,28 @@
 
 jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
   if (i <= 0) {
-    EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
-    Thread::Current()->SetState(Thread::kRunnable);
-    ObjectArray<StackTraceElement>* trace_array = Thread::Current()->AllocStackTrace();
+    // We want to check raw Object*/Array* below
+    ScopedJniThreadState ts(env);
+
+    // Build stack trace
+    jobject internal = Thread::Current()->CreateInternalStackTrace();
+    jobjectArray ste_array =
+        Thread::InternalStackTraceToStackTraceElementArray(internal, env);
+    ObjectArray<StackTraceElement>* trace_array =
+        Decode<ObjectArray<StackTraceElement>*>(env, ste_array);
     EXPECT_TRUE(trace_array != NULL);
     EXPECT_EQ(11, trace_array->GetLength());
 
+    // Check stack trace entries have expected values
     for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
       EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
-      EXPECT_STREQ("MyClassNatives.java", trace_array->Get(i)->GetFileName()->ToModifiedUtf8().c_str());
-      EXPECT_STREQ("MyClass", trace_array->Get(i)->GetDeclaringClass()->ToModifiedUtf8().c_str());
-      EXPECT_STREQ("fooI", trace_array->Get(i)->GetMethodName()->ToModifiedUtf8().c_str());
+      StackTraceElement* ste = trace_array->Get(i);
+      EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
+      EXPECT_STREQ("MyClass", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
+      EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
     }
-    Thread::Current()->SetState(Thread::kNative);
+
+    // end recursion
     return 0;
   } else {
     jclass jklass = env->FindClass("MyClass");
@@ -500,7 +514,10 @@
     jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
     EXPECT_TRUE(jmethod != NULL);
 
+    // Recurse with i - 1
     jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
+
+    // Return sum of all depths
     return i + result;
   }
 }
@@ -508,7 +525,7 @@
 TEST_F(JniCompilerTest, NativeStackTraceElement) {
   SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
   jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
-  EXPECT_EQ(55, result);
+  EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
 }
 
 jobject Java_MyClass_fooO(JNIEnv* env, jobject thisObj, jobject x) {