Commit 18744d9b by Bryce McKinlay Committed by Bryce McKinlay

New Stack Trace infrastructure.

2005-03-10  Bryce McKinlay  <mckinlay@redhat.com>

	New Stack Trace infrastructure.
	* Makefile.am (libgcj0_convenience_la_SOURCES): Add stacktrace.cc.
	(gnu/gcj/runtime/StackTrace.lo): Removed.
	(ordinary_java_source_files): Remove obsolete files.
	(nat_source_files): Remove obsolete files. Add natVMThrowable.cc.
	* configure.host (fallback_backtrace_h): Set backtrace header
	for mingw and cygwin targets.
	* configure.ac: Make symlink for fallback backtrace headers.
	* Makefile.in, configure: Rebuilt.
	* defineclass.cc (_Jv_ClassReader::read_one_code_attribute):
	Read 'LineNumberTable' attribute.
	(_Jv_ClassReader::read_one_class_attribute): Read 'SourceFile'
	attribute.
	(_Jv_ClassReader::handleCodeAttribute): Initialize method line
	table fields.
	* exception.cc: Remove unused include.
	* interpret.cc (DIRECT_THREADED, insn_slot): Moved to java-interp.h.
	(SAVE_PC): New macro. Save current PC in the interpreter frame.
	(NULLCHECK, NULLARRAYCHECK): Use SAVE_PC.
	(_Jv_InterpMethod::compile): Translate bytecode PC values in the line
	table to direct threaded instruction values.
	(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): Removed.
	(_Jv_InterpMethod::run): No longer member function. All
	callers updated. Remove _Unwind calls. Call SAVE_PC whenever a call
	is made or where an instruction could throw.
	(_Jv_InterpMethod::get_source_line): New. Look up source line numbers
	in line_table.
	* prims.cc (catch_segv): Construct exception after MAKE_THROW_FRAME.
	(catch_fpe): Likewise.
	* stacktrace.cc: New file. Stack trace code now here.
	* gnu/gcj/runtime/MethodRef.java:
	* gnu/gcj/runtime/NameFinder.java: Mostly reimplemented. Now simply
	calls addr2line to look up PC addresses in a given binary or shared
	library.
	* gnu/gcj/runtime/StackTrace.java, gnu/gcj/runtime/natNameFinder.cc,
	gnu/gcj/runtime/natStackTrace.cc: Removed.
	* gnu/java/lang/MainThread.java (call_main): Add comment warning that
	this function name is specially recognised by the stack trace code
	and shouldn't be changed.
	* include/java-interp.h (DIRECT_THREADED, insn_slot): Moved here.
	(struct  _Jv_LineTableEntry, line_table, line_table_len): New.
	(_Jv_InterpMethod::run): Update declaration.
	(_Jv_StackTrace_): New friend. NameFinder and StackTrace no longer
	friends.
	(_Jv_InterpFrame): Renamed from _Jv_MethodChain. Add PC field.
	* include/java-stack.h: New file. Declarations for stack tracing.
	* include/jvm.h (_Jv_Frame_info): Removed.
	* java/lang/Class.h: Update friend declarations.
	* java/lang/VMClassLoader.java (getSystemClassLoader): Simplify
	exception message.
	* java/lang/VMThrowable.java (fillInStackTrace): Now native.
	(getStackTrace): Now native.
	(data): New RawDataManaged field.
	* java/lang/natClass.cc: Update includes.
	(forName): Use _Jv_StackTrace::GetCallingClass for
	calling-classloader check.
	(getClassLoader): Likewise.
	* java/lang/natRuntime.cc: Update includes.
	(_load): Use _Jv_StackTrace::GetFirstNonSystemClassLoader.
	* java/lang/natVMSecurityManager.cc: Update includes.
	(getClassContext): Use _Jv_StackTrace::GetClassContext.
	* java/lang/natVMThrowable.cc: New file. Native methods for
	VMThrowable.
	* java/lang/reflect/natArray.cc: Update includes.
	(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/lang/reflect/natConstructor.cc: Update includes.
	(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/lang/reflect/natField.cc: Update includes.
	(getAddr): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/lang/reflect/natMethod.cc: Update includes.
	(invoke): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/util/natResourceBundle.cc: Update includes.
	(getCallingClassLoader): Use _Jv_StackTrace::GetCallingClass.
	* java/util/logging/natLogger.cc: Update includes. Use
	_Jv_StackTrace::GetCallerInfo to get call-site info.
	* sysdep/generic/backtrace.h: Fallback backtrace code. Stub
	implementation.
	* sysdep/i386/backtrace.h: New. Fallback backtrace code. i386
	implementation.

From-SVN: r96253
parent ca1593fd
2005-03-10 Bryce McKinlay <mckinlay@redhat.com>
New Stack Trace infrastructure.
* Makefile.am (libgcj0_convenience_la_SOURCES): Add stacktrace.cc.
(gnu/gcj/runtime/StackTrace.lo): Removed.
(ordinary_java_source_files): Remove obsolete files.
(nat_source_files): Remove obsolete files. Add natVMThrowable.cc.
* configure.host (fallback_backtrace_h): Set backtrace header
for mingw and cygwin targets.
* configure.ac: Make symlink for fallback backtrace headers.
* Makefile.in, configure: Rebuilt.
* defineclass.cc (_Jv_ClassReader::read_one_code_attribute):
Read 'LineNumberTable' attribute.
(_Jv_ClassReader::read_one_class_attribute): Read 'SourceFile'
attribute.
(_Jv_ClassReader::handleCodeAttribute): Initialize method line
table fields.
* exception.cc: Remove unused include.
* interpret.cc (DIRECT_THREADED, insn_slot): Moved to java-interp.h.
(SAVE_PC): New macro. Save current PC in the interpreter frame.
(NULLCHECK, NULLARRAYCHECK): Use SAVE_PC.
(_Jv_InterpMethod::compile): Translate bytecode PC values in the line
table to direct threaded instruction values.
(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): Removed.
(_Jv_InterpMethod::run): No longer member function. All
callers updated. Remove _Unwind calls. Call SAVE_PC whenever a call
is made or where an instruction could throw.
(_Jv_InterpMethod::get_source_line): New. Look up source line numbers
in line_table.
* prims.cc (catch_segv): Construct exception after MAKE_THROW_FRAME.
(catch_fpe): Likewise.
* stacktrace.cc: New file. Stack trace code now here.
* gnu/gcj/runtime/MethodRef.java:
* gnu/gcj/runtime/NameFinder.java: Mostly reimplemented. Now simply
calls addr2line to look up PC addresses in a given binary or shared
library.
* gnu/gcj/runtime/StackTrace.java, gnu/gcj/runtime/natNameFinder.cc,
gnu/gcj/runtime/natStackTrace.cc: Removed.
* gnu/java/lang/MainThread.java (call_main): Add comment warning that
this function name is specially recognised by the stack trace code
and shouldn't be changed.
* include/java-interp.h (DIRECT_THREADED, insn_slot): Moved here.
(struct _Jv_LineTableEntry, line_table, line_table_len): New.
(_Jv_InterpMethod::run): Update declaration.
(_Jv_StackTrace_): New friend. NameFinder and StackTrace no longer
friends.
(_Jv_InterpFrame): Renamed from _Jv_MethodChain. Add PC field.
* include/java-stack.h: New file. Declarations for stack tracing.
* include/jvm.h (_Jv_Frame_info): Removed.
* java/lang/Class.h: Update friend declarations.
* java/lang/VMClassLoader.java (getSystemClassLoader): Simplify
exception message.
* java/lang/VMThrowable.java (fillInStackTrace): Now native.
(getStackTrace): Now native.
(data): New RawDataManaged field.
* java/lang/natClass.cc: Update includes.
(forName): Use _Jv_StackTrace::GetCallingClass for
calling-classloader check.
(getClassLoader): Likewise.
* java/lang/natRuntime.cc: Update includes.
(_load): Use _Jv_StackTrace::GetFirstNonSystemClassLoader.
* java/lang/natVMSecurityManager.cc: Update includes.
(getClassContext): Use _Jv_StackTrace::GetClassContext.
* java/lang/natVMThrowable.cc: New file. Native methods for
VMThrowable.
* java/lang/reflect/natArray.cc: Update includes.
(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
accessibility check.
* java/lang/reflect/natConstructor.cc: Update includes.
(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
accessibility check.
* java/lang/reflect/natField.cc: Update includes.
(getAddr): Use _Jv_StackTrace::GetCallingClass to implement
accessibility check.
* java/lang/reflect/natMethod.cc: Update includes.
(invoke): Use _Jv_StackTrace::GetCallingClass to implement
accessibility check.
* java/util/natResourceBundle.cc: Update includes.
(getCallingClassLoader): Use _Jv_StackTrace::GetCallingClass.
* java/util/logging/natLogger.cc: Update includes. Use
_Jv_StackTrace::GetCallerInfo to get call-site info.
* sysdep/generic/backtrace.h: Fallback backtrace code. Stub
implementation.
* sysdep/i386/backtrace.h: New. Fallback backtrace code. i386
implementation.
2005-03-10 Ranjit Mathew <rmathew@hotmail.com> 2005-03-10 Ranjit Mathew <rmathew@hotmail.com>
* testsuite/libjava.compile/PR20312.java: New file. * testsuite/libjava.compile/PR20312.java: New file.
......
...@@ -217,7 +217,7 @@ libgij_la_LDFLAGS = -rpath $(toolexeclibdir) \ ...@@ -217,7 +217,7 @@ libgij_la_LDFLAGS = -rpath $(toolexeclibdir) \
# convenience library suddenly invokes the --whole-archive path instead. # convenience library suddenly invokes the --whole-archive path instead.
# This allows the build to succeed for targets that allocate multiple got # This allows the build to succeed for targets that allocate multiple got
# subsections in the linker, such as Alpha and MIPS. # subsections in the linker, such as Alpha and MIPS.
libgcj0_convenience_la_SOURCES = prims.cc jni.cc exception.cc \ libgcj0_convenience_la_SOURCES = prims.cc jni.cc exception.cc stacktrace.cc \
link.cc defineclass.cc interpret.cc verify.cc \ link.cc defineclass.cc interpret.cc verify.cc \
$(nat_source_files) $(math_c_source_files) $(java_source_files) \ $(nat_source_files) $(math_c_source_files) $(java_source_files) \
$(gnu_xml_source_files) $(built_java_source_files) \ $(gnu_xml_source_files) $(built_java_source_files) \
...@@ -588,20 +588,12 @@ clean-nat: ...@@ -588,20 +588,12 @@ clean-nat:
SUFFIXES = .class .java .h .properties SUFFIXES = .class .java .h .properties
## Note: we omit StackTrace here, since it has an explicit rule a bit $(javao_files) $(xlib_javao_files): %.lo: %.java
## later, and GNU make will warn in this case.
$(filter-out gnu/gcj/runtime/StackTrace.lo, $(javao_files)) $(xlib_javao_files): %.lo: %.java
$(LTGCJCOMPILE) -o $@ -c $< $(LTGCJCOMPILE) -o $@ -c $<
$(gtk_awt_peer_sources:.java=.lo) $(gnu_xml_source_files:.java=.lo): %.lo: %.java $(gtk_awt_peer_sources:.java=.lo) $(gnu_xml_source_files:.java=.lo): %.lo: %.java
$(LTGCJCOMPILE) -fjni -o $@ -c $< $(LTGCJCOMPILE) -fjni -o $@ -c $<
## A special case. The sibcall optimization can change the number of
## frames on the stack, and StackTrace makes assumptions about this
## number.
gnu/gcj/runtime/StackTrace.lo: gnu/gcj/runtime/StackTrace.java
$(LTGCJCOMPILE) -fno-optimize-sibling-calls -o $@ -c $<
## Pass the list of object files to libtool in a temporary file to ## Pass the list of object files to libtool in a temporary file to
## avoid tripping platform command line length limits. ## avoid tripping platform command line length limits.
libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES) libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES)
...@@ -2911,12 +2903,10 @@ gnu/gcj/io/SimpleSHSStream.java \ ...@@ -2911,12 +2903,10 @@ gnu/gcj/io/SimpleSHSStream.java \
gnu/gcj/runtime/FileDeleter.java \ gnu/gcj/runtime/FileDeleter.java \
gnu/gcj/runtime/FinalizerThread.java \ gnu/gcj/runtime/FinalizerThread.java \
gnu/gcj/runtime/JNIWeakRef.java \ gnu/gcj/runtime/JNIWeakRef.java \
gnu/gcj/runtime/MethodRef.java \
gnu/gcj/runtime/NameFinder.java \ gnu/gcj/runtime/NameFinder.java \
gnu/gcj/runtime/PersistentByteMap.java \ gnu/gcj/runtime/PersistentByteMap.java \
gnu/gcj/runtime/SharedLibHelper.java \ gnu/gcj/runtime/SharedLibHelper.java \
gnu/gcj/runtime/SharedLibLoader.java \ gnu/gcj/runtime/SharedLibLoader.java \
gnu/gcj/runtime/StackTrace.java \
gnu/gcj/runtime/StringBuffer.java \ gnu/gcj/runtime/StringBuffer.java \
gnu/gcj/runtime/SystemClassLoader.java \ gnu/gcj/runtime/SystemClassLoader.java \
gnu/gcj/runtime/VMClassLoader.java \ gnu/gcj/runtime/VMClassLoader.java \
...@@ -3676,9 +3666,7 @@ gnu/gcj/convert/natOutput_SJIS.cc \ ...@@ -3676,9 +3666,7 @@ gnu/gcj/convert/natOutput_SJIS.cc \
gnu/gcj/io/natSimpleSHSStream.cc \ gnu/gcj/io/natSimpleSHSStream.cc \
gnu/gcj/io/shs.cc \ gnu/gcj/io/shs.cc \
gnu/gcj/runtime/natFinalizerThread.cc \ gnu/gcj/runtime/natFinalizerThread.cc \
gnu/gcj/runtime/natNameFinder.cc \
gnu/gcj/runtime/natSharedLibLoader.cc \ gnu/gcj/runtime/natSharedLibLoader.cc \
gnu/gcj/runtime/natStackTrace.cc \
gnu/gcj/runtime/natStringBuffer.cc \ gnu/gcj/runtime/natStringBuffer.cc \
gnu/gcj/runtime/natVMClassLoader.cc \ gnu/gcj/runtime/natVMClassLoader.cc \
gnu/gcj/util/natDebug.cc \ gnu/gcj/util/natDebug.cc \
...@@ -3708,6 +3696,7 @@ java/lang/natSystem.cc \ ...@@ -3708,6 +3696,7 @@ java/lang/natSystem.cc \
java/lang/natThread.cc \ java/lang/natThread.cc \
java/lang/natVMClassLoader.cc \ java/lang/natVMClassLoader.cc \
java/lang/natVMSecurityManager.cc \ java/lang/natVMSecurityManager.cc \
java/lang/natVMThrowable.cc \
java/lang/ref/natReference.cc \ java/lang/ref/natReference.cc \
java/lang/reflect/natArray.cc \ java/lang/reflect/natArray.cc \
java/lang/reflect/natConstructor.cc \ java/lang/reflect/natConstructor.cc \
......
...@@ -8454,6 +8454,8 @@ fi ...@@ -8454,6 +8454,8 @@ fi
if test -d sysdep; then true; else mkdir sysdep; fi if test -d sysdep; then true; else mkdir sysdep; fi
ac_config_links="$ac_config_links sysdep/locks.h:sysdep/$sysdeps_dir/locks.h" ac_config_links="$ac_config_links sysdep/locks.h:sysdep/$sysdeps_dir/locks.h"
ac_config_links="$ac_config_links sysdep/backtrace.h:$fallback_backtrace_h"
HASH_SYNC_SPEC= HASH_SYNC_SPEC=
# Hash synchronization is only useful with posix threads right now. # Hash synchronization is only useful with posix threads right now.
...@@ -16482,6 +16484,7 @@ do ...@@ -16482,6 +16484,7 @@ do
"include/java-gc.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-gc.h:include/$GCHDR" ;; "include/java-gc.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-gc.h:include/$GCHDR" ;;
"include/java-threads.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-threads.h:include/$THREADH" ;; "include/java-threads.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-threads.h:include/$THREADH" ;;
"sysdep/locks.h" ) CONFIG_LINKS="$CONFIG_LINKS sysdep/locks.h:sysdep/$sysdeps_dir/locks.h" ;; "sysdep/locks.h" ) CONFIG_LINKS="$CONFIG_LINKS sysdep/locks.h:sysdep/$sysdeps_dir/locks.h" ;;
"sysdep/backtrace.h" ) CONFIG_LINKS="$CONFIG_LINKS sysdep/backtrace.h:$fallback_backtrace_h" ;;
"include/java-signal.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-signal.h:$SIGNAL_HANDLER" ;; "include/java-signal.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-signal.h:$SIGNAL_HANDLER" ;;
"include/java-signal-aux.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-signal-aux.h:$SIGNAL_HANDLER_AUX" ;; "include/java-signal-aux.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-signal-aux.h:$SIGNAL_HANDLER_AUX" ;;
"depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
......
...@@ -710,6 +710,7 @@ AM_CONDITIONAL(USING_NO_THREADS, test "$THREADS" = none) ...@@ -710,6 +710,7 @@ AM_CONDITIONAL(USING_NO_THREADS, test "$THREADS" = none)
if test -d sysdep; then true; else mkdir sysdep; fi if test -d sysdep; then true; else mkdir sysdep; fi
AC_CONFIG_LINKS(sysdep/locks.h:sysdep/$sysdeps_dir/locks.h) AC_CONFIG_LINKS(sysdep/locks.h:sysdep/$sysdeps_dir/locks.h)
AC_CONFIG_LINKS(sysdep/backtrace.h:$fallback_backtrace_h)
HASH_SYNC_SPEC= HASH_SYNC_SPEC=
# Hash synchronization is only useful with posix threads right now. # Hash synchronization is only useful with posix threads right now.
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
# from a signal handler. # from a signal handler.
# disable_dladdr Set to "yes" if dladdr should not be used # disable_dladdr Set to "yes" if dladdr should not be used
# (i.e it is broken). # (i.e it is broken).
# fallback_backtrace_h Header to use for fallback backtrace implementation
# (only for targets that don't support DWARF2 unwind)
libgcj_flags= libgcj_flags=
libgcj_cflags= libgcj_cflags=
...@@ -42,6 +44,7 @@ sysdeps_dir=generic ...@@ -42,6 +44,7 @@ sysdeps_dir=generic
slow_pthread_self= slow_pthread_self=
can_unwind_signal=no can_unwind_signal=no
disable_dladdr= disable_dladdr=
fallback_backtrace_h=sysdep/generic/backtrace.h
case "${target_optspace}:${host}" in case "${target_optspace}:${host}" in
yes:*) yes:*)
...@@ -258,6 +261,13 @@ EOF ...@@ -258,6 +261,13 @@ EOF
;; ;;
esac esac
case "${host}" in
*-cygwin* | *-mingw*)
fallback_backtrace_h=sysdep/i386/backtrace.h
;;
esac
libgcj_cflags="${libgcj_cflags} ${libgcj_flags}" libgcj_cflags="${libgcj_cflags} ${libgcj_flags}"
libgcj_cxxflags="${libgcj_cxxflags} ${libgcj_flags}" libgcj_cxxflags="${libgcj_cxxflags} ${libgcj_flags}"
libgcj_javaflags="${libgcj_javaflags} ${libgcj_flags}" libgcj_javaflags="${libgcj_javaflags} ${libgcj_flags}"
...@@ -229,6 +229,7 @@ struct _Jv_ClassReader { ...@@ -229,6 +229,7 @@ struct _Jv_ClassReader {
len = length; len = length;
pos = 0; pos = 0;
def = klass; def = klass;
def->size_in_bytes = -1; def->size_in_bytes = -1;
def->vtable_method_count = -1; def->vtable_method_count = -1;
def->engine = &_Jv_soleInterpreterEngine; def->engine = &_Jv_soleInterpreterEngine;
...@@ -613,26 +614,54 @@ void _Jv_ClassReader::read_one_method_attribute (int method_index) ...@@ -613,26 +614,54 @@ void _Jv_ClassReader::read_one_method_attribute (int method_index)
} }
} }
void _Jv_ClassReader::read_one_code_attribute (int /*method*/) void _Jv_ClassReader::read_one_code_attribute (int method_index)
{ {
/* ignore for now, ... later we may want to pick up int name = read2u ();
line number information, for debugging purposes;
in fact, the whole debugger issue is open! */
/* int name = */ read2u ();
int length = read4 (); int length = read4 ();
skip (length); if (is_attribute_name (name, "LineNumberTable"))
{
_Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
(def_interp->interpreted_methods[method_index]);
if (method->line_table != NULL)
throw_class_format_error ("Method already has LineNumberTable");
int table_len = read2u ();
_Jv_LineTableEntry* table
= (_Jv_LineTableEntry *) JvAllocBytes (table_len
* sizeof (_Jv_LineTableEntry));
for (int i = 0; i < table_len; i++)
{
table[i].bytecode_pc = read2u ();
table[i].line = read2u ();
}
method->line_table_len = table_len;
method->line_table = table;
}
else
{
/* ignore unknown code attributes */
skip (length);
}
} }
void _Jv_ClassReader::read_one_class_attribute () void _Jv_ClassReader::read_one_class_attribute ()
{ {
/* we also ignore the class attributes, ... int name = read2u ();
some day we'll add inner-classes support. */
/* int name = */ read2u ();
int length = read4 (); int length = read4 ();
skip (length); if (is_attribute_name (name, "SourceFile"))
{
int source_index = read2u ();
check_tag (source_index, JV_CONSTANT_Utf8);
prepare_pool_entry (source_index, JV_CONSTANT_Utf8);
def_interp->source_file_name = _Jv_NewStringUtf8Const
(def->constants.data[source_index].utf8);
}
else
{
/* Currently, we ignore most class attributes.
FIXME: Add inner-classes attributes support. */
skip (length);
}
} }
...@@ -1279,6 +1308,9 @@ void _Jv_ClassReader::handleCodeAttribute ...@@ -1279,6 +1308,9 @@ void _Jv_ClassReader::handleCodeAttribute
method->defining_class = def; method->defining_class = def;
method->self = &def->methods[method_index]; method->self = &def->methods[method_index];
method->prepared = NULL; method->prepared = NULL;
method->line_table_len = 0;
method->line_table = NULL;
// grab the byte code! // grab the byte code!
memcpy ((void*) method->bytecode (), memcpy ((void*) method->bytecode (),
......
...@@ -15,7 +15,6 @@ details. */ ...@@ -15,7 +15,6 @@ details. */
#include <java/lang/Class.h> #include <java/lang/Class.h>
#include <java/lang/NullPointerException.h> #include <java/lang/NullPointerException.h>
#include <gnu/gcj/runtime/StackTrace.h>
#include <gnu/gcj/runtime/MethodRef.h> #include <gnu/gcj/runtime/MethodRef.h>
#include <gnu/gcj/RawData.h> #include <gnu/gcj/RawData.h>
#include <gcj/cni.h> #include <gcj/cni.h>
......
...@@ -52,7 +52,7 @@ public interface Configuration ...@@ -52,7 +52,7 @@ public interface Configuration
// For libgcj we never load the JNI libraries. // For libgcj we never load the JNI libraries.
boolean INIT_LOAD_LIBRARY = false; boolean INIT_LOAD_LIBRARY = false;
// For libgcj we have native methods for proxy support.... // For libgcj we have native methods for dynamic proxy support....
boolean HAVE_NATIVE_GET_PROXY_DATA = false; boolean HAVE_NATIVE_GET_PROXY_DATA = false;
boolean HAVE_NATIVE_GET_PROXY_CLASS = false; boolean HAVE_NATIVE_GET_PROXY_CLASS = false;
boolean HAVE_NATIVE_GENERATE_PROXY_CLASS = false; boolean HAVE_NATIVE_GENERATE_PROXY_CLASS = false;
......
...@@ -127,5 +127,7 @@ final class MainThread extends Thread ...@@ -127,5 +127,7 @@ final class MainThread extends Thread
return mainName; return mainName;
} }
// Note: this function name is known to the stack tracing code.
// You shouldn't change this without also updating stacktrace.cc.
private native void call_main(); private native void call_main();
} }
...@@ -23,6 +23,11 @@ details. */ ...@@ -23,6 +23,11 @@ details. */
#include <java/lang/ClassLoader.h> #include <java/lang/ClassLoader.h>
#include <java/lang/reflect/Modifier.h> #include <java/lang/reflect/Modifier.h>
// Define this to get the direct-threaded interpreter. If undefined,
// we revert to a basic bytecode interpreter. The former is faster
// but uses more memory.
#define DIRECT_THREADED
extern "C" { extern "C" {
#include <ffi.h> #include <ffi.h>
} }
...@@ -95,6 +100,41 @@ public: ...@@ -95,6 +100,41 @@ public:
} }
}; };
// The type of the PC depends on whether we're doing direct threading
// or a more ordinary bytecode interpreter.
#ifdef DIRECT_THREADED
// Slot in the "compiled" form of the bytecode.
union insn_slot
{
// Address of code.
void *insn;
// An integer value used by an instruction.
jint int_val;
// A pointer value used by an instruction.
void *datum;
};
typedef insn_slot *pc_t;
#else
typedef unsigned char *pc_t;
#endif
// This structure holds the bytecode pc and corresponding source code
// line number. An array (plus length field) of this structure is put
// in each _Jv_InterpMethod and used to resolve the (internal) program
// counter of the interpreted method to an actual java source file
// line.
struct _Jv_LineTableEntry
{
union
{
pc_t pc;
int bytecode_pc;
};
int line;
};
class _Jv_InterpMethod : public _Jv_MethodBase class _Jv_InterpMethod : public _Jv_MethodBase
{ {
_Jv_ushort max_stack; _Jv_ushort max_stack;
...@@ -103,6 +143,10 @@ class _Jv_InterpMethod : public _Jv_MethodBase ...@@ -103,6 +143,10 @@ class _Jv_InterpMethod : public _Jv_MethodBase
_Jv_ushort exc_count; _Jv_ushort exc_count;
// Length of the line_table - when this is zero then line_table is NULL.
int line_table_len;
_Jv_LineTableEntry *line_table;
void *prepared; void *prepared;
unsigned char* bytecode () unsigned char* bytecode ()
...@@ -135,17 +179,19 @@ class _Jv_InterpMethod : public _Jv_MethodBase ...@@ -135,17 +179,19 @@ class _Jv_InterpMethod : public _Jv_MethodBase
static void run_class (ffi_cif*, void*, ffi_raw*, void*); static void run_class (ffi_cif*, void*, ffi_raw*, void*);
static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*); static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
void run (void*, ffi_raw *); static void run (void*, ffi_raw *, _Jv_InterpMethod *);
// Returns source file line number for given PC value, or -1 if line
// number info is unavailable.
int get_source_line(pc_t mpc);
public: public:
static void dump_object(jobject o); static void dump_object(jobject o);
friend class _Jv_ClassReader; friend class _Jv_ClassReader;
friend class _Jv_BytecodeVerifier; friend class _Jv_BytecodeVerifier;
friend class gnu::gcj::runtime::NameFinder; friend class _Jv_StackTrace;
friend class gnu::gcj::runtime::StackTrace;
friend class _Jv_InterpreterEngine; friend class _Jv_InterpreterEngine;
#ifdef JV_MARKOBJ_DECL #ifdef JV_MARKOBJ_DECL
friend JV_MARKOBJ_DECL; friend JV_MARKOBJ_DECL;
...@@ -155,11 +201,14 @@ class _Jv_InterpMethod : public _Jv_MethodBase ...@@ -155,11 +201,14 @@ class _Jv_InterpMethod : public _Jv_MethodBase
class _Jv_InterpClass class _Jv_InterpClass
{ {
_Jv_MethodBase **interpreted_methods; _Jv_MethodBase **interpreted_methods;
_Jv_ushort *field_initializers; _Jv_ushort *field_initializers;
jstring source_file_name;
friend class _Jv_ClassReader; friend class _Jv_ClassReader;
friend class _Jv_InterpMethod; friend class _Jv_InterpMethod;
friend class _Jv_StackTrace;
friend class _Jv_InterpreterEngine; friend class _Jv_InterpreterEngine;
friend void _Jv_InitField (jobject, jclass, int); friend void _Jv_InitField (jobject, jclass, int);
#ifdef JV_MARKOBJ_DECL #ifdef JV_MARKOBJ_DECL
friend JV_MARKOBJ_DECL; friend JV_MARKOBJ_DECL;
...@@ -219,23 +268,24 @@ public: ...@@ -219,23 +268,24 @@ public:
} }
}; };
// A structure of this type is used to link together interpreter // The interpreted call stack, represented by a linked list of frames.
// invocations on the stack. struct _Jv_InterpFrame
struct _Jv_MethodChain
{ {
const _Jv_InterpMethod *self; _Jv_InterpMethod *self;
_Jv_MethodChain **ptr; _Jv_InterpFrame **ptr;
_Jv_MethodChain *next; _Jv_InterpFrame *next;
pc_t pc;
_Jv_MethodChain (const _Jv_InterpMethod *s, _Jv_MethodChain **n) _Jv_InterpFrame (_Jv_InterpMethod *s, _Jv_InterpFrame **n)
{ {
self = s; self = s;
ptr = n; ptr = n;
next = *n; next = *n;
*n = this; *n = this;
pc = NULL;
} }
~_Jv_MethodChain () ~_Jv_InterpFrame ()
{ {
*ptr = next; *ptr = next;
} }
......
// java-stack.h - Definitions for unwinding & inspecting the call stack. // java-stack.h - Definitions for unwinding & inspecting the call stack.
/* Copyright (C) 2003 Free Software Foundation /* Copyright (C) 2005 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -21,10 +21,12 @@ details. */ ...@@ -21,10 +21,12 @@ details. */
#include <java/lang/Class.h> #include <java/lang/Class.h>
#include <java/lang/StackTraceElement.h> #include <java/lang/StackTraceElement.h>
#include <java/lang/Throwable.h> #include <java/lang/Throwable.h>
#include <java/lang/Thread.h>
#include <gnu/gcj/runtime/NameFinder.h> #include <gnu/gcj/runtime/NameFinder.h>
using namespace gnu::gcj::runtime; using namespace gnu::gcj::runtime;
using namespace java::lang;
enum _Jv_FrameType enum _Jv_FrameType
{ {
...@@ -51,13 +53,44 @@ struct _Jv_StackFrame ...@@ -51,13 +53,44 @@ struct _Jv_StackFrame
#ifdef INTERPRETER #ifdef INTERPRETER
_Jv_InterpFrameInfo interp; _Jv_InterpFrameInfo interp;
#endif #endif
void *ip; struct {
void *ip;
void *start_ip;
};
}; };
// _Jv_FrameInfo info; /* Frame-type specific data. */ // _Jv_FrameInfo info; /* Frame-type specific data. */
jclass klass; jclass klass;
_Jv_Method *meth; _Jv_Method *meth;
}; };
typedef struct _Jv_UnwindState;
typedef _Unwind_Reason_Code (*_Jv_TraceFn) (_Jv_UnwindState *);
struct _Jv_UnwindState
{
jint length; // length of FRAMES
jint pos; // current position in FRAMES
_Jv_StackFrame *frames; // array of stack frame data to be filled.
_Jv_InterpFrame *interp_frame; // current frame in the interpreter stack.
_Jv_TraceFn trace_function; // function to call back after each frame
// is enumerated. May be NULL.
void *trace_data; // additional state data for trace_function.
_Jv_UnwindState (jint ln)
{
length = ln;
pos = 0;
frames = NULL;
Thread *thread = Thread::currentThread();
// Check for NULL currentThread(), in case an exception is created
// very early during the runtime startup.
if (thread)
interp_frame = (_Jv_InterpFrame *) thread->interp_frame;
trace_function = NULL;
trace_data = NULL;
}
};
class _Jv_StackTrace class _Jv_StackTrace
{ {
private: private:
...@@ -65,20 +98,28 @@ private: ...@@ -65,20 +98,28 @@ private:
_Jv_StackFrame frames[]; _Jv_StackFrame frames[];
static void UpdateNCodeMap (); static void UpdateNCodeMap ();
static jclass ClassForIP (void *ip, void **ncode); static jclass ClassForFrame (_Jv_StackFrame *frame);
static void FillInFrameInfo (_Jv_StackFrame *frame); static void FillInFrameInfo (_Jv_StackFrame *frame);
static void getLineNumberForFrame(_Jv_StackFrame *frame, NameFinder *finder, static void getLineNumberForFrame(_Jv_StackFrame *frame, NameFinder *finder,
jstring *sourceFileName, jint *lineNum); jstring *sourceFileName, jint *lineNum);
static _Unwind_Reason_Code UnwindTraceFn (struct _Unwind_Context *context, static _Unwind_Reason_Code UnwindTraceFn (struct _Unwind_Context *context,
void *state_ptr); void *state_ptr);
static _Unwind_Reason_Code calling_class_trace_fn (_Jv_UnwindState *state);
static _Unwind_Reason_Code non_system_trace_fn (_Jv_UnwindState *state);
public: public:
static _Jv_StackTrace *GetStackTrace (void); static _Jv_StackTrace *GetStackTrace (void);
static JArray< ::java::lang::StackTraceElement *>* static JArray< ::java::lang::StackTraceElement *>*
GetStackTraceElements (_Jv_StackTrace *trace, GetStackTraceElements (_Jv_StackTrace *trace,
java::lang::Throwable *throwable); java::lang::Throwable *throwable);
static jclass GetCallingClass (void); static jclass GetCallingClass (jclass);
static void GetCallerInfo (jclass checkClass, jclass *, _Jv_Method **);
static JArray<jclass> *GetClassContext (jclass checkClass);
static ClassLoader *GetFirstNonSystemClassLoader (void);
}; };
#endif /* __JV_STACKTRACE_H__ */ #endif /* __JV_STACKTRACE_H__ */
...@@ -120,20 +120,6 @@ union _Jv_value ...@@ -120,20 +120,6 @@ union _Jv_value
jobject object_value; jobject object_value;
}; };
// An instance of this type is used to represent a single frame in a
// backtrace. If the interpreter has been built, we also include
// information about the interpreted method.
struct _Jv_frame_info
{
// PC value.
void *addr;
#ifdef INTERPRETER
// Actually a _Jv_InterpMethod, but we don't want to include
// java-interp.h everywhere.
void *interp;
#endif // INTERPRETER
};
/* Extract a character from a Java-style Utf8 string. /* Extract a character from a Java-style Utf8 string.
* PTR points to the current character. * PTR points to the current character.
* LIMIT points to the end of the Utf8 string. * LIMIT points to the end of the Utf8 string.
......
...@@ -21,7 +21,6 @@ details. */ ...@@ -21,7 +21,6 @@ details. */
#include <java/lang/reflect/Modifier.h> #include <java/lang/reflect/Modifier.h>
#include <java/security/ProtectionDomain.h> #include <java/security/ProtectionDomain.h>
#include <java/lang/Package.h> #include <java/lang/Package.h>
#include <gnu/gcj/runtime/StackTrace.h>
// We declare these here to avoid including gcj/cni.h. // We declare these here to avoid including gcj/cni.h.
extern "C" void _Jv_InitClass (jclass klass); extern "C" void _Jv_InitClass (jclass klass);
...@@ -238,13 +237,13 @@ jclass _Jv_GetArrayClass (jclass klass, java::lang::ClassLoader *loader); ...@@ -238,13 +237,13 @@ jclass _Jv_GetArrayClass (jclass klass, java::lang::ClassLoader *loader);
jboolean _Jv_IsInterpretedClass (jclass); jboolean _Jv_IsInterpretedClass (jclass);
void _Jv_InitField (jobject, jclass, int); void _Jv_InitField (jobject, jclass, int);
class _Jv_ClassReader; class _Jv_ClassReader;
class _Jv_InterpClass; class _Jv_InterpClass;
class _Jv_InterpMethod; class _Jv_InterpMethod;
#endif #endif
class _Jv_StackTrace;
class _Jv_BytecodeVerifier; class _Jv_BytecodeVerifier;
class gnu::gcj::runtime::StackTrace;
class java::io::VMObjectStreamClass; class java::io::VMObjectStreamClass;
void _Jv_sharedlib_register_hook (jclass klass); void _Jv_sharedlib_register_hook (jclass klass);
...@@ -473,6 +472,7 @@ private: ...@@ -473,6 +472,7 @@ private:
friend class ::_Jv_ClassReader; friend class ::_Jv_ClassReader;
friend class ::_Jv_InterpClass; friend class ::_Jv_InterpClass;
friend class ::_Jv_InterpMethod; friend class ::_Jv_InterpMethod;
friend class ::_Jv_StackTrace;
#endif #endif
#ifdef JV_MARKOBJ_DECL #ifdef JV_MARKOBJ_DECL
...@@ -480,7 +480,6 @@ private: ...@@ -480,7 +480,6 @@ private:
#endif #endif
friend class ::_Jv_BytecodeVerifier; friend class ::_Jv_BytecodeVerifier;
friend class gnu::gcj::runtime::StackTrace;
friend class java::io::VMObjectStreamClass; friend class java::io::VMObjectStreamClass;
friend class ::_Jv_Linker; friend class ::_Jv_Linker;
......
...@@ -304,12 +304,10 @@ final class VMClassLoader ...@@ -304,12 +304,10 @@ final class VMClassLoader
default_sys default_sys
= (ClassLoader) c.newInstance(new Object[] { default_sys }); = (ClassLoader) c.newInstance(new Object[] { default_sys });
} }
catch (Exception e) catch (Exception ex)
{ {
System.err.println("Requested system classloader " throw new Error("Failed to load requested system classloader "
+ loader + " failed, using " + loader, ex);
+ "gnu.gcj.runtime.VMClassLoader");
e.printStackTrace();
} }
} }
return default_sys; return default_sys;
......
/* java.lang.VMThrowable -- VM support methods for Throwable. /* java.lang.VMThrowable -- VM support methods for Throwable.
Copyright (C) 1998, 1999, 2002, 2004 Free Software Foundation, Inc. Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
...@@ -37,8 +37,7 @@ exception statement from your version. */ ...@@ -37,8 +37,7 @@ exception statement from your version. */
package java.lang; package java.lang;
import gnu.gcj.runtime.NameFinder; import gnu.gcj.RawDataManaged;
import gnu.gcj.runtime.StackTrace;
/** /**
* VM dependent state and support methods Throwable. * VM dependent state and support methods Throwable.
...@@ -51,10 +50,8 @@ import gnu.gcj.runtime.StackTrace; ...@@ -51,10 +50,8 @@ import gnu.gcj.runtime.StackTrace;
*/ */
final class VMThrowable final class VMThrowable
{ {
private gnu.gcj.runtime.StackTrace trace;
/** /**
* Private contructor, create VMThrowables with fillInStackTrace(); * Private contructor, create VMThrowables with StackTrace();
*/ */
private VMThrowable() { } private VMThrowable() { }
...@@ -67,20 +64,7 @@ final class VMThrowable ...@@ -67,20 +64,7 @@ final class VMThrowable
* @return a new VMThrowable containing the current execution stack trace. * @return a new VMThrowable containing the current execution stack trace.
* @see Throwable#fillInStackTrace() * @see Throwable#fillInStackTrace()
*/ */
static VMThrowable fillInStackTrace(Throwable t) static native VMThrowable fillInStackTrace(Throwable t);
{
VMThrowable state = null;
/* FIXME: size of the stack trace is limited to 128 elements.
It's undoubtedly sensible to limit the stack trace, but 128 is
rather arbitrary. It may be better to configure this. */
if (trace_enabled)
{
state = new VMThrowable ();
state.trace = new gnu.gcj.runtime.StackTrace(128);
}
return state;
}
/** /**
* Returns an <code>StackTraceElement</code> array based on the execution * Returns an <code>StackTraceElement</code> array based on the execution
...@@ -90,21 +74,11 @@ final class VMThrowable ...@@ -90,21 +74,11 @@ final class VMThrowable
* @return a non-null but possible zero length array of StackTraceElement. * @return a non-null but possible zero length array of StackTraceElement.
* @see Throwable#getStackTrace() * @see Throwable#getStackTrace()
*/ */
StackTraceElement[] getStackTrace(Throwable t) native StackTraceElement[] getStackTrace(Throwable t);
{
StackTraceElement[] result;
if (trace != null)
{
NameFinder nameFinder = new NameFinder();
result = nameFinder.lookup(t, trace);
nameFinder.close();
}
else
result = new StackTraceElement[0];
return result;
}
// Setting this flag to false prevents fillInStackTrace() from running. // Setting this flag to false prevents fillInStackTrace() from running.
static boolean trace_enabled = true; static boolean trace_enabled = true;
// Native stack data.
private RawDataManaged data;
} }
...@@ -53,7 +53,6 @@ details. */ ...@@ -53,7 +53,6 @@ details. */
#include <java/lang/SecurityManager.h> #include <java/lang/SecurityManager.h>
#include <java/lang/StringBuffer.h> #include <java/lang/StringBuffer.h>
#include <java/lang/VMClassLoader.h> #include <java/lang/VMClassLoader.h>
#include <gnu/gcj/runtime/StackTrace.h>
#include <gcj/method.h> #include <gcj/method.h>
#include <gnu/gcj/runtime/MethodRef.h> #include <gnu/gcj/runtime/MethodRef.h>
#include <gnu/gcj/RawData.h> #include <gnu/gcj/RawData.h>
...@@ -62,6 +61,7 @@ details. */ ...@@ -62,6 +61,7 @@ details. */
#include <java-cpool.h> #include <java-cpool.h>
#include <java-interp.h> #include <java-interp.h>
#include <java-assert.h> #include <java-assert.h>
#include <java-stack.h>
#include <execution.h> #include <execution.h>
...@@ -101,20 +101,10 @@ jclass ...@@ -101,20 +101,10 @@ jclass
java::lang::Class::forName (jstring className) java::lang::Class::forName (jstring className)
{ {
java::lang::ClassLoader *loader = NULL; java::lang::ClassLoader *loader = NULL;
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4); jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
java::lang::Class *klass = NULL; if (caller)
try loader = caller->getClassLoaderInternal();
{
for (int i = 1; !klass; i++)
{
klass = t->classAt (i);
}
loader = klass->getClassLoaderInternal();
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
return forName (className, true, loader); return forName (className, true, loader);
} }
...@@ -125,21 +115,10 @@ java::lang::Class::getClassLoader (void) ...@@ -125,21 +115,10 @@ java::lang::Class::getClassLoader (void)
java::lang::SecurityManager *s = java::lang::System::getSecurityManager(); java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
if (s != NULL) if (s != NULL)
{ {
gnu::gcj::runtime::StackTrace *t jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
ClassLoader *caller_loader = NULL; ClassLoader *caller_loader = NULL;
try if (caller)
{ caller_loader = caller->getClassLoaderInternal();
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
caller_loader = caller->getClassLoaderInternal();
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
// If the caller has a non-null class loader, and that loader // If the caller has a non-null class loader, and that loader
// is not this class' loader or an ancestor thereof, then do a // is not this class' loader or an ancestor thereof, then do a
......
...@@ -16,6 +16,7 @@ details. */ ...@@ -16,6 +16,7 @@ details. */
#include <gcj/cni.h> #include <gcj/cni.h>
#include <jvm.h> #include <jvm.h>
#include <java-props.h> #include <java-props.h>
#include <java-stack.h>
#include <java/lang/Long.h> #include <java/lang/Long.h>
#include <java/lang/Runtime.h> #include <java/lang/Runtime.h>
#include <java/lang/UnknownError.h> #include <java/lang/UnknownError.h>
...@@ -29,8 +30,6 @@ details. */ ...@@ -29,8 +30,6 @@ details. */
#include <java/lang/Process.h> #include <java/lang/Process.h>
#include <java/lang/ConcreteProcess.h> #include <java/lang/ConcreteProcess.h>
#include <java/lang/ClassLoader.h> #include <java/lang/ClassLoader.h>
#include <gnu/gcj/runtime/StackTrace.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <jni.h> #include <jni.h>
...@@ -164,27 +163,7 @@ java::lang::Runtime::_load (jstring path, jboolean do_search) ...@@ -164,27 +163,7 @@ java::lang::Runtime::_load (jstring path, jboolean do_search)
if (do_search) if (do_search)
{ {
ClassLoader *sys = ClassLoader::systemClassLoader; ClassLoader *sys = ClassLoader::systemClassLoader;
ClassLoader *look = NULL; ClassLoader *look = _Jv_StackTrace::GetFirstNonSystemClassLoader ();
gnu::gcj::runtime::StackTrace *t = new gnu::gcj::runtime::StackTrace(10);
try
{
for (int i = 0; i < 10; ++i)
{
jclass klass = t->classAt(i);
if (klass != NULL)
{
ClassLoader *loader = klass->getClassLoaderInternal();
if (loader != NULL && loader != sys)
{
look = loader;
break;
}
}
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
if (look != NULL) if (look != NULL)
{ {
......
...@@ -12,43 +12,18 @@ details. */ ...@@ -12,43 +12,18 @@ details. */
#include <gcj/cni.h> #include <gcj/cni.h>
#include <jvm.h> #include <jvm.h>
#include <java-stack.h>
#include <java/lang/VMSecurityManager.h> #include <java/lang/VMSecurityManager.h>
#include <java/lang/SecurityManager.h> #include <java/lang/SecurityManager.h>
#include <java/lang/ClassLoader.h> #include <java/lang/ClassLoader.h>
#include <java/lang/Class.h> #include <java/lang/Class.h>
#include <gnu/gcj/runtime/StackTrace.h>
JArray<jclass> * JArray<jclass> *
java::lang::VMSecurityManager::getClassContext () java::lang::VMSecurityManager::getClassContext ()
{ {
JArray<jclass> *result = NULL; JArray<jclass> *result =
gnu::gcj::runtime::StackTrace *t = new gnu::gcj::runtime::StackTrace(); _Jv_StackTrace::GetClassContext (&SecurityManager::class$);
if (t)
{
int maxlen = t->length();
int len = 0;
for (int i=0; i<maxlen; i++)
{
jclass klass = t->classAt(i);
if (klass != NULL && klass != &java::lang::VMSecurityManager::class$
&& klass != &java::lang::SecurityManager::class$)
++len;
}
result =
(JArray<jclass> *) _Jv_NewObjectArray (len, &java::lang::Class::class$,
NULL);
len = 0;
for (int i=0; i<maxlen; i++)
{
jclass klass = t->classAt(i);
if (klass != NULL && klass != &java::lang::VMSecurityManager::class$
&& klass != &java::lang::SecurityManager::class$)
elements(result)[len++] = klass;
}
}
return result; return result;
} }
// natVMThrowable.cc - Native part of VMThrowable class.
/* Copyright (C) 2003 Free Software Foundation
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. */
#include <config.h>
#include <stdlib.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <java-stack.h>
#include <java/lang/Throwable.h>
#include <java/lang/VMThrowable.h>
using namespace gnu::gcj;
java::lang::VMThrowable *
java::lang::VMThrowable::fillInStackTrace (java::lang::Throwable *)
{
using namespace java::lang;
// Don't trace stack during initialization of the runtime.
if (! trace_enabled)
return NULL;
_Jv_StackTrace *trace = _Jv_StackTrace::GetStackTrace ();
VMThrowable *vmthrowable = new VMThrowable ();
vmthrowable->data = (RawDataManaged *) trace;
return vmthrowable;
}
JArray< ::java::lang::StackTraceElement *> *
java::lang::VMThrowable::getStackTrace (java::lang::Throwable *throwable)
{
_Jv_StackTrace *trace = reinterpret_cast <_Jv_StackTrace *> (data);
return _Jv_StackTrace::GetStackTraceElements (trace, throwable);
}
...@@ -14,6 +14,7 @@ details. */ ...@@ -14,6 +14,7 @@ details. */
#include <jvm.h> #include <jvm.h>
#include <gcj/cni.h> #include <gcj/cni.h>
#include <java-stack.h>
#include <java/lang/reflect/Array.h> #include <java/lang/reflect/Array.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h> #include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/IllegalArgumentException.h> #include <java/lang/IllegalArgumentException.h>
...@@ -54,21 +55,10 @@ java::lang::reflect::Array::newInstance (jclass componentType, ...@@ -54,21 +55,10 @@ java::lang::reflect::Array::newInstance (jclass componentType,
if (ndims == 1) if (ndims == 1)
return newInstance (componentType, dims[0]); return newInstance (componentType, dims[0]);
gnu::gcj::runtime::StackTrace *t Class *caller = _Jv_StackTrace::GetCallingClass (&Array::class$);
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
ClassLoader *caller_loader = NULL; ClassLoader *caller_loader = NULL;
try if (caller)
{ caller_loader = caller->getClassLoaderInternal();
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
caller_loader = caller->getClassLoaderInternal();
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
jclass arrayType = componentType; jclass arrayType = componentType;
for (int i = 0; i < ndims; i++) for (int i = 0; i < ndims; i++)
......
...@@ -12,6 +12,7 @@ details. */ ...@@ -12,6 +12,7 @@ details. */
#include <gcj/cni.h> #include <gcj/cni.h>
#include <jvm.h> #include <jvm.h>
#include <java-stack.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h> #include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/IllegalAccessException.h> #include <java/lang/IllegalAccessException.h>
...@@ -55,20 +56,7 @@ java::lang::reflect::Constructor::newInstance (jobjectArray args) ...@@ -55,20 +56,7 @@ java::lang::reflect::Constructor::newInstance (jobjectArray args)
// Check accessibility, if required. // Check accessibility, if required.
if (! (Modifier::isPublic (meth->accflags) || this->isAccessible())) if (! (Modifier::isPublic (meth->accflags) || this->isAccessible()))
{ {
gnu::gcj::runtime::StackTrace *t Class *caller = _Jv_StackTrace::GetCallingClass (&Constructor::class$);
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags)) if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags))
throw new IllegalAccessException; throw new IllegalAccessException;
} }
......
...@@ -13,6 +13,7 @@ details. */ ...@@ -13,6 +13,7 @@ details. */
#include <stdlib.h> #include <stdlib.h>
#include <jvm.h> #include <jvm.h>
#include <java-stack.h>
#include <java/lang/reflect/Field.h> #include <java/lang/reflect/Field.h>
#include <java/lang/reflect/Modifier.h> #include <java/lang/reflect/Modifier.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h> #include <java/lang/ArrayIndexOutOfBoundsException.h>
...@@ -78,18 +79,7 @@ getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj, ...@@ -78,18 +79,7 @@ getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj,
// Check accessibility, if required. // Check accessibility, if required.
if (! (Modifier::isPublic (flags) || field->isAccessible())) if (! (Modifier::isPublic (flags) || field->isAccessible()))
{ {
gnu::gcj::runtime::StackTrace *t caller = _Jv_StackTrace::GetCallingClass (&Field::class$);
= new gnu::gcj::runtime::StackTrace(7);
try
{
// We want to skip all the frames on the stack from this class.
for (int i = 1; !caller || caller == &Field::class$; i++)
caller = t->classAt (i);
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
if (! _Jv_CheckAccess (caller, field->getDeclaringClass(), flags)) if (! _Jv_CheckAccess (caller, field->getDeclaringClass(), flags))
throw new java::lang::IllegalAccessException; throw new java::lang::IllegalAccessException;
} }
......
...@@ -13,6 +13,7 @@ details. */ ...@@ -13,6 +13,7 @@ details. */
#include <gcj/cni.h> #include <gcj/cni.h>
#include <jvm.h> #include <jvm.h>
#include <jni.h> #include <jni.h>
#include <java-stack.h>
#include <java/lang/reflect/Method.h> #include <java/lang/reflect/Method.h>
#include <java/lang/reflect/Constructor.h> #include <java/lang/reflect/Constructor.h>
...@@ -168,20 +169,7 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args) ...@@ -168,20 +169,7 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
// Check accessibility, if required. // Check accessibility, if required.
if (! (Modifier::isPublic (meth->accflags) || this->isAccessible())) if (! (Modifier::isPublic (meth->accflags) || this->isAccessible()))
{ {
gnu::gcj::runtime::StackTrace *t Class *caller = _Jv_StackTrace::GetCallingClass (&Method::class$);
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags)) if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags))
throw new IllegalAccessException; throw new IllegalAccessException;
} }
......
...@@ -17,7 +17,7 @@ details. */ ...@@ -17,7 +17,7 @@ details. */
#include <gcj/cni.h> #include <gcj/cni.h>
#include <jvm.h> #include <jvm.h>
#include <java-stack.h>
#include <java/lang/Object.h> #include <java/lang/Object.h>
#include <java/lang/Class.h> #include <java/lang/Class.h>
...@@ -25,31 +25,19 @@ details. */ ...@@ -25,31 +25,19 @@ details. */
#include <java/lang/StackTraceElement.h> #include <java/lang/StackTraceElement.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h> #include <java/lang/ArrayIndexOutOfBoundsException.h>
using namespace java::util::logging;
java::lang::StackTraceElement* java::lang::StackTraceElement*
java::util::logging::Logger::getCallerStackFrame () java::util::logging::Logger::getCallerStackFrame ()
{ {
gnu::gcj::runtime::StackTrace *t jclass klass = NULL;
= new gnu::gcj::runtime::StackTrace(4); _Jv_Method *meth = NULL;
java::lang::Class *klass = NULL; _Jv_StackTrace::GetCallerInfo (&Logger::class$, &klass, &meth);
int i = 2;
try
{
// skip until this class
while ((klass = t->classAt (i)) != getClass())
i++;
// skip the stackentries of this class
while ((klass = t->classAt (i)) == getClass() || klass == NULL)
i++;
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
// FIXME: RuntimeError
}
java::lang::StackTraceElement *e java::lang::StackTraceElement *e
= new java::lang::StackTraceElement = new java::lang::StackTraceElement
(JvNewStringUTF (""), 0, (JvNewStringUTF (""), 0,
klass->getName(), t->methodAt(i), false); klass->getName(), _Jv_NewStringUtf8Const (meth->name), false);
return e; return e;
} }
/* Copyright (C) 2002, 2003 Free Software Foundation /* Copyright (C) 2002, 2003, 2005 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -12,31 +12,18 @@ details. */ ...@@ -12,31 +12,18 @@ details. */
#include <gcj/cni.h> #include <gcj/cni.h>
#include <jvm.h> #include <jvm.h>
#include <java-stack.h>
#include <java/util/ResourceBundle.h> #include <java/util/ResourceBundle.h>
#include <java/lang/SecurityManager.h>
#include <java/lang/ClassLoader.h> #include <java/lang/ClassLoader.h>
#include <java/lang/Class.h> #include <java/lang/Class.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <gnu/gcj/runtime/StackTrace.h> using namespace java::lang;
java::lang::ClassLoader * java::lang::ClassLoader *
java::util::ResourceBundle::getCallingClassLoader () java::util::ResourceBundle::getCallingClassLoader ()
{ {
gnu::gcj::runtime::StackTrace *t = new gnu::gcj::runtime::StackTrace(6); jclass caller = _Jv_StackTrace::GetCallingClass (&ResourceBundle::class$);
try if (caller)
{ return caller->getClassLoaderInternal();
/* Frame 0 is this method, frame 1 is getBundle, so starting at
frame 2 we might see the user's class. FIXME: should account
for reflection, JNI, etc, here. */
for (int i = 2; ; ++i)
{
jclass klass = t->classAt(i);
if (klass != NULL)
return klass->getClassLoaderInternal();
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
return NULL; return NULL;
} }
...@@ -147,10 +147,10 @@ unblock_signal (int signum __attribute__ ((__unused__))) ...@@ -147,10 +147,10 @@ unblock_signal (int signum __attribute__ ((__unused__)))
#ifdef HANDLE_SEGV #ifdef HANDLE_SEGV
SIGNAL_HANDLER (catch_segv) SIGNAL_HANDLER (catch_segv)
{ {
java::lang::NullPointerException *nullp
= new java::lang::NullPointerException;
unblock_signal (SIGSEGV); unblock_signal (SIGSEGV);
MAKE_THROW_FRAME (nullp); MAKE_THROW_FRAME (nullp);
java::lang::NullPointerException *nullp
= new java::lang::NullPointerException;
throw nullp; throw nullp;
} }
#endif #endif
...@@ -158,14 +158,14 @@ SIGNAL_HANDLER (catch_segv) ...@@ -158,14 +158,14 @@ SIGNAL_HANDLER (catch_segv)
#ifdef HANDLE_FPE #ifdef HANDLE_FPE
SIGNAL_HANDLER (catch_fpe) SIGNAL_HANDLER (catch_fpe)
{ {
java::lang::ArithmeticException *arithexception
= new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
unblock_signal (SIGFPE); unblock_signal (SIGFPE);
#ifdef HANDLE_DIVIDE_OVERFLOW #ifdef HANDLE_DIVIDE_OVERFLOW
HANDLE_DIVIDE_OVERFLOW; HANDLE_DIVIDE_OVERFLOW;
#else #else
MAKE_THROW_FRAME (arithexception); MAKE_THROW_FRAME (arithexception);
#endif #endif
java::lang::ArithmeticException *arithexception
= new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
throw arithexception; throw arithexception;
} }
#endif #endif
......
// backtrace.h - Fallback backtrace implementation. default implementation.
/* Copyright (C) 2005 Free Software Foundation
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. */
#ifndef __SYSDEP_BACKTRACE_H__
#define __SYSDEP_BACKTRACE_H__
#include <java-stack.h>
/* Store return addresses of the current program stack in
STATE and return the exact number of values stored. */
void
fallback_backtrace (_Jv_UnwindState *)
{
}
#endif
// backtrace.h - Fallback backtrace implementation. i386 implementation.
/* Copyright (C) 2005 Free Software Foundation
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. */
#ifndef __SYSDEP_BACKTRACE_H__
#define __SYSDEP_BACKTRACE_H__
#include <java-stack.h>
#define HAVE_FALLBACK_BACKTRACE
/* Store return addresses of the current program stack in
STATE and return the exact number of values stored. */
void
fallback_backtrace (_Jv_UnwindState *state)
{
register void *_ebp __asm__ ("ebp");
register void *_esp __asm__ ("esp");
unsigned int *rfp;
int i = state->pos;
for (rfp = *(unsigned int**)_ebp;
rfp && i < state->length;
rfp = *(unsigned int **)rfp)
{
int diff = *rfp - (unsigned int)rfp;
if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0)
break;
state->frames[i].type = frame_native;
state->frames[i].ip = (void*)(rfp[1]-4);
i++;
}
state->pos = i;
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment