From bc21650c967b161e3a86e67baae5b63ee7b30189 Mon Sep 17 00:00:00 2001 From: jowenn Date: Sat, 4 Dec 2004 12:02:08 +0000 Subject: [PATCH 1/1] use two functions for creating/removing items of the native stackframe list (i386), make it work on FreeBSD (tested: 5.3-CURRENT) i386, dynamic loading of natives (x86_64) --- configure.in | 2 +- contrib/debugSetPathes | 2 +- src/boehm-gc/autogen.sh | 7 +- src/native/vm/VMRuntime.c | 4 +- src/native/vm/VMSecurityManager.c | 32 +- src/native/vm/VMThrowable.c | 121 ++--- src/vm/global.h | 12 +- src/vm/jit/asmpart.h | 5 +- src/vm/jit/codegen.inc | 40 +- src/vm/jit/i386/asmoffsets.h | 28 ++ src/vm/jit/i386/asmpart.S | 541 +++++++-------------- src/vm/jit/i386/codegen.c | 178 ++++--- src/vm/jit/i386/symcat.h | 49 ++ src/vm/jit/stack.c | 4 +- src/vm/jit/stacktrace.c | 408 ++++++++++++++++ src/vm/jit/x86_64/asmpart.S | 19 +- src/vm/jit/x86_64/codegen.c | 87 ++-- tests/InlineExTest.java | 1 + tests/stack/nestedstaticinitializers2.java | 1 + tests/stack/nestedstaticinitializers3.java | 39 ++ 20 files changed, 998 insertions(+), 582 deletions(-) create mode 100644 src/vm/jit/i386/asmoffsets.h create mode 100644 src/vm/jit/i386/symcat.h create mode 100644 src/vm/jit/stacktrace.c create mode 100644 tests/stack/nestedstaticinitializers3.java diff --git a/configure.in b/configure.in index f148eb16f..3c58e945f 100644 --- a/configure.in +++ b/configure.in @@ -40,7 +40,7 @@ powerpc* | ppc* ) x86_64* ) ARCH_DIR="x86_64" - STATIC_CLASSPATH="1" + STATIC_CLASSPATH="0" CFLAGS="-D__X86_64__" ;; diff --git a/contrib/debugSetPathes b/contrib/debugSetPathes index 20f93f67b..f06b2ee5a 100644 --- a/contrib/debugSetPathes +++ b/contrib/debugSetPathes @@ -3,5 +3,5 @@ $PWD/classpath/native/jni/java-util/.libs:$PWD/classpath/native/jni/java-awt/.li $PWD/classpath/native/jni/java-io/.libs:$PWD/classpath/native/jni/classpath/.libs:\ $PWD/classpath/native/jni/java-net/.libs:$LD_LIBRARY_PATH export CLASSPATH=.:$PWD/classpath/lib/glibj.zip:$CLASSPATH -export PATH=$PWD:$PATH +export PATH=$PWD/cacao:$PATH diff --git a/src/boehm-gc/autogen.sh b/src/boehm-gc/autogen.sh index b97a7c902..0ab131fa3 100755 --- a/src/boehm-gc/autogen.sh +++ b/src/boehm-gc/autogen.sh @@ -1,7 +1,12 @@ #!/bin/sh libtoolize --automake -aclocal +if test `uname` == 'FreeBSD'; then + echo "FreeBSD (only tested with 5.3-RELEASE though" + aclocal -I . -I /usr/local/share/aclocal -I /usr/local/share/aclocal19 +else + aclocal +fi autoheader automake --add-missing autoconf diff --git a/src/native/vm/VMRuntime.c b/src/native/vm/VMRuntime.c index 5cf652e48..ba11e35aa 100644 --- a/src/native/vm/VMRuntime.c +++ b/src/native/vm/VMRuntime.c @@ -29,7 +29,7 @@ Changes: Joseph Wenninger Christian Thalinger - $Id: VMRuntime.c 1621 2004-11-30 13:06:55Z twisti $ + $Id: VMRuntime.c 1680 2004-12-04 12:02:08Z jowenn $ */ @@ -333,7 +333,7 @@ JNIEXPORT s4 JNICALL Java_java_lang_VMRuntime_nativeLoad(JNIEnv *env, jclass cla #ifndef STATIC_CLASSPATH /*here it could be interesting to store the references in a list eg for nicely cleaning up or for certain platforms*/ if (dlopen(data->text,RTLD_NOW | RTLD_GLOBAL)) { - log_text("LIBLOADED"); + /*log_text("LIBLOADED");*/ retVal=1; } #else diff --git a/src/native/vm/VMSecurityManager.c b/src/native/vm/VMSecurityManager.c index d2f122095..a4e2df869 100644 --- a/src/native/vm/VMSecurityManager.c +++ b/src/native/vm/VMSecurityManager.c @@ -1,4 +1,4 @@ -/* native/vm/VMSecurityManager.c - java/lang/VMSecurityManager +/* nat/SecurityManager.c - java/lang/SecurityManager Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, @@ -28,11 +28,10 @@ Changes: Joseph Wenninger - $Id: VMSecurityManager.c 1621 2004-11-30 13:06:55Z twisti $ + $Id: VMSecurityManager.c 1680 2004-12-04 12:02:08Z jowenn $ */ - #include "native/jni.h" #include "native/native.h" #include "native/include/java_lang_ClassLoader.h" @@ -40,8 +39,6 @@ #include "vm/builtin.h" #include "vm/tables.h" - -#ifndef __I386__ /* * Class: java/lang/SecurityManager * Method: currentClassLoader @@ -51,19 +48,20 @@ JNIEXPORT java_lang_ClassLoader* JNICALL Java_java_lang_VMSecurityManager_curren { log_text("Java_java_lang_VMSecurityManager_currentClassLoader"); - /* XXX TWISTI temporary hack! FIX ME jowenn */ if (cacao_initializing) return NULL; - init_systemclassloader(); +#ifdef __I386__ + return cacao_currentClassLoader(); +#else + return 0; +#endif +/* init_systemclassloader(); - return SystemClassLoader; + return SystemClassLoader;*/ } -#endif -#ifndef __I386__ -/*THIS IS IN ASMPART NOW*/ /* * Class: java/lang/SecurityManager * Method: getClassContext @@ -71,12 +69,14 @@ JNIEXPORT java_lang_ClassLoader* JNICALL Java_java_lang_VMSecurityManager_curren */ JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMSecurityManager_getClassContext(JNIEnv *env, jclass clazz) { - log_text("Java_java_lang_VMSecurityManager_getClassContext called"); - - /* XXX should use vftbl directly */ - return (java_objectarray *) builtin_newarray(0, class_array_of(class_java_lang_Class)->vftbl); -} + log_text("Java_java_lang_VMSecurityManager_getClassContext called"); + if (cacao_initializing) return 0; +#ifdef __I386__ + return cacao_createClassContextArray(); +#else + return 0; #endif +} java_objectarray* temporaryGetClassContextHelper(methodinfo *m) { if (!m) { diff --git a/src/native/vm/VMThrowable.c b/src/native/vm/VMThrowable.c index f2a3a4b79..3a7ad0b67 100644 --- a/src/native/vm/VMThrowable.c +++ b/src/native/vm/VMThrowable.c @@ -1,4 +1,4 @@ -/* native/vm/VMThrowable.c - java/lang/VMThrowable +/* nat/VMThrowable.c - java/lang/Throwable Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, @@ -26,11 +26,10 @@ Authors: Joseph Wenninger - $Id: VMThrowable.c 1621 2004-11-30 13:06:55Z twisti $ + $Id: VMThrowable.c 1680 2004-12-04 12:02:08Z jowenn $ */ - #include "native/jni.h" #include "native/native.h" #include "native/include/java_lang_Class.h" @@ -64,18 +63,15 @@ JNIEXPORT java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackT if (vmthrow == NULL) panic("Needed instance of class java.lang.VMThrowable could not be created"); -#if defined(__I386__) - (void) asm_get_stackTrace(&(vmthrow->vmData)); -#else - vmthrow->vmData=0; +#ifdef __I386__ + cacao_stacktrace_NormalTrace(&(vmthrow->vmData)); #endif - return vmthrow; } - -java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *source,long pos,long size) +static +java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *el,long size) { long resultPos; methodinfo *m; @@ -103,13 +99,12 @@ java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *source, return 0; /* printf("Should return an array with %ld element(s)\n",size);*/ - pos--; - + /*pos--;*/ - for(resultPos=0;pos>=0;resultPos++,pos--) { + for(resultPos=0;size>0;size--,el++,resultPos++) { java_objectheader *element; - if (source[pos].method==0) { + if (el->method==0) { resultPos--; continue; } @@ -123,25 +118,25 @@ java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *source, #endif #if 0 (*env)->CallVoidMethod(env,element,m, - javastring_new(source[pos].method->class->sourcefile), + javastring_new(el->method->class->sourcefile), source[size].linenumber, - javastring_new(source[pos].method->class->name), - javastring_new(source[pos].method->name), - source[pos].method->flags & ACC_NATIVE); + javastring_new(el->method->class->name), + javastring_new(el->method->name), + el->method->flags & ACC_NATIVE); #else - if (!(source[pos].method->flags & ACC_NATIVE))setfield_critical(c,element,"fileName", + if (!(el->method->flags & ACC_NATIVE))setfield_critical(c,element,"fileName", "Ljava/lang/String;", jobject, - (jobject) javastring_new(source[pos].method->class->sourcefile)); + (jobject) javastring_new(el->method->class->sourcefile)); /* setfield_critical(c,element,"className", "Ljava/lang/String;", jobject, */ -/* (jobject) javastring_new(source[pos].method->class->name)); */ - setfield_critical(c,element,"declaringClass", "Ljava/lang/String;", jobject, - (jobject) Java_java_lang_VMClass_getName(env, NULL, (java_lang_Class *) source[pos].method->class)); +/* (jobject) javastring_new(el->method->class->name)); */ + setfield_critical(c,element,"declaringClass", "Ljava/lang/String;", jobject, + (jobject) Java_java_lang_VMClass_getName(env, NULL, (java_lang_Class *) el->method->class)); setfield_critical(c,element,"methodName", "Ljava/lang/String;", jobject, - (jobject) javastring_new(source[pos].method->name)); + (jobject) javastring_new(el->method->name)); setfield_critical(c,element,"lineNumber", "I", jint, - (jint) ((source[pos].method->flags & ACC_NATIVE) ? -1:(source[pos].linenumber))); + (jint) ((el->method->flags & ACC_NATIVE) ? -1:(el->linenumber))); setfield_critical(c,element,"isNative", "Z", jboolean, - (jboolean) ((source[pos].method->flags & ACC_NATIVE) ? 1:0)); + (jboolean) ((el->method->flags & ACC_NATIVE) ? 1:0)); #endif @@ -161,56 +156,46 @@ java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *source, */ JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, java_lang_VMThrowable *this, java_lang_Throwable *par1) { - long pos; - long maxpos; - long sizediff; - utf* classname=par1->header.vftbl->class->name; +#ifdef __I386__ + stackTraceBuffer *buf=(stackTraceBuffer*)this->vmData; + u8 size; + stacktraceelement *el; + classinfo *excClass=par1->header.vftbl->class; 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");*/ - - sizediff=0; - if (el == 0) { - return generateStackTraceArray(env, el, 0,0); - } - - for (pos = 0; !((el[pos].method == 0) && (el[pos].linenumber ==-1)); pos++) { - if (el[pos].method==0) sizediff++; - } - - if (pos == 0) { - panic("Stacktrace cannot have zero length"); - } - - pos--; - pos--; - maxpos = pos; - if (el[pos].method!=0) { /* if == 0 -> some builtin native */ - 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--) { -/* log_text("ignoring:"); - utf_display(el[pos].method->name); - log_text(""); - utf_display(el[pos].method->class->name); - log_text("");*/ - - }; - pos--; - if (pos < 0) { - log_text("Invalid stack trace for Throwable.getStackTrace()"); + long destElementCount; + stacktraceelement *tmpEl; + if (!buf) panic("Invalid java.lang.VMThrowable.vmData field in java.lang.VMThrowable.getStackTrace native code"); + + size=buf->full; + if (size<=2) panic("Invalid java.lang.VMThrowable.vmData field in java.lang.VMThrowable.getStackTrace native code (length<=2)"); + size -=2; + el=&(buf->start[2]); /* element 0==VMThrowable.fillInStackTrace native call, 1==Throwable.fillInStackTrace*/ + if (el->method!=0) { /* => not a builtin native wrapper*/ + if ((el->method->class->name==throwable) && (el->method->name == init) ){ + /* We assume that we are within the initializer of the exception object, the exception object itself should not appear + in the stack trace, so we skip till we reach the first function, which is not an init function or till we reach the exception object class*/ + for (; (size>0) && (el->method->name==init) && (el->method->class!=excClass); el++, size--) { + /* just loop*/ + } + size --; + el++; + if (size<1) { + log_text("Invalid stacktrace for VMThrowable.getStackTrace()"); } } } + - /* build the result array*/ - pos++; /*arraysize*/ + for (destElementCount = 0, tmpEl=el; size>0; size--,tmpEl++) { + if (tmpEl->method!=0) destElementCount++; + } - return generateStackTraceArray(env,el,pos,pos-sizediff); + return generateStackTraceArray(env,el,destElementCount); +#else + return 0; +#endif } diff --git a/src/vm/global.h b/src/vm/global.h index 94051a376..8f5f2c63b 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -31,7 +31,7 @@ Philipp Tomsich Edwin Steiner - $Id: global.h 1658 2004-12-03 15:28:15Z twisti $ + $Id: global.h 1680 2004-12-04 12:02:08Z jowenn $ */ @@ -303,6 +303,7 @@ struct native_stackframeinfo { void *oldThreadspecificHeadValue; void **addressOfThreadspecificHead; methodinfo *method; + void *beginOfJavaStackframe; /*only used if != 0*/ void *returnToFromNative; #if 0 @@ -327,6 +328,15 @@ struct stacktraceelement { typedef struct stacktraceelement stacktraceelement; +typedef struct stackTraceBuffer { + int needsFree; + struct stacktraceelement* start; + size_t size; + size_t full; +} stackTraceBuffer; + + + /* data structure for calls from c code to java methods */ struct jni_callblock { diff --git a/src/vm/jit/asmpart.h b/src/vm/jit/asmpart.h index 0af87fd08..9ed169035 100644 --- a/src/vm/jit/asmpart.h +++ b/src/vm/jit/asmpart.h @@ -29,7 +29,7 @@ Changes: Christian Thalinger - $Id: asmpart.h 1661 2004-12-03 15:45:56Z twisti $ + $Id: asmpart.h 1680 2004-12-04 12:02:08Z jowenn $ */ @@ -128,6 +128,9 @@ extern threadcritnode asm_criticalsections; void asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out); +void asm_prepare_native_stackinfo(void*ret,void*stackbegin); +void asm_remove_native_stackinfo(); + #if defined(USE_THREADS) && !defined(NATIVE_THREADS) void asm_perform_threadswitch(u1 **from, u1 **to, u1 **stackTop); u1* asm_initialize_thread_stack(void *func, u1 *stack); diff --git a/src/vm/jit/codegen.inc b/src/vm/jit/codegen.inc index 12fc08811..a2300e621 100644 --- a/src/vm/jit/codegen.inc +++ b/src/vm/jit/codegen.inc @@ -47,10 +47,12 @@ 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 1662 2004-12-03 15:46:18Z twisti $ + $Id: codegen.inc 1680 2004-12-04 12:02:08Z jowenn $ */ +#ifndef _CODEGEN_INC_H_ +#define _CODEGEN_INC_H_ #include @@ -965,16 +967,20 @@ static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmp void *sym; builtin_monitorenter((java_objectheader*) m); +#if defined(__X86_64__) + if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) { +#else if ((*jmpPatchTarget)==jmpTarget) { +#endif builtin_monitorexit((java_objectheader*) m); return; } - log_text("trying to resolve a native method"); + /*log_text("trying to resolve a native method"); utf_display(m->class->name); - utf_display(m->name); + utf_display(m->name);*/ - lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL); - if (lib) { + lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL); /* open the application execution image */ + if (lib) { /* it did work -> good, otherwise fail with error*/ int ok=0; /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/ nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1; @@ -999,38 +1005,46 @@ static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmp /* printf("nativename: %s\n",nativeName); */ + /*try to find the symbal fo the function */ sym=dlsym(lib,nativeName); if (sym) { - ok=1; - log_text("resolved"); + ok=1; /* it worked, everything fine */ + /*log_text("resolved");*/ MFREE(nativeName,char,nativeLen); - } else { + } else { /* we didn't find the symbol yet, try to resolve an overlaoded function (having the types in it's name*/ size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor); char *overloadedNative=MNEW(char,overloadedNativeLen); sprintf(overloadedNative,"%s",nativeName); MFREE(nativeName,char,nativeLen); codegen_fillInOverloadPart(overloadedNative,m->descriptor); - log_text("symbol not found,trying harder (overloaded member ?)"); + /*log_text("symbol not found,trying harder (overloaded member ?)");*/ sym=dlsym(lib,overloadedNative); if (sym) { MFREE(overloadedNative,char,overloadedNativeLen); - ok=1; - log_text("resolved"); + ok=1; /* we eventually found the native function -> everything ok*/ + /*log_text("resolved");*/ } else { + /* we failed to find the native function within the execution image (app + loaded libraries) -> will cause an exit*/ MFREE(overloadedNative,char,overloadedNativeLen); log_text("It was not possible to find the native function implementation. Not even in overloading case"); } } + /* patch the address of the native function into the stub and make the stub jump over this function call in the future */ if (ok) { (*insertionPoint)=sym; +#if defined(__X86_64__) + (*((s4*)jmpPatchTarget))=(s4)jmpTarget; +#else (*jmpPatchTarget)=jmpTarget; +#endif builtin_monitorexit((java_objectheader *) m ); return; } } else log_text("library not found"); - + /* There was an error, either the app image could not be opened or the native does not exist in the application and the + loaded libraries. Show an additional error and exit the vm*/ { char *info; size_t slen; @@ -1047,6 +1061,8 @@ static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmp #endif +#endif + /* * 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/asmoffsets.h b/src/vm/jit/i386/asmoffsets.h new file mode 100644 index 000000000..801ffdfd8 --- /dev/null +++ b/src/vm/jit/i386/asmoffsets.h @@ -0,0 +1,28 @@ +#ifndef __ASMOFFSETS_H_ +#define __ASMOFFSETS_H_ + +/* data segment offsets */ + +#define MethodPointer -4 +#define FrameSize -8 +#define IsSync -12 +#define IsLeaf -16 +#define IntSave -20 +#define FltSave -24 +#define LineNumberTableSize -28 +#define LineNumberTableStart -32 +#define ExTableSize -36 +#define ExTableStart -36 + +#define ExEntrySize -16 +#define ExStartPC -4 +#define ExEndPC -8 +#define ExHandlerPC -12 +#define ExCatchType -16 + + +#define LineEntrySize -8 +#define LinePC 0 +#define LineLine -4 + +#endif diff --git a/src/vm/jit/i386/asmpart.S b/src/vm/jit/i386/asmpart.S index 602525902..0908b73c6 100644 --- a/src/vm/jit/i386/asmpart.S +++ b/src/vm/jit/i386/asmpart.S @@ -29,38 +29,14 @@ Reinhard Grafl Christian Thalinger - $Id: asmpart.S 1623 2004-11-30 14:18:19Z twisti $ + $Id: asmpart.S 1680 2004-12-04 12:02:08Z jowenn $ */ #include "config.h" #include "vm/jit/i386/offsets.h" - - -/* data segment offsets */ - -#define MethodPointer -4 -#define FrameSize -8 -#define IsSync -12 -#define IsLeaf -16 -#define IntSave -20 -#define FltSave -24 -#define LineNumberTableSize -28 -#define LineNumberTableStart -32 -#define ExTableSize -36 -#define ExTableStart -36 - -#define ExEntrySize -16 -#define ExStartPC -4 -#define ExEndPC -8 -#define ExHandlerPC -12 -#define ExCatchType -16 - - -#define LineEntrySize -8 -#define LinePC 0 -#define LineLine -4 +#include "vm/jit/i386/asmoffsets.h" #define itmp1 %eax @@ -107,13 +83,11 @@ .globl asm_initialize_thread_stack .globl asm_switchstackandcall .globl asm_getcallingmethod - .globl Java_java_lang_VMSecurityManager_getClassContext - .globl Java_java_lang_VMSecurityManager_currentClassLoader .globl asm_builtin_new - .globl asm_get_stackTrace .globl asm_criticalsections .globl asm_getclassvalues_atomic - + .globl asm_prepare_native_stackinfo + .globl asm_remove_native_stackinfo /*************************** imported functions *******************************/ .globl jit_compile @@ -122,9 +96,6 @@ .globl builtin_trace_exception .globl class_java_lang_Object .globl codegen_findmethod -/* .globl codegen_findmethod1*/ - .globl builtin_asm_createclasscontextarray - .globl builtin_asm_getclassloader .globl callgetexceptionptrptr .globl asm_throw_and_handle_exception .globl asm_throw_and_handle_hardware_arithmetic_exception @@ -400,7 +371,14 @@ L_exception: pop %ecx /* delete return address */ sub $2,%ecx /* faulting address is return adress - 2 */ -L_refillinStacktrace: +L_refillinStacktrace: /*a compilation error should cause a stacktrace + which starts at the method call, which caused + the compilation of the new function. Until this + point the trace is invalid anyways, since it is + not complete. Compared to other runtimes it will + not be correct either, since we report eg class + not found errors too early, since we always + compile methods completely*/ push %ecx /* store fault adress */ push %eax /* temporarily save exception pointer*/ call builtin_asm_get_stackframeinfo @@ -457,18 +435,6 @@ 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 @@ -704,33 +670,25 @@ asm_check_clinit: test %eax,%eax jnz L_is_initialized -#if 0 - sub $16,%esp /* build stack frame (4 * 4 bytes) */ - mov %eax,(%esp) /* put classpointer on stack */ - call builtin_asm_get_stackframeinfo - - movl $0,12(%esp) - mov %eax,8(%esp) - mov (%eax),%ecx - mov %ecx,4(%esp) - mov %esp,%ecx - add $4,%ecx - mov %ecx,(%eax) -#endif + /*3*4 bytes*/ + mov 16(%esp),itmp1 + push itmp1 /*return adress into java machine code */ + mov 4(%esp),itmp1 + push itmp1 /*begin of java stack frame*/ + pushl $0 /*internal (invisible) method*/ + call asm_prepare_native_stackinfo /*puts additional 2 *4 bytes of + data onto the stack */ sub $4,%esp - mov 4+4(%esp),itmp1 /* get class pointer */ + mov 20+4+4(%esp),itmp1 /* get class pointer */ mov itmp1,(%esp) /* store class pointer as a0 */ call class_init /* call class_init function */ add $4,%esp -#if 0 - mov 4(%esp),%edx - mov 8(%esp),%ecx - mov %edx,(%ecx) - - add $16,%esp -#endif + call asm_remove_native_stackinfo /* removes 4* 4 bytes and leaves ret + into java machine code on stack */ + add $4,%esp /* ret address no longer needed, is still + on stack a few bytes above */ test %eax,%eax /* we had an exception */ je L_initializererror @@ -1045,11 +1003,18 @@ nb_aastore_null: jmp asm_handle_exception #endif nb_aastore_bound: - push %ecx /* itmp2 contains array index */ + add $12,%esp + mov %ecx,%eax /* itmp2 contains array index */ + pushl $0 /*directly below return adress*/ + pushl $0 /*internal (invisible) method*/ + call asm_prepare_native_stackinfo /* puts 2*4 bytes onto stack*/ + + push %eax call new_arrayindexoutofboundsexception add $(1*4),%esp - add $12,%esp + call asm_remove_native_stackinfo /*return adress is the first on stack again*/ + pop %ecx /* delete return address */ sub $2,%ecx /* faulting address is return adress - 2 */ jmp asm_handle_exception @@ -1207,224 +1172,39 @@ asm_switchstackandcall: ret -Java_java_lang_VMSecurityManager_currentClassLoader: - mov cacao_initializing,%eax - test %eax,%eax - jz Java_java_lang_VMSecurityManager_cont - - mov $0,%eax - ret -Java_java_lang_VMSecurityManager_cont: - lea builtin_asm_getclassloader,%eax - push %eax /*store collector function pointer*/ - jmp getClassContext_begin -Java_java_lang_VMSecurityManager_getClassContext: - lea builtin_asm_createclasscontextarray,%eax - push %eax /*store collector function pointer*/ -getClassContext_begin: /*start the real work*/ - - mov %esp,%eax - sub $4,%eax - sub $68,%esp /*64 memory location without overwriting return adress and collector function adress*/ - mov %esp,%ebx /*end of allocated memory block for classpointers is the adress of the working data block +4 */ - push $0 /*%esp+32 was native*/ - push %eax /*%esp+24 blkbegin*/ - push %eax /*%esp+20 currentpos*/ - push %ebx /*%esp+16 blkend*/ - - call builtin_asm_get_threadrootmethod - push %eax /*%esp+12*/ - movl 104(%esp),%eax /*(stack contains: threadRootMethod,blkend,blkpos,blkbegin,was native, data(64kB),collector,ret,env,class,frame stack info of stub, we want the frame stack info of thestub*/ - movl %esp,%edx - addl $116, %edx - push %edx /*esp+8*/ /*position of return address of native stub*/ - call builtin_asm_get_stackframeinfo -/* movl (%eax),%eax*/ /*TEST*/ - push 0(%eax) /*esp+4*/ /*address of frame info block*/ - movl 124(%esp),%edx - -/*DEBUG*/ -/* mov %esp,%eax - addl $116,%eax - push %eax - call i386_native_stub_debug - pop %eax*/ - - push %edx /*esp+0*/ /*return adress out of native stub*/ - call codegen_findmethod /*find calling java method, this one is still to be skipped (==SecurityManager.getClassContext (or .currentClassLoader)*/ - -/*DEBUGGING*/ -/* push %eax - movl MethodPointer(%eax),%eax - push %eax - call temporaryGetClassContextHelper - pop %eax - call traverseStackInfo - pop %eax -*/ - - movl 20(%esp),%edx - movl MethodPointer(%eax),%ebx - movl offclassmethodinfo(%ebx),%ecx - movl %ecx,(%edx) - subl $4,%edx - movl %edx,20(%esp) - - mov 8(%esp),%ebx /*pos of return adress */ - add FrameSize(%eax),%ebx - add $4,%ebx /*adress of new return adress (out of Securitymanager.*/ - mov %ebx,8(%esp) - mov %eax,(%esp) - - /* by now we have skipped this method call*/ - -getClassContext_next: - movl 8(%esp),%eax - movl (%eax),%eax - movl %eax,(%esp) /*return adress*/ - - call codegen_findmethod - - cmp $1,32(%esp) - mov 8(%esp),%ebx - add FrameSize(%eax),%ebx - add $4,%ebx - mov %ebx,8(%esp) /*store adress of next return adress*/ -getClassContext_nextRetStored: - - mov MethodPointer(%eax),%ecx /*get struct methodinfo*/ - - cmp $0,%ecx - je getClassContext_nativeCall - /*save class pointer*/ - movl $0,32(%esp) -getClassContext_saveClassPointer: - movl 20(%esp),%ebx /*get temporary memory adress in stack*/ - movl offclassmethodinfo(%ecx),%edx /* get class pointer of method*/ - movl %edx,(%ebx) /*save */ - sub $4,%ebx /*calculate next position */ - movl %ebx,20(%esp) /* check if the new adress would overwrite our working data */ - cmp %ebx,16(%esp) - je getClassContext_incStack -getClassContext_checkLeave: - - cmp 12(%esp),%ecx /*check if we reached the toplevel method of our thread*/ - je getClassContext_leave /*yes ->leave*/ - -/*DEBUGING*/ -/* mov %ecx,(%esp) - call temporaryGetClassContextHelper -*/ - - - jmp getClassContext_next /*continue*/ - - -getClassContext_nativeCall: - movl $1,32(%esp) - movl 4(%esp),%eax /*get top most element on stackframe help information stack*/ - test %eax,%eax - jz getClassContext_leave - movl 0(%eax),%ecx - movl %ecx,4(%esp) - addl $8,%eax - movl (%eax),%ecx - addl $4,%eax - movl %eax,8(%esp) - - cmp $0,%ecx - je getClassContext_checkLeave - jmp getClassContext_saveClassPointer - -getClassContext_incStack: - /*make another 64 in our temporary storage free and store the workingdata */ - movl %esp,%edx - subl $40,%esp /*should be 32*/ - push 32(%edx) - push 28(%edx) - push 24(%edx) - push 20(%edx) - push 16(%edx) - push 12(%edx) - push 8(%edx) - push 4(%edx) - push 0(%edx) - subl $64,16(%esp) - - jmp getClassContext_checkLeave /* continue */ - -getClassContext_leave: -/*DEBUGING*/ -/* mov %ecx,(%esp) - call temporaryGetClassContextHelper*/ - - /*call collector function with begin/end of temporary classarray*/ - push 24(%esp) - push 24(%esp) - - movl 32(%esp),%eax - add $4,%eax - movl (%eax),%ebx - call *%ebx - - /* free stack memory of this function*/ - mov 32(%esp),%esp - add $8,%esp - ret - - asm_throw_and_handle_exception: - sub $20,%esp /*build stack frame*/ - mov %ecx,16(%esp) /*save eip of problem */ - mov %eax,(%esp) - movl $0,12(%esp) /*internal function -> no function description */ - call builtin_asm_get_stackframeinfo - mov %eax,8(%esp) - mov (%eax),%ecx - mov %ecx,4(%esp) - mov %esp,%ecx - add $4,%ecx - mov %ecx,(%eax) + push %ecx + pushl $0 /* the pushed XPC is directly below the java frame*/ + pushl $0 + call asm_prepare_native_stackinfo /* be aware of the stack effect and calling convention explained below*/ -/* mov string_java_lang_NullPointerException,%eax - mov %eax,(%esp)*/ - call new_exception push %eax - mov 8(%esp),%eax - mov 12(%esp),%ecx - mov %eax,(%ecx) - pop %eax - add $16,%esp + call new_exception + add $4,%esp /*remove parameter*/ + + call asm_remove_native_stackinfo /* be aware of the stack effect and calling convention explained below*/ + pop %ecx jmp asm_handle_exception ret /*should never be reached */ asm_throw_and_handle_hardware_arithmetic_exception: - sub $24,%esp /*build stack frame*/ - mov %ecx,20(%esp) /*save eip of problem */ - movl $0,16(%esp) /*internal function -> no function description */ - call builtin_asm_get_stackframeinfo - mov %eax,12(%esp) - mov (%eax),%ecx - mov %ecx,8(%esp) - mov %esp,%ecx - add $8,%ecx - mov %ecx,(%eax) + push %ecx + pushl $0 /* the pushed XPC is directly below the java frame*/ + pushl $0 + call asm_prepare_native_stackinfo /* be aware of the stack effect and calling convention explained below*/ - mov string_java_lang_ArithmeticException,%eax - mov %eax,(%esp) mov string_java_lang_ArithmeticException_message,%eax - mov %eax,4(%esp) + push %eax + mov string_java_lang_ArithmeticException,%eax + push %eax call new_exception_message + add $8,%esp /*remove parameters */ + + call asm_remove_native_stackinfo /* be aware of the stack effect and calling convention explained below*/ - push %eax - mov 12(%esp),%eax - mov 16(%esp),%ecx - mov %eax,(%ecx) - pop %eax - add $20,%esp pop %ecx jmp asm_handle_exception ret /*should never be reached */ @@ -1442,6 +1222,13 @@ asm_builtin_new: test %ecx,%ecx jnz L_builtin_new_noinit + mov 4(%esp),%eax /* class pointer, is kept during the asm_prepare... calls */ + + /* 2 *4 bytes, the return adress is used directy */ + pushl $0 /* the structure is placed directly below the java stackframe*/ + pushl $0 /* builtin (invisible) method */ + call asm_prepare_native_stackinfo /*puts 2*4 additional bytes on stack*/ +#if 0 sub $16,%esp /* build stack frame (4 * 4 bytes) */ mov 20(%esp),%eax @@ -1455,15 +1242,20 @@ asm_builtin_new: mov %esp,%ecx add $4,%ecx mov %ecx,(%eax) - +#endif + push %eax call builtin_new + add $4,%esp + call asm_remove_native_stackinfo /*first element on stack is return adress again*/ +#if 0 + call mov 4(%esp),%ebx mov 8(%esp),%ecx mov %ebx,(%ecx) add $16,%esp - +#endif jmp L_builtin_new_patch @@ -1485,104 +1277,6 @@ L_builtin_new_patch: -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 codegen_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 - asm_getclassvalues_atomic: _crit_restart2: @@ -1614,6 +1308,107 @@ asm_criticalsections: #endif .long 0 + + +/************************ function asm_prepare_native_stackinfo **************************** +* * +* creates a stackfame for the begin of a native function (either builtin or not ) * +* expected stack at begin of function * +* .... * +* address of the jit call which invokes the native * +* begin address of stack frame of the java method * +* method pointer or 0 (for built ins) * +* return address * +* * +* at end of function: * +* ... * +* address of the jit call which invokes the native * +* begin address of stack frame of the java method * +* method pointer or 0 (for built ins) * +* address of thread specific top of native list * +* old value of thread specific head * +* return address * +* * +* .... * +* This thing is less efficient than the original #define (callerside) * +* destroyes REG_ITMP2, keeps REG_ITMP1 * +********************************************************************************************/ + + +asm_prepare_native_stackinfo: + sub $8,%esp + mov 8(%esp),%ecx + mov %ecx,(%esp) + push %eax + lea builtin_asm_get_stackframeinfo,%ecx + call *%ecx + mov %eax, 12(%esp) + mov (%eax),%ecx + mov %ecx,8(%esp) + mov %esp,%ecx + add $8,%ecx + mov %ecx,(%eax) + pop %eax + ret +#if 0 +#define PREPARE_NATIVE_STACKINFO \ + i386_push_reg(cd, REG_ITMP1); /*save itmp1, needed by some stubs */ \ + i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \ + i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \ + i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/ \ + i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \ + i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \ + i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \ + i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \ + i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */ \ + i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \ + i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \ + i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */ +#endif + + +/************************ function asm_remove _native_stackinfo ******************************************* +* * +* creates a stackfame for the begin of a native function (either builtin or not) * +* expected stack at begin of function * +* address of the jit call which invokes the native * +* begin address of stack frame of the java method * +* method pointer or 0 (for built ins) * +* address thread specific top of native list * +* old value of thread specific head * +* return address * +* * +* at end of function: * +* .... * +* return adresss of the jit call which invokes the native * +* return address * +* * +* REG_ITMP2_XPC = address of the jit call which invokes the native * +* * +* * +* This thing is less efficient than the original #define (callerside), uses ITMP3,uses ITMP3,keeps ITMP1 * +***********************************************************************************************************/ + +asm_remove_native_stackinfo: + mov 4(%esp),%ecx + mov 8(%esp),%edx + mov %ecx,(%edx) + pop %edx + add $16,%esp + push %edx + ret + +#if 0 +#define REMOVE_NATIVE_STACKINFO \ + i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \ + i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \ + i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \ + i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP); +#endif + + + + /* * 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 f3065623e..00be85b01 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 1641 2004-12-01 13:13:31Z christian $ + $Id: codegen.c 1680 2004-12-04 12:02:08Z jowenn $ */ @@ -37,6 +37,9 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif #include "config.h" #include "native/jni.h" @@ -53,6 +56,9 @@ #include "vm/jit/i386/codegen.h" #include "vm/jit/i386/emitfuncs.h" #include "vm/jit/i386/types.h" +#include "vm/jit/i386/asmoffsets.h" +#include "vm/jit/stacktrace.inc" + /* register descripton - array ************************************************/ @@ -106,33 +112,18 @@ void codegen_general_stubcalled() { void thread_restartcriticalsection(ucontext_t *uc) { void *critical; +#ifdef __FreeBSD__ + if ((critical = thread_checkcritical((void*) uc->uc_mcontext.mc_eip)) != NULL) + uc->uc_mcontext.mc_eip = (u4) critical; +#else if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL) uc->uc_mcontext.gregs[REG_EIP] = (u4) critical; + +#endif } #endif -#define PREPARE_NATIVE_STACKINFO \ - i386_push_reg(cd, REG_ITMP1); /*save itmp1, needed by some stubs */ \ - i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \ - i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \ - i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/ \ - i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \ - i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \ - i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \ - i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \ - i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */ \ - i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \ - i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \ - i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */ - - -#define REMOVE_NATIVE_STACKINFO \ - i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \ - i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \ - i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \ - i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP); - /* NullPointerException signal handler for hardware null pointer check */ @@ -141,8 +132,13 @@ void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p) sigset_t nsig; /* long faultaddr; */ - struct ucontext *_uc = (struct ucontext *) _p; - struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext; +#ifdef __FreeBSD__ + ucontext_t *_uc = (ucontext_t *) _p; + mcontext_t *sigctx = (mcontext_t *) &_uc->uc_mcontext; +#else + struct ucontext *_uc = (struct ucontext *) _p; + struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext; +#endif struct sigaction act; /* Reset signal handler - necessary for SysV, does no harm for BSD */ @@ -158,15 +154,20 @@ void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p) act.sa_flags = SA_SIGINFO; sigaction(sig, &act, NULL); /* reinstall handler */ - sigemptyset(&nsig); - sigaddset(&nsig, sig); - sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */ + sigemptyset(&nsig); + sigaddset(&nsig, sig); + sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */ - sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */ - sigctx->eax = (u4) string_java_lang_NullPointerException; - sigctx->eip = (u4) asm_throw_and_handle_exception; - - return; +#ifdef __FreeBSD__ + sigctx->mc_ecx = sigctx->mc_eip; /* REG_ITMP2_XPC*/ + sigctx->mc_eax = (u4) string_java_lang_NullPointerException; + sigctx->mc_eip = (u4) asm_throw_and_handle_exception; +#else + sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */ + sigctx->eax = (u4) string_java_lang_NullPointerException; + sigctx->eip = (u4) asm_throw_and_handle_exception; +#endif + return; /* } else { */ /* faultaddr += (long) ((instr << 16) >> 16); */ @@ -184,8 +185,15 @@ void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p) /* void **_p = (void **) &sig; */ /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */ - struct ucontext *_uc = (struct ucontext *) _p; - struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext; + +#ifdef __FreeBSD__ + ucontext_t *_uc = (ucontext_t *) _p; + mcontext_t *sigctx = (mcontext_t *) &_uc->uc_mcontext; +#else + struct ucontext *_uc = (struct ucontext *) _p; + struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext; +#endif + struct sigaction act; /* Reset signal handler - necessary for SysV, does no harm for BSD */ @@ -199,9 +207,13 @@ void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p) sigaddset(&nsig, sig); sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */ - sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */ +#ifdef __FreeBSD__ + sigctx->mc_ecx = sigctx->mc_eip; /* REG_ITMP2_XPC */ + sigctx->mc_eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception; +#else + sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */ sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception; - +#endif return; } @@ -4466,7 +4478,11 @@ gen_method: { i386_push_reg(cd, REG_ITMP2_XPC); - PREPARE_NATIVE_STACKINFO; + /*PREPARE_NATIVE_STACKINFO;*/ + i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/ + i386_push_imm(cd,0); + i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP); i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4); @@ -4474,7 +4490,9 @@ gen_method: { i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */ i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP); - REMOVE_NATIVE_STACKINFO; + /*REMOVE_NATIVE_STACKINFO;*/ + i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); i386_pop_reg(cd, REG_ITMP2_XPC); @@ -4514,14 +4532,23 @@ gen_method: { i386_push_reg(cd, REG_ITMP2_XPC); - PREPARE_NATIVE_STACKINFO; + /*PREPARE_NATIVE_STACKINFO;*/ + i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/ + i386_push_imm(cd,0); + i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + + i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1); i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */ /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/ - REMOVE_NATIVE_STACKINFO; + /*REMOVE_NATIVE_STACKINFO;*/ + i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + i386_pop_reg(cd, REG_ITMP2_XPC); @@ -4561,14 +4588,22 @@ gen_method: { i386_push_reg(cd, REG_ITMP2_XPC); - PREPARE_NATIVE_STACKINFO; + /*PREPARE_NATIVE_STACKINFO;*/ + i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/ + i386_push_imm(cd,0); + i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1); i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */ /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/ - REMOVE_NATIVE_STACKINFO; + /*REMOVE_NATIVE_STACKINFO;*/ + i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + i386_pop_reg(cd, REG_ITMP2_XPC); @@ -4608,12 +4643,21 @@ gen_method: { i386_push_reg(cd, REG_ITMP2_XPC); - PREPARE_NATIVE_STACKINFO; + /*PREPARE_NATIVE_STACKINFO;*/ + i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/ + i386_push_imm(cd,0); + i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + + i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1); i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */ - REMOVE_NATIVE_STACKINFO; + /*REMOVE_NATIVE_STACKINFO;*/ + i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + i386_pop_reg(cd, REG_ITMP2_XPC); @@ -4653,7 +4697,12 @@ gen_method: { i386_push_reg(cd, REG_ITMP2_XPC); - PREPARE_NATIVE_STACKINFO; + /*PREPARE_NATIVE_STACKINFO;*/ + i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/ + i386_push_imm(cd,0); + i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1); i386_call_reg(cd, REG_ITMP1); @@ -4701,7 +4750,10 @@ java stack at this point*/ i386_pop_reg(cd, REG_ITMP1_XPTR); i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/ - REMOVE_NATIVE_STACKINFO; + /*REMOVE_NATIVE_STACKINFO;*/ + i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + i386_pop_reg(cd, REG_ITMP2_XPC); @@ -4741,7 +4793,13 @@ java stack at this point*/ i386_push_reg(cd, REG_ITMP2_XPC); - PREPARE_NATIVE_STACKINFO; + /*PREPARE_NATIVE_STACKINFO;*/ + i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/ + i386_push_imm(cd,0); + i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + + #if 0 /* create native call block*/ @@ -4763,7 +4821,10 @@ java stack at this point*/ i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1); i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */ - REMOVE_NATIVE_STACKINFO; + /*REMOVE_NATIVE_STACKINFO;*/ + i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3); + i386_call_reg(cd,REG_ITMP3); + #if 0 /* restore native call stack */ @@ -4928,8 +4989,8 @@ u1 *createnativestub(functionptr f, methodinfo *m) int addmethod=0; u1 *tptr; int i; - int stackframesize = 4+12; /* initial 4 bytes is space for jni env, - + 4 byte thread pointer + 4 byte previous pointer + method info*/ + int stackframesize = 4+16; /* initial 4 bytes is space for jni env, + + 4 byte thread pointer + 4 byte previous pointer + method info + 4 offset native*/ int stackframeoffset = 4; int p, t; @@ -5096,14 +5157,15 @@ u1 *createnativestub(functionptr f, methodinfo *m) i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP); /* CREATE DYNAMIC STACK INFO -- BEGIN*/ - i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4); + i386_mov_imm_membase(cd,0,REG_SP,stackframesize-4); + i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8); i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1); i386_call_reg(cd, REG_ITMP1); - i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/ + i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-12); /*save thread specific pointer*/ i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); - i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/ + i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-16); /*save previous value of memory adress pointed to by thread specific pointer*/ i386_mov_reg_reg(cd, REG_SP,REG_ITMP2); - i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2); + i386_alu_imm_reg(cd, I386_ADD,stackframesize-16,REG_ITMP2); i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0); /*TESTING ONLY */ @@ -5116,7 +5178,7 @@ u1 *createnativestub(functionptr f, methodinfo *m) /* RESOLVE NATIVE METHOD -- BEGIN*/ #ifndef STATIC_CLASSPATH if (f==0) { - log_text("Dynamic classpath: preparing for delayed native function resolving"); + /*log_text("Dynamic classpath: preparing for delayed native function resolving");*/ i386_jmp_imm(cd,0); jmpInstrPos=cd->mcodeptr-4; /*patchposition*/ @@ -5143,7 +5205,7 @@ u1 *createnativestub(functionptr f, methodinfo *m) i386_pop_reg(cd,REG_ITMP1); /*fix jmp offset replacement*/ (*jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-4; - } else log_text("Dynamic classpath: immediate native function resolution possible"); + } /*else log_text("Dynamic classpath: immediate native function resolution possible");*/ #endif /* RESOLVE NATIVE METHOD -- END*/ @@ -5191,8 +5253,8 @@ u1 *createnativestub(functionptr f, methodinfo *m) /*REMOVE DYNAMIC STACK INFO -BEGIN */ i386_push_reg(cd, REG_RESULT2); - i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/ - i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/ + i386_mov_membase_reg(cd, REG_SP,stackframesize-12,REG_ITMP2); /*old value*/ + i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_RESULT2); /*pointer*/ i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0); i386_pop_reg(cd, REG_RESULT2); /*REMOVE DYNAMIC STACK INFO -END */ diff --git a/src/vm/jit/i386/symcat.h b/src/vm/jit/i386/symcat.h new file mode 100644 index 000000000..61ce1e9b3 --- /dev/null +++ b/src/vm/jit/i386/symcat.h @@ -0,0 +1,49 @@ +/* Symbol concatenation utilities. + + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SYM_CAT_H +#define SYM_CAT_H + +#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) +#define CONCAT2(a,b) a##b +#define CONCAT3(a,b,c) a##b##c +#define CONCAT4(a,b,c,d) a##b##c##d +#define STRINGX(s) #s +#else +/* Note one should never pass extra whitespace to the CONCATn macros, + e.g. CONCAT2(foo, bar) because traditonal C will keep the space between + the two labels instead of concatenating them. Instead, make sure to + write CONCAT2(foo,bar). */ +#define CONCAT2(a,b) a/**/b +#define CONCAT3(a,b,c) a/**/b/**/c +#define CONCAT4(a,b,c,d) a/**/b/**/c/**/d +#define STRINGX(s) "s" +#endif + +#define XCONCAT2(a,b) CONCAT2(a,b) +#define XCONCAT3(a,b,c) CONCAT3(a,b,c) +#define XCONCAT4(a,b,c,d) CONCAT4(a,b,c,d) + +/* Note the layer of indirection here is typically used to allow + stringification of the expansion of macros. I.e. "#define foo + bar", "XSTRING(foo)", to yield "bar". Be aware that this only + works for __STDC__, not for traditional C which will still resolve + to "foo". */ +#define XSTRING(s) STRINGX(s) + +#endif /* SYM_CAT_H */ diff --git a/src/vm/jit/stack.c b/src/vm/jit/stack.c index 2b56938fe..25fad8880 100644 --- a/src/vm/jit/stack.c +++ b/src/vm/jit/stack.c @@ -28,7 +28,7 @@ Changes: Edwin Steiner - $Id: stack.c 1642 2004-12-01 13:21:54Z christian $ + $Id: stack.c 1680 2004-12-04 12:02:08Z jowenn $ */ @@ -2630,7 +2630,7 @@ void show_icmd(instruction *iptr, bool deadcode) } break; } -/* printf(" Line number: %d, method:",iptr->line); */ + printf(" Line number: %d, method:",iptr->line); /* printf("\t\t"); utf_display(iptr->method->class->name); printf("."); diff --git a/src/vm/jit/stacktrace.c b/src/vm/jit/stacktrace.c new file mode 100644 index 000000000..8f6746fba --- /dev/null +++ b/src/vm/jit/stacktrace.c @@ -0,0 +1,408 @@ +/* jit/stacktrace.inc + + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 + R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, + M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, + P. Tomsich, J. Wenninger + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + + Contact: cacao@complang.tuwien.ac.at + + Authors: Joseph Wenninger + + $Id: stacktrace.c 1680 2004-12-04 12:02:08Z jowenn $ + +*/ + +#ifndef _STACKTRACE_H_ +#define _STACKTRACE_H_ + +#include "vm/global.h" +#include "toolbox/logging.h" +#include "vm/jit/codegen.inc" + +#include +#include + +#undef JWDEBUG + +extern classinfo *class_java_lang_Class; +extern classinfo *class_java_lang_SecurityManager; + +/* the line number is only u2, but to avoid alignment problems it is made the same size as a native + pointer. In the structures where this is used, values of -1 or -2 have a special meainging, so + if java bytecode is ever extended to support more than 65535 lines/file, this could will have to + be changed.*/ + +#ifdef _ALPHA_ + #define LineNumber u8 +#else + #define LineNumber u4 +#endif + +typedef struct lineNumberTableEntry { +/* The special value of -1 means that a inlined function starts, a value of -2 means that an inlined function ends*/ + LineNumber lineNr; + void *pc; +} lineNumberTableEntry; + +typedef struct lineNumberTableEntryInlineBegin { +/*this should have the same layout and size as the lineNumberTableEntry*/ + LineNumber lineNrOuter; + methodinfo *method; +} lineNumberTableEntryInlineBegin; + + +typedef void(*CacaoStackTraceCollector)(void **,stackTraceBuffer*); + +#define BLOCK_INITIALSIZE 40 +#define BLOCK_SIZEINCREMENT 40 + +static void addEntry(stackTraceBuffer* buffer,methodinfo*method ,LineNumber line) { + if (buffer->size>buffer->full) { + stacktraceelement *tmp=&(buffer->start[buffer->full]); + tmp->method=method; + tmp->linenumber=line; + buffer->full = buffer->full + 1; +#ifdef JWDEBUG + log_text("addEntry (stacktrace):"); + if (method) utf_display(method->name); else printf("Native"); + if (method) {printf("\n");utf_display(method->class->name);} + printf("\nLine:%ld\n",line); +#endif + } else { + stacktraceelement *newBuffer=(stacktraceelement*) + malloc((buffer->size+BLOCK_SIZEINCREMENT)*sizeof(stacktraceelement)); + if (newBuffer==0) panic("OOM during stacktrace creation"); + memcpy(newBuffer,buffer->start,buffer->size*sizeof(stacktraceelement)); + if (buffer->needsFree) free(buffer->start); + buffer->start=newBuffer; + buffer->size=buffer->size+BLOCK_SIZEINCREMENT; + buffer->needsFree=1; + addEntry(buffer,method,line); + } +} + +static int fillInStackTrace_methodRecursive(stackTraceBuffer *buffer,methodinfo + *method,lineNumberTableEntry *startEntry, lineNumberTableEntry **entry, size_t *entriesAhead,void *adress) { + + size_t ahead=*entriesAhead; + lineNumberTableEntry *ent=*entry; + lineNumberTableEntryInlineBegin *ilStart; + + for (;ahead>0;ahead--,ent++) { + if (adress>=ent->pc) { + switch (ent->lineNr) { + case -1: /*begin of inlined method */ + ilStart=(lineNumberTableEntryInlineBegin*)(++ent); + ent ++; + ahead--; ahead--; + if (fillInStackTrace_methodRecursive(buffer,ilStart->method,ent,&ent,&ahead,adress)) { + addEntry(buffer,method,ilStart->lineNrOuter); + return 1; + } + break; + case -2: /*end of inlined method*/ + *entry=ent; + *entriesAhead=ahead; + return 0; + break; + default: + if (adress==ent->pc) { + addEntry(buffer,method,ent->lineNr); + return 1; + } + break; + } + } else { + if (adress>startEntry->pc) { + ent--; + addEntry(buffer,method,ent->lineNr); + return 1; + } else panic("trace point before method"); + } + } + ent--; + addEntry(buffer,method,ent->lineNr); + return 1; + +} + +static void fillInStackTrace_method(stackTraceBuffer *buffer,methodinfo *method,char *dataSeg, void* adress) { + size_t lineNumberTableSize=(*((size_t*)(dataSeg+LineNumberTableSize))); + + + if ( lineNumberTableSize == 0) { + /*right now this happens only on + i386,if the native stub causes an exception in a invocation (jowenn)*/ + addEntry(buffer,method,0); + return; + } else { + lineNumberTableEntry *ent; /*=(lineNumberTableEntry*) ((*((char**)(dataSeg+LineNumberTableStart))) - (sizeof(lineNumberTableEntry)-sizeof(void*)));*/ + void **calc; + lineNumberTableEntry *startEntry; + + /* printf("dataSeg: %p\n",dataSeg);*/ + calc=dataSeg+LineNumberTableStart; + /* printf("position of line number table start reference in data segment: %p\n",calc); + printf("line number table start as found in table: %p\n",*calc);*/ + ent=(lineNumberTableEntry *) (((char*)(*calc) - (sizeof(lineNumberTableEntry)-sizeof(void*)))); + /* printf("line number table start as calculated: %p\n",ent);*/ + ent-=(lineNumberTableSize-1); + startEntry=ent; + /* printf("line number table real start (bottom end) as calculated(2): %p\n",startEntry);*/ + + if (!fillInStackTrace_methodRecursive(buffer,method,startEntry,&ent,&lineNumberTableSize,adress)) { + panic("Trace point not found in suspected method"); + } + } +} + + +void cacao_stacktrace_fillInStackTrace(void **target,CacaoStackTraceCollector coll) +{ + + stacktraceelement primaryBlock[BLOCK_INITIALSIZE*sizeof(stacktraceelement)]; + /*In most cases this should be enough -> one malloc less. I don't think temporary data should be + allocated with the GC, only the result*/ + stackTraceBuffer buffer; + buffer.needsFree=0; + buffer.start=primaryBlock; + buffer.size=BLOCK_INITIALSIZE*sizeof(stacktraceelement); + buffer.full=0; + + + { + struct native_stackframeinfo *info=(*(((void**)(builtin_asm_get_stackframeinfo())))); + if (!info) { + log_text("info ==0"); + *target=0; + return; + } else { + char *dataseg; /*make it byte addressable*/ + methodinfo *currentMethod=0; + void *returnAdress; + char* stackPtr; + +/* utf_display(info->method->class->name); + utf_display(info->method->name);*/ + + while ((currentMethod!=0) || (info!=0)) { + if (currentMethod==0) { /*some builtin native */ + currentMethod=info->method; + returnAdress=info->returnToFromNative; + /*log_text("native");*/ + if (currentMethod) { + /*utf_display(currentMethod->class->name); + utf_display(currentMethod->name);*/ + addEntry(&buffer,currentMethod,0); + } + dataseg=codegen_findmethod(returnAdress); + currentMethod=(*((methodinfo**)(dataseg+MethodPointer))); + if (info->beginOfJavaStackframe==0) + stackPtr=((char*)info)+sizeof(native_stackframeinfo); + else + stackPtr=(char*)(info->beginOfJavaStackframe)+sizeof(void*); + info=info->oldThreadspecificHeadValue; + } else { /*method created by jit*/ + u4 frameSize; + /*log_text("JIT");*/ + if (currentMethod->isleafmethod) panic("How could that happen ??? A leaf method in the middle of a stacktrace ??"); + /*utf_display(currentMethod->class->name); + utf_display(currentMethod->name);*/ + fillInStackTrace_method(&buffer,currentMethod,dataseg,returnAdress); + frameSize=*((u4*)(dataseg+FrameSize)); +#ifdef __ALPHA__ + /* cacao saves the return adress as the first element of the stack frame on alphas*/ + dataseg=codegen_findmethod(*((void**)(stackPtr+frameSize-sizeof(void*)))); + returnAdress=(*((void**)(stackPtr+frameSize-sizeof(void*)))); +#else + /* on i386 the return adress is the first element before the stack frme*/ + returnAdress=(*((void**)(stackPtr+frameSize))); + dataseg=codegen_findmethod(*((void**)(stackPtr+frameSize))); +#endif +/* printf ("threadrootmethod %p\n",builtin_asm_get_threadrootmethod()); + if (currentMethod==builtin_asm_get_threadrootmethod()) break;*/ + currentMethod=(*((methodinfo**)(dataseg+MethodPointer))); +#ifdef __ALPHA__ + stackPtr+=frameSize; +#else + stackPtr+=frameSize+sizeof(void*); +#endif + } + } + + if (coll) coll(target,&buffer); + if (buffer.needsFree) free(buffer.start); + return; + } + /*log_text("\n=========================================================");*/ + } + *target=0; + +} + + +static +void stackTraceCollector(void **target, stackTraceBuffer *buffer) { + stackTraceBuffer *dest=*target=heap_allocate(sizeof(stackTraceBuffer)+buffer->full*sizeof(stacktraceelement),true,0); + memcpy(*target,buffer,sizeof(stackTraceBuffer)); + memcpy(dest+1,buffer->start,buffer->full*sizeof(stacktraceelement)); + + dest->needsFree=0; + dest->size=dest->full; + dest->start=dest+1; + + /* + if (buffer->full>0) { + printf("SOURCE BUFFER:%s\n",buffer->start[0].method->name->text); + printf("DEST BUFFER:%s\n",dest->start[0].method->name->text); + } else printf("Buffer is empty\n"); + */ +} + + +void cacao_stacktrace_NormalTrace(void **target) { + cacao_stacktrace_fillInStackTrace(target,&stackTraceCollector); +} + + + +static +void classContextCollector(void **target, stackTraceBuffer *buffer) { + java_objectarray *tmpArray; + int i; + stacktraceelement *current; + stacktraceelement *start; + classinfo *c; + size_t size; + size_t targetSize; + + size=buffer->full; + targetSize=0; + for (i=0;istart[i].method!=0) targetSize++; + start=buffer->start; + start++; + targetSize--; + if (!class_java_lang_Class) + class_java_lang_Class = class_new(utf_new_char("java/lang/Class")); + + if (!class_java_lang_SecurityManager) + class_java_lang_SecurityManager = + class_new(utf_new_char("java/lang/SecurityManager")); + + if (targetSize > 0) { + if ((start->method) && (start->method->class== class_java_lang_SecurityManager)) { + targetSize--; + start++; + } + } + + tmpArray = + builtin_newarray(targetSize, class_array_of(class_java_lang_Class)->vftbl); + + for(i = 0, current = start; i < targetSize; i++, current++) { + if (current->method==0) { i--; continue;} + /*printf("adding item to class context array:%s\n",current->method->class->name->text); + printf("method for class: :%s\n",current->method->name->text);*/ + use_class_as_object(current->method->class); + tmpArray->data[i] = (java_objectheader *) current->method->class; + } + + *target=tmpArray; +} + + + +java_objectarray *cacao_createClassContextArray() { + java_objectarray *array=0; + cacao_stacktrace_fillInStackTrace(&array,&classContextCollector); + return array; + +} + + +static +void classLoaderCollector(void **target, stackTraceBuffer *buffer) { + int i; + stacktraceelement *current; + stacktraceelement *start; + methodinfo *m; + classinfo *privilegedAction; + size_t size; + + size = buffer->full; + + + if (!class_java_lang_SecurityManager) + class_java_lang_SecurityManager = + class_new(utf_new_char("java/lang/SecurityManager")); + + if (size > 1) { + size--; + start=&(buffer->start[1]); + if (start == class_java_lang_SecurityManager) { + size--; + start--; + } + } else { + start=0; + size=0; + } + privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction")); + + for(i=0, current = start; i < size; i++, current++) { + m=start->method; + if (!m) continue; + + if (m->class == privilegedAction) { + *target=NULL; + return; + } + + if (m->class->classloader) { + *target= (java_lang_ClassLoader *) m->class->classloader; + return; + } + } + + *target=NULL; +} + +java_objectheader *cacao_currentClassLoader() { + java_objectheader *header=0; + cacao_stacktrace_fillInStackTrace(&header,&classLoaderCollector); + return header; +} + +#endif + +/* + * 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 + * Emacs will automagically detect them. + * --------------------------------------------------------------------- + * Local variables: + * mode: c + * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --git a/src/vm/jit/x86_64/asmpart.S b/src/vm/jit/x86_64/asmpart.S index cec1b9e43..f1a9f5441 100644 --- a/src/vm/jit/x86_64/asmpart.S +++ b/src/vm/jit/x86_64/asmpart.S @@ -29,7 +29,7 @@ Reinhard Grafl Christian Thalinger - $Id: asmpart.S 1621 2004-11-30 13:06:55Z twisti $ + $Id: asmpart.S 1680 2004-12-04 12:02:08Z jowenn $ */ @@ -37,22 +37,7 @@ #include "config.h" #include "vm/jit/x86_64/arch.h" #include "vm/jit/x86_64/offsets.h" - - -#define MethodPointer -8 -#define FrameSize -12 -#define IsSync -16 -#define IsLeaf -20 -#define IntSave -24 -#define FltSave -28 -#define ExTableSize -32 -#define ExTableStart -32 - -#define ExEntrySize -32 -#define ExStartPC -8 -#define ExEndPC -16 -#define ExHandlerPC -24 -#define ExCatchType -32 +#include "vm/jit/x86_64/asmoffsets.h" /* define it like the risc way */ diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index 5385908ad..25cb8f0d8 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -28,7 +28,7 @@ Authors: Andreas Krall Christian Thalinger - $Id: codegen.c 1668 2004-12-03 16:39:40Z twisti $ + $Id: codegen.c 1680 2004-12-04 12:02:08Z jowenn $ */ @@ -52,7 +52,10 @@ #include "vm/jit/x86_64/codegen.h" #include "vm/jit/x86_64/emitfuncs.h" #include "vm/jit/x86_64/types.h" - +#include "vm/jit/x86_64/asmoffsets.h" +#if 0 +#include "vm/jit/stacktrace.inc" +#endif /* register descripton - array ************************************************/ @@ -3857,6 +3860,10 @@ u1 *createnativestub(functionptr f, methodinfo *m) t_inlining_globals *id; s4 dumpsize; + void **callAddrPatchPos=0; + u1 *jmpInstrPos=0; + void **jmpInstrPatchPos=0; + /* mark start of dump memory area */ dumpsize = dump_size(); @@ -3886,27 +3893,28 @@ u1 *createnativestub(functionptr f, methodinfo *m) } } - if (runverbose) { - s4 p, l, s1; - x86_64_alu_imm_reg(cd, X86_64_SUB, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP); + x86_64_alu_imm_reg(cd, X86_64_SUB, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP); - x86_64_mov_reg_membase(cd, rd->argintregs[0], REG_SP, 1 * 8); - x86_64_mov_reg_membase(cd, rd->argintregs[1], REG_SP, 2 * 8); - x86_64_mov_reg_membase(cd, rd->argintregs[2], REG_SP, 3 * 8); - x86_64_mov_reg_membase(cd, rd->argintregs[3], REG_SP, 4 * 8); - x86_64_mov_reg_membase(cd, rd->argintregs[4], REG_SP, 5 * 8); - x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 6 * 8); + x86_64_mov_reg_membase(cd, rd->argintregs[0], REG_SP, 1 * 8); + x86_64_mov_reg_membase(cd, rd->argintregs[1], REG_SP, 2 * 8); + x86_64_mov_reg_membase(cd, rd->argintregs[2], REG_SP, 3 * 8); + x86_64_mov_reg_membase(cd, rd->argintregs[3], REG_SP, 4 * 8); + x86_64_mov_reg_membase(cd, rd->argintregs[4], REG_SP, 5 * 8); + x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 6 * 8); - x86_64_movq_reg_membase(cd, rd->argfltregs[0], REG_SP, 7 * 8); - x86_64_movq_reg_membase(cd, rd->argfltregs[1], REG_SP, 8 * 8); - x86_64_movq_reg_membase(cd, rd->argfltregs[2], REG_SP, 9 * 8); - x86_64_movq_reg_membase(cd, rd->argfltregs[3], REG_SP, 10 * 8); + x86_64_movq_reg_membase(cd, rd->argfltregs[0], REG_SP, 7 * 8); + x86_64_movq_reg_membase(cd, rd->argfltregs[1], REG_SP, 8 * 8); + x86_64_movq_reg_membase(cd, rd->argfltregs[2], REG_SP, 9 * 8); + x86_64_movq_reg_membase(cd, rd->argfltregs[3], REG_SP, 10 * 8); /* x86_64_movq_reg_membase(cd, rd->argfltregs[4], REG_SP, 11 * 8); */ /* x86_64_movq_reg_membase(cd, rd->argfltregs[5], REG_SP, 12 * 8); */ /* x86_64_movq_reg_membase(cd, rd->argfltregs[6], REG_SP, 13 * 8); */ /* x86_64_movq_reg_membase(cd, rd->argfltregs[7], REG_SP, 14 * 8); */ + if (runverbose) { + s4 p, l, s1; + /* show integer hex code for float arguments */ for (p = 0, l = 0; p < m->paramcount; p++) { if (IS_FLT_DBL_TYPE(m->paramtypes[p])) { @@ -3921,27 +3929,44 @@ u1 *createnativestub(functionptr f, methodinfo *m) x86_64_mov_imm_reg(cd, (s8) m, REG_ITMP1); x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 8); - x86_64_mov_imm_reg(cd, (s8) builtin_trace_args, REG_ITMP1); + x86_64_mov_imm_reg(cd, (s8) builtin_trace_args, REG_ITMP1); x86_64_call_reg(cd, REG_ITMP1); + } +/* call method to resolve native function if needed */ +#ifndef STATIC_CLASSPATH + if (f==0) { /* only if not already resolved */ + x86_64_jmp_imm(cd,0); + jmpInstrPos=cd->mcodeptr-4; /*needed to patch a jump over this block*/ + x86_64_mov_imm_reg(cd,(u8)m,rd->argintregs[0]); + x86_64_mov_imm_reg(cd,0,rd->argintregs[1]); + callAddrPatchPos=cd->mcodeptr-8; /* at this position the place is specified where the native function adress should be patched into*/ + x86_64_mov_imm_reg(cd,0,rd->argintregs[2]); + jmpInstrPatchPos=cd->mcodeptr-8; + x86_64_mov_imm_reg(cd,jmpInstrPos,rd->argintregs[3]); + x86_64_mov_imm_reg(cd,(s8)codegen_resolve_native,REG_ITMP1); + x86_64_call_reg(cd,REG_ITMP1); + *(jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-1; /*=opcode jmp_imm size*/ + } +#endif - x86_64_mov_membase_reg(cd, REG_SP, 1 * 8, rd->argintregs[0]); - x86_64_mov_membase_reg(cd, REG_SP, 2 * 8, rd->argintregs[1]); - x86_64_mov_membase_reg(cd, REG_SP, 3 * 8, rd->argintregs[2]); - x86_64_mov_membase_reg(cd, REG_SP, 4 * 8, rd->argintregs[3]); - x86_64_mov_membase_reg(cd, REG_SP, 5 * 8, rd->argintregs[4]); - x86_64_mov_membase_reg(cd, REG_SP, 6 * 8, rd->argintregs[5]); - - x86_64_movq_membase_reg(cd, REG_SP, 7 * 8, rd->argfltregs[0]); - x86_64_movq_membase_reg(cd, REG_SP, 8 * 8, rd->argfltregs[1]); - x86_64_movq_membase_reg(cd, REG_SP, 9 * 8, rd->argfltregs[2]); - x86_64_movq_membase_reg(cd, REG_SP, 10 * 8, rd->argfltregs[3]); + x86_64_mov_membase_reg(cd, REG_SP, 1 * 8, rd->argintregs[0]); + x86_64_mov_membase_reg(cd, REG_SP, 2 * 8, rd->argintregs[1]); + x86_64_mov_membase_reg(cd, REG_SP, 3 * 8, rd->argintregs[2]); + x86_64_mov_membase_reg(cd, REG_SP, 4 * 8, rd->argintregs[3]); + x86_64_mov_membase_reg(cd, REG_SP, 5 * 8, rd->argintregs[4]); + x86_64_mov_membase_reg(cd, REG_SP, 6 * 8, rd->argintregs[5]); + + x86_64_movq_membase_reg(cd, REG_SP, 7 * 8, rd->argfltregs[0]); + x86_64_movq_membase_reg(cd, REG_SP, 8 * 8, rd->argfltregs[1]); + x86_64_movq_membase_reg(cd, REG_SP, 9 * 8, rd->argfltregs[2]); + x86_64_movq_membase_reg(cd, REG_SP, 10 * 8, rd->argfltregs[3]); /* x86_64_movq_membase_reg(cd, REG_SP, 11 * 8, rd->argfltregs[4]); */ /* x86_64_movq_membase_reg(cd, REG_SP, 12 * 8, rd->argfltregs[5]); */ /* x86_64_movq_membase_reg(cd, REG_SP, 13 * 8, rd->argfltregs[6]); */ /* x86_64_movq_membase_reg(cd, REG_SP, 14 * 8, rd->argfltregs[7]); */ - x86_64_alu_imm_reg(cd, X86_64_ADD, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP); - } + x86_64_alu_imm_reg(cd, X86_64_ADD, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP); + #if 0 x86_64_alu_imm_reg(cd, X86_64_SUB, 7 * 8, REG_SP); /* keep stack 16-byte aligned */ @@ -4010,6 +4035,10 @@ u1 *createnativestub(functionptr f, methodinfo *m) x86_64_mov_imm_reg(cd, (u8) &env, rd->argintregs[0]); x86_64_mov_imm_reg(cd, (u8) f, REG_ITMP1); +#ifndef STATIC_CLASSPATH + if (f==0) + (*callAddrPatchPos)=cd->mcodeptr-8; +#endif x86_64_call_reg(cd, REG_ITMP1); /* remove stackframe if there is one */ diff --git a/tests/InlineExTest.java b/tests/InlineExTest.java index c89ec81c1..542673400 100644 --- a/tests/InlineExTest.java +++ b/tests/InlineExTest.java @@ -13,6 +13,7 @@ public class InlineExTest { System.out.println("ERROR EXCEPTION EXPECTED"); } catch (Exception e) { System.out.println(e); + e.printStackTrace(); System.out.println("End of outer exception handler"); System.exit(0); } diff --git a/tests/stack/nestedstaticinitializers2.java b/tests/stack/nestedstaticinitializers2.java index a1dc61681..583f033ba 100644 --- a/tests/stack/nestedstaticinitializers2.java +++ b/tests/stack/nestedstaticinitializers2.java @@ -31,6 +31,7 @@ class nestedstaticinitializers2 { public static void main (String args[]) { try { nestedstaticinitializers2_clinit1 x[]=new nestedstaticinitializers2_clinit1[10]; + x[0]=new nestedstaticinitializers2_clinit1(); } catch (Throwable t) { t.printStackTrace(); } diff --git a/tests/stack/nestedstaticinitializers3.java b/tests/stack/nestedstaticinitializers3.java new file mode 100644 index 000000000..d5b40f801 --- /dev/null +++ b/tests/stack/nestedstaticinitializers3.java @@ -0,0 +1,39 @@ +class nestedstaticinitializers3_clinit1 extends nestedstaticinitializers3_clinit2 { + + public nestedstaticinitializers3_clinit1() { + System.out.println("Never reached"); + } + + public static int x1; + static { + x1=1; + } + +} + +class nestedstaticinitializers3_clinit2 { + public static int x; + static { + nestedstaticinitializers2_clinit3.x=3; + } + +} + +class nestedstaticinitializers3_clinit3 { + public static int x; + static { + int y[]=new int[-1]; + } + +} + +class nestedstaticinitializers3 { + public static void main (String args[]) { + try { + nestedstaticinitializers2_clinit1 x[]=new nestedstaticinitializers2_clinit1[10]; + x[0]=new nestedstaticinitializers2_clinit1(); + } catch (Throwable t) { + t.printStackTrace(); + } + } +} -- 2.25.1