Bug in Jitter

Godmar Back gback at cs.utah.edu
Tue Jul 7 20:10:52 PDT 1998


 Alexandre,

> 
> AFAIK, the only case that may raise this kind of exception is
> NullPointerException.  Any other case would be the result of calling a
> soft_* function or a method, and this would have spilled all registers
> before the call.  Thus, I see two alternatives:
> 
> 1) #define CHECK_NULL(a,b,c) sync_registers()
>    unless it is already defined in some platform-specific
>    header-file.
> 
>    This would ensure that any registers are saved in the stack before
>    a NullPointerException may be thrown, with a very small performance
>    impact.  Only registers that are dirty and would be overwritten in
>    the near future will be unnecessarily spilled; others may be
>    written to the stack frame earlier and marked as clean, so they
>    won't be spilled any more.
> 
>    sync_registers() does not exist on the intrp, so it may be defined
>    to nothing in this case.  Furthermore, on x86, a patch that ensures
>    that sync_registers() does not remove a floating-point value from
>    the top of the FP stack must be installed.
> 

 I bet you wrote this off the top of your head or with a non-current
version in mind.  The CHECK_NULL macro is defined in machine.c, so there's
no need to define a sync_register for the interpreter.  I don't think
it's intended to be redefined by md.h either.

Also, sync_register doesn't reset the modified flags.  Therefore,
the register would unnecessarily spilled again if a function call follows.
I think what we want is prepare_function_call() (maybe minus the part 
where temps are spilled?).

It seems that a similar situation arises for BadArrayIndex
exceptions.  jit/icode.c already emits conditional spill code if that
can happen.  The code is conditional in the sense that a canCatch()
macro will only emit it if the exception in question is in fact caught
in the current method.

With all that said:  I tried it, and I believe your idea works.

I defined CHECK_NULL for the hardware version like this:

+#define CHECK_NULL(_i, _s, _n)	\
+	if (canCatch(NULLPOINTER)) {		\
+		prepare_function_call(); 	\
+	}

where I added NULLPOINTER as a second flag to BADARRAYINDEX.

I append the patches to baseClasses.c and jit/machine.[ch].
They fix the FinalTest example and pass the regression tests.

For what it's worth, I counted the instructions generated while jitting
a large javac compile:

434420: kaffe with CREATE_NULLPOINTER_CHECKS defined.
312067: kaffe with if canCatch(NULL) -> prepare_function_call
306914:	current, incorrect Kaffe

Could you elaborate some more on that patch for the x86 you're mentioned?

	- Godmar

-- patches --

Index: baseClasses.c
===================================================================
RCS file: /home/cvspublic/kaffe/kaffe/kaffevm/baseClasses.c,v
retrieving revision 1.5
diff -u -r1.5 baseClasses.c
--- baseClasses.c	1998/07/06 23:43:01	1.5
+++ baseClasses.c	1998/07/08 02:56:21
@@ -56,6 +56,7 @@
 Hjava_lang_Class* javaLangDoubleClass;
 
 Hjava_lang_Class* javaLangArrayIndexOutOfBoundsException;
+Hjava_lang_Class* javaLangNullPointerException;
 
 #define SYSTEMCLASS "java/lang/System"
 #define	SERIALCLASS "java/io/Serializable"
@@ -163,6 +164,7 @@
 
 	/* Exception handling types */
 	loadStaticClass(&javaLangArrayIndexOutOfBoundsException, "java/lang/ArrayIndexOutOfBoundsException");
+	loadStaticClass(&javaLangNullPointerException, "java/lang/NullPointerException");
 
 	/* Fixup primitive types */
 	finishTypes();
cvs server: Diffing jit
Index: jit/machine.c
===================================================================
RCS file: /home/cvspublic/kaffe/kaffe/kaffevm/jit/machine.c,v
retrieving revision 1.3
diff -u -r1.3 machine.c
--- machine.c	1998/05/28 18:37:01	1.3
+++ machine.c	1998/07/08 02:56:21
@@ -66,6 +66,7 @@
 
 /* Various exception related things */
 extern Hjava_lang_Class javaLangArrayIndexOutOfBoundsException;
+extern Hjava_lang_Class javaLangNullPointerException;
 
 jitflags willcatch;
 
@@ -77,7 +78,10 @@
       softcall_nullpointer();                                 \
       set_label(_i, _n)
 #else
-#define CHECK_NULL(_i, _s, _n)
+#define CHECK_NULL(_i, _s, _n)	\
+	if (canCatch(NULLPOINTER)) {		\
+		prepare_function_call(); 	\
+	}
 #endif
 
 /* Unit in which code block is increased when overrun */
@@ -193,6 +197,7 @@
 	len = meth->c.bcode.codelen;
 
 	willcatch.BADARRAYINDEX = false;
+	willcatch.NULLPOINTER = false;
 
 	/* Deterimine various exception conditions */
 	if (meth->exception_table != 0) {
@@ -201,10 +206,14 @@
 			etype = meth->exception_table->entry[i].catch_type;
 			if (etype == 0) {
 				willCatch(BADARRAYINDEX);
+				willCatch(NULLPOINTER);
 			}
 			else {
 				if (instanceof(&javaLangArrayIndexOutOfBoundsException, etype)) {
 					willCatch(BADARRAYINDEX);
+				}
+				if (instanceof(&javaLangNullPointerException, etype)) {
+					willCatch(NULLPOINTER);
 				}
 			}
 		}
Index: jit/machine.h
===================================================================
RCS file: /home/cvspublic/kaffe/kaffe/kaffevm/jit/machine.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 machine.h
--- machine.h	1998/03/31 19:10:54	1.1.1.1
+++ machine.h	1998/07/08 02:56:21
@@ -98,6 +98,7 @@
 
 typedef struct {
         bool BADARRAYINDEX;
+        bool NULLPOINTER;
 } jitflags;
 
 extern jitflags willcatch;


More information about the kaffe mailing list