am d83d4c86: Merge "Fix stack trace for proxy methods and added test case."

* commit 'd83d4c86c89357a74e94963994ad0c42ea7299c3':
  Fix stack trace for proxy methods and added test case.
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 1add507..d816ca1 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1281,7 +1281,7 @@
       return true;  // Ignore runtime frames (in particular callee save).
     }
     method_trace_->Set(count_, m);
-    dex_pc_trace_->Set(count_, GetDexPc());
+    dex_pc_trace_->Set(count_, m->IsProxyMethod() ? DexFile::kDexNoIndex : GetDexPc());
     ++count_;
     return true;
   }
@@ -1363,19 +1363,31 @@
     // Prepare parameters for StackTraceElement(String cls, String method, String file, int line)
     mirror::ArtMethod* method = down_cast<mirror::ArtMethod*>(method_trace->Get(i));
     MethodHelper mh(method);
-    mirror::IntArray* pc_trace = down_cast<mirror::IntArray*>(method_trace->Get(depth));
-    uint32_t dex_pc = pc_trace->Get(i);
-    int32_t line_number = mh.GetLineNumFromDexPC(dex_pc);
-    // Allocate element, potentially triggering GC
-    // TODO: reuse class_name_object via Class::name_?
-    const char* descriptor = mh.GetDeclaringClassDescriptor();
-    CHECK(descriptor != NULL);
-    std::string class_name(PrettyDescriptor(descriptor));
-    SirtRef<mirror::String> class_name_object(soa.Self(),
-                                              mirror::String::AllocFromModifiedUtf8(soa.Self(),
-                                                                                    class_name.c_str()));
-    if (class_name_object.get() == NULL) {
-      return NULL;
+    int32_t line_number;
+    SirtRef<mirror::String> class_name_object(soa.Self(), NULL);
+    SirtRef<mirror::String> source_name_object(soa.Self(), NULL);
+    if (method->IsProxyMethod()) {
+      line_number = -1;
+      class_name_object.reset(method->GetDeclaringClass()->GetName());
+      // source_name_object intentionally left null for proxy methods
+    } else {
+      mirror::IntArray* pc_trace = down_cast<mirror::IntArray*>(method_trace->Get(depth));
+      uint32_t dex_pc = pc_trace->Get(i);
+      line_number = mh.GetLineNumFromDexPC(dex_pc);
+      // Allocate element, potentially triggering GC
+      // TODO: reuse class_name_object via Class::name_?
+      const char* descriptor = mh.GetDeclaringClassDescriptor();
+      CHECK(descriptor != NULL);
+      std::string class_name(PrettyDescriptor(descriptor));
+      class_name_object.reset(mirror::String::AllocFromModifiedUtf8(soa.Self(), class_name.c_str()));
+      if (class_name_object.get() == NULL) {
+        return NULL;
+      }
+      const char* source_file = mh.GetDeclaringClassSourceFile();
+      source_name_object.reset(mirror::String::AllocFromModifiedUtf8(soa.Self(), source_file));
+      if (source_name_object.get() == NULL) {
+        return NULL;
+      }
     }
     const char* method_name = mh.GetName();
     CHECK(method_name != NULL);
@@ -1385,10 +1397,6 @@
     if (method_name_object.get() == NULL) {
       return NULL;
     }
-    const char* source_file = mh.GetDeclaringClassSourceFile();
-    SirtRef<mirror::String> source_name_object(soa.Self(),
-                                               mirror::String::AllocFromModifiedUtf8(soa.Self(),
-                                                                                     source_file));
     mirror::StackTraceElement* obj = mirror::StackTraceElement::Alloc(
         soa.Self(), class_name_object, method_name_object, source_name_object, line_number);
     if (obj == NULL) {
diff --git a/test/044-proxy/expected.txt b/test/044-proxy/expected.txt
index 13e3a28..12df250 100644
--- a/test/044-proxy/expected.txt
+++ b/test/044-proxy/expected.txt
@@ -42,6 +42,7 @@
  (no args)
 --- blob
 Success: method blob res=mix
+$Proxy1.getTrace null:-1
 Invoke public abstract void Shapes.upChuck()
  (no args)
 Got expected ioobe
@@ -49,8 +50,8 @@
  (no args)
 Got expected ie
 
-Proxy interfaces: [interface Quads, interface Colors]
-Proxy methods: [public final java.lang.String $Proxy1.blob(), public final double $Proxy1.blue(int), public final R0a $Proxy1.checkMe(), public final R0aa $Proxy1.checkMe(), public final R0base $Proxy1.checkMe(), public final void $Proxy1.circle(int), public final boolean $Proxy1.equals(java.lang.Object), public final int $Proxy1.green(double), public final int $Proxy1.hashCode(), public final int $Proxy1.mauve(java.lang.String), public final int $Proxy1.rectangle(int,int), public final int $Proxy1.red(float), public final int $Proxy1.square(int,int), public final java.lang.String $Proxy1.toString(), public final int $Proxy1.trapezoid(int,double,int), public final void $Proxy1.upCheck() throws java.lang.InterruptedException, public final void $Proxy1.upChuck()]
+Proxy interfaces: [interface Quads, interface Colors, interface Trace]
+Proxy methods: [public final java.lang.String $Proxy1.blob(), public final double $Proxy1.blue(int), public final R0a $Proxy1.checkMe(), public final R0aa $Proxy1.checkMe(), public final R0base $Proxy1.checkMe(), public final void $Proxy1.circle(int), public final boolean $Proxy1.equals(java.lang.Object), public final void $Proxy1.getTrace(), public final int $Proxy1.green(double), public final int $Proxy1.hashCode(), public final int $Proxy1.mauve(java.lang.String), public final int $Proxy1.rectangle(int,int), public final int $Proxy1.red(float), public final int $Proxy1.square(int,int), public final java.lang.String $Proxy1.toString(), public final int $Proxy1.trapezoid(int,double,int), public final void $Proxy1.upCheck() throws java.lang.InterruptedException, public final void $Proxy1.upChuck()]
 Decl annos: []
 Param annos (0) : []
 Dupe threw expected exception
diff --git a/test/044-proxy/src/BasicTest.java b/test/044-proxy/src/BasicTest.java
index 46aa3fe..ea46f49 100644
--- a/test/044-proxy/src/BasicTest.java
+++ b/test/044-proxy/src/BasicTest.java
@@ -51,6 +51,8 @@
         colors.blue(777);
         colors.mauve("sorry");
         colors.blob();
+        Trace trace = (Trace) proxy;
+        trace.getTrace();
 
         try {
             shapes.upChuck();
@@ -96,7 +98,7 @@
 
         /* create the proxy class */
         Class proxyClass = Proxy.getProxyClass(Shapes.class.getClassLoader(),
-                            new Class[] { Quads.class, Colors.class });
+                            new Class[] { Quads.class, Colors.class, Trace.class });
 
         /* create a proxy object, passing the handler object in */
         Object proxy = null;
@@ -156,6 +158,10 @@
     public R0aa checkMe();
 }
 
+interface Trace {
+    public void getTrace();
+}
+
 /*
  * Some return types.
  */
@@ -248,6 +254,20 @@
                 throw new RuntimeException("huh?");
         }
 
+        if (method.getDeclaringClass() == Trace.class) {
+          if (method.getName().equals("getTrace")) {
+            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+            for (int i = 0; i < stackTrace.length; i++) {
+                StackTraceElement ste = stackTrace[i];
+                if (ste.getMethodName().equals("getTrace")) {
+                  System.out.println(ste.getClassName() + "." + ste.getMethodName() + " " +
+                                     ste.getFileName() + ":" + ste.getLineNumber());
+                }
+            }
+            return null;
+          }
+        }
+
         System.out.println("Invoke " + method);
         if (args == null || args.length == 0) {
             System.out.println(" (no args)");