Re: Question about a comment in _Jv_StackTrace::UnwindTraceFn

Andrew Haley <[email protected]>
Newsgroups gmane.comp.gcc.java.devel
Message-ID <[email protected]>
Dave Korn wrote:
>     Hi java team,
> 
>   It suggests to me here that there should be an entry on the interpreter
> stack corresponding to every entry though the interpreter's main function on
> the CPU's native stack:
> 
> 122       // If we see the interpreter's main function, "pop" an entry off the
> 123       // interpreter stack and use that instead, so that the trace goes
> through
> 124       // the java code and not the interpreter itself. This assumes a 1:1
> 125       // correspondance between call frames in the interpreted stack and
> occurances
> 126       // of _Jv_InterpMethod::run() on the native stack.
> 
>   I wonder if this assumption is still correct?  Or maybe it's a side-effect
> of having configured with --enable-libgcj-debug?
> 
> 127     #ifdef INTERPRETER
> 128       void *interp_run = NULL;
> 129
> 130       if (::gnu::classpath::jdwp::Jdwp::isDebugging)
> (gdb)
> 131             interp_run = (void *) &_Jv_InterpMethod::run_debug;
> 132       else
> 133         interp_run = (void *) &_Jv_InterpMethod::run;
> 134
> 135       if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
> 136         {
> 137           state->frames[pos].type = frame_interpreter;
> 138           _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame);
> 139           state->frames[pos].interp.meth
> 140             = static_cast<_Jv_InterpMethod *> (frame->self);
> 
> ... because I'm getting a NULL pointer here.  I saw that
> gnu::classpath::jdwp::Jdwp::isDebugging is zero, so we're looking for the
> plain run method, not run_debug.
> 
> (gdb) print ((_Jv_UnwindState *) state_ptr)[0]
> $6 = {length = 100, pos = 23, frames = 0x22bba0, interp_frame = 0x0,
>   trace_function = 0, trace_data = 0x0}
> (gdb)
> 
>   There's no interp_frame entries.  Looking at the stack trace:
> 
> (gdb) bt
> #0  _Jv_StackTrace::UnwindTraceFn (context=0x22bafc, state_ptr=0x22c388)
>     at /gnu/gcc/gcc-patched/libjava/stacktrace.cc:140
> #1  0x67f0660d in _Unwind_Backtrace (
>     trace=0x5f0940 <_Jv_StackTrace::UnwindTraceFn(_Unwind_Context*, void*)>,
>     trace_argument=0x22c388)
>     at /usr/src/gcc/gcc4-4.3.2-2/src/gcc-4.3.2/libgcc/../gcc/unwind.inc:302
> #2  0x005f0d2f in _Jv_StackTrace::GetStackTrace ()
>     at /gnu/gcc/gcc-patched/libjava/stacktrace.cc:192
> #3  0x005c5354 in java::lang::VMThrowable::fillInStackTrace ()
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natVMThrowable.cc:33
> #4  0x00406400 in java.lang.Throwable.fillInStackTrace()java.lang.Throwable (
>     this=0x29e8468)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Throwable.java:500
> #5  0x0041c84d in java.lang.Throwable.Throwable(java.lang.String) (
>     this=0x29e8468, message=0x29ef5b0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Throwable.java:161
> #6  0x0041faf7 in java.lang.Exception.Exception(java.lang.String) (
>     this=0x29e8468, s=0x29ef5b0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Exception.java:78
> #7  0x005468d7 in java.io.IOException.IOException(java.lang.String) (
>     this=0x29e8468, message=0x29ef5b0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/io/IOException.java:72
> #8  0x0073c154 in gnu::gcj::Core::create (name=0x29e8498)
>     at /gnu/gcc/gcc-patched/libjava/gnu/gcj/natCore.cc:118
> #9  0x005f1f05 in gnu.java.net.protocol.core.Connection.connect()void (
>     this=0x29ef5e8)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:5
> 0
> #10 0x005f208f in gnu.java.net.protocol.core.Connection.getHeaders()void (
>     this=0x29ef5e8)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:1
> 54
> #11 0x005f22c5 in gnu.java.net.protocol.core.Connection.getHeaderField(java.lang
> .String)java.lang.String (this=0x29ef5e8, name=0x28f8070)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:6
> 9
> #12 0x0051cdae in java.net.URLConnection.getHeaderFieldInt(java.lang.String, int
> )int (this=0x29ef5e8, name=0x28f8070, defaultValue=-1)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLConnection.java:426
> #13 0x0051b8a3 in java.net.URLConnection.getContentLength()int (
>     this=0x29ef5e8)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLConnection.java:302
> #14 0x0071db1b in gnu.java.net.loader.RemoteURLLoader.getResource(java.lang.Stri
> ng)gnu.java.net.loader.Resource (this=0x29d1dc0, name=0x29e84c8)
>     at /gnu/gcc/gcc-patched/libjava/classpath/gnu/java/net/loader/RemoteURLLoade
> r.java:79
> #15 0x00532d7c in java.net.URLClassLoader.findClass(java.lang.String)java.lang.C
> lass (this=0x29ab370, className=0x29f8ec0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLClassLoader.java:528
> #16 0x004311cc in gnu.gcj.runtime.BootClassLoader.bootLoadClass(java.lang.String
> )java.lang.Class (this=0x29ab370, name=0x29f8ec0)
>     at /gnu/gcc/gcc-patched/libjava/gnu/gcj/runtime/BootClassLoader.java:68
> #17 0x005c7ff5 in java::lang::VMClassLoader::loadClass (name=0x29f8ec0,
>     resolve=0 '\0')
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natVMClassLoader.cc:223
> #18 0x0042022b in java.lang.ClassLoader.loadClass(java.lang.String, boolean)java
> .lang.Class (this=0x29120f0, name=0x29f8ec0, resolve=false)
> ---Type <return> to continue, or q <return> to quit---
>     at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:439
> #19 0x0042020d in java.lang.ClassLoader.loadClass(java.lang.String, boolean)java
> .lang.Class (this=0x2912050, name=0x29f8ec0, resolve=false)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:445
> #20 0x00407701 in java.lang.ClassLoader.loadClass(java.lang.String)java.lang.Cla
> ss (this=0x2912050, name=0x29f8ec0)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:387
> #21 0x004496a2 in _Jv_FindClass (name=0x29e7930, loader=0x2912050)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natClassLoader.cc:512
> #22 0x00449737 in _Jv_FindClassNoException (name=0x29e7930, loader=0x2912050)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natClassLoader.cc:476
> #23 0x0043e86b in _Jv_Linker::resolve_pool_entry (klass=0x294d4c0, index=97,
>     lazy=false) at /gnu/gcc/gcc-patched/libjava/link.cc:440
> #24 0x0044e695 in _Jv_InterpMethod::run (retp=0x22cb40, args=0x22cb60,
>     meth=0x292e870) at /gnu/gcc/gcc-patched/libjava/interpret-run.cc:2385
> #25 0x00780c45 in ffi_closure_raw_SYSV ()
>     at /gnu/gcc/gcc-patched/libffi/src/x86/win32.S:338
> #26 0x0044836c in java::lang::Class::initializeClass (this=0x294d4c0)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natClass.cc:780
> #27 0x00451d3b in _Jv_InterpMethod::run_class (ret=0x22cbc0, args=0x22cbe0,
>     __this=0x2918c00) at /gnu/gcc/gcc-patched/libjava/java/lang/Class.h:742
> #28 0x00780c45 in ffi_closure_raw_SYSV ()
>     at /gnu/gcc/gcc-patched/libffi/src/x86/win32.S:338
> #29 0x0061c684 in gnu::java::lang::MainThread::call_main (this=0x29af540)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/lang/natMainThread.cc:54
> #30 0x0043946a in gnu.java.lang.MainThread.run()void (this=0x29af540)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/lang/MainThread.java:106
> #31 0x004687b4 in _Jv_ThreadRun (thread=0x29af540)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natThread.cc:335
> #32 0x00404b7d in _Jv_RunMain (vm_args=0x22ccb0, klass=0x0,
>     name=0x22cd4c "/gnu/gcc/gcc-patched/libjava/testsuite/libjava.jar/TestClosur
> eGC.jar", argc=1, argv=0x28b9d48, is_jar=true)
>     at /gnu/gcc/gcc-patched/libjava/prims.cc:1789
> #33 0x00401392 in main (argc=3, argv=0x28b9d40)
>     at /gnu/gcc/gcc-patched/libjava/gij.cc:333
> (gdb)
> 
> ... there is a single call to _Jv_InterpMethod::run, at frame #24, coming from
> a call to ffi_closure_raw_SYSV.
> 
>   I've worked around this before by just avoiding the situation with
> 
> Index: libjava/stacktrace.cc
> ===================================================================
> --- libjava/stacktrace.cc	(revision 147638)
> +++ libjava/stacktrace.cc	(working copy)
> @@ -132,7 +132,8 @@
>    else
>      interp_run = (void *) &_Jv_InterpMethod::run;
>    	
> -  if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
> +  if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run)
> +      && state->interp_frame)
>      {
>        state->frames[pos].type = frame_interpreter;
>        _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame);
> 
> ... but is that the right thing to do?  Where should state->interp_frame have
> been set up?  It appears to fix testsuite failures, but I don't know for sure
> if they're doing everything right internally.  I'll run it through a test
> cycle if just avoiding the problem in this way is indeed correct, but a
> pointer or two could speed me on the way or save me barking up any wrong trees.

You need to put a breakpoint at the constructor of _Jv_InterpFrame.  It creates
a node and pushes it into the linked list starting at thr->interp_frame:

  _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyCls = NULL,
                   pc_t *pc = NULL,
		   _Jv_FrameType frame_type = frame_interpreter)
  : _Jv_Frame (reinterpret_cast<_Jv_MethodBase *> (meth), thr,
	             frame_type)
  {
    next_interp = (_Jv_InterpFrame *) thr->interp_frame;
    proxyClass = proxyCls;
    thr->interp_frame = (gnu::gcj::RawData *) this;
    obj_ptr = NULL;
    pc_ptr = pc;
  }

This constructor is called from interpret-run.cc:27.

Andrew.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.