// natStackTrace.cc - native helper methods for Throwable

/* Copyright (C) 2000, 2002, 2003  Free Software Foundation, Inc

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

/**
 * @author Andrew Haley <aph@cygnus.com>
 * @author Mark Wielaard <mark@klomp.org>
 *
 * Native helper methods for VM specific Throwable support.
 */

#include <config.h>
#include <platform.h>

#include <string.h>

#include <jvm.h>
#include <gcj/cni.h>
#include <gnu/gcj/RawData.h>
#include <java/lang/Object.h>
#include <java-threads.h>
#include <gnu/gcj/runtime/MethodRef.h>
#include <gnu/gcj/runtime/StackTrace.h>
#include <java/lang/Thread.h>
#include <java-interp.h>
#include <java/util/IdentityHashMap.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>

#include <sys/types.h>

#include <stdlib.h>

#include <unistd.h>

#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif

#include <unwind.h>


#ifdef INTERPRETER
extern "C" void *_Unwind_FindEnclosingFunction (void *pc)
  __attribute__((pure));
#endif // INTERPRETER

// Fill in this stack trace with MAXLEN elements starting at offset.
void
gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
{
#ifdef HAVE_BACKTRACE
  offset += 1;
  void *_p[maxlen + offset];
  len = backtrace (_p, maxlen + offset) - offset;
  void **p = _p + offset;
  _Jv_frame_info *frame;
  if (len > 0)
    {
#ifdef INTERPRETER
      extern void *const _Jv_StartOfInterpreter;
      extern void * _Jv_EndOfInterpreter;

      java::lang::Thread *thread = java::lang::Thread::currentThread();
      _Jv_MethodChain *interp_frame
	= (thread ? reinterpret_cast<_Jv_MethodChain *> (thread->interp_frame)
	   : NULL);
#endif // INTERPRETER

      frame = (_Jv_frame_info *) _Jv_Malloc (len * sizeof (_Jv_frame_info));
      for (int n = 0; n < len; n++)
	{
	  void *pc = p[n];
	  frame[n].addr = pc;

#ifdef INTERPRETER
	  frame[n].interp = 0;

	  // If _Jv_StartOfInterpreter is NULL either we've never
	  // entered the intepreter or _Unwind_FindEnclosingFunction
	  // is broken.
	  if (__builtin_expect (_Jv_StartOfInterpreter != NULL, false))
	    {
	      // _Jv_StartOfInterpreter marks the very first
	      // instruction in the interpreter, but
	      // _Jv_EndOfInterpreter is an upper bound.  If PC is
	      // less than _Jv_EndOfInterpreter it might be in the
	      // interpreter: we call _Unwind_FindEnclosingFunction to
	      // find out.
	      if (pc >= _Jv_StartOfInterpreter
		  && (pc < _Jv_EndOfInterpreter
		      || _Jv_EndOfInterpreter == NULL))
		{
		  if (_Unwind_FindEnclosingFunction (pc) 
		      == _Jv_StartOfInterpreter)
		    {
		      frame[n].interp = (void *) interp_frame->self;
		      interp_frame = interp_frame->next;
		    }
		  else
		    {
		      // We've found an address that we know is not within
		      // the interpreter.  We use that to refine our upper
		      // bound on where the interpreter ends.
		      _Jv_EndOfInterpreter = pc;
		    }
		}
	    }
#endif // INTERPRETER

	}
    }
  else
    frame = NULL;

  addrs = reinterpret_cast<gnu::gcj::RawData *> (frame);
#else // HAVE_BACKTRACE
  (void)maxlen;
  (void)offset;
#endif // HAVE_BACKTRACE
}

/* Obtain the next power-of-2 of some integer.  */
static inline jint
nextpowerof2 (jint n)
{
  n |= (n >> 1);
  n |= (n >> 2);
  n |= (n >> 4);
  n |= (n >> 8);
  n |= (n >> 16);
  return n+1;
}

#define GET_FRAME(N)						\
({								\
  if ((N) >= len)						\
    fillInStackTrace (nextpowerof2 (N), 1);			\
  if ((N) < 0 || (N) >= len)					\
    throw new ::java::lang::ArrayIndexOutOfBoundsException ();	\
								\
  _Jv_frame_info *frame = (_Jv_frame_info *)addrs;		\
  &frame[N];							\
})

gnu::gcj::runtime::MethodRef *
gnu::gcj::runtime::StackTrace::getCompiledMethodRef (gnu::gcj::RawData *addr)
{
  void *p = _Unwind_FindEnclosingFunction (addr);
  return gnu::gcj::runtime::StackTrace
    ::methodAtAddress ((gnu::gcj::RawData *)p);
}

java::lang::Class *
gnu::gcj::runtime::StackTrace::getClass (gnu::gcj::RawData *p)
{
  gnu::gcj::runtime::MethodRef *ref = getCompiledMethodRef (p);
  if (ref)
    return ref->klass;
  else
    return NULL;
}

java::lang::Class *
gnu::gcj::runtime::StackTrace::classAt (jint n)
{
  _Jv_frame_info *frame = GET_FRAME (n);

#ifdef INTERPRETER
  if (frame->interp)
    {
      _Jv_InterpMethod *meth
	= reinterpret_cast<_Jv_InterpMethod *> (frame->interp);
      return meth->defining_class;
    }
#endif // INTERPRETER
  
  return getClass ((gnu::gcj::RawData *)frame->addr);
}

java::lang::String*
gnu::gcj::runtime::StackTrace::methodAt (jint n)
{
  _Jv_frame_info *frame = GET_FRAME (n);
  _Jv_Method *meth = NULL;

#ifdef INTERPRETER
  if (frame->interp)
    {
      meth
	= reinterpret_cast<_Jv_InterpMethod *> (frame->interp)
	->get_method();
    }
#endif // INTERPRETER
  
  if (! meth)
    {
      gnu::gcj::runtime::MethodRef *ref
	= getCompiledMethodRef ((gnu::gcj::RawData *)frame->addr);
      if (ref)
	meth = (_Jv_Method *)ref->method;
    }

  return meth 
    ? _Jv_NewStringUtf8Const (meth->name)
    : NULL ;
}

void
gnu::gcj::runtime::StackTrace::update(void)
{
  jclass klass;

  while ((klass = _Jv_PopClass ()))
    {
      for (int i=0; i<klass->method_count; i++)
	{
	  JvSynchronize sync (map);
	  _Jv_Method *meth = &(klass->methods[i]);
	  if (meth->ncode) // i.e. if p is not abstract
	    {
	      gnu::gcj::runtime::MethodRef *ref
		= new gnu::gcj::runtime::MethodRef 
		((gnu::gcj::RawData *)meth, klass);
	      map->put ((java::lang::Object*)(meth->ncode), ref);
	    }
	}
    }
}

void
gnu::gcj::runtime::StackTrace::finalize(void)
{
  if (addrs != NULL)
    _Jv_Free (addrs);
}
