Patch: FYI: assume-compiled runtime fix

Tom Tromey tromey@redhat.com
Fri Jan 24 19:57:00 GMT 2003


I'm checking this in on the trunk.
It isn't going on the 3.3 branch because we currently don't support
-fno-assume-compiled on the branch, and I believe the bugs this fixes
aren't observable without that feature.

This fixes a bug in the runtime revealed by -fno-assume-compiled.
With this option, we might make a call to a static method before the
ncode field is set for the method.

We never saw this before because the interpreter called _Jv_InitClass
before a static call.  However, this behavior is also incorrect, since
the gcj ABI is to have the callee init.

This is fixed below by changing the interpreter to avoid the caller
init, and also to have the interpreter init as the callee.  Also we
set things up so that the ncode field is computed for each static
interpreted method when the class is defined.  This adds a bit of
overhead, but I didn't see how to avoid that.

Note that we do still keep the redundant init in the interpreter
during `new'.  This is just expedient; I didn't want to force full
layout at load time, and I didn't want to put a special case in the
allocator functions just to avoid a redundant init call in the
interpreter.

Long term it may be smarter for us to move class init to the caller.
That would let us optimize out some initialization calls.  At the same
time we could move the _Jv_InitClass call out of the allocators; this
would let us avoid it in some cases.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	* defineclass.cc (handleMethodsEnd): Precompute code for static
	method.
	(handleCodeAttribute): Likewise.
	* resolve.cc (ncode): Use run_class for unsynchronized static
	methods.
	* include/java-interp.h (class _Jv_InterpMethod): Declare
	run_class.
	* interpret.cc (run_synch_class): Initialize class.
	(run) [insn_invokestatic]: Don't initialize class.
	[insn_anewarray]: Likewise.
	[insn_multianewarray]: Likewise.
	(run_class): New function.

Index: defineclass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/defineclass.cc,v
retrieving revision 1.32
diff -u -r1.32 defineclass.cc
--- defineclass.cc 19 Dec 2002 19:31:53 -0000 1.32
+++ defineclass.cc 24 Jan 2003 19:45:08 -0000
@@ -1,6 +1,6 @@
 // defineclass.cc - defining a class from .class format.
 
-/* Copyright (C) 1999, 2000, 2001, 2002  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -1267,6 +1267,15 @@
 	  code_length);
 
   def->interpreted_methods[method_index] = method;
+
+  if ((method->self->accflags & java::lang::reflect::Modifier::STATIC))
+    {
+      // Precompute the ncode field for a static method.  This lets us
+      // call a static method of an interpreted class from precompiled
+      // code without first resolving the class (that will happen
+      // during class initialization instead).
+      method->self->ncode = method->ncode ();
+    }
 }
 
 void _Jv_ClassReader::handleExceptionTableEntry
@@ -1302,6 +1311,16 @@
 	      m->self = method;
 	      m->function = NULL;
 	      def->interpreted_methods[i] = m;
+
+	      if ((method->accflags & Modifier::STATIC))
+		{
+		  // Precompute the ncode field for a static method.
+		  // This lets us call a static method of an
+		  // interpreted class from precompiled code without
+		  // first resolving the class (that will happen
+		  // during class initialization instead).
+		  method->ncode = m->ncode ();
+		}
 	    }
 	}
       else if ((method->accflags & Modifier::ABSTRACT) != 0)
Index: resolve.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/resolve.cc,v
retrieving revision 1.35
diff -u -r1.35 resolve.cc
--- resolve.cc 19 Dec 2002 19:31:53 -0000 1.35
+++ resolve.cc 24 Jan 2003 19:45:09 -0000
@@ -1,6 +1,6 @@
 // resolve.cc - Code for linking and resolving classes and pool entries.
 
-/* Copyright (C) 1999, 2000, 2001 , 2002 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation
 
    This file is part of libgcj.
 
@@ -947,7 +947,10 @@
     }
   else
     {
-      fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+      if (staticp)
+	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+      else
+	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
     }
 
   FFI_PREP_RAW_CLOSURE (&closure->closure,
@@ -958,7 +961,6 @@
   self->ncode = (void*)closure;
   return self->ncode;
 }
-
 
 void *
 _Jv_JNIMethod::ncode ()
Index: interpret.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/interpret.cc,v
retrieving revision 1.38
diff -u -r1.38 interpret.cc
--- interpret.cc 28 Dec 2002 06:38:51 -0000 1.38
+++ interpret.cc 24 Jan 2003 19:45:10 -0000
@@ -1,6 +1,6 @@
 // interpret.cc - Code for the interpreter
 
-/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation
 
    This file is part of libgcj.
 
@@ -240,19 +240,21 @@
     }									      \
   while (0)
 
-void _Jv_InterpMethod::run_normal (ffi_cif *,
-				   void* ret,
-				   ffi_raw * args,
-				   void* __this)
+void
+_Jv_InterpMethod::run_normal (ffi_cif *,
+			      void* ret,
+			      ffi_raw * args,
+			      void* __this)
 {
   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
   _this->run (ret, args);
 }
 
-void _Jv_InterpMethod::run_synch_object (ffi_cif *,
-					 void* ret,
-					 ffi_raw * args,
-					 void* __this)
+void
+_Jv_InterpMethod::run_synch_object (ffi_cif *,
+				    void* ret,
+				    ffi_raw * args,
+				    void* __this)
 {
   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
 
@@ -262,14 +264,27 @@
   _this->run (ret, args);
 }
 
-void _Jv_InterpMethod::run_synch_class (ffi_cif *,
-					void* ret,
-					ffi_raw * args,
-					void* __this)
+void
+_Jv_InterpMethod::run_class (ffi_cif *,
+			     void* ret,
+			     ffi_raw * args,
+			     void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  _Jv_InitClass (_this->defining_class);
+  _this->run (ret, args);
+}
+
+void
+_Jv_InterpMethod::run_synch_class (ffi_cif *,
+				   void* ret,
+				   ffi_raw * args,
+				   void* __this)
 {
   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
 
   jclass sync = _this->defining_class;
+  _Jv_InitClass (sync);
   JvSynchronize mutex (sync);
 
   _this->run (ret, args);
@@ -2833,7 +2848,6 @@
 
 	sp -= rmeth->stack_item_count;
 
-	_Jv_InitClass (rmeth->klass);
 	fun = (void (*)()) rmeth->method->ncode;
 
 #ifdef DIRECT_THREADED
@@ -2903,6 +2917,9 @@
       {
 	int index = GET2U ();
 	jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
+	// We initialize here because otherwise `size_in_bytes' may
+	// not be set correctly, leading us to pass `0' as the size.
+	// FIXME: fix in the allocator?  There is a PR for this.
 	_Jv_InitClass (klass);
 	jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
 	PUSHA (res);
@@ -2938,7 +2955,6 @@
 	int index = GET2U ();
 	jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
 	int size  = POPI();
-	_Jv_InitClass (klass);
 	jobject result = _Jv_NewObjectArray (size, klass, 0);
 	PUSHA (result);
 
@@ -3072,7 +3088,6 @@
 
 	jclass type    
 	  = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
-	_Jv_InitClass (type);
 	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
 
 	for (int i = dim - 1; i >= 0; i--)
Index: include/java-interp.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/java-interp.h,v
retrieving revision 1.21
diff -u -r1.21 java-interp.h
--- include/java-interp.h 19 Dec 2002 19:31:54 -0000 1.21
+++ include/java-interp.h 24 Jan 2003 19:45:10 -0000
@@ -1,6 +1,6 @@
 // java-interp.h - Header file for the bytecode interpreter.  -*- c++ -*-
 
-/* Copyright (C) 1999, 2000, 2001, 2002  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -132,6 +132,7 @@
 
   static void run_normal (ffi_cif*, void*, ffi_raw*, void*);
   static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_class (ffi_cif*, void*, ffi_raw*, void*);
   static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
 
   void run (void*, ffi_raw *);



More information about the Java-patches mailing list