From 242cbae52cc953bbfdbd188e04cd27a05d4ba9a2 Mon Sep 17 00:00:00 2001 From: jowenn Date: Mon, 15 Mar 2004 07:37:49 +0000 Subject: [PATCH] exception back traces for i386 --- Makefile.am | 3 +- asmpart.h | 4 +- builtin.c | 44 +++++-- builtin.h | 5 +- global.h | 15 ++- headers.c | 3 +- jit/alpha/asmpart.S | 18 ++- jit/alpha/codegen.c | 14 ++- jit/codegen.inc | 41 +++++-- jit/i386/asmpart.S | 148 +++++++++++++++++++++-- jit/i386/codegen.c | 6 +- jni.c | 4 +- loader.c | 11 +- main.c | 32 +++-- main.h | 3 +- nat/Makefile.am | 3 +- nat/VMThrowable.c | 152 ++++++++++++++++++++++++ nat/java_lang_VMThrowable.h | 30 +++++ src/cacao/cacao.c | 32 +++-- src/cacao/cacao.h | 3 +- src/cacaoh/headers.c | 3 +- src/native/jni.c | 4 +- src/native/vm/Makefile.am | 3 +- src/native/vm/VMThrowable.c | 152 ++++++++++++++++++++++++ src/vm/builtin.c | 44 +++++-- src/vm/builtin.h | 5 +- src/vm/global.h | 15 ++- src/vm/jit/alpha/asmpart.S | 18 ++- src/vm/jit/alpha/codegen.c | 14 ++- src/vm/jit/asmpart.h | 4 +- src/vm/jit/codegen.inc | 41 +++++-- src/vm/jit/i386/asmpart.S | 148 +++++++++++++++++++++-- src/vm/jit/i386/codegen.c | 6 +- src/vm/loader.c | 11 +- src/vm/tables.c | 3 +- tables.c | 3 +- tests/stack/classcontextnativeTest.java | 66 +++++----- tests/stack/exception.java | 7 ++ 38 files changed, 978 insertions(+), 140 deletions(-) create mode 100644 nat/VMThrowable.c create mode 100644 nat/java_lang_VMThrowable.h create mode 100644 src/native/vm/VMThrowable.c diff --git a/Makefile.am b/Makefile.am index 98f6fc8dd..265304cdf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -# $Id: Makefile.am 914 2004-02-05 21:44:29Z twisti $ +# $Id: Makefile.am 963 2004-03-15 07:37:49Z jowenn $ @SET_MAKE@ @@ -199,6 +199,7 @@ nativetypes.hh jit/@ARCH_DIR@/offsets.h nativetable.hh: cacaoh Makefile.am Makef java.util.Properties \ java.lang.Runtime \ java.lang.Throwable \ + java.lang.VMThrowable \ gnu.java.security.x509.X509Certificate \ java.lang.JOWENNTest1 \ @AWTPEERS@ diff --git a/asmpart.h b/asmpart.h index 3da6d4c7f..b938f1158 100644 --- a/asmpart.h +++ b/asmpart.h @@ -29,7 +29,7 @@ Changes: Christian Thalinger - $Id: asmpart.h 930 2004-03-02 21:18:23Z jowenn $ + $Id: asmpart.h 963 2004-03-15 07:37:49Z jowenn $ */ @@ -90,6 +90,8 @@ void asm_handle_builtin_exception(classinfo *); methodinfo *asm_getcallingmethod(); java_objectarray* Java_java_lang_VMSecurityManager_getClassContext(JNIEnv *env, jclass clazz); +stacktraceelement *asm_get_stackTrace(); + /*java_lang_ClassLoader* Java_java_lang_VMSecurityManager_currentClassLoader(JNIEnv *env, jclass clazz);*/ /* This funtion saves all callee saved registers and calls the function diff --git a/builtin.c b/builtin.c index acd8f5070..6f003d3a0 100644 --- a/builtin.c +++ b/builtin.c @@ -34,7 +34,7 @@ calls instead of machine instructions, using the C calling convention. - $Id: builtin.c 957 2004-03-14 21:01:12Z twisti $ + $Id: builtin.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -775,8 +775,8 @@ java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims) u4 methodindent = 0; java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, - methodinfo *method, - int *pos, + methodinfo *method, int *pos, + int line, int noindent) { if (!noindent) { @@ -785,12 +785,14 @@ java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, else log_text("WARNING: unmatched methodindent--"); } - if (verbose || runverbose) { - printf("Exception "); + if (verbose || runverbose || verboseexception) { if (_exceptionptr) { - utf_display_classname(_exceptionptr->vftbl->class->name); + printf("Exception "); + utf_display(_exceptionptr->vftbl->class->name); } else { + printf("Some Throwable"); +/* printf("Error: "); if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0"); if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0"); @@ -802,7 +804,7 @@ java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0"); if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0"); if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0"); - + */ } printf(" thrown in "); @@ -811,10 +813,20 @@ java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, printf("."); utf_display(method->name); if (method->flags & ACC_SYNCHRONIZED) - printf("(SYNC)"); + printf("(SYNC"); else - printf("(NOSYNC)"); - printf("(%p) at position %p\n", method->entrypoint, pos); + printf("(NOSYNC"); + if (method->flags & ACC_NATIVE) { + printf(",NATIVE"); + printf(")(%p) at position %p\n", method->entrypoint, pos); + } else { + printf(")(%p) at position %p (",method->entrypoint,pos); + if (method->class->sourcefile==NULL) + printf(""); + else + utf_display(method->class->sourcefile); + printf(":%d)\n",line); + } } else printf("call_java_method\n"); @@ -1825,6 +1837,18 @@ builtin_asm_get_stackframeinfo(){ #endif } +stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) { +/* stacktraceelement *el;*/ + size_t s; + s=(end-begin); + /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/ + *el=GCNEW(stacktraceelement,s+1); + memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement)); + (*el)[s].method=0; + (*el)[s].linenumber=0; + return *el; +} + /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where diff --git a/builtin.h b/builtin.h index c223378c5..bc290a456 100644 --- a/builtin.h +++ b/builtin.h @@ -28,7 +28,7 @@ Changes: Edwin Steiner - $Id: builtin.h 951 2004-03-11 17:30:03Z jowenn $ + $Id: builtin.h 963 2004-03-15 07:37:49Z jowenn $ */ @@ -172,7 +172,7 @@ java_objectheader *builtin_throw_exception(java_objectheader *exception); /* NOT AN OP */ java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, methodinfo *method, - int *pos, int noindent); + int *pos, int line, int noindent); /* NOT AN OP */ static inline java_objectheader **builtin_get_exceptionptrptr(); @@ -418,6 +418,7 @@ points here---->| previous element in list | ------------------------------------------------ */ void *builtin_asm_get_stackframeinfo(); +stacktraceelement *builtin_stacktrace_copy(stacktraceelement **,stacktraceelement *begin, stacktraceelement *end); #endif /* _BUILTIN_H */ diff --git a/global.h b/global.h index d9cf9dd71..596059445 100644 --- a/global.h +++ b/global.h @@ -31,7 +31,7 @@ Philipp Tomsich Edwin Steiner - $Id: global.h 941 2004-03-06 17:27:56Z jowenn $ + $Id: global.h 963 2004-03-15 07:37:49Z jowenn $ */ @@ -301,6 +301,17 @@ struct native_stackframeinfo { typedef struct native_stackframeinfo native_stackframeinfo; +struct stacktraceelement { +#if POINTERSIZE == 8 + u8 linenumber; +#else + u4 linenumber; +#endif + methodinfo *method; +}; + +typedef struct stacktraceelement stacktraceelement; + /* data structure for calls from c code to java methods */ struct jni_callblock { @@ -668,6 +679,7 @@ struct classinfo { /* class structure */ classSetNode *impldBy; /* implemented by class set */ utf *packagename; /* full name of the package */ + utf *sourcefile; /* classfile name containing this class */ java_objectheader *classloader; /* 0 for bootstrap classloader */ }; @@ -836,6 +848,7 @@ extern java_objectheader *proto_java_lang_ThreadDeath; extern bool compileall; extern bool runverbose; +extern bool verboseexception; extern bool verbose; extern bool opt_rt; /* Rapid Type Analysis for better inlining CO-RT*/ extern bool opt_xta; /* X Type Analysis for better inlining CO-XTA*/ diff --git a/headers.c b/headers.c index e4dd1bfca..0d6e8a878 100644 --- a/headers.c +++ b/headers.c @@ -29,7 +29,7 @@ Changes: Mark Probst Philipp Tomsich - $Id: headers.c 960 2004-03-14 23:41:11Z twisti $ + $Id: headers.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -52,6 +52,7 @@ /* replace command line options */ bool verbose = false; +bool verboseexception = false; bool compileall = false; bool runverbose = false; bool collectverbose = false; diff --git a/jit/alpha/asmpart.S b/jit/alpha/asmpart.S index c377bc333..04a3968ee 100644 --- a/jit/alpha/asmpart.S +++ b/jit/alpha/asmpart.S @@ -28,7 +28,7 @@ Authors: Andreas Krall Reinhard Grafl - $Id: asmpart.S 948 2004-03-07 22:12:28Z twisti $ + $Id: asmpart.S 963 2004-03-15 07:37:49Z jowenn $ */ @@ -171,8 +171,11 @@ synchronize_caches: #define IsLeaf -20 #define IntSave -24 #define FltSave -28 -#define ExTableSize -32 -#define ExTableStart -32 +#define LineNumberTableSize -32 +#define LineNumberTableStart -40 +#define ExTableSize -48 +#define ExTableStart -48 + #define ExEntrySize -32 #define ExStartPC -8 @@ -180,6 +183,11 @@ synchronize_caches: #define ExHandlerPC -24 #define ExCatchType -32 +#define LineEntrySize -16 +#define LinePC 0 +#define LineLine -8 + + /********************* function asm_calljavafunction *************************** * * * This function calls a Java-method (which possibly needs compilation) * @@ -205,6 +213,8 @@ call_name: .quad calljava_xhandler /* end pc */ .quad asm_calljavafunction /* start pc */ .long 1 /* extable size */ + .quad 0 /* line number table start */ + .quad 0 /* line number table size */ .long 0 /* fltsave */ .long 0 /* intsave */ .long 0 /* isleaf */ @@ -266,6 +276,8 @@ call_name2: .quad calljava_xhandler2 /* end pc */ .quad asm_calljavafunction2 /* start pc */ .long 1 /* extable size */ + .quad 0 /* line number table start */ + .quad 0 /* line number table size */ .long 0 /* fltsave */ .long 1 /* intsave */ .long 0 /* isleaf */ diff --git a/jit/alpha/codegen.c b/jit/alpha/codegen.c index 92f01d1d9..1f44c1c3c 100644 --- a/jit/alpha/codegen.c +++ b/jit/alpha/codegen.c @@ -28,7 +28,7 @@ Authors: Andreas Krall Reinhard Grafl - $Id: codegen.c 948 2004-03-07 22:12:28Z twisti $ + $Id: codegen.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -400,6 +400,7 @@ void codegen() basicblock *bptr; instruction *iptr; xtable *ex; + u2 currentline=0; { int p, pa, t, l, r; @@ -444,6 +445,9 @@ void codegen() (void) dseg_adds4(isleafmethod); /* IsLeaf */ (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */ (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */ + + (void) dseg_addlinenumbertablesize() /* line number table size + start*/ + (void) dseg_adds4(exceptiontablelength); /* ExTableSize */ /* create exception table */ @@ -732,6 +736,12 @@ void codegen() src = iptr->dst, len--, iptr++) { MCODECHECK(64); /* an instruction usually needs < 64 words */ + + if (iptr->line!=currentline) { + dseg_addlinenumber(iptr->line,mcodeptr); + currentline=iptr->line; + } + switch (iptr->opc) { case ICMD_NOP: /* ... ==> ... */ @@ -3658,6 +3668,8 @@ makeactualcall: /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */ + codegen_createlinenumbertable(); + { /* generate bound check stubs */ diff --git a/jit/codegen.inc b/jit/codegen.inc index 017eeee8d..cf920fb89 100644 --- a/jit/codegen.inc +++ b/jit/codegen.inc @@ -48,7 +48,7 @@ memory. All functions writing values into the data area return the offset relative the begin of the code area (start of procedure). - $Id: codegen.inc 955 2004-03-13 12:51:30Z jowenn $ + $Id: codegen.inc 963 2004-03-15 07:37:49Z jowenn $ */ @@ -87,6 +87,8 @@ static branchref *xcastrefs; /* list of cast check branches */ static branchref *xdivrefs; /* list of divide by zero branches */ static linenumberref *linenumberreferences; /*list of line numbers and the program counters of their first instruction*/ static s4 linenumbertablesizepos; +static s4 linenumbertablestartpos; +static s4 linenumbertab; static struct threadcritnodetemp *threadcrit; /* List of critical code regions */ @@ -144,6 +146,8 @@ void codegen_init() linenumberreferences=NULL; linenumbertablesizepos=0; + linenumbertablestartpos=0; + linenumbertab=0; jumpreferences = NULL; datareferences = NULL; xboundrefs = NULL; @@ -319,13 +323,14 @@ static void dseg_adddata(u1 *ptr) } static void dseg_addlinenumbertablesize() { - linenumbertablesizepos=dseg_addaddress(NULL); /*although it is not an adress, I'll do this here alignment reasons*/ + linenumbertablesizepos=dseg_addaddress(NULL); + linenumbertablestartpos=dseg_addaddress(NULL); /*although it is not an adress, I'll do this here alignment reasons*/ } static void dseg_addlinenumber(u2 linenumber,u1 *ptr) { linenumberref *lr=DNEW(linenumberref); - lr->tablepos=dseg_addaddress(NULL); - dseg_addaddress(linenumber); /*although it is not an adress, I'll do this here alignment reasons*/ + lr->linenumber=linenumber; + lr->tablepos=0; lr->targetmpc=(ptr-mcodebase); lr->next=linenumberreferences; linenumberreferences=lr; @@ -415,6 +420,22 @@ static void codegen_addxdivrefs(void *branchptr) +static void codegen_createlinenumbertable() { +#ifdef __I386__ + /*log_text("codegen_createlinnumbertable");*/ + { + linenumberref *lr; + for (lr=linenumberreferences;lr!=NULL;lr=lr->next) { + /*log_text("Adding line number entry");*/ + lr->tablepos=dseg_addaddress(NULL); + if (linenumbertab==0) linenumbertab=lr->tablepos; + dseg_addaddress(lr->linenumber); + } + } +#endif +} + + static void codegen_finish(int mcodelen) { jumpref *jr; @@ -461,11 +482,13 @@ static void codegen_finish(int mcodelen) *((void**)(epoint+lr->tablepos))=epoint+lr->targetmpc; /*log_text("resolving line number information");*/ } - #if POINTERSIZE == 8 - *((s8*)(epoint+linenumbertablesizepos))=lrtlen; - #else - *((s4*)(epoint+linenumbertablesizepos))=lrtlen; - #endif + + *((void**)(epoint+linenumbertablestartpos))=epoint+linenumbertab; +#if POINTERSIZE == 8 + *((s8*)(epoint+linenumbertablesizepos))=lrtlen; +#else + *((s4*)(epoint+linenumbertablesizepos))=lrtlen; +#endif } #endif diff --git a/jit/i386/asmpart.S b/jit/i386/asmpart.S index 64a265937..b7a5808b1 100644 --- a/jit/i386/asmpart.S +++ b/jit/i386/asmpart.S @@ -29,7 +29,7 @@ Reinhard Grafl Christian Thalinger - $Id: asmpart.S 951 2004-03-11 17:30:03Z jowenn $ + $Id: asmpart.S 963 2004-03-15 07:37:49Z jowenn $ */ @@ -45,8 +45,9 @@ #define IntSave -20 #define FltSave -24 #define LineNumberTableSize -28 -#define ExTableSize -32 -#define ExTableStart -32 +#define LineNumberTableStart -32 +#define ExTableSize -36 +#define ExTableStart -36 #define ExEntrySize -16 #define ExStartPC -4 @@ -54,6 +55,10 @@ #define ExHandlerPC -12 #define ExCatchType -16 + +#define LineEntrySize -8 +#define LinePC 0 +#define LineLine -4 .text @@ -94,6 +99,8 @@ .globl Java_java_lang_VMSecurityManager_getClassContext .globl Java_java_lang_VMSecurityManager_currentClassLoader .globl asm_builtin_new + .globl asm_get_stackTrace + /*************************** imported functions *******************************/ .globl jit_compile @@ -153,6 +160,7 @@ call_name: .long calljava_xhandler /* end pc */ .long asm_calljavafunction /* start pc */ .long 1 /* extable size */ + .long 0 /* line number table start */ .long 0 /* line number table size */ .long 0 /* fltsave */ .long 0 /* intsave */ @@ -238,6 +246,7 @@ call_name2: .long calljava_xhandler2 /* end pc */ .long asm_calljavafunction2 /* start pc */ .long 1 /* extable size */ + .long 0 /* line number table start */ .long 0 /* line number table size */ .long 0 /* fltsave */ .long 0 /* intsave */ @@ -442,6 +451,19 @@ asm_handle_nat_exception: add $4,%esp /* clear return address of native stub */ asm_handle_exception: +#if 0 + push %ebp + mov %esp,%ebp + push %eax /* exception pointer */ + push %ecx /* excepiton pc */ + + call asm_get_stackTrace + + pop %ecx + pop %eax + pop %ebp +#endif +asm_handle_exception_loop: push %ebp mov %esp,%ebp @@ -464,15 +486,17 @@ asm_handle_exception: push %edi ex_stack_loop: - sub $16,%esp + sub $20,%esp mov %eax,(%esp) /* exception pointer */ mov MethodPointer(%edx),%eax /* method pointer */ mov %eax,4(%esp) mov %ecx,8(%esp) /* exception pc */ - movl $1,12(%esp) /* set no unwind flag */ - call builtin_trace_exception - add $16,%esp + movl $0,12(%esp) /* line number */ + + movl $1,16(%esp) /* set no unwind flag */ + call builtin_trace_exception + add $20,%esp mov -12(%ebp),%esi /* %esi = data segment pointer */ mov ExTableSize(%esi),%ecx /* %ecx = exception table size */ test %ecx,%ecx /* if empty table skip */ @@ -615,7 +639,7 @@ noflt: pop %ecx /* the new xpc is return address */ sub $2,%ecx - jmp asm_handle_exception + jmp asm_handle_exception_loop /********************* function asm_check_clinit ******************************* @@ -1231,6 +1255,114 @@ asm_builtin_new: ret + + + + + + + + + + +asm_get_stackTrace: + push %ebp /*(%ebp-4)*/ + mov %esp,%ebp + add $4,%ebp + push %edi /*(%ebp-8)*/ + push %esi /*(%ebp-12)*/ + push %ebx /*(%ebp-16)*/ + call builtin_asm_get_stackframeinfo + movl (%eax),%eax + pushl 0(%eax) /*(%ebp-20)*/ + lea 12(%eax),%edi + call builtin_asm_get_threadrootmethod + pushl %eax /*(%ebp-24)*/ + + pushl (%edi) +asm_get_stackTraceLoop: + call findmethod + mov %eax,%esi + add $4,%esp + pushl $1 /*no indent*/ + + mov (%edi),%edx + sub $4,%edx + +get_stackTrace_line: + movl LineNumberTableSize(%esi),%ecx + test %ecx,%ecx /* skip if empty line table */ + je get_stackTrace_noLineInfo + + movl LineNumberTableStart(%esi),%ebx + +get_stackTrace_lineLoop: + cmp %edx,LinePC(%ebx) + jg get_stackTrace_nextLineInfo + + pushl LineLine(%ebx) + jmp get_stackTrace_cont + +get_stackTrace_nextLineInfo: + lea LineEntrySize(%ebx),%ebx + dec %ecx + test %ecx,%ecx + + jne get_stackTrace_lineLoop + +get_stackTrace_noLineInfo: + pushl $0 + + +get_stackTrace_cont: + pushl (%edi) /*4*/ + pushl MethodPointer(%esi) + pushl $0 /*8(%ebp)*/ /*exception ptr*/ + call builtin_trace_exception + add $12,%esp + + movl MethodPointer(%esi),%eax + movl %eax,4(%esp) + test %eax,%eax + je get_stackTrace_nat + + cmp %eax,-24(%ebp) + je get_stackTrace_leave + + mov FrameSize(%esi),%eax + add $4,%edi + add %eax,%edi + pushl (%edi) + jmp asm_get_stackTraceLoop + +get_stackTrace_nat: + add $8,%esp + movl -20(%ebp),%eax + cmp $0,%eax + je get_stackTrace_leave + movl 0(%eax),%ebx + movl %ebx,-20(%ebp) + pushl 8(%eax) + pushl $0 + lea 12(%eax),%edi + pushl (%edi) + jmp asm_get_stackTraceLoop + +get_stackTrace_leave: + mov %esp,%eax + lea -24(%ebp),%ebx + push %ebx + push %eax + push 4(%ebp) + call builtin_stacktrace_copy + + lea -16(%ebp),%esp + pop %ebx + pop %esi + pop %edi + pop %ebp + ret + /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where diff --git a/jit/i386/codegen.c b/jit/i386/codegen.c index 869b86947..4e34abe10 100644 --- a/jit/i386/codegen.c +++ b/jit/i386/codegen.c @@ -28,7 +28,7 @@ Authors: Andreas Krall Christian Thalinger - $Id: codegen.c 955 2004-03-13 12:51:30Z jowenn $ + $Id: codegen.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -4608,6 +4608,8 @@ gen_method: { } /* if (bptr -> flags >= BBREACHED) */ } /* for basic block */ + codegen_createlinenumbertable(); + /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */ { @@ -4836,7 +4838,7 @@ gen_method: { } } } - + codegen_finish((int)((u1*) mcodeptr - mcodebase)); } diff --git a/jni.c b/jni.c index 270684a0a..b74fadf79 100644 --- a/jni.c +++ b/jni.c @@ -28,7 +28,7 @@ Changes: Joseph Wenninger - $Id: jni.c 944 2004-03-06 20:50:31Z twisti $ + $Id: jni.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -586,7 +586,7 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar if (argcount > 3) { *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. CallObjectMethod does not support that"); + log_text("Too many arguments. CallIntegerMethod does not support that"); return 0; } diff --git a/loader.c b/loader.c index 7db23e9e4..46835c9ab 100644 --- a/loader.c +++ b/loader.c @@ -30,7 +30,7 @@ Mark Probst Edwin Steiner - $Id: loader.c 959 2004-03-14 23:39:31Z twisti $ + $Id: loader.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -87,6 +87,7 @@ static utf *utf_constantvalue; /* ConstantValue */ static utf *utf_code; /* Code */ static utf *utf_exceptions; /* Exceptions */ static utf *utf_linenumbertable; /* LineNumberTable */ +static utf *utf_sourcefile; /*SourceFile*/ static utf *utf_finalize; /* finalize */ static utf *utf_fidesc; /* ()V changed */ static utf *utf_init; /* */ @@ -696,7 +697,10 @@ static void attribute_load(u4 num, classinfo *c) info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */ info->flags = suck_u2(); /* access_flags bitmask */ } - + } else if (aname==utf_sourcefile) { + suck_u4(); + /*log_text("source file attribute found");*/ + c->sourcefile = class_getconstant(c, suck_u2(), CONSTANT_Utf8); } else { /* unknown attribute */ skipattributebody(); @@ -2279,7 +2283,7 @@ void class_link(classinfo *c) /* check super class */ - if (super == NULL) { /* class java.long.Object */ + if (super == NULL) { /* class java.lang.Object */ c->index = 0; c->classUsed = USED; /* Object class is always used CO-RT*/ c->impldBy = NULL; @@ -3803,6 +3807,7 @@ void loader_init(u1 *stackbottom) utf_code = utf_new_char("Code"); utf_exceptions = utf_new_char("Exceptions"); utf_linenumbertable = utf_new_char("LineNumberTable"); + utf_sourcefile = utf_new_char("SourceFile"); utf_finalize = utf_new_char("finalize"); utf_fidesc = utf_new_char("()V"); utf_init = utf_new_char(""); diff --git a/main.c b/main.c index 9b3dbb043..7d79a47b8 100644 --- a/main.c +++ b/main.c @@ -37,7 +37,7 @@ - Calling the class loader - Running the main method - $Id: main.c 958 2004-03-14 21:02:49Z twisti $ + $Id: main.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -68,6 +68,7 @@ bool verbose = false; bool compileall = false; bool runverbose = false; /* trace all method invocation */ +bool verboseexception = false; /* trace all method invocation */ bool collectverbose = false; bool loadverbose = false; @@ -161,7 +162,7 @@ void **stackbottom = 0; #define OPT_VERBOSETC 29 #define OPT_NOVERIFY 30 #define OPT_LIBERALUTF 31 - +#define OPT_VERBOSEEXCEPTION 32 struct {char *name; bool arg; int value;} opts[] = { {"classpath", true, OPT_CLASSPATH}, @@ -177,6 +178,7 @@ struct {char *name; bool arg; int value;} opts[] = { {"verbose", false, OPT_VERBOSE}, {"verbosegc", false, OPT_VERBOSEGC}, {"verbosecall", false, OPT_VERBOSECALL}, + {"verboseexception", false, OPT_VERBOSEEXCEPTION}, #ifdef TYPECHECK_VERBOSE {"verbosetc", false, OPT_VERBOSETC}, #endif @@ -269,6 +271,7 @@ static void print_usage() printf(" -verbose ............. write more information\n"); printf(" -verbosegc ........... write message for each GC\n"); printf(" -verbosecall ......... write message for each call\n"); + printf(" -verboseexception .... write message for each step of stack unwinding\n"); #ifdef TYPECHECK_VERBOSE printf(" -verbosetc ........... write debug messages while typechecking\n"); #endif @@ -689,6 +692,10 @@ int main(int argc, char **argv) compileverbose = true; break; + case OPT_VERBOSEEXCEPTION: + verboseexception = true; + break; + case OPT_VERBOSEGC: collectverbose = true; break; @@ -945,15 +952,24 @@ int main(int argc, char **argv) asm_calljavafunction(mainmethod, a, NULL, NULL, NULL); if (*exceptionptr) { - printf("Exception in thread \"main\" "); - utf_display_classname((*exceptionptr)->vftbl->class->name); + methodinfo *main_unhandled_print=class_resolvemethod_approx((*exceptionptr)->vftbl->class, + utf_new_char("printStackTrace"), + utf_new_char("()V")); + if (main_unhandled_print) { + java_objectheader *exo=*exceptionptr; + *exceptionptr=0; + asm_calljavafunction(main_unhandled_print,exo,NULL,NULL,NULL); + } else { + printf("Exception in thread \"main\" "); + utf_display_classname((*exceptionptr)->vftbl->class->name); - /* do we have a detail message? */ - if (((java_lang_Throwable *) *exceptionptr)->detailMessage) { - printf(": "); + /* do we have a detail message? */ + if (((java_lang_Throwable *) *exceptionptr)->detailMessage) { + printf(": "); utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false)); + } + printf("\n"); } - printf("\n"); } #if defined(USE_THREADS) && !defined(NATIVE_THREADS) diff --git a/main.h b/main.h index 171eee3da..f6cf04886 100644 --- a/main.h +++ b/main.h @@ -27,7 +27,7 @@ Authors: Christian Thalinger - $Id: main.h 907 2004-01-29 13:20:05Z carolyn $ + $Id: main.h 963 2004-03-15 07:37:49Z jowenn $ */ @@ -42,6 +42,7 @@ extern bool compileall; extern bool verbose; extern bool runverbose; +extern bool verboseexception; extern bool collectverbose; extern bool loadverbose; /* Print debug messages during loading */ diff --git a/nat/Makefile.am b/nat/Makefile.am index a56e183f4..29965e504 100644 --- a/nat/Makefile.am +++ b/nat/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -# $Id: Makefile.am 930 2004-03-02 21:18:23Z jowenn $ +# $Id: Makefile.am 963 2004-03-15 07:37:49Z jowenn $ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/jit -I$(top_srcdir)/jit/@ARCH_DIR@ @@ -24,6 +24,7 @@ libnat_a_SOURCES = \ VMSecurityManager.c \ VMString.c \ VMSystem.c \ + VMThrowable.c \ JOWENNTest1.c \ classcontextnativeTest.c diff --git a/nat/VMThrowable.c b/nat/VMThrowable.c new file mode 100644 index 000000000..9a5db1a8a --- /dev/null +++ b/nat/VMThrowable.c @@ -0,0 +1,152 @@ +#include "global.h" +#include "jni.h" +#include "java_lang_Throwable.h" +#include "java_lang_VMThrowable.h" +#include "asmpart.h" +#include "loader.h" +#include "builtin.h" +#include "tables.h" +#include "native.h" + + +/* + * Class: java/lang/VMThrowable + * Method: fillInStackTrace + * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable; + */ +JNIEXPORT struct java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, + jclass clazz, struct java_lang_Throwable* par1) { + + classinfo *class_java_lang_VMThrowable=0; + java_lang_VMThrowable *vmthrow; + +/* log_text("java_lang_VMThrowable");*/ + + if (!class_java_lang_VMThrowable) + class_java_lang_VMThrowable = class_new(utf_new_char ("java/lang/VMThrowable")); + + if (class_java_lang_VMThrowable==0) + panic("Needed class java.lang.VMThrowable missing"); + + vmthrow=(java_lang_VMThrowable*)native_new_and_init(class_java_lang_VMThrowable); + + if (vmthrow==0) + panic("Needed instance of class java.lang.VMThrowable could not be created"); + + + (void)asm_get_stackTrace(&(vmthrow->vmData)); + + return vmthrow; +} + + + +java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *source,long size) { + long resultPos; + methodinfo *constructor; + classinfo *class_stacktraceelement; + java_objectarray *array_stacktraceelement; + class_stacktraceelement = (classinfo *) loader_load(utf_new_char ("java/lang/StackTraceElement")); + + if (!class_stacktraceelement) + return 0; + + + constructor=class_findmethod(class_stacktraceelement,utf_new_char(""), + utf_new_char("(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Z)V")); + if (!constructor) + panic("java.lang.StackTraceElement misses needed constructor"); + + array_stacktraceelement = builtin_anewarray(size, class_stacktraceelement); + + if (!array_stacktraceelement) + return 0; + +/* printf("Should return an array with %ld element(s)\n",size);*/ + size--; + + + for(resultPos=0;size>=0;resultPos++,size--) { + java_objectheader *element=builtin_new(class_stacktraceelement); + if (!element) { + panic("Memory for stack trace element could not be allocated"); + } +#ifdef __GNUC__ +#warning call constructor once jni is fixed to allow more than three parameters +#endif +#if 0 + (*env)->CallVoidMethod(env,element,constructor, + javastring_new(source[size].method->class->sourcefile), + source[size].linenumber, + javastring_new(source[size].method->class->name), + javastring_new(source[size].method->name), + source[size].method->flags & ACC_NATIVE); +#else + if (!(source[size].method->flags & ACC_NATIVE))setfield_critical(class_stacktraceelement,element,"fileName", + "Ljava/lang/String;", jobject, + (jobject) javastring_new(source[size].method->class->sourcefile)); + setfield_critical(class_stacktraceelement,element,"className", "Ljava/lang/String;", jobject, + (jobject) javastring_new(source[size].method->class->name)); + setfield_critical(class_stacktraceelement,element,"methodName", "Ljava/lang/String;", jobject, + (jobject) javastring_new(source[size].method->name)); + setfield_critical(class_stacktraceelement,element,"lineNumber", "I", jint, + (jint) ((source[size].method->flags & ACC_NATIVE) ? -1:(source[size].linenumber))); + setfield_critical(class_stacktraceelement,element,"isNative", "Z", jboolean, + (jboolean) ((source[size].method->flags & ACC_NATIVE) ? 1:0)); + + +#endif + + array_stacktraceelement->data[resultPos]=element; + } + + return array_stacktraceelement; + +} + + + +/* + * Class: java/lang/VMThrowable + * Method: getStackTrace + * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement; + */ +JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, + struct java_lang_VMThrowable* this, struct java_lang_Throwable* par1) { + + long pos; + long maxpos; + utf* classname=par1->header.vftbl->class->name; + utf* init=utf_new_char(""); + utf* throwable=utf_new_char("java/lang/Throwable"); + stacktraceelement *el=(stacktraceelement*)this->vmData; + +/* log_text("Java_java_lang_VMThrowable_getStackTrace"); + utf_display(par1->header.vftbl->class->name); + printf("\n----------------------------------------------\n");*/ + + for (pos=0;el[pos].method!=0;pos++); + if (pos==0) { + panic("Stacktrace cannot have zero length"); + } + pos--; + pos--; + maxpos=pos; + if ( (el[pos].method->class->name==throwable) && (el[pos].method->name==init) ) { + for (; (pos>=0) && (el[pos].method->name==init) && (el[pos].method->class->name!=classname);pos--); + pos --; + if (pos<0) { + panic("Invalid stack trace for Throwable.getStackTrace()"); + } + } + + /* build the result array*/ + pos++; /*arraysize*/ + return generateStackTraceArray(env,el,pos); + +} + + + + + diff --git a/nat/java_lang_VMThrowable.h b/nat/java_lang_VMThrowable.h new file mode 100644 index 000000000..b476132f7 --- /dev/null +++ b/nat/java_lang_VMThrowable.h @@ -0,0 +1,30 @@ +/* This file is machine generated, don't edit it !*/ + +#ifndef _JAVA_LANG_VMTHROWABLE_H +#define _JAVA_LANG_VMTHROWABLE_H + +/* Structure information for class: java/lang/VMThrowable */ + +typedef struct java_lang_VMThrowable { + java_objectheader header; + struct gnu_classpath_RawData* vmData; +} java_lang_VMThrowable; + + +/* + * Class: java/lang/VMThrowable + * Method: fillInStackTrace + * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable; + */ +JNIEXPORT struct java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, jclass clazz, struct java_lang_Throwable* par1); + + +/* + * Class: java/lang/VMThrowable + * Method: getStackTrace + * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement; + */ +JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, struct java_lang_VMThrowable* this, struct java_lang_Throwable* par1); + +#endif + diff --git a/src/cacao/cacao.c b/src/cacao/cacao.c index 32e95b298..38b3512e2 100644 --- a/src/cacao/cacao.c +++ b/src/cacao/cacao.c @@ -37,7 +37,7 @@ - Calling the class loader - Running the main method - $Id: cacao.c 958 2004-03-14 21:02:49Z twisti $ + $Id: cacao.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -68,6 +68,7 @@ bool verbose = false; bool compileall = false; bool runverbose = false; /* trace all method invocation */ +bool verboseexception = false; /* trace all method invocation */ bool collectverbose = false; bool loadverbose = false; @@ -161,7 +162,7 @@ void **stackbottom = 0; #define OPT_VERBOSETC 29 #define OPT_NOVERIFY 30 #define OPT_LIBERALUTF 31 - +#define OPT_VERBOSEEXCEPTION 32 struct {char *name; bool arg; int value;} opts[] = { {"classpath", true, OPT_CLASSPATH}, @@ -177,6 +178,7 @@ struct {char *name; bool arg; int value;} opts[] = { {"verbose", false, OPT_VERBOSE}, {"verbosegc", false, OPT_VERBOSEGC}, {"verbosecall", false, OPT_VERBOSECALL}, + {"verboseexception", false, OPT_VERBOSEEXCEPTION}, #ifdef TYPECHECK_VERBOSE {"verbosetc", false, OPT_VERBOSETC}, #endif @@ -269,6 +271,7 @@ static void print_usage() printf(" -verbose ............. write more information\n"); printf(" -verbosegc ........... write message for each GC\n"); printf(" -verbosecall ......... write message for each call\n"); + printf(" -verboseexception .... write message for each step of stack unwinding\n"); #ifdef TYPECHECK_VERBOSE printf(" -verbosetc ........... write debug messages while typechecking\n"); #endif @@ -689,6 +692,10 @@ int main(int argc, char **argv) compileverbose = true; break; + case OPT_VERBOSEEXCEPTION: + verboseexception = true; + break; + case OPT_VERBOSEGC: collectverbose = true; break; @@ -945,15 +952,24 @@ int main(int argc, char **argv) asm_calljavafunction(mainmethod, a, NULL, NULL, NULL); if (*exceptionptr) { - printf("Exception in thread \"main\" "); - utf_display_classname((*exceptionptr)->vftbl->class->name); + methodinfo *main_unhandled_print=class_resolvemethod_approx((*exceptionptr)->vftbl->class, + utf_new_char("printStackTrace"), + utf_new_char("()V")); + if (main_unhandled_print) { + java_objectheader *exo=*exceptionptr; + *exceptionptr=0; + asm_calljavafunction(main_unhandled_print,exo,NULL,NULL,NULL); + } else { + printf("Exception in thread \"main\" "); + utf_display_classname((*exceptionptr)->vftbl->class->name); - /* do we have a detail message? */ - if (((java_lang_Throwable *) *exceptionptr)->detailMessage) { - printf(": "); + /* do we have a detail message? */ + if (((java_lang_Throwable *) *exceptionptr)->detailMessage) { + printf(": "); utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false)); + } + printf("\n"); } - printf("\n"); } #if defined(USE_THREADS) && !defined(NATIVE_THREADS) diff --git a/src/cacao/cacao.h b/src/cacao/cacao.h index a6086f266..07bae9ec7 100644 --- a/src/cacao/cacao.h +++ b/src/cacao/cacao.h @@ -27,7 +27,7 @@ Authors: Christian Thalinger - $Id: cacao.h 907 2004-01-29 13:20:05Z carolyn $ + $Id: cacao.h 963 2004-03-15 07:37:49Z jowenn $ */ @@ -42,6 +42,7 @@ extern bool compileall; extern bool verbose; extern bool runverbose; +extern bool verboseexception; extern bool collectverbose; extern bool loadverbose; /* Print debug messages during loading */ diff --git a/src/cacaoh/headers.c b/src/cacaoh/headers.c index e4dd1bfca..0d6e8a878 100644 --- a/src/cacaoh/headers.c +++ b/src/cacaoh/headers.c @@ -29,7 +29,7 @@ Changes: Mark Probst Philipp Tomsich - $Id: headers.c 960 2004-03-14 23:41:11Z twisti $ + $Id: headers.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -52,6 +52,7 @@ /* replace command line options */ bool verbose = false; +bool verboseexception = false; bool compileall = false; bool runverbose = false; bool collectverbose = false; diff --git a/src/native/jni.c b/src/native/jni.c index 270684a0a..b74fadf79 100644 --- a/src/native/jni.c +++ b/src/native/jni.c @@ -28,7 +28,7 @@ Changes: Joseph Wenninger - $Id: jni.c 944 2004-03-06 20:50:31Z twisti $ + $Id: jni.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -586,7 +586,7 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar if (argcount > 3) { *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. CallObjectMethod does not support that"); + log_text("Too many arguments. CallIntegerMethod does not support that"); return 0; } diff --git a/src/native/vm/Makefile.am b/src/native/vm/Makefile.am index a56e183f4..29965e504 100644 --- a/src/native/vm/Makefile.am +++ b/src/native/vm/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -# $Id: Makefile.am 930 2004-03-02 21:18:23Z jowenn $ +# $Id: Makefile.am 963 2004-03-15 07:37:49Z jowenn $ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/jit -I$(top_srcdir)/jit/@ARCH_DIR@ @@ -24,6 +24,7 @@ libnat_a_SOURCES = \ VMSecurityManager.c \ VMString.c \ VMSystem.c \ + VMThrowable.c \ JOWENNTest1.c \ classcontextnativeTest.c diff --git a/src/native/vm/VMThrowable.c b/src/native/vm/VMThrowable.c new file mode 100644 index 000000000..9a5db1a8a --- /dev/null +++ b/src/native/vm/VMThrowable.c @@ -0,0 +1,152 @@ +#include "global.h" +#include "jni.h" +#include "java_lang_Throwable.h" +#include "java_lang_VMThrowable.h" +#include "asmpart.h" +#include "loader.h" +#include "builtin.h" +#include "tables.h" +#include "native.h" + + +/* + * Class: java/lang/VMThrowable + * Method: fillInStackTrace + * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable; + */ +JNIEXPORT struct java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, + jclass clazz, struct java_lang_Throwable* par1) { + + classinfo *class_java_lang_VMThrowable=0; + java_lang_VMThrowable *vmthrow; + +/* log_text("java_lang_VMThrowable");*/ + + if (!class_java_lang_VMThrowable) + class_java_lang_VMThrowable = class_new(utf_new_char ("java/lang/VMThrowable")); + + if (class_java_lang_VMThrowable==0) + panic("Needed class java.lang.VMThrowable missing"); + + vmthrow=(java_lang_VMThrowable*)native_new_and_init(class_java_lang_VMThrowable); + + if (vmthrow==0) + panic("Needed instance of class java.lang.VMThrowable could not be created"); + + + (void)asm_get_stackTrace(&(vmthrow->vmData)); + + return vmthrow; +} + + + +java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *source,long size) { + long resultPos; + methodinfo *constructor; + classinfo *class_stacktraceelement; + java_objectarray *array_stacktraceelement; + class_stacktraceelement = (classinfo *) loader_load(utf_new_char ("java/lang/StackTraceElement")); + + if (!class_stacktraceelement) + return 0; + + + constructor=class_findmethod(class_stacktraceelement,utf_new_char(""), + utf_new_char("(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Z)V")); + if (!constructor) + panic("java.lang.StackTraceElement misses needed constructor"); + + array_stacktraceelement = builtin_anewarray(size, class_stacktraceelement); + + if (!array_stacktraceelement) + return 0; + +/* printf("Should return an array with %ld element(s)\n",size);*/ + size--; + + + for(resultPos=0;size>=0;resultPos++,size--) { + java_objectheader *element=builtin_new(class_stacktraceelement); + if (!element) { + panic("Memory for stack trace element could not be allocated"); + } +#ifdef __GNUC__ +#warning call constructor once jni is fixed to allow more than three parameters +#endif +#if 0 + (*env)->CallVoidMethod(env,element,constructor, + javastring_new(source[size].method->class->sourcefile), + source[size].linenumber, + javastring_new(source[size].method->class->name), + javastring_new(source[size].method->name), + source[size].method->flags & ACC_NATIVE); +#else + if (!(source[size].method->flags & ACC_NATIVE))setfield_critical(class_stacktraceelement,element,"fileName", + "Ljava/lang/String;", jobject, + (jobject) javastring_new(source[size].method->class->sourcefile)); + setfield_critical(class_stacktraceelement,element,"className", "Ljava/lang/String;", jobject, + (jobject) javastring_new(source[size].method->class->name)); + setfield_critical(class_stacktraceelement,element,"methodName", "Ljava/lang/String;", jobject, + (jobject) javastring_new(source[size].method->name)); + setfield_critical(class_stacktraceelement,element,"lineNumber", "I", jint, + (jint) ((source[size].method->flags & ACC_NATIVE) ? -1:(source[size].linenumber))); + setfield_critical(class_stacktraceelement,element,"isNative", "Z", jboolean, + (jboolean) ((source[size].method->flags & ACC_NATIVE) ? 1:0)); + + +#endif + + array_stacktraceelement->data[resultPos]=element; + } + + return array_stacktraceelement; + +} + + + +/* + * Class: java/lang/VMThrowable + * Method: getStackTrace + * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement; + */ +JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, + struct java_lang_VMThrowable* this, struct java_lang_Throwable* par1) { + + long pos; + long maxpos; + utf* classname=par1->header.vftbl->class->name; + utf* init=utf_new_char(""); + utf* throwable=utf_new_char("java/lang/Throwable"); + stacktraceelement *el=(stacktraceelement*)this->vmData; + +/* log_text("Java_java_lang_VMThrowable_getStackTrace"); + utf_display(par1->header.vftbl->class->name); + printf("\n----------------------------------------------\n");*/ + + for (pos=0;el[pos].method!=0;pos++); + if (pos==0) { + panic("Stacktrace cannot have zero length"); + } + pos--; + pos--; + maxpos=pos; + if ( (el[pos].method->class->name==throwable) && (el[pos].method->name==init) ) { + for (; (pos>=0) && (el[pos].method->name==init) && (el[pos].method->class->name!=classname);pos--); + pos --; + if (pos<0) { + panic("Invalid stack trace for Throwable.getStackTrace()"); + } + } + + /* build the result array*/ + pos++; /*arraysize*/ + return generateStackTraceArray(env,el,pos); + +} + + + + + diff --git a/src/vm/builtin.c b/src/vm/builtin.c index acd8f5070..6f003d3a0 100644 --- a/src/vm/builtin.c +++ b/src/vm/builtin.c @@ -34,7 +34,7 @@ calls instead of machine instructions, using the C calling convention. - $Id: builtin.c 957 2004-03-14 21:01:12Z twisti $ + $Id: builtin.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -775,8 +775,8 @@ java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims) u4 methodindent = 0; java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, - methodinfo *method, - int *pos, + methodinfo *method, int *pos, + int line, int noindent) { if (!noindent) { @@ -785,12 +785,14 @@ java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, else log_text("WARNING: unmatched methodindent--"); } - if (verbose || runverbose) { - printf("Exception "); + if (verbose || runverbose || verboseexception) { if (_exceptionptr) { - utf_display_classname(_exceptionptr->vftbl->class->name); + printf("Exception "); + utf_display(_exceptionptr->vftbl->class->name); } else { + printf("Some Throwable"); +/* printf("Error: "); if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0"); if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0"); @@ -802,7 +804,7 @@ java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0"); if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0"); if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0"); - + */ } printf(" thrown in "); @@ -811,10 +813,20 @@ java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, printf("."); utf_display(method->name); if (method->flags & ACC_SYNCHRONIZED) - printf("(SYNC)"); + printf("(SYNC"); else - printf("(NOSYNC)"); - printf("(%p) at position %p\n", method->entrypoint, pos); + printf("(NOSYNC"); + if (method->flags & ACC_NATIVE) { + printf(",NATIVE"); + printf(")(%p) at position %p\n", method->entrypoint, pos); + } else { + printf(")(%p) at position %p (",method->entrypoint,pos); + if (method->class->sourcefile==NULL) + printf(""); + else + utf_display(method->class->sourcefile); + printf(":%d)\n",line); + } } else printf("call_java_method\n"); @@ -1825,6 +1837,18 @@ builtin_asm_get_stackframeinfo(){ #endif } +stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) { +/* stacktraceelement *el;*/ + size_t s; + s=(end-begin); + /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/ + *el=GCNEW(stacktraceelement,s+1); + memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement)); + (*el)[s].method=0; + (*el)[s].linenumber=0; + return *el; +} + /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where diff --git a/src/vm/builtin.h b/src/vm/builtin.h index c223378c5..bc290a456 100644 --- a/src/vm/builtin.h +++ b/src/vm/builtin.h @@ -28,7 +28,7 @@ Changes: Edwin Steiner - $Id: builtin.h 951 2004-03-11 17:30:03Z jowenn $ + $Id: builtin.h 963 2004-03-15 07:37:49Z jowenn $ */ @@ -172,7 +172,7 @@ java_objectheader *builtin_throw_exception(java_objectheader *exception); /* NOT AN OP */ java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr, methodinfo *method, - int *pos, int noindent); + int *pos, int line, int noindent); /* NOT AN OP */ static inline java_objectheader **builtin_get_exceptionptrptr(); @@ -418,6 +418,7 @@ points here---->| previous element in list | ------------------------------------------------ */ void *builtin_asm_get_stackframeinfo(); +stacktraceelement *builtin_stacktrace_copy(stacktraceelement **,stacktraceelement *begin, stacktraceelement *end); #endif /* _BUILTIN_H */ diff --git a/src/vm/global.h b/src/vm/global.h index d9cf9dd71..596059445 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -31,7 +31,7 @@ Philipp Tomsich Edwin Steiner - $Id: global.h 941 2004-03-06 17:27:56Z jowenn $ + $Id: global.h 963 2004-03-15 07:37:49Z jowenn $ */ @@ -301,6 +301,17 @@ struct native_stackframeinfo { typedef struct native_stackframeinfo native_stackframeinfo; +struct stacktraceelement { +#if POINTERSIZE == 8 + u8 linenumber; +#else + u4 linenumber; +#endif + methodinfo *method; +}; + +typedef struct stacktraceelement stacktraceelement; + /* data structure for calls from c code to java methods */ struct jni_callblock { @@ -668,6 +679,7 @@ struct classinfo { /* class structure */ classSetNode *impldBy; /* implemented by class set */ utf *packagename; /* full name of the package */ + utf *sourcefile; /* classfile name containing this class */ java_objectheader *classloader; /* 0 for bootstrap classloader */ }; @@ -836,6 +848,7 @@ extern java_objectheader *proto_java_lang_ThreadDeath; extern bool compileall; extern bool runverbose; +extern bool verboseexception; extern bool verbose; extern bool opt_rt; /* Rapid Type Analysis for better inlining CO-RT*/ extern bool opt_xta; /* X Type Analysis for better inlining CO-XTA*/ diff --git a/src/vm/jit/alpha/asmpart.S b/src/vm/jit/alpha/asmpart.S index c377bc333..04a3968ee 100644 --- a/src/vm/jit/alpha/asmpart.S +++ b/src/vm/jit/alpha/asmpart.S @@ -28,7 +28,7 @@ Authors: Andreas Krall Reinhard Grafl - $Id: asmpart.S 948 2004-03-07 22:12:28Z twisti $ + $Id: asmpart.S 963 2004-03-15 07:37:49Z jowenn $ */ @@ -171,8 +171,11 @@ synchronize_caches: #define IsLeaf -20 #define IntSave -24 #define FltSave -28 -#define ExTableSize -32 -#define ExTableStart -32 +#define LineNumberTableSize -32 +#define LineNumberTableStart -40 +#define ExTableSize -48 +#define ExTableStart -48 + #define ExEntrySize -32 #define ExStartPC -8 @@ -180,6 +183,11 @@ synchronize_caches: #define ExHandlerPC -24 #define ExCatchType -32 +#define LineEntrySize -16 +#define LinePC 0 +#define LineLine -8 + + /********************* function asm_calljavafunction *************************** * * * This function calls a Java-method (which possibly needs compilation) * @@ -205,6 +213,8 @@ call_name: .quad calljava_xhandler /* end pc */ .quad asm_calljavafunction /* start pc */ .long 1 /* extable size */ + .quad 0 /* line number table start */ + .quad 0 /* line number table size */ .long 0 /* fltsave */ .long 0 /* intsave */ .long 0 /* isleaf */ @@ -266,6 +276,8 @@ call_name2: .quad calljava_xhandler2 /* end pc */ .quad asm_calljavafunction2 /* start pc */ .long 1 /* extable size */ + .quad 0 /* line number table start */ + .quad 0 /* line number table size */ .long 0 /* fltsave */ .long 1 /* intsave */ .long 0 /* isleaf */ diff --git a/src/vm/jit/alpha/codegen.c b/src/vm/jit/alpha/codegen.c index 92f01d1d9..1f44c1c3c 100644 --- a/src/vm/jit/alpha/codegen.c +++ b/src/vm/jit/alpha/codegen.c @@ -28,7 +28,7 @@ Authors: Andreas Krall Reinhard Grafl - $Id: codegen.c 948 2004-03-07 22:12:28Z twisti $ + $Id: codegen.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -400,6 +400,7 @@ void codegen() basicblock *bptr; instruction *iptr; xtable *ex; + u2 currentline=0; { int p, pa, t, l, r; @@ -444,6 +445,9 @@ void codegen() (void) dseg_adds4(isleafmethod); /* IsLeaf */ (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */ (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */ + + (void) dseg_addlinenumbertablesize() /* line number table size + start*/ + (void) dseg_adds4(exceptiontablelength); /* ExTableSize */ /* create exception table */ @@ -732,6 +736,12 @@ void codegen() src = iptr->dst, len--, iptr++) { MCODECHECK(64); /* an instruction usually needs < 64 words */ + + if (iptr->line!=currentline) { + dseg_addlinenumber(iptr->line,mcodeptr); + currentline=iptr->line; + } + switch (iptr->opc) { case ICMD_NOP: /* ... ==> ... */ @@ -3658,6 +3668,8 @@ makeactualcall: /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */ + codegen_createlinenumbertable(); + { /* generate bound check stubs */ diff --git a/src/vm/jit/asmpart.h b/src/vm/jit/asmpart.h index 3da6d4c7f..b938f1158 100644 --- a/src/vm/jit/asmpart.h +++ b/src/vm/jit/asmpart.h @@ -29,7 +29,7 @@ Changes: Christian Thalinger - $Id: asmpart.h 930 2004-03-02 21:18:23Z jowenn $ + $Id: asmpart.h 963 2004-03-15 07:37:49Z jowenn $ */ @@ -90,6 +90,8 @@ void asm_handle_builtin_exception(classinfo *); methodinfo *asm_getcallingmethod(); java_objectarray* Java_java_lang_VMSecurityManager_getClassContext(JNIEnv *env, jclass clazz); +stacktraceelement *asm_get_stackTrace(); + /*java_lang_ClassLoader* Java_java_lang_VMSecurityManager_currentClassLoader(JNIEnv *env, jclass clazz);*/ /* This funtion saves all callee saved registers and calls the function diff --git a/src/vm/jit/codegen.inc b/src/vm/jit/codegen.inc index 017eeee8d..cf920fb89 100644 --- a/src/vm/jit/codegen.inc +++ b/src/vm/jit/codegen.inc @@ -48,7 +48,7 @@ memory. All functions writing values into the data area return the offset relative the begin of the code area (start of procedure). - $Id: codegen.inc 955 2004-03-13 12:51:30Z jowenn $ + $Id: codegen.inc 963 2004-03-15 07:37:49Z jowenn $ */ @@ -87,6 +87,8 @@ static branchref *xcastrefs; /* list of cast check branches */ static branchref *xdivrefs; /* list of divide by zero branches */ static linenumberref *linenumberreferences; /*list of line numbers and the program counters of their first instruction*/ static s4 linenumbertablesizepos; +static s4 linenumbertablestartpos; +static s4 linenumbertab; static struct threadcritnodetemp *threadcrit; /* List of critical code regions */ @@ -144,6 +146,8 @@ void codegen_init() linenumberreferences=NULL; linenumbertablesizepos=0; + linenumbertablestartpos=0; + linenumbertab=0; jumpreferences = NULL; datareferences = NULL; xboundrefs = NULL; @@ -319,13 +323,14 @@ static void dseg_adddata(u1 *ptr) } static void dseg_addlinenumbertablesize() { - linenumbertablesizepos=dseg_addaddress(NULL); /*although it is not an adress, I'll do this here alignment reasons*/ + linenumbertablesizepos=dseg_addaddress(NULL); + linenumbertablestartpos=dseg_addaddress(NULL); /*although it is not an adress, I'll do this here alignment reasons*/ } static void dseg_addlinenumber(u2 linenumber,u1 *ptr) { linenumberref *lr=DNEW(linenumberref); - lr->tablepos=dseg_addaddress(NULL); - dseg_addaddress(linenumber); /*although it is not an adress, I'll do this here alignment reasons*/ + lr->linenumber=linenumber; + lr->tablepos=0; lr->targetmpc=(ptr-mcodebase); lr->next=linenumberreferences; linenumberreferences=lr; @@ -415,6 +420,22 @@ static void codegen_addxdivrefs(void *branchptr) +static void codegen_createlinenumbertable() { +#ifdef __I386__ + /*log_text("codegen_createlinnumbertable");*/ + { + linenumberref *lr; + for (lr=linenumberreferences;lr!=NULL;lr=lr->next) { + /*log_text("Adding line number entry");*/ + lr->tablepos=dseg_addaddress(NULL); + if (linenumbertab==0) linenumbertab=lr->tablepos; + dseg_addaddress(lr->linenumber); + } + } +#endif +} + + static void codegen_finish(int mcodelen) { jumpref *jr; @@ -461,11 +482,13 @@ static void codegen_finish(int mcodelen) *((void**)(epoint+lr->tablepos))=epoint+lr->targetmpc; /*log_text("resolving line number information");*/ } - #if POINTERSIZE == 8 - *((s8*)(epoint+linenumbertablesizepos))=lrtlen; - #else - *((s4*)(epoint+linenumbertablesizepos))=lrtlen; - #endif + + *((void**)(epoint+linenumbertablestartpos))=epoint+linenumbertab; +#if POINTERSIZE == 8 + *((s8*)(epoint+linenumbertablesizepos))=lrtlen; +#else + *((s4*)(epoint+linenumbertablesizepos))=lrtlen; +#endif } #endif diff --git a/src/vm/jit/i386/asmpart.S b/src/vm/jit/i386/asmpart.S index 64a265937..b7a5808b1 100644 --- a/src/vm/jit/i386/asmpart.S +++ b/src/vm/jit/i386/asmpart.S @@ -29,7 +29,7 @@ Reinhard Grafl Christian Thalinger - $Id: asmpart.S 951 2004-03-11 17:30:03Z jowenn $ + $Id: asmpart.S 963 2004-03-15 07:37:49Z jowenn $ */ @@ -45,8 +45,9 @@ #define IntSave -20 #define FltSave -24 #define LineNumberTableSize -28 -#define ExTableSize -32 -#define ExTableStart -32 +#define LineNumberTableStart -32 +#define ExTableSize -36 +#define ExTableStart -36 #define ExEntrySize -16 #define ExStartPC -4 @@ -54,6 +55,10 @@ #define ExHandlerPC -12 #define ExCatchType -16 + +#define LineEntrySize -8 +#define LinePC 0 +#define LineLine -4 .text @@ -94,6 +99,8 @@ .globl Java_java_lang_VMSecurityManager_getClassContext .globl Java_java_lang_VMSecurityManager_currentClassLoader .globl asm_builtin_new + .globl asm_get_stackTrace + /*************************** imported functions *******************************/ .globl jit_compile @@ -153,6 +160,7 @@ call_name: .long calljava_xhandler /* end pc */ .long asm_calljavafunction /* start pc */ .long 1 /* extable size */ + .long 0 /* line number table start */ .long 0 /* line number table size */ .long 0 /* fltsave */ .long 0 /* intsave */ @@ -238,6 +246,7 @@ call_name2: .long calljava_xhandler2 /* end pc */ .long asm_calljavafunction2 /* start pc */ .long 1 /* extable size */ + .long 0 /* line number table start */ .long 0 /* line number table size */ .long 0 /* fltsave */ .long 0 /* intsave */ @@ -442,6 +451,19 @@ asm_handle_nat_exception: add $4,%esp /* clear return address of native stub */ asm_handle_exception: +#if 0 + push %ebp + mov %esp,%ebp + push %eax /* exception pointer */ + push %ecx /* excepiton pc */ + + call asm_get_stackTrace + + pop %ecx + pop %eax + pop %ebp +#endif +asm_handle_exception_loop: push %ebp mov %esp,%ebp @@ -464,15 +486,17 @@ asm_handle_exception: push %edi ex_stack_loop: - sub $16,%esp + sub $20,%esp mov %eax,(%esp) /* exception pointer */ mov MethodPointer(%edx),%eax /* method pointer */ mov %eax,4(%esp) mov %ecx,8(%esp) /* exception pc */ - movl $1,12(%esp) /* set no unwind flag */ - call builtin_trace_exception - add $16,%esp + movl $0,12(%esp) /* line number */ + + movl $1,16(%esp) /* set no unwind flag */ + call builtin_trace_exception + add $20,%esp mov -12(%ebp),%esi /* %esi = data segment pointer */ mov ExTableSize(%esi),%ecx /* %ecx = exception table size */ test %ecx,%ecx /* if empty table skip */ @@ -615,7 +639,7 @@ noflt: pop %ecx /* the new xpc is return address */ sub $2,%ecx - jmp asm_handle_exception + jmp asm_handle_exception_loop /********************* function asm_check_clinit ******************************* @@ -1231,6 +1255,114 @@ asm_builtin_new: ret + + + + + + + + + + +asm_get_stackTrace: + push %ebp /*(%ebp-4)*/ + mov %esp,%ebp + add $4,%ebp + push %edi /*(%ebp-8)*/ + push %esi /*(%ebp-12)*/ + push %ebx /*(%ebp-16)*/ + call builtin_asm_get_stackframeinfo + movl (%eax),%eax + pushl 0(%eax) /*(%ebp-20)*/ + lea 12(%eax),%edi + call builtin_asm_get_threadrootmethod + pushl %eax /*(%ebp-24)*/ + + pushl (%edi) +asm_get_stackTraceLoop: + call findmethod + mov %eax,%esi + add $4,%esp + pushl $1 /*no indent*/ + + mov (%edi),%edx + sub $4,%edx + +get_stackTrace_line: + movl LineNumberTableSize(%esi),%ecx + test %ecx,%ecx /* skip if empty line table */ + je get_stackTrace_noLineInfo + + movl LineNumberTableStart(%esi),%ebx + +get_stackTrace_lineLoop: + cmp %edx,LinePC(%ebx) + jg get_stackTrace_nextLineInfo + + pushl LineLine(%ebx) + jmp get_stackTrace_cont + +get_stackTrace_nextLineInfo: + lea LineEntrySize(%ebx),%ebx + dec %ecx + test %ecx,%ecx + + jne get_stackTrace_lineLoop + +get_stackTrace_noLineInfo: + pushl $0 + + +get_stackTrace_cont: + pushl (%edi) /*4*/ + pushl MethodPointer(%esi) + pushl $0 /*8(%ebp)*/ /*exception ptr*/ + call builtin_trace_exception + add $12,%esp + + movl MethodPointer(%esi),%eax + movl %eax,4(%esp) + test %eax,%eax + je get_stackTrace_nat + + cmp %eax,-24(%ebp) + je get_stackTrace_leave + + mov FrameSize(%esi),%eax + add $4,%edi + add %eax,%edi + pushl (%edi) + jmp asm_get_stackTraceLoop + +get_stackTrace_nat: + add $8,%esp + movl -20(%ebp),%eax + cmp $0,%eax + je get_stackTrace_leave + movl 0(%eax),%ebx + movl %ebx,-20(%ebp) + pushl 8(%eax) + pushl $0 + lea 12(%eax),%edi + pushl (%edi) + jmp asm_get_stackTraceLoop + +get_stackTrace_leave: + mov %esp,%eax + lea -24(%ebp),%ebx + push %ebx + push %eax + push 4(%ebp) + call builtin_stacktrace_copy + + lea -16(%ebp),%esp + pop %ebx + pop %esi + pop %edi + pop %ebp + ret + /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where diff --git a/src/vm/jit/i386/codegen.c b/src/vm/jit/i386/codegen.c index 869b86947..4e34abe10 100644 --- a/src/vm/jit/i386/codegen.c +++ b/src/vm/jit/i386/codegen.c @@ -28,7 +28,7 @@ Authors: Andreas Krall Christian Thalinger - $Id: codegen.c 955 2004-03-13 12:51:30Z jowenn $ + $Id: codegen.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -4608,6 +4608,8 @@ gen_method: { } /* if (bptr -> flags >= BBREACHED) */ } /* for basic block */ + codegen_createlinenumbertable(); + /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */ { @@ -4836,7 +4838,7 @@ gen_method: { } } } - + codegen_finish((int)((u1*) mcodeptr - mcodebase)); } diff --git a/src/vm/loader.c b/src/vm/loader.c index 7db23e9e4..46835c9ab 100644 --- a/src/vm/loader.c +++ b/src/vm/loader.c @@ -30,7 +30,7 @@ Mark Probst Edwin Steiner - $Id: loader.c 959 2004-03-14 23:39:31Z twisti $ + $Id: loader.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -87,6 +87,7 @@ static utf *utf_constantvalue; /* ConstantValue */ static utf *utf_code; /* Code */ static utf *utf_exceptions; /* Exceptions */ static utf *utf_linenumbertable; /* LineNumberTable */ +static utf *utf_sourcefile; /*SourceFile*/ static utf *utf_finalize; /* finalize */ static utf *utf_fidesc; /* ()V changed */ static utf *utf_init; /* */ @@ -696,7 +697,10 @@ static void attribute_load(u4 num, classinfo *c) info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */ info->flags = suck_u2(); /* access_flags bitmask */ } - + } else if (aname==utf_sourcefile) { + suck_u4(); + /*log_text("source file attribute found");*/ + c->sourcefile = class_getconstant(c, suck_u2(), CONSTANT_Utf8); } else { /* unknown attribute */ skipattributebody(); @@ -2279,7 +2283,7 @@ void class_link(classinfo *c) /* check super class */ - if (super == NULL) { /* class java.long.Object */ + if (super == NULL) { /* class java.lang.Object */ c->index = 0; c->classUsed = USED; /* Object class is always used CO-RT*/ c->impldBy = NULL; @@ -3803,6 +3807,7 @@ void loader_init(u1 *stackbottom) utf_code = utf_new_char("Code"); utf_exceptions = utf_new_char("Exceptions"); utf_linenumbertable = utf_new_char("LineNumberTable"); + utf_sourcefile = utf_new_char("SourceFile"); utf_finalize = utf_new_char("finalize"); utf_fidesc = utf_new_char("()V"); utf_init = utf_new_char(""); diff --git a/src/vm/tables.c b/src/vm/tables.c index 41f7b24b0..df459f9fa 100644 --- a/src/vm/tables.c +++ b/src/vm/tables.c @@ -35,7 +35,7 @@ - the heap - additional support functions - $Id: tables.c 935 2004-03-05 23:49:12Z twisti $ + $Id: tables.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -922,6 +922,7 @@ classinfo *class_new(utf *u) c->classUsed = 0; c->impldBy = NULL; c->classloader = NULL; + c->sourcefile = NULL; /* prepare loading of the class */ list_addlast(&unloadedclasses, c); diff --git a/tables.c b/tables.c index 41f7b24b0..df459f9fa 100644 --- a/tables.c +++ b/tables.c @@ -35,7 +35,7 @@ - the heap - additional support functions - $Id: tables.c 935 2004-03-05 23:49:12Z twisti $ + $Id: tables.c 963 2004-03-15 07:37:49Z jowenn $ */ @@ -922,6 +922,7 @@ classinfo *class_new(utf *u) c->classUsed = 0; c->impldBy = NULL; c->classloader = NULL; + c->sourcefile = NULL; /* prepare loading of the class */ list_addlast(&unloadedclasses, c); diff --git a/tests/stack/classcontextnativeTest.java b/tests/stack/classcontextnativeTest.java index 44334bbba..665769665 100644 --- a/tests/stack/classcontextnativeTest.java +++ b/tests/stack/classcontextnativeTest.java @@ -2,89 +2,93 @@ public class classcontextnativeTest { public classcontextnativeTest() {} - private static void z() { - try { + private static void z() throws Exception{ +// try { Object o=Class.forName("blup",true,null).newInstance(); - } catch (Throwable e) { - System.out.println("TEST: "+e.toString()); - } +// } catch (Throwable e) { +// System.out.println("TEST: "+e.toString()); +// } } - private static native void y(); + private static native void y() throws Exception; - private static void x() { + private static void x() throws Exception { y(); } - private static void w() { + private static void w() throws Exception{ x(); } - private static void v() { + private static void v() throws Exception{ w(); } - private static void u() { + private static void u() throws Exception{ v(); } - private static void t() { + private static void t() throws Exception{ u(); } - private static void s() { + private static void s() throws Exception{ t(); } - private static void r() { + private static void r() throws Exception{ s(); } - private static void q() { + private static void q() throws Exception{ r(); } - private static void p() { + private static void p() throws Exception{ q(); } - private static void o() { + private static void o() throws Exception{ p(); } - private static void n() { + private static void n() throws Exception{ o(); } - private static void m() { + private static void m() throws Exception{ n(); } - private static void l() { + private static void l() throws Exception{ m(); } - private native static void k(); + private native static void k() throws Exception; - private static void j() { + private static void j() throws Exception{ k(); } - private static void i() { + private static void i() throws Exception{ j(); } - private static void h() { + private static void h() throws Exception{ i(); } - private static void g() { + private static void g() throws Exception{ h(); } - private static void f() { + private static void f() throws Exception{ g(); } - private static void e() { + private static void e() throws Exception{ f(); } - private static void d() { + private static void d() throws Exception{ e(); } - private static void c() { + private static void c() throws Exception{ d(); } - private static void b() { + private static void b() throws Exception{ c(); } - private native static void a(); + private native static void a() throws Exception; public static void main(String args[]) { System.setSecurityManager(new SecurityManager()); - a(); + try { + a(); + } catch (Exception e) { + e.printStackTrace(); + } } } diff --git a/tests/stack/exception.java b/tests/stack/exception.java index bc65e869f..7b126ebd4 100644 --- a/tests/stack/exception.java +++ b/tests/stack/exception.java @@ -94,6 +94,13 @@ public class exception { } + try { + throw new ClassCastException(); + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + throw new ClassCastException(); } } -- 2.25.1