[kaffe] trampoline/class loader/misc fixes
Timothy Stack
stack@flux.utah.edu
Mon, 12 Aug 2002 16:43:30 -0600 (MDT)
--%--multipart-mixed-boundary-1.42812.1029192210--%
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
hi,
I've attached a bunch of patches for the aforementioned trampoline and
class loader problems as well as some miscellaneous fixes. Also, I
changed the current behaviour for missing static field references so
that the method will throw an exception at the reference and not when
the method is jitted, this is similar to what jdk1.3.1 does. For
example, the method:
void referenceMissingClass()
{
try
{
MissingClass.foo = 4;
}
catch(NoClassDefError e)
{
}
}
Would fail to compile previously, now it will compile, but the
reference to "foo" will cause a NoSuchClassDefError to be thrown.
Heres the rest of the ChangeLog:
config/i386/trampolines.c: Create a real stack frame for
i386_do_fixup_trampoline so it doesn't mask the caller's frame.
kaffe/kaffeh/support.c: startFields/startMethods now return
success/failure and take errorInfo's.
kaffe/kaffevm/baseClasses.[ch]: Load in ClassNotFoundException and
NoClassDefFoundError.
kaffe/kaffevm/classMethod.[ch]: startFields/startMethods now return
success/failure and take errorInfo's. Use postExceptionMessage in
addMethod/addField before returning failure. Post a
NoClassDefFoundError if ClassLoader.loadClass() throws a
ClassNotFoundException.
kaffe/kaffevm/code-analyse.c: Check for NoClassDefFoundErrors in
PUTSTATIC/GETSTATIC handlers.
kaffe/kaffevm/kaffe.def: Handle unknown classes in field references
using softcall_nosuchclass() instead of failing/throwing an
exception.
kaffe/kaffevm/lookup.c: For getField(), set ret->field/ret->class to
NULL and set ret->cname/name/signature from the information
available in the current class so that a failure will not leave
these fields undefined.
kaffe/kaffevm/readClass.c: check return values of
startFields()/startMethods()
kaffe/kaffevm/[intrp/jit/jit3]/machine.h: Add
get_static_field_info_noerror() define.
test/regression/LostTrampolineFrame.java: Test for x86 lost
trampoline frame bug.
test/regression/NoClassDefTest.java: Tests for NoClassDefFoundErrors
in combination with ClassLoaders.
test/regression/Makefile.[am|in]: Add LostTrampolineFrame.java and
NoClassDefTest.java tests.
I ran it through FullTest.sh and it resulted only in known failures
(stringUninternString race and the linker shuffling JNI functions
around).
thanks,
tim stack
--%--multipart-mixed-boundary-1.42812.1029192210--%
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Description: ASCII Java program text
Content-Disposition: attachment; filename="NoClassDefTest.java"
import java.io.File;
import java.io.FileInputStream;
/**
* Test for NoClassDefFoundErrors when ClassLoaders are involved.
*/
public class NoClassDefTest
extends ClassLoader
{
/**
* A class that is visible during the compile, but will be missing at run
* time.
*/
public static class MissingClass
{
/**
* A static field we can reference to force a NoClassDefFoundError.
*/
public static int foo = 1;
/**
* A method we can reference to force a NoClassDefFoundError.
*/
public MissingClass()
{
}
}
/**
* This is an intermediate class we use to reference the missing class'
* method.
*/
public static class MethodReferenceClass
implements Runnable
{
public MethodReferenceClass()
{
}
public void run()
{
try
{
new MissingClass();
}
catch(NoClassDefFoundError e)
{
System.out.println("Caught NoClassDefError for method "
+ "MissingClass.<init> in class: "
+ e.getMessage());
}
}
}
/**
* This is an intermediate class we use to reference the missing class'
* field.
*/
public static class FieldReferenceClass
implements Runnable
{
public FieldReferenceClass()
{
}
public void run()
{
try
{
MissingClass.foo = 1;
}
catch(NoClassDefFoundError e)
{
System.out.println("Caught NoClassDefError for field "
+ "MissingClass.foo in class: "
+ e.getMessage());
}
}
}
/**
* This is an intermediate class we use to test a cast of missing class.
*/
public static class CastReferenceClass
implements Runnable
{
public CastReferenceClass()
{
}
public void run()
{
try
{
Object obj = null;
obj = (MissingClass)obj;
}
catch(NoClassDefFoundError e)
{
System.out.println("Caught NoClassDefError for cast of class: "
+ e.getMessage());
}
}
}
/**
* Read in the byte code for the given class.
*
* @param name The name of the class to read in.
* @return The byte code for the class.
*/
static byte [] readin(String name) throws Exception
{
File cf = new File(name);
FileInputStream cfi = new FileInputStream(cf);
int len = (int)cf.length();
byte [] cb = new byte[len];
if (cfi.read(cb) != len)
throw new Exception("short read for " + name);
return cb;
}
public synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class retval = null;
if( !name.startsWith("NoClassDefTest") )
{
/* System class... */
retval = super.findSystemClass(name);
}
else if( !name.equals("NoClassDefTest$MissingClass") )
{
/* One of our class' and not the MissingClass. */
try
{
byte []b = readin(name + ".class");
retval = defineClass(name, b, 0, b.length);
}
catch(Exception e)
{
throw new ClassNotFoundException(name);
}
}
else
{
throw new ClassNotFoundException(name);
}
if( resolve )
super.resolveClass(retval);
return retval;
}
public static void main(String args[])
throws Throwable
{
NoClassDefTest test;
Runnable run;
Class cl;
/* Create our ClassLoader */
test = new NoClassDefTest();
/* Load the intermediate classes and force NoClassDefFoundErrors. */
cl = test.loadClass("NoClassDefTest$MethodReferenceClass");
run = (Runnable)cl.newInstance();
run.run();
cl = test.loadClass("NoClassDefTest$FieldReferenceClass");
run = (Runnable)cl.newInstance();
run.run();
cl = test.loadClass("NoClassDefTest$CastReferenceClass");
run = (Runnable)cl.newInstance();
run.run();
}
}
/* Expected Output:
Caught NoClassDefError for method MissingClass.<init> in class: NoClassDefTest$MissingClass
Caught NoClassDefError for field MissingClass.foo in class: NoClassDefTest$MissingClass
Caught NoClassDefError for cast of class: NoClassDefTest$MissingClass
*/
--%--multipart-mixed-boundary-1.42812.1029192210--%
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Description: ASCII Java program text
Content-Disposition: attachment; filename="LostTrampolineFrame.java"
import java.util.Vector;
import java.io.File;
import java.io.FileInputStream;
/**
* This class will check for a bug in the x86 trampoline (and possibly others)
* that caused kaffe to ignore the stack frame of a routine that jumped through
* a trampoline. By "ignore", we mean that an exception handler in the calling
* routine wasn't found and executed.
*/
class LostTrampolineFrame
extends ClassLoader
{
/**
* We use a bad class to get the jitter to throw an exception through the
* trampoline. The following byte code was generated by disassembling the
* DamagedClass class below, tweaking some values, and then reassembling
* it.
*/
public static byte damagedByteCode[] = {
(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe,
(byte)0x0, (byte)0x3, (byte)0x0, (byte)0x2d,
(byte)0x0, (byte)0xd, (byte)0xa, (byte)0x0,
(byte)0x4, (byte)0x0, (byte)0xa, (byte)0x1,
(byte)0x0, (byte)0x4, (byte)0x43, (byte)0x6f,
(byte)0x64, (byte)0x65, (byte)0x7, (byte)0x0,
(byte)0x8, (byte)0x7, (byte)0x0, (byte)0x9,
(byte)0x1, (byte)0x0, (byte)0x6, (byte)0x3c,
(byte)0x69, (byte)0x6e, (byte)0x69, (byte)0x74,
(byte)0x3e, (byte)0x1, (byte)0x0, (byte)0xa,
(byte)0x53, (byte)0x6f, (byte)0x75, (byte)0x72,
(byte)0x63, (byte)0x65, (byte)0x46, (byte)0x69,
(byte)0x6c, (byte)0x65, (byte)0x1, (byte)0x0,
(byte)0xf, (byte)0x4c, (byte)0x69, (byte)0x6e,
(byte)0x65, (byte)0x4e, (byte)0x75, (byte)0x6d,
(byte)0x62, (byte)0x65, (byte)0x72, (byte)0x54,
(byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65,
(byte)0x1, (byte)0x0, (byte)0x20, (byte)0x4c,
(byte)0x6f, (byte)0x73, (byte)0x74, (byte)0x54,
(byte)0x72, (byte)0x61, (byte)0x6d, (byte)0x70,
(byte)0x6f, (byte)0x6c, (byte)0x69, (byte)0x6e,
(byte)0x65, (byte)0x46, (byte)0x72, (byte)0x61,
(byte)0x6d, (byte)0x65, (byte)0x24, (byte)0x44,
(byte)0x61, (byte)0x6d, (byte)0x61, (byte)0x67,
(byte)0x65, (byte)0x64, (byte)0x43, (byte)0x6c,
(byte)0x61, (byte)0x73, (byte)0x73, (byte)0x1,
(byte)0x0, (byte)0x10, (byte)0x6a, (byte)0x61,
(byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c,
(byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f,
(byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65,
(byte)0x63, (byte)0x74, (byte)0xc, (byte)0x0,
(byte)0x5, (byte)0x0, (byte)0xc, (byte)0x1,
(byte)0x0, (byte)0x18, (byte)0x4c, (byte)0x6f,
(byte)0x73, (byte)0x74, (byte)0x54, (byte)0x72,
(byte)0x61, (byte)0x6d, (byte)0x70, (byte)0x6f,
(byte)0x6c, (byte)0x69, (byte)0x6e, (byte)0x65,
(byte)0x46, (byte)0x72, (byte)0x61, (byte)0x6d,
(byte)0x65, (byte)0x2e, (byte)0x6a, (byte)0x61,
(byte)0x76, (byte)0x61, (byte)0x1, (byte)0x0,
(byte)0x3, (byte)0x28, (byte)0x29, (byte)0x56,
(byte)0x0, (byte)0x21, (byte)0x0, (byte)0x3,
(byte)0x0, (byte)0x4, (byte)0x0, (byte)0x0,
(byte)0x0, (byte)0x0, (byte)0x0, (byte)0x1,
(byte)0x0, (byte)0x1, (byte)0x0, (byte)0x5,
(byte)0x0, (byte)0xc, (byte)0x0, (byte)0x1,
(byte)0x0, (byte)0x2, (byte)0x0, (byte)0x0,
(byte)0x0, (byte)0x21, (byte)0x0, (byte)0x0,
(byte)0x0, (byte)0x1, (byte)0x0, (byte)0x0,
(byte)0x0, (byte)0x5, (byte)0x2a, (byte)0xb7,
(byte)0x0, (byte)0x1, (byte)0xb1, (byte)0x0,
(byte)0x0, (byte)0x0, (byte)0x1, (byte)0x0,
(byte)0x7, (byte)0x0, (byte)0x0, (byte)0x0,
(byte)0xa, (byte)0x0, (byte)0x2, (byte)0x0,
(byte)0x0, (byte)0x0, (byte)0x53, (byte)0x0,
(byte)0x4, (byte)0x0, (byte)0x54, (byte)0x0,
(byte)0x1, (byte)0x0, (byte)0x6, (byte)0x0,
(byte)0x0, (byte)0x0, (byte)0x2, (byte)0x0,
(byte)0xb
};
/**
* Read in the byte code for the given class.
*
* @param name The name of the class to read in.
* @return The byte code for the class.
*/
static byte [] readin(String name) throws Exception
{
File cf = new File(name);
FileInputStream cfi = new FileInputStream(cf);
int len = (int)cf.length();
byte [] cb = new byte[len];
if (cfi.read(cb) != len)
throw new Exception("short read for " + name);
return cb;
}
public synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class retval = null;
if( !name.startsWith("LostTrampolineFrame") )
{
/* System class... */
retval = super.findSystemClass(name);
}
else if( name.equals("LostTrampolineFrame$DamagedClass") )
{
/* Load our damaged class file. */
retval = defineClass(name,
damagedByteCode,
0,
damagedByteCode.length);
}
else
{
/* One of our class' and not the DamagedClass. */
try
{
byte []b = readin(name + ".class");
retval = defineClass(name, b, 0, b.length);
}
catch(Exception e)
{
throw new ClassNotFoundException(name);
}
}
if( resolve )
super.resolveClass(retval);
return retval;
}
/**
* The original class that was used to generate damagedByteCode. NOTE:
* This is not actually used.
*/
public static class DamagedClass
{
public DamagedClass()
{
}
}
/**
* An intermediate class that will try to construct a DamagedClass object.
*/
public static class IntermediateClass
implements Runnable
{
public IntermediateClass()
{
}
public void run()
{
try
{
/* The constructor shouldn't verify ... */
new DamagedClass();
}
catch(VerifyError e)
{
/*
* If the VerifyError isn't caught here, that means the
* trampoline is hiding the stack frame.
*/
System.out.println("Success");
}
}
}
public static void main(String args[])
throws Throwable
{
LostTrampolineFrame ltf;
Runnable run;
Class cl;
ltf = new LostTrampolineFrame();
cl = ltf.loadClass("LostTrampolineFrame$IntermediateClass");
try
{
run = (Runnable)cl.newInstance();
run.run();
}
catch(VerifyError e)
{
/*
* If the VerifyError is caught here, that means the trampoline is
* hiding the stack frame.
*/
System.out.println("Bad trampoline");
}
}
}
/* Expected Output:
Success
*/
--%--multipart-mixed-boundary-1.42812.1029192210--%
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Description: ASCII C++ program text, with very long lines
Content-Disposition: attachment; filename="trcl.diff"
Index: config/i386/trampolines.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/config/i386/trampolines.c,v
retrieving revision 1.5
diff -u -r1.5 trampolines.c
--- config/i386/trampolines.c 6 Dec 1999 06:47:17 -0000 1.5
+++ config/i386/trampolines.c 12 Aug 2002 22:36:37 -0000
@@ -34,8 +34,12 @@
asm(
START_ASM_FUNC() C_FUNC_NAME(i386_do_fixup_trampoline) "\n"
C_FUNC_NAME(i386_do_fixup_trampoline) ": \n
+ popl %eax \n
+ push %ebp \n
+ mov %esp,%ebp \n
+ push %eax \n
call " C_FUNC_NAME(soft_fixup_trampoline) " \n
- popl %ecx \n
+ leave \n
jmp *%eax"
END_ASM_FUNC()
);
Index: kaffe/kaffeh/support.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffeh/support.c,v
retrieving revision 1.25
diff -u -r1.25 support.c
--- kaffe/kaffeh/support.c 29 May 2002 22:58:43 -0000 1.25
+++ kaffe/kaffeh/support.c 12 Aug 2002 22:36:37 -0000
@@ -336,11 +336,12 @@
}
}
=
-void
-startFields(Hjava_lang_Class* this, u2 fct)
+int
+startFields(Hjava_lang_Class* this, u2 fct, errorInfo *einfo)
{
this->fields =3D malloc(fct * sizeof(Field));
this->nfields =3D 0; // incremented by addField()
+ return true;
}
=
Field*
@@ -487,9 +488,10 @@
}
}
=
-void
-startMethods(Hjava_lang_Class* this, u2 mct)
+int
+startMethods(Hjava_lang_Class* this, u2 mct, errorInfo *einfo)
{
+ return true;
}
=
Method*
Index: kaffe/kaffevm/baseClasses.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/baseClasses.c,v
retrieving revision 1.38
diff -u -r1.38 baseClasses.c
--- kaffe/kaffevm/baseClasses.c 7 Aug 2002 08:40:39 -0000 1.38
+++ kaffe/kaffevm/baseClasses.c 12 Aug 2002 22:36:37 -0000
@@ -74,6 +74,8 @@
Hjava_lang_Class* javaLangArrayIndexOutOfBoundsException;
Hjava_lang_Class* javaLangNullPointerException;
Hjava_lang_Class* javaLangArithmeticException;
+Hjava_lang_Class* javaLangClassNotFoundException;
+Hjava_lang_Class* javaLangNoClassDefFoundError;
Hjava_lang_Class* javaLangStackOverflowError;
/* Let's not load this if we can't open Klasses.jar */
Hjava_lang_Class* javaIoIOException;
@@ -273,6 +275,8 @@
loadStaticClass(&javaLangArrayIndexOutOfBoundsException, "java/lang/Arr=
ayIndexOutOfBoundsException");
loadStaticClass(&javaLangNullPointerException, "java/lang/NullPointerEx=
ception");
loadStaticClass(&javaLangArithmeticException, "java/lang/ArithmeticExce=
ption");
+ loadStaticClass(&javaLangClassNotFoundException, "java/lang/ClassNotFou=
ndException");
+ loadStaticClass(&javaLangNoClassDefFoundError, "java/lang/NoClassDefFou=
ndError");
loadStaticClass(&javaLangStackOverflowError, "java/lang/StackOverflowEr=
ror");
loadStaticClass(&javaIoIOException, "java/io/IOException");
=
Index: kaffe/kaffevm/baseClasses.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/baseClasses.h,v
retrieving revision 1.12
diff -u -r1.12 baseClasses.h
--- kaffe/kaffevm/baseClasses.h 7 Aug 2002 08:40:39 -0000 1.12
+++ kaffe/kaffevm/baseClasses.h 12 Aug 2002 22:36:37 -0000
@@ -51,6 +51,8 @@
extern struct Hjava_lang_Class* javaLangNullPointerException;
extern struct Hjava_lang_Class* javaLangArithmeticException;
extern struct Hjava_lang_Class* javaLangArrayIndexOutOfBoundsException;
+extern struct Hjava_lang_Class* javaLangClassNotFoundException;
+extern struct Hjava_lang_Class* javaLangNoClassDefFoundError;
extern struct Hjava_lang_Class* javaLangStackOverflowError;
=
#endif
Index: kaffe/kaffevm/classMethod.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/classMethod.c,v
retrieving revision 1.90
diff -u -r1.90 classMethod.c
--- kaffe/kaffevm/classMethod.c 29 May 2002 22:58:43 -0000 1.90
+++ kaffe/kaffevm/classMethod.c 12 Aug 2002 22:36:38 -0000
@@ -769,16 +769,26 @@
return true;
}
=
-void
-startMethods(Hjava_lang_Class* this, u2 methct)
+int
+startMethods(Hjava_lang_Class* this, u2 methct, errorInfo *einfo)
{
if (methct =3D=3D 0)
+ {
this->methods =3D NULL;
+ }
else
+ {
this->methods =3D gc_malloc(sizeof(Method)*(methct), GC_ALLOC_METHOD);=
+ if (this->methods =3D=3D NULL)
+ {
+ postOutOfMemory(einfo);
+ return false;
+ }
+ }
GC_WRITE(this, this->methods);
=
this->nmethods =3D 0; /* updated in addMethod */
+ return true;
}
=
Method*
@@ -804,12 +814,19 @@
if (pool->tags[nc] !=3D CONSTANT_Utf8) {
/* XXX fill in einfo! */
DBG(RESERROR, dprintf("addMethod: no method name.\n"); )
+ postExceptionMessage(einfo,
+ JAVA_LANG(ClassFormatError),
+ "No method name");
return (0);
}
sc =3D signature_index;
if (pool->tags[sc] !=3D CONSTANT_Utf8) {
/* XXX fill in einfo! */
DBG(RESERROR, dprintf("addMethod: no signature name.\n"); )
+ postExceptionMessage(einfo,
+ JAVA_LANG(ClassFormatError),
+ "No signature for method: %s",
+ WORD2UTF (pool->data[nc])->data);
return (0);
}
name =3D WORD2UTF (pool->data[nc]);
@@ -870,6 +887,9 @@
nc =3D name_index;
if (pool->tags[nc] !=3D CONSTANT_Utf8) {
DBG(RESERROR, dprintf("addField: no field name.\n"); )
+ postExceptionMessage(einfo,
+ JAVA_LANG(ClassFormatError),
+ "No field name");
return (0);
}
=
@@ -890,6 +910,10 @@
sc =3D signature_index;
if (pool->tags[sc] !=3D CONSTANT_Utf8) {
DBG(RESERROR, dprintf("addField: no signature name.\n"); )
+ postExceptionMessage(einfo,
+ JAVA_LANG(ClassFormatError),
+ "No signature name for field: %s",
+ CLASS_CONST_UTF8(c, nc)->data);
CLASS_NFIELDS(c)++;
return (0);
}
@@ -932,8 +956,8 @@
ft->accflags |=3D FIELD_CONSTANT_VALUE;
}
=
-void
-startFields(Hjava_lang_Class* this, u2 fieldct)
+int
+startFields(Hjava_lang_Class* this, u2 fieldct, errorInfo *einfo)
{
CLASS_NFIELDS(this) =3D 0; /* updated in addField() */
CLASS_FSIZE(this) =3D fieldct;
@@ -943,9 +967,14 @@
else {
CLASS_FIELDS(this) =3D (Field*) gc_malloc(sizeof(Field) * fieldct,
GC_ALLOC_FIELD);
+ if (!CLASS_FIELDS(this)) {
+ postOutOfMemory(einfo);
+ return false;
+ }
}
GC_WRITE(this, CLASS_FIELDS(this)); /* XXX */
=
+ return true;
}
=
void
@@ -1074,6 +1103,15 @@
)
einfo->type =3D KERR_RETHROW;
einfo->throwable =3D excobj;
+ if( (einfo->throwable->base.dtable->class =3D=3D
+ javaLangClassNotFoundException) )
+ {
+ postNoClassDefFoundError(
+ einfo,
+ stringJava2C(einfo->
+ throwable->
+ message));
+ }
clazz =3D NULL;
} else
if (clazz =3D=3D NULL) {
Index: kaffe/kaffevm/classMethod.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/classMethod.h,v
retrieving revision 1.49
diff -u -r1.49 classMethod.h
--- kaffe/kaffevm/classMethod.h 31 Jul 2002 23:35:46 -0000 1.49
+++ kaffe/kaffevm/classMethod.h 12 Aug 2002 22:36:38 -0000
@@ -401,7 +401,7 @@
constIndex, u2, Hjava_lang_ClassLoader*, errorInfo*);
bool addSourceFile(Hjava_lang_Class* c, int idx, errorInfo*);
bool addInnerClasses(Hjava_lang_Class* c, uint32 len, struct classFile=
* fp, errorInfo *info);
-void startMethods(Hjava_lang_Class*, u2 methct);
+int startMethods(Hjava_lang_Class*, u2 methct, errorInfo*);
Method* addMethod(Hjava_lang_Class*, u2 access_flags,
u2 name_index, u2 signature_index, errorInfo*);
Method* addExceptionMethod(Hjava_lang_Class*, Utf8Const*, Utf8Const*);=
@@ -442,7 +442,7 @@
int countArgsInSignature(const char *);
parsed_signature_t* parseSignature(Utf8Const *, errorInfo*);
=
-void startFields(Hjava_lang_Class*, u2 fieldct);
+int startFields(Hjava_lang_Class*, u2 fieldct, errorInfo*);
void finishFields(Hjava_lang_Class*);
Method* findMethodFromPC(uintp);
=
Index: kaffe/kaffevm/code-analyse.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/code-analyse.c,v
retrieving revision 1.35
diff -u -r1.35 code-analyse.c
--- kaffe/kaffevm/code-analyse.c 7 Aug 2002 09:51:26 -0000 1.35
+++ kaffe/kaffevm/code-analyse.c 12 Aug 2002 22:36:39 -0000
@@ -1395,14 +1395,12 @@
=
case GETSTATIC:
if (getField(WORD(pc+1), meth->class, true, &finfo, einfo) =3D=3D 0) =
{
- failed =3D true;
- goto done;
+ if (!checkNoClassDefFoundError(einfo)) {
+ failed =3D true;
+ goto done;
+ }
}
- if (!FIELD_ISPRIM(finfo.field)) {
- STKPUSH(1);
- STACKOUT(0, TOBJ);
- }
- else switch (CLASS_PRIM_SIG(FIELD_TYPE(finfo.field))){
+ switch (finfo.signature->data[0]){
case 'I':
case 'Z':
case 'S':
@@ -1425,6 +1423,11 @@
STACKOUT(0, TDOUBLE);
STACKOUT(1, TVOID);
break;
+ case '[':
+ case 'L':
+ STKPUSH(1);
+ STACKOUT(0, TOBJ);
+ break;
default:
ABORT();
break;
@@ -1434,14 +1437,12 @@
=
case PUTSTATIC:
if (getField(WORD(pc+1), meth->class, true, &finfo, einfo) =3D=3D 0) =
{
- failed =3D true;
- goto done;
+ if (!checkNoClassDefFoundError(einfo)) {
+ failed =3D true;
+ goto done;
+ }
}
- if (!FIELD_ISPRIM(finfo.field)) {
- STACKIN(0, TOBJ);
- STKPOP(1);
- }
- else switch (CLASS_PRIM_SIG(FIELD_TYPE(finfo.field))){
+ switch (finfo.signature->data[0]){
case 'I':
case 'Z':
case 'S':
@@ -1463,6 +1464,11 @@
STACKIN(0, TDOUBLE);
STACKIN(1, TVOID);
STKPOP(2);
+ break;
+ case '[':
+ case 'L':
+ STACKIN(0, TOBJ);
+ STKPOP(1);
break;
default:
ABORT();
Index: kaffe/kaffevm/kaffe.def
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/kaffe.def,v
retrieving revision 1.23
diff -u -r1.23 kaffe.def
--- kaffe/kaffevm/kaffe.def 29 Jul 2002 16:31:50 -0000 1.23
+++ kaffe/kaffevm/kaffe.def 12 Aug 2002 22:36:40 -0000
@@ -2190,7 +2190,20 @@
=
trace_jcode (("getstatic %d\n", idx));
=
- get_static_field_info(idx);
+ get_static_field_info_noerror(idx);
+ if (field_class() =3D=3D 0) {
+ softcall_nosuchclass(field_classname());
+ switch (field_sig()->data[0]) {
+ case 'J':
+ case 'D':
+ push(2);
+ break;
+ default:
+ push(1);
+ break;
+ }
+ break;
+ }
INIT_STATIC_CLASS(field_class());
=
if (field_field() =3D=3D 0) {
@@ -2256,7 +2269,20 @@
idx =3D (uint16)((getpc(0) << 8) | getpc(1));
trace_jcode (("putstatic %d\n", idx));
=
- get_static_field_info(idx);
+ get_static_field_info_noerror(idx);
+ if (field_class() =3D=3D 0) {
+ softcall_nosuchclass(field_classname());
+ switch (field_sig()->data[0]) {
+ case 'J':
+ case 'D':
+ pop(2);
+ break;
+ default:
+ pop(1);
+ break;
+ }
+ break;
+ }
INIT_STATIC_CLASS(field_class());
=
if (field_field() =3D=3D 0) {
Index: kaffe/kaffevm/lookup.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/lookup.c,v
retrieving revision 1.27
diff -u -r1.27 lookup.c
--- kaffe/kaffevm/lookup.c 29 May 2002 22:58:44 -0000 1.27
+++ kaffe/kaffevm/lookup.c 12 Aug 2002 22:36:40 -0000
@@ -207,6 +207,9 @@
Field* field;
Hjava_lang_Class* class;
=
+ ret->field =3D 0;
+ ret->class =3D 0;
+ =
pool =3D CLASS_CONSTANTS(this);
if (pool->tags[idx] !=3D CONSTANT_Fieldref) {
DBG(RESERROR, dprintf("No Fieldref found\n"); )
@@ -217,17 +220,17 @@
=
ci =3D FIELDREF_CLASS(idx, pool);
=
- class =3D getClass(ci, this, einfo);
- if (class =3D=3D NULL) {
- return (false);
- }
-
ni =3D FIELDREF_NAMEANDTYPE(idx, pool);
=
- ret->cname =3D class->name;
+ ret->cname =3D WORD2UTF(pool->data[ci]);
ret->name =3D WORD2UTF(pool->data[NAMEANDTYPE_NAME(ni, pool)]);
ret->signature =3D WORD2UTF(pool->data[NAMEANDTYPE_SIGNATURE(ni, pool)]=
);
=
+ class =3D getClass(ci, this, einfo);
+ if (class =3D=3D NULL) {
+ return (false);
+ }
+
DBG(FLOOKUP, dprintf("*** getField(%s,%s,%s)\n",
class->name->data, =
WORD2UTF(pool->data[NAMEANDTYPE_NAME(ni, pool)])->data, =
@@ -238,6 +241,8 @@
if (field =3D=3D 0) {
return (false);
}
+
+ /* XXX Should we verify that ret->signature matches field? */
=
ret->field =3D field;
ret->class =3D class;
Index: kaffe/kaffevm/readClass.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/readClass.c,v
retrieving revision 1.15
diff -u -r1.15 readClass.c
--- kaffe/kaffevm/readClass.c 31 May 2002 18:44:50 -0000 1.15
+++ kaffe/kaffevm/readClass.c 12 Aug 2002 22:36:40 -0000
@@ -157,7 +157,8 @@
dprintf("%s: fields_count=3D%d\n", CLASS_CNAME(this), fields_count)=
;
);
=
- startFields(this, fields_count);
+ if( !startFields(this, fields_count, einfo) )
+ return false;
=
for (i =3D 0; i < fields_count; i++) {
Field* fieldThis;
@@ -310,7 +311,8 @@
dprintf("%s: methods_count=3D%d\n", CLASS_CNAME(this), methods_coun=
t);
);
=
- startMethods(this, methods_count);
+ if( !startMethods(this, methods_count, einfo) )
+ return false;
=
for (i =3D 0; i < methods_count; i++) {
Method* methodThis;
Index: kaffe/kaffevm/intrp/machine.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/intrp/machine.h,v
retrieving revision 1.7
diff -u -r1.7 machine.h
--- kaffe/kaffevm/intrp/machine.h 30 May 2002 22:47:33 -0000 1.7
+++ kaffe/kaffevm/intrp/machine.h 12 Aug 2002 22:36:40 -0000
@@ -63,6 +63,9 @@
throwError(&einfo); \
}
=
+#define get_static_field_info_noerror(IDX) \
+ getField((constIndex)(IDX), meth->class, true, &finfo, &einfo)
+
#define get_static_field_info(IDX) \
if (getField(IDX, meth->class, true, &finfo, &einfo) =3D=3D false) { \=
throwError(&einfo); \
Index: kaffe/kaffevm/jit/machine.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit/machine.h,v
retrieving revision 1.15
diff -u -r1.15 machine.h
--- kaffe/kaffevm/jit/machine.h 20 Dec 2000 02:42:21 -0000 1.15
+++ kaffe/kaffevm/jit/machine.h 12 Aug 2002 22:36:40 -0000
@@ -76,6 +76,9 @@
success =3D false; goto done; \
}
=
+#define get_static_field_info_noerror(IDX) \
+ getField((constIndex)(IDX), xmeth->class, true, &finfo, einfo)
+
#define get_static_field_info(IDX) \
if (getField((IDX), meth->class, true, &finfo, einfo) =3D=3D false) { =
\
success =3D false; goto done; \
Index: kaffe/kaffevm/jit3/machine.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit3/machine.h,v
retrieving revision 1.13
diff -u -r1.13 machine.h
--- kaffe/kaffevm/jit3/machine.h 20 Dec 2000 02:42:38 -0000 1.13
+++ kaffe/kaffevm/jit3/machine.h 12 Aug 2002 22:36:40 -0000
@@ -74,6 +74,9 @@
success =3D false ; goto done; \
}
=
+#define get_static_field_info_noerror(IDX) \
+ getField((constIndex)(IDX), xmeth->class, true, &finfo, einfo)
+
#define get_static_field_info(IDX) \
if (getField((constIndex)(IDX), xmeth->class, true, &finfo, einfo) =3D=3D=
false) { \
success =3D false ; goto done; \
Index: test/regression/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/test/regression/Makefile.am,v
retrieving revision 1.62
diff -u -r1.62 Makefile.am
--- test/regression/Makefile.am 20 Jun 2002 01:49:17 -0000 1.62
+++ test/regression/Makefile.am 12 Aug 2002 22:36:42 -0000
@@ -92,12 +92,14 @@
ReaderReadVoidTest.java \
PipeTest.java \
GetField.java \
+ LostTrampolineFrame.java \
## simple test for Method.invoke
ReflectInvoke.java \
## simple test for InvocationTargetExceptions
InvTarExcTest.java \
## tests for ClassLoader
SystemLoaderTest.java \
+ NoClassDefTest.java \
CLTest.java \
CLTestConc.java \
CLTestJLock.java \
Index: test/regression/Makefile.in
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/kaffe/kaffe/test/regression/Makefile.in,v
retrieving revision 1.95
diff -u -r1.95 Makefile.in
--- test/regression/Makefile.in 20 Jun 2002 01:49:17 -0000 1.95
+++ test/regression/Makefile.in 12 Aug 2002 22:36:42 -0000
@@ -137,7 +137,7 @@
=
TESTS_ENVIRONMENT =3D $(SETUP_ENVIRONMENT) $(SHELL) TestScript
=
-ALWAYS_TESTS =3D HelloWorldApp.class.save HelloWorldApp.java TestInt=
Long.java TestFloatDouble.java DoubleCvt.java DoubleNeg.java DoubleCo=
nst.java DoublePrint.java DoubleComp.java ModuloTest.java LongNeg.jav=
a FPUStack.java divtest.java Str.java Str2.java InternHog.java Inde=
xTest.java StackDump.java tname.java ttest.java ThreadInterrupt.java =
ThreadState.java UncaughtException.java IllegalWait.java Preempt.java=
ReflectInterfaces.java InnerTest.java SerialUID.java TestSerializa=
ble.java TestSerializable2.java TestCasts.java Alias.java NullPointer=
Test.java NullInvoke.java TableSwitch.java LostFrame.java Constructor=
Test.java burford.java IllegalInterface.java GetInterfaces.java IntfT=
est.java SignedShort.java CharCvt.java BadFloatTest.java ProcessTest.=
java UDPTest.java SoTimeout.java wc.java FileTest.java FileChecks.ja=
va finalexc.java finaltest.java finaltest2.java forNameTest.java Loa=
derTest.java ArrayForName.java KaffeVerifyBug.java Schtum.java Reflec=
t.java MethodBug.java Bean.java SortTest.java HashTest.java MapTest.=
java URLTest.java PropertiesTest.java ReaderTest.java CharArrayReader=
Test.java LineNumberReaderTest.java BufferedReaderTest.java ReaderRead=
VoidTest.java PipeTest.java GetField.java ReflectInvoke.java InvTarEx=
cTest.java SystemLoaderTest.java CLTest.java CLTestConc.java CLTestJL=
ock.java CLTestLie.java CLTestFindLoaded.java ClassDeadLock.java Exce=
ptionTest.java ExceptionTestClassLoader.java ExceptionTestClassLoader2.=
java TestClassRef.java ClassGC.java GCTest.java ThreadLocalTest.java =
BeanBug.java BitSetTest.java ExceptionInInitializerTest.java InitTest=
=2Ejava ProcessClassTest.java ProcessClassInst.java ProcessClassStop.j=
ava FindSystemClass.java ProcessClassLockTest.java DoubleBug.java Tes=
tUnlock.java MarkResetTest.java HashtableTest1.java ReflectMultiArray.=
java ExecTest.java CatchDeath.java ThreadStop.java DeadThread.java t=
thrd1.java SoInterrupt.java sysdepCallMethod.java DosTimeVerify.java =
ZipVerify.java ZipTest.java TruncatedClass.java TestNative.java
+ALWAYS_TESTS =3D HelloWorldApp.class.save HelloWorldApp.java TestInt=
Long.java TestFloatDouble.java DoubleCvt.java DoubleNeg.java DoubleCo=
nst.java DoublePrint.java DoubleComp.java ModuloTest.java LongNeg.jav=
a FPUStack.java divtest.java Str.java Str2.java InternHog.java Inde=
xTest.java StackDump.java tname.java ttest.java ThreadInterrupt.java =
ThreadState.java UncaughtException.java IllegalWait.java Preempt.java=
ReflectInterfaces.java InnerTest.java SerialUID.java TestSerializa=
ble.java TestSerializable2.java TestCasts.java Alias.java NullPointer=
Test.java NullInvoke.java TableSwitch.java LostFrame.java Constructor=
Test.java burford.java IllegalInterface.java GetInterfaces.java IntfT=
est.java SignedShort.java CharCvt.java BadFloatTest.java ProcessTest.=
java UDPTest.java SoTimeout.java wc.java FileTest.java FileChecks.ja=
va finalexc.java finaltest.java finaltest2.java forNameTest.java Loa=
derTest.java ArrayForName.java KaffeVerifyBug.java Schtum.java Reflec=
t.java MethodBug.java Bean.java SortTest.java HashTest.java MapTest.=
java URLTest.java PropertiesTest.java ReaderTest.java CharArrayReader=
Test.java LineNumberReaderTest.java BufferedReaderTest.java ReaderRead=
VoidTest.java PipeTest.java GetField.java LostTrampolineFrame.java Re=
flectInvoke.java InvTarExcTest.java SystemLoaderTest.java NoClassDefTe=
st.java CLTest.java CLTestConc.java CLTestJLock.java CLTestLie.java =
CLTestFindLoaded.java ClassDeadLock.java ExceptionTest.java ExceptionT=
estClassLoader.java ExceptionTestClassLoader2.java TestClassRef.java C=
lassGC.java GCTest.java ThreadLocalTest.java BeanBug.java BitSetTest.=
java ExceptionInInitializerTest.java InitTest.java ProcessClassTest.ja=
va ProcessClassInst.java ProcessClassStop.java FindSystemClass.java P=
rocessClassLockTest.java DoubleBug.java TestUnlock.java MarkResetTest.=
java HashtableTest1.java ReflectMultiArray.java ExecTest.java CatchDe=
ath.java ThreadStop.java DeadThread.java tthrd1.java SoInterrupt.java=
sysdepCallMethod.java DosTimeVerify.java ZipVerify.java ZipTest.java=
TruncatedClass.java TestNative.java
=
=
TEST_Overflow =3D Overflow.java
--%--multipart-mixed-boundary-1.42812.1029192210--%--