[ecj] Improved VMStackWalker.getCallingClass()

Gary Benson gbenson@redhat.com
Thu Dec 7 12:40:00 GMT 2006


Hi all,

This commit makes VMStackWalker.getCallingClass() unwind only
as much of the stack as it needs in the cases when it has to.

Cheers,
Gary
-------------- next part --------------
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 119614)
+++ ChangeLog	(working copy)
@@ -1,3 +1,14 @@
+2006-12-07  Gary Benson  <gbenson@redhat.com>
+
+	* include/java-stack.h (stackwalker_trace_fn,
+	GetStackWalkerCallingClass): Declare.
+	* stacktrace.cc (stackwalker_trace_fn,
+	GetStackWalkerCallingClass): New methods.
+	* gnu/classpath/natVMStackWalker.cc
+	(getCallingClass): Use the above.
+	* gnu/classpath/VMStackWalker.java
+	(getCallingClass): Replace with native method.
+
 2006-12-06  Tom Tromey  <tromey@redhat.com>
 
 	PR java/24938:
Index: include/java-stack.h
===================================================================
--- include/java-stack.h	(revision 119614)
+++ include/java-stack.h	(working copy)
@@ -133,6 +133,7 @@
   static _Unwind_Reason_Code calling_class_trace_fn (_Jv_UnwindState *state);
   static _Unwind_Reason_Code non_system_trace_fn (_Jv_UnwindState *state);
   static _Unwind_Reason_Code accesscontrol_trace_fn (_Jv_UnwindState *state);
+  static _Unwind_Reason_Code stackwalker_trace_fn (_Jv_UnwindState *state);
 
 public:
   static _Jv_StackTrace *GetStackTrace (void);
@@ -144,6 +145,7 @@
   static ClassLoader *GetFirstNonSystemClassLoader (void);
   static jobjectArray GetAccessControlStack ();
   static JArray<jclass> *GetStackWalkerStack ();
+  static jclass GetStackWalkerCallingClass ();
 
   friend jclass _Jv_GetMethodDeclaringClass (jmethodID);
   friend class gnu::classpath::VMStackWalker;
Index: stacktrace.cc
===================================================================
--- stacktrace.cc	(revision 119614)
+++ stacktrace.cc	(working copy)
@@ -678,3 +678,78 @@
  
   return result;
 }
+
+typedef enum
+  {
+    VMSW_GETCLASSCONTEXT,
+    JLRM_INVOKE_OR_CALLER,
+    CALLER,
+    CALLER_OF_CALLER
+  } gswcc_expect;
+
+struct StackWalkerTraceData
+{
+  gswcc_expect expect;
+  jclass result;
+};
+
+_Unwind_Reason_Code
+_Jv_StackTrace::stackwalker_trace_fn (_Jv_UnwindState *state)
+{
+  StackWalkerTraceData *trace_data = (StackWalkerTraceData *)
+    state->trace_data;
+  _Jv_StackFrame *frame = &state->frames[state->pos];
+  FillInFrameInfo (frame);
+
+  if (!(frame->klass && frame->meth))
+    return _URC_NO_REASON;
+
+  switch (trace_data->expect)
+    {
+    case VMSW_GETCLASSCONTEXT:
+      JvAssert (
+	frame->klass == &::gnu::classpath::VMStackWalker::class$
+	&& strcmp (frame->meth->name->chars(), "getClassContext") == 0);
+      trace_data->expect = JLRM_INVOKE_OR_CALLER;
+      break;
+
+    case JLRM_INVOKE_OR_CALLER:
+      if (frame->klass == &::java::lang::reflect::Method::class$
+	  && strcmp (frame->meth->name->chars(), "invoke") == 0)
+	trace_data->expect = CALLER;
+      else
+	trace_data->expect = CALLER_OF_CALLER;
+      break;
+
+    case CALLER:
+      trace_data->expect = CALLER_OF_CALLER;
+      break;
+
+    case CALLER_OF_CALLER:
+      trace_data->result = frame->klass;
+      return _URC_NORMAL_STOP;
+    }
+
+  return _URC_NO_REASON;
+}
+
+jclass
+_Jv_StackTrace::GetStackWalkerCallingClass (void)
+{
+  int trace_size = 100;
+  _Jv_StackFrame frames[trace_size];
+  _Jv_UnwindState state (trace_size);
+  state.frames = (_Jv_StackFrame *) &frames;
+
+  StackWalkerTraceData trace_data;
+  trace_data.expect = VMSW_GETCLASSCONTEXT;
+  trace_data.result = NULL;
+  
+  state.trace_function = stackwalker_trace_fn;
+  state.trace_data = (void *) &trace_data;
+
+  UpdateNCodeMap();
+  _Unwind_Backtrace (UnwindTraceFn, &state);
+
+  return trace_data.result;
+}
Index: gnu/classpath/natVMStackWalker.cc
===================================================================
--- gnu/classpath/natVMStackWalker.cc	(revision 119614)
+++ gnu/classpath/natVMStackWalker.cc	(working copy)
@@ -25,6 +25,12 @@
 }
 
 jclass
+gnu::classpath::VMStackWalker::getCallingClass(void)
+{
+  return _Jv_StackTrace::GetStackWalkerCallingClass ();
+}
+
+jclass
 gnu::classpath::VMStackWalker::getCallingClass(::gnu::gcj::RawData *pc)
 {
   void *f = _Unwind_FindEnclosingFunction (pc);
@@ -43,11 +49,7 @@
   // is an interpreted frame then klass will be null and we need to
   // unwind the stack.
   if (klass == NULL)
-    {
-      JArray<jclass> *ctx = getClassContext ();
-      if (ctx->length >= 3)
-	klass = elements(ctx)[2];
-    }
+    klass = _Jv_StackTrace::GetStackWalkerCallingClass ();
 
   return klass;
 }
Index: gnu/classpath/VMStackWalker.java
===================================================================
--- gnu/classpath/VMStackWalker.java	(revision 119614)
+++ gnu/classpath/VMStackWalker.java	(working copy)
@@ -85,13 +85,7 @@
    * method. <code>getCallingClass(addr)</code> does not unwind the
    * stack, so is therefore more efficient.
    */
-  public static Class getCallingClass()
-  {
-    Class[] ctx = getClassContext();
-    if (ctx.length < 3)
-      return null;
-    return ctx[2];
-  }
+  public static native Class getCallingClass();
 
   /**
    * Get the class associated with the method invoking the method


More information about the Java-patches mailing list