aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Green <green@gcc.gnu.org>1999-08-08 14:06:23 +0000
committerAnthony Green <green@gcc.gnu.org>1999-08-08 14:06:23 +0000
commit58eb6e7cef1cea515f8da18d24341a4aa53ccb70 (patch)
tree277498eeeff558237a9cd88b0ea8b3788b31d645
parent63e5e3e0dbb7207e95c0437499b980a304665589 (diff)
downloadgcc-58eb6e7cef1cea515f8da18d24341a4aa53ccb70.zip
gcc-58eb6e7cef1cea515f8da18d24341a4aa53ccb70.tar.gz
gcc-58eb6e7cef1cea515f8da18d24341a4aa53ccb70.tar.bz2
[multiple changes]
1999-08-09 Anthony Green <green@cygnus.com> * gij.cc: New file. * include/config.h.in: Rebuilt. * acconfig.h: Add INTERPRETER. * configure: Rebuilt. * Makefile.in: Rebuilt. * Makefile.am (libffi_files): Identify the libffi object files for inclusion in libgcj. (LIBFFIINCS): Define. * interpret.cc (gnu::gcj::runtime::MethodInvocation::continue1): Dummy definition for configurations without an interpreter. * java/net/natPlainSocketImpl.cc (getOption): Disamiguate call to java::lang::Boolean constructor. * include/java-interp.h: Always include java-cpool.h. * java/lang/natClassLoader.cc (getVMClassLoader0): Always return 0 when INTERPRETER not defined. * java/lang/Class.h (finalize): Define. * gnu/gcj/util/path/DirectoryPathEntry.java (getURL): Catch IOException from File.getCanonicalPath. (getStream): Likewise. * NEWS: More news. * THANKS: More thanks. 1999-08-09 Kresten Krab Thorup <krab@gnu.org> * resolve.cc (get_ffi_type_from_signature): Generate uint16 for jchar type. (_Jv_PrepareClass): Allow non-abstract classes to have abstract subclasses. (_Jv_ResolvePoolEntry): Revert subclass check for protected fields and methods. * interpret.cc (continue1/perform_invoke): Don't sign extend uint16 return val. (continue1/lshl,lshr): Push long, not int. (continue1/ulshr): Use UINT64, not long long. * defineclass.cc (handleFieldsEnd): Handle case when all fields are static. * java/lang/natClass.cc (forName): Add call to _Jv_InitClass. * java/lang/FirstThread.java (run): Add top-level exception handler. (run0): Renamed from run. 1999-08-08 Kresten Krab Thorup <krab@gnu.org> * configure.in (--with-interpreter): Added. * include/config.h.in (INTERPRETER): Added. * java/lang/ClassLoader.java: File replaced. * java/lang/VMClassLoader.java: New file. * java/lang/natClassLoader.cc: New file. * gnu/gcj/runtime/MethodInvocation.java: New file. * gnu/gcj/util/path/SearchPath.java: New file. * gnu/gcj/util/path/PathEntry.java: New file. * gnu/gcj/util/path/DirectoryPathEntry.java: New file. * gnu/gcj/util/path/ZipPathEntry.java: New file. * gnu/gcj/util/path/URLPathEntry.java: New file. * gnu/gcj/util/path/CacheEntry.java: New file. * include/java-interp.h: New file. * include/java-cpool.h: New file. * include/java-insns.h: New file. * defineclass.cc: New file. * interpret.cc: New file. * resolve.cc: New file. * java/lang/natClass.cc (loaded_classes, _Jv_RegisterClass, _Jv_RegisterClasses, _Jv_FindClassInCache, _Jv_FindClass, _Jv_NewClass, _Jv_FindArrayClass): Moved to natClassLoader.cc. (finalize): New. (STATE_NOTHING, STATE_RESOLVED, STATE_IN_PROGRESS, STATE_DONE, STATE_ERROR): Moved to java/lang/Class.h and renamed with JV_ prefix. (initializeClass): Use new JV_ prefixed names. Also, call ClassLoader::resolveClass instead of _Jv_ResolveClass. * java/lang/Class.h (JV_STATE_PRELOADING, JV_STATE_LOADING, JV_STATE_LOADED, JV_STATE_COMPILED, JV_STATE_PREPARED, JV_STATE_LINKED): New. (_Jv_WaitForState, _Jv_RegisterInitiatingLoader, _Jv_UnregisterClass, _Jv_InternClassStrings): New friends. (_Jv_IsInterpretedClass, _Jv_InitField, _Jv_LookupDeclaredMethod, _Jv_DetermineVTableIndex, _Jv_ResolvePoolEntry, _Jv_PrepareClass, _Jv_ClassReader, _Jv_InterpClass, _Jv_InterpMethod, _Jv_InterpMethodInvocation): New friends for interpreter. (finalize): New. (CONSTANT_Class, CONSTANT_String, etc.): Moved to include/java-cpool.h and renamed with JV_ prefix. * include/jvm.h (_Jv_makeUtf8Const, _Jv_makeUtf8TypeConst): New decls. (_Jv_UnregisterClass): New decl. * java/lang/natClassLoader.cc (_Jv_FindArrayClass): Added class loader argument. (_Jv_FindClass): Use class loader. * prims.cc (_Jv_makeUtf8Const): New function. (_Jv_NewObjectArray): Change use of _Jv_FindArrayClass. (_Jv_NewPrimArray): Ditto. (_Jv_FindClassFromSignature): Ditto. * java/lang/reflect/natArray.cc (newInstance): Ditto. * java/lang/reflect/natMethod.cc (getType): Ditto. * include/java-field.h (_Jv_Field::isRef): Make robust for non-resolved contexts. * boehm.cc (_Jv_MarkObj): Mark interpreter-related fields. Also, don't mark class->next field. * java/lang/VirtualMachineError.java: Added FIXME note. * configure.in (INTERPSPEC): New spec. * libgcj.spec.in: Added INTERPSPEC. * Makefile.am: Added gcjh friends for java/lang/VMClassLoader and gnu/gcj/runtime/MethodInvocation. (libgcj_la_SOURCES): Added resolve.cc defineclass.cc interpret.cc. (ordinary_java_source_files): Added above mentioned java classes. * configure: Rebuilt. * Makefile.in: Rebuilt. From-SVN: r28597
-rw-r--r--libjava/ChangeLog129
-rw-r--r--libjava/Makefile.am53
-rw-r--r--libjava/Makefile.in81
-rw-r--r--libjava/NEWS4
-rw-r--r--libjava/THANKS5
-rw-r--r--libjava/acconfig.h3
-rw-r--r--libjava/boehm.cc78
-rwxr-xr-xlibjava/configure417
-rw-r--r--libjava/configure.in15
-rw-r--r--libjava/defineclass.cc1556
-rw-r--r--libjava/gij.cc27
-rw-r--r--libjava/gnu/gcj/runtime/MethodInvocation.java32
-rw-r--r--libjava/gnu/gcj/util/path/CacheEntry.java65
-rw-r--r--libjava/gnu/gcj/util/path/DirectoryPathEntry.java136
-rw-r--r--libjava/gnu/gcj/util/path/PathEntry.java55
-rw-r--r--libjava/gnu/gcj/util/path/SearchPath.java205
-rw-r--r--libjava/gnu/gcj/util/path/URLPathEntry.java67
-rw-r--r--libjava/gnu/gcj/util/path/ZipPathEntry.java86
-rw-r--r--libjava/include/config.h.in3
-rw-r--r--libjava/include/java-cpool.h173
-rw-r--r--libjava/include/java-field.h13
-rw-r--r--libjava/include/java-insns.h247
-rw-r--r--libjava/include/java-interp.h172
-rw-r--r--libjava/include/javaprims.h1
-rw-r--r--libjava/include/jvm.h4
-rw-r--r--libjava/interpret.cc2449
-rw-r--r--libjava/java/lang/Class.h82
-rw-r--r--libjava/java/lang/Class.java3
-rw-r--r--libjava/java/lang/ClassLoader.java426
-rw-r--r--libjava/java/lang/FirstThread.java21
-rw-r--r--libjava/java/lang/VMClassLoader.java117
-rw-r--r--libjava/java/lang/VirtualMachineError.java5
-rw-r--r--libjava/java/lang/natClass.cc386
-rw-r--r--libjava/java/lang/natClassLoader.cc624
-rw-r--r--libjava/java/lang/natFirstThread.cc8
-rw-r--r--libjava/java/lang/reflect/natArray.cc7
-rw-r--r--libjava/java/lang/reflect/natMethod.cc4
-rw-r--r--libjava/java/net/natPlainSocketImpl.cc2
-rw-r--r--libjava/libgcj.spec.in2
-rw-r--r--libjava/prims.cc61
-rw-r--r--libjava/resolve.cc1101
-rw-r--r--libjava/testsuite/Makefile.in2
42 files changed, 8335 insertions, 592 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 1954795..24051fc 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,132 @@
+1999-08-09 Anthony Green <green@cygnus.com>
+
+ * gij.cc: New file.
+
+ * include/config.h.in: Rebuilt.
+ * acconfig.h: Add INTERPRETER.
+
+ * Makefile.in: Rebuilt.
+ * Makefile.am (libffi_files): Identify the libffi object files for
+ inclusion in libgcj.
+ (LIBFFIINCS): Define.
+
+ * interpret.cc (gnu::gcj::runtime::MethodInvocation::continue1):
+ Dummy definition for configurations without an interpreter.
+
+ * java/net/natPlainSocketImpl.cc (getOption): Disamiguate call to
+ java::lang::Boolean constructor.
+
+ * include/java-interp.h: Always include java-cpool.h.
+
+ * java/lang/natClassLoader.cc (getVMClassLoader0): Always return 0
+ when INTERPRETER not defined.
+
+ * java/lang/Class.h (finalize): Define.
+
+ * gnu/gcj/util/path/DirectoryPathEntry.java (getURL): Catch
+ IOException from File.getCanonicalPath.
+ (getStream): Likewise.
+
+ * NEWS: More news.
+ * THANKS: More thanks.
+
+1999-08-09 Kresten Krab Thorup <krab@gnu.org>
+
+ * resolve.cc (get_ffi_type_from_signature): Generate uint16 for
+ jchar type.
+ (_Jv_PrepareClass): Allow non-abstract classes to
+ have abstract subclasses.
+ (_Jv_ResolvePoolEntry): Revert subclass check for protected
+ fields and methods.
+ * interpret.cc (continue1/perform_invoke): Don't sign extend
+ uint16 return val.
+ (continue1/lshl,lshr): Push long, not int.
+ (continue1/ulshr): Use UINT64, not long long.
+ * defineclass.cc (handleFieldsEnd): Handle case when all fields
+ are static.
+ * java/lang/natClass.cc (forName): Add call to _Jv_InitClass.
+ * java/lang/FirstThread.java (run): Add top-level exception
+ handler.
+ (run0): Renamed from run.
+
+1999-08-08 Kresten Krab Thorup <krab@gnu.org>
+
+ * configure.in (--with-interpreter): Added.
+ * include/config.h.in (INTERPRETER): Added.
+
+ * java/lang/ClassLoader.java: File replaced.
+ * java/lang/VMClassLoader.java: New file.
+ * java/lang/natClassLoader.cc: New file.
+ * gnu/gcj/runtime/MethodInvocation.java: New file.
+ * gnu/gcj/util/path/SearchPath.java: New file.
+ * gnu/gcj/util/path/PathEntry.java: New file.
+ * gnu/gcj/util/path/DirectoryPathEntry.java: New file.
+ * gnu/gcj/util/path/ZipPathEntry.java: New file.
+ * gnu/gcj/util/path/URLPathEntry.java: New file.
+ * gnu/gcj/util/path/CacheEntry.java: New file.
+ * include/java-interp.h: New file.
+ * include/java-cpool.h: New file.
+ * include/java-insns.h: New file.
+ * defineclass.cc: New file.
+ * interpret.cc: New file.
+ * resolve.cc: New file.
+
+ * java/lang/natClass.cc (loaded_classes, _Jv_RegisterClass,
+ _Jv_RegisterClasses, _Jv_FindClassInCache, _Jv_FindClass,
+ _Jv_NewClass, _Jv_FindArrayClass): Moved to natClassLoader.cc.
+ (finalize): New.
+ (STATE_NOTHING, STATE_RESOLVED, STATE_IN_PROGRESS, STATE_DONE,
+ STATE_ERROR): Moved to java/lang/Class.h and renamed with JV_
+ prefix.
+ (initializeClass): Use new JV_ prefixed names. Also, call
+ ClassLoader::resolveClass instead of _Jv_ResolveClass.
+
+ * java/lang/Class.h (JV_STATE_PRELOADING, JV_STATE_LOADING,
+ JV_STATE_LOADED, JV_STATE_COMPILED, JV_STATE_PREPARED,
+ JV_STATE_LINKED): New.
+ (_Jv_WaitForState, _Jv_RegisterInitiatingLoader,
+ _Jv_UnregisterClass, _Jv_InternClassStrings): New friends.
+ (_Jv_IsInterpretedClass, _Jv_InitField, _Jv_LookupDeclaredMethod,
+ _Jv_DetermineVTableIndex, _Jv_ResolvePoolEntry, _Jv_PrepareClass,
+ _Jv_ClassReader, _Jv_InterpClass, _Jv_InterpMethod,
+ _Jv_InterpMethodInvocation): New friends for interpreter.
+ (finalize): New.
+ (CONSTANT_Class, CONSTANT_String, etc.): Moved to
+ include/java-cpool.h and renamed with JV_ prefix.
+
+ * include/jvm.h (_Jv_makeUtf8Const, _Jv_makeUtf8TypeConst): New
+ decls.
+ (_Jv_UnregisterClass): New decl.
+
+ * java/lang/natClassLoader.cc (_Jv_FindArrayClass): Added
+ class loader argument.
+ (_Jv_FindClass): Use class loader.
+
+ * prims.cc (_Jv_makeUtf8Const): New function.
+ (_Jv_NewObjectArray): Change use of _Jv_FindArrayClass.
+ (_Jv_NewPrimArray): Ditto.
+ (_Jv_FindClassFromSignature): Ditto.
+ * java/lang/reflect/natArray.cc (newInstance): Ditto.
+ * java/lang/reflect/natMethod.cc (getType): Ditto.
+
+ * include/java-field.h (_Jv_Field::isRef): Make robust for
+ non-resolved contexts.
+
+ * boehm.cc (_Jv_MarkObj): Mark interpreter-related fields.
+ Also, don't mark class->next field.
+
+ * java/lang/VirtualMachineError.java: Added FIXME note.
+
+ * configure.in (INTERPSPEC): New spec.
+ * libgcj.spec.in: Added INTERPSPEC.
+ * Makefile.am: Added gcjh friends for java/lang/VMClassLoader and
+ gnu/gcj/runtime/MethodInvocation.
+ (libgcj_la_SOURCES): Added resolve.cc defineclass.cc interpret.cc.
+ (ordinary_java_source_files): Added above mentioned java classes.
+
+ * configure: Rebuilt.
+ * Makefile.in: Rebuilt.
+
1999-08-06 Tom Tromey <tromey@cygnus.com>
* configure: Rebuilt.
diff --git a/libjava/Makefile.am b/libjava/Makefile.am
index c9cc9b9..83217c8 100644
--- a/libjava/Makefile.am
+++ b/libjava/Makefile.am
@@ -27,7 +27,7 @@ data_DATA = libgcj.zip
## For now, only on native systems.
if NATIVE
-bin_PROGRAMS = jv-convert
+bin_PROGRAMS = jv-convert gij
endif
## ################################################################
@@ -77,8 +77,10 @@ endif
JCFLAGS = -g
JC1FLAGS = -g @LIBGCJ_JAVAFLAGS@
+LIBFFIINCS = -I$(top_srcdir)/../libffi/include -I../libffi/include
+
INCLUDES = -Iinclude -I$(top_srcdir)/include $(GCINCS) $(THREADINCS) \
- $(EH_COMMON_INCLUDE) $(ZINCS)
+ $(EH_COMMON_INCLUDE) $(ZINCS) $(LIBFFIINCS)
DIVIDESPEC = @DIVIDESPEC@
@@ -97,13 +99,17 @@ c_files = $(c_source_files:.c=.lo)
javao_files = $(java_source_files:.java=.lo) \
$(built_java_source_files:.java=.lo)
-libgcj_la_SOURCES = prims.cc jni.cc exception.cc
+## Extract the libffi object file names.
+libffi_files = `$(AR) t ../libffi/.libs/libffi.a 2>/dev/null | sed 's/\.o/\.lo/g' | sed 's/^/..\/libffi\//g'`
+
+libgcj_la_SOURCES = prims.cc jni.cc exception.cc \
+ resolve.cc defineclass.cc interpret.cc
EXTRA_libgcj_la_SOURCES = boehm.cc nogc.cc posix-threads.cc no-threads.cc \
$(c_source_files) $(java_source_files) $(built_java_source_files)
libgcj_la_DEPENDENCIES = libgcj.zip $(javao_files) $(nat_files) \
$(c_files) $(GCOBJS) $(THREADOBJS)
libgcj_la_LIBADD = $(javao_files) $(nat_files) $(c_files) $(GCOBJS) \
- $(THREADOBJS)
+ $(THREADOBJS) $(libffi_files)
libgcj_la_LDFLAGS = -rpath $(toolexeclibdir) \
## The mysterious backslash is consumed by make.
-version-info `grep -v '^\#' $(srcdir)/libtool-version`
@@ -230,6 +236,16 @@ java/lang/reflect/Method.h: java/lang/reflect/Method.class libgcj.zip
-friend 'java::lang::Class;' \
$(basename $<)
+java/lang/VMClassLoader.h: java/lang/VMClassLoader.class libgcj.zip
+ $(GCJH) -classpath $(top_builddir) \
+ -friend 'java::lang::ClassLoader;' \
+ $(basename $<)
+
+gnu/gcj/runtime/MethodInvocation.h: gnu/gcj/runtime/MethodInvocation.class libgcj.zip
+ $(GCJH) -classpath $(top_builddir) \
+ -friend 'class _Jv_InterpMethod;' \
+ $(basename $<)
+
## ################################################################
@@ -299,6 +315,26 @@ jv_convert_LDADD = $(convert_source_files:.java=.lo) libgcj.la \
jv_convert_DEPENDENCIES = $(convert_source_files:.java=.lo) \
$(GCDEPS) $(THREADDEPS) $(ZDEPS) libgcj.la libgcj.spec
+gij_SOURCES =
+EXTRA_gij_SOURCES = gij.cc
+## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'. We
+## need this because we are explicitly using libtool to link using the
+## `.la' file.
+gij_LDFLAGS = -rpath $(toolexeclibdir)
+gij_LINK = $(LIBTOOL) --mode=link $(GCJ) $(JC1FLAGS) $(LDFLAGS) \
+ -o gij
+## We explicitly link in the libraries we need. This way we don't
+## need -nodefaultlibs, so we can still rely on gcj picking up the
+## system libraries we need (via the specs file).
+## We need the -L so that gcj can find libgcj with `-lgcj'.
+## FIXME: should be _libs on some systems.
+gij_LDADD = gij.lo libgcj.la \
+ $(GCLIBS) $(THREADLIBS) $(ZLIBS) -L$(here)/.libs
+## Depend on the spec file to make sure it is up to date before
+## linking this program.
+gij_DEPENDENCIES = gij.lo \
+ $(GCDEPS) $(THREADDEPS) $(ZDEPS) libgcj.la libgcj.spec
+
# The Unicode consortium does not permit re-distributing the file JIS0201.TXT.
# You can get it from ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/.
@@ -444,6 +480,13 @@ built_java_source_files = java/lang/ConcreteProcess.java
## convert_source_files. If the .java file has a hand-maintained
## header, please list it in special_java_source_files.
ordinary_java_source_files = $(convert_source_files) \
+gnu/gcj/runtime/MethodInvocation.java \
+gnu/gcj/util/path/SearchPath.java \
+gnu/gcj/util/path/PathEntry.java \
+gnu/gcj/util/path/DirectoryPathEntry.java \
+gnu/gcj/util/path/ZipPathEntry.java \
+gnu/gcj/util/path/URLPathEntry.java \
+gnu/gcj/util/path/CacheEntry.java \
gnu/gcj/text/BaseBreakIterator.java \
gnu/gcj/text/CharacterBreakIterator.java \
gnu/gcj/text/LineBreakIterator.java \
@@ -522,6 +565,7 @@ java/lang/ClassCastException.java \
java/lang/ClassCircularityError.java \
java/lang/ClassFormatError.java \
java/lang/ClassLoader.java \
+java/lang/VMClassLoader.java \
java/lang/ClassNotFoundException.java \
java/lang/CloneNotSupportedException.java \
java/lang/Cloneable.java \
@@ -719,6 +763,7 @@ java/io/natFile.cc \
java/io/natFileDescriptor.cc \
java/lang/natCharacter.cc \
java/lang/natClass.cc \
+java/lang/natClassLoader.cc \
java/lang/natConcreteProcess.cc \
java/lang/natDouble.cc \
java/lang/natFirstThread.cc \
diff --git a/libjava/Makefile.in b/libjava/Makefile.in
index 94e4189..c03c3223 100644
--- a/libjava/Makefile.in
+++ b/libjava/Makefile.in
@@ -78,6 +78,7 @@ GCINCS = @GCINCS@
GCLIBS = @GCLIBS@
GCOBJS = @GCOBJS@
GCSPEC = @GCSPEC@
+INTERPSPEC = @INTERPSPEC@
LD = @LD@
LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@
LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@
@@ -120,7 +121,7 @@ toolexeclib_DATA = libgcj.spec
data_DATA = libgcj.zip
@NATIVE_TRUE@bin_PROGRAMS = \
-@NATIVE_TRUE@jv-convert
+@NATIVE_TRUE@jv-convert gij
@CANADIAN_TRUE@@NULL_TARGET_TRUE@GCJ = \
@CANADIAN_TRUE@@NULL_TARGET_TRUE@gcj
@CANADIAN_TRUE@@NULL_TARGET_FALSE@GCJ = \
@@ -156,8 +157,10 @@ AM_CXXFLAGS = -fno-rtti -fvtable-thunks @LIBGCJ_CXXFLAGS@ $(WARNINGS)
JCFLAGS = -g
JC1FLAGS = -g @LIBGCJ_JAVAFLAGS@
+LIBFFIINCS = -I$(top_srcdir)/../libffi/include -I../libffi/include
+
INCLUDES = -Iinclude -I$(top_srcdir)/include $(GCINCS) $(THREADINCS) \
- $(EH_COMMON_INCLUDE) $(ZINCS)
+ $(EH_COMMON_INCLUDE) $(ZINCS) $(LIBFFIINCS)
DIVIDESPEC = @DIVIDESPEC@
@@ -168,7 +171,11 @@ javao_files = $(java_source_files:.java=.lo) \
$(built_java_source_files:.java=.lo)
-libgcj_la_SOURCES = prims.cc jni.cc exception.cc
+libffi_files = `$(AR) t ../libffi/.libs/libffi.a 2>/dev/null | sed 's/\.o/\.lo/g' | sed 's/^/..\/libffi\//g'`
+
+libgcj_la_SOURCES = prims.cc jni.cc exception.cc \
+ resolve.cc defineclass.cc interpret.cc
+
EXTRA_libgcj_la_SOURCES = boehm.cc nogc.cc posix-threads.cc no-threads.cc \
$(c_source_files) $(java_source_files) $(built_java_source_files)
@@ -176,7 +183,7 @@ libgcj_la_DEPENDENCIES = libgcj.zip $(javao_files) $(nat_files) \
$(c_files) $(GCOBJS) $(THREADOBJS)
libgcj_la_LIBADD = $(javao_files) $(nat_files) $(c_files) $(GCOBJS) \
- $(THREADOBJS)
+ $(THREADOBJS) $(libffi_files)
libgcj_la_LDFLAGS = -rpath $(toolexeclibdir) \
-version-info `grep -v '^\#' $(srcdir)/libtool-version`
@@ -217,6 +224,19 @@ jv_convert_DEPENDENCIES = $(convert_source_files:.java=.lo) \
$(GCDEPS) $(THREADDEPS) $(ZDEPS) libgcj.la libgcj.spec
+gij_SOURCES =
+EXTRA_gij_SOURCES = gij.cc
+gij_LDFLAGS = -rpath $(toolexeclibdir)
+gij_LINK = $(LIBTOOL) --mode=link $(GCJ) $(JC1FLAGS) $(LDFLAGS) \
+ -o gij
+
+gij_LDADD = gij.lo libgcj.la \
+ $(GCLIBS) $(THREADLIBS) $(ZLIBS) -L$(here)/.libs
+
+gij_DEPENDENCIES = gij.lo \
+ $(GCDEPS) $(THREADDEPS) $(ZDEPS) libgcj.la libgcj.spec
+
+
gen_from_JIS_SOURCES =
EXTRA_gen_from_JIS_SOURCES = $(srcdir)/$(CONVERT_DIR)/gen-from-JIS.c \
$(srcdir)/$(CONVERT_DIR)/make-trie.c \
@@ -294,6 +314,13 @@ java/awt/peer/WindowPeer.java
built_java_source_files = java/lang/ConcreteProcess.java
ordinary_java_source_files = $(convert_source_files) \
+gnu/gcj/runtime/MethodInvocation.java \
+gnu/gcj/util/path/SearchPath.java \
+gnu/gcj/util/path/PathEntry.java \
+gnu/gcj/util/path/DirectoryPathEntry.java \
+gnu/gcj/util/path/ZipPathEntry.java \
+gnu/gcj/util/path/URLPathEntry.java \
+gnu/gcj/util/path/CacheEntry.java \
gnu/gcj/text/BaseBreakIterator.java \
gnu/gcj/text/CharacterBreakIterator.java \
gnu/gcj/text/LineBreakIterator.java \
@@ -372,6 +399,7 @@ java/lang/ClassCastException.java \
java/lang/ClassCircularityError.java \
java/lang/ClassFormatError.java \
java/lang/ClassLoader.java \
+java/lang/VMClassLoader.java \
java/lang/ClassNotFoundException.java \
java/lang/CloneNotSupportedException.java \
java/lang/Cloneable.java \
@@ -569,6 +597,7 @@ java/io/natFile.cc \
java/io/natFileDescriptor.cc \
java/lang/natCharacter.cc \
java/lang/natClass.cc \
+java/lang/natClassLoader.cc \
java/lang/natConcreteProcess.cc \
java/lang/natDouble.cc \
java/lang/natFirstThread.cc \
@@ -655,13 +684,15 @@ DEFS = @DEFS@ -I. -I$(srcdir) -I./include
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
-libgcj_la_OBJECTS = prims.lo jni.lo exception.lo
-@NATIVE_TRUE@bin_PROGRAMS = jv-convert$(EXEEXT)
+libgcj_la_OBJECTS = prims.lo jni.lo exception.lo resolve.lo \
+defineclass.lo interpret.lo
+@NATIVE_TRUE@bin_PROGRAMS = jv-convert$(EXEEXT) gij$(EXEEXT)
@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = \
@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@gen-from-JIS$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
jv_convert_OBJECTS =
+gij_OBJECTS =
gen_from_JIS_OBJECTS =
gen_from_JIS_LDFLAGS =
CXXFLAGS = @CXXFLAGS@
@@ -688,9 +719,9 @@ GZIP_ENV = --best
DIST_SUBDIRS = testsuite
DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/$(srcdir)/$(CONVERT_DIR)/make-trie.P .deps/boehm.P \
-.deps/exception.P .deps/gnu/gcj/RawData.P \
-.deps/gnu/gcj/convert/BytesToUnicode.P .deps/gnu/gcj/convert/Convert.P \
-.deps/gnu/gcj/convert/Input_8859_1.P \
+.deps/defineclass.P .deps/exception.P .deps/gij.P \
+.deps/gnu/gcj/RawData.P .deps/gnu/gcj/convert/BytesToUnicode.P \
+.deps/gnu/gcj/convert/Convert.P .deps/gnu/gcj/convert/Input_8859_1.P \
.deps/gnu/gcj/convert/Input_EUCJIS.P \
.deps/gnu/gcj/convert/Input_JavaSrc.P \
.deps/gnu/gcj/convert/Input_SJIS.P .deps/gnu/gcj/convert/Input_UTF8.P \
@@ -703,6 +734,7 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/gnu/gcj/protocol/file/Handler.P \
.deps/gnu/gcj/protocol/http/Connection.P \
.deps/gnu/gcj/protocol/http/Handler.P \
+.deps/gnu/gcj/runtime/MethodInvocation.P \
.deps/gnu/gcj/text/BaseBreakIterator.P \
.deps/gnu/gcj/text/CharacterBreakIterator.P \
.deps/gnu/gcj/text/LineBreakIterator.P \
@@ -711,6 +743,12 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/gnu/gcj/text/SentenceBreakIterator.P \
.deps/gnu/gcj/text/WordBreakIterator.P \
.deps/gnu/gcj/util/EnumerationChain.P \
+.deps/gnu/gcj/util/path/CacheEntry.P \
+.deps/gnu/gcj/util/path/DirectoryPathEntry.P \
+.deps/gnu/gcj/util/path/PathEntry.P \
+.deps/gnu/gcj/util/path/SearchPath.P \
+.deps/gnu/gcj/util/path/URLPathEntry.P \
+.deps/gnu/gcj/util/path/ZipPathEntry.P .deps/interpret.P \
.deps/java/io/BufferedInputStream.P \
.deps/java/io/BufferedOutputStream.P .deps/java/io/BufferedReader.P \
.deps/java/io/BufferedWriter.P .deps/java/io/ByteArrayInputStream.P \
@@ -788,8 +826,9 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/java/lang/Throwable.P .deps/java/lang/UnknownError.P \
.deps/java/lang/UnsatisfiedLinkError.P \
.deps/java/lang/UnsupportedOperationException.P \
-.deps/java/lang/VerifyError.P .deps/java/lang/VirtualMachineError.P \
-.deps/java/lang/Void.P .deps/java/lang/dtoa.P .deps/java/lang/e_acos.P \
+.deps/java/lang/VMClassLoader.P .deps/java/lang/VerifyError.P \
+.deps/java/lang/VirtualMachineError.P .deps/java/lang/Void.P \
+.deps/java/lang/dtoa.P .deps/java/lang/e_acos.P \
.deps/java/lang/e_asin.P .deps/java/lang/e_atan2.P \
.deps/java/lang/e_exp.P .deps/java/lang/e_fmod.P \
.deps/java/lang/e_log.P .deps/java/lang/e_pow.P \
@@ -872,9 +911,9 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/java/util/zip/ZipException.P .deps/java/util/zip/ZipFile.P \
.deps/java/util/zip/ZipInputStream.P \
.deps/java/util/zip/ZipOutputStream.P .deps/jni.P .deps/no-threads.P \
-.deps/nogc.P .deps/posix-threads.P .deps/prims.P
-SOURCES = $(libgcj_la_SOURCES) $(EXTRA_libgcj_la_SOURCES) $(jv_convert_SOURCES) $(EXTRA_jv_convert_SOURCES) $(gen_from_JIS_SOURCES) $(EXTRA_gen_from_JIS_SOURCES)
-OBJECTS = $(libgcj_la_OBJECTS) $(jv_convert_OBJECTS) $(gen_from_JIS_OBJECTS)
+.deps/nogc.P .deps/posix-threads.P .deps/prims.P .deps/resolve.P
+SOURCES = $(libgcj_la_SOURCES) $(EXTRA_libgcj_la_SOURCES) $(jv_convert_SOURCES) $(EXTRA_jv_convert_SOURCES) $(gij_SOURCES) $(EXTRA_gij_SOURCES) $(gen_from_JIS_SOURCES) $(EXTRA_gen_from_JIS_SOURCES)
+OBJECTS = $(libgcj_la_OBJECTS) $(jv_convert_OBJECTS) $(gij_OBJECTS) $(gen_from_JIS_OBJECTS)
all: all-redirect
.SUFFIXES:
@@ -1022,6 +1061,10 @@ jv-convert$(EXEEXT): $(jv_convert_OBJECTS) $(jv_convert_DEPENDENCIES)
@rm -f jv-convert$(EXEEXT)
$(jv_convert_LINK) $(jv_convert_LDFLAGS) $(jv_convert_OBJECTS) $(jv_convert_LDADD) $(LIBS)
+gij$(EXEEXT): $(gij_OBJECTS) $(gij_DEPENDENCIES)
+ @rm -f gij$(EXEEXT)
+ $(gij_LINK) $(gij_LDFLAGS) $(gij_OBJECTS) $(gij_LDADD) $(LIBS)
+
gen-from-JIS$(EXEEXT): $(gen_from_JIS_OBJECTS) $(gen_from_JIS_DEPENDENCIES)
@rm -f gen-from-JIS$(EXEEXT)
$(LINK) $(gen_from_JIS_LDFLAGS) $(gen_from_JIS_OBJECTS) $(gen_from_JIS_LDADD) $(LIBS)
@@ -1451,6 +1494,16 @@ java/lang/reflect/Method.h: java/lang/reflect/Method.class libgcj.zip
-friend 'java::lang::Class;' \
$(basename $<)
+java/lang/VMClassLoader.h: java/lang/VMClassLoader.class libgcj.zip
+ $(GCJH) -classpath $(top_builddir) \
+ -friend 'java::lang::ClassLoader;' \
+ $(basename $<)
+
+gnu/gcj/runtime/MethodInvocation.h: gnu/gcj/runtime/MethodInvocation.class libgcj.zip
+ $(GCJH) -classpath $(top_builddir) \
+ -friend 'class _Jv_InterpMethod;' \
+ $(basename $<)
+
maintainer-check: libgcj.la
$(NM) .libs/libgcj.a | grep ' T ' \
| grep -v '4java' \
diff --git a/libjava/NEWS b/libjava/NEWS
index 114e48a..e83836d 100644
--- a/libjava/NEWS
+++ b/libjava/NEWS
@@ -1,3 +1,7 @@
+New in libgcj X.XX:
+
+* libgcj now includes a bytecode interpreter.
+
New in libgcj 2.95:
* First public release
diff --git a/libjava/THANKS b/libjava/THANKS
index 93b24a8..5b9b9f8 100644
--- a/libjava/THANKS
+++ b/libjava/THANKS
@@ -10,9 +10,10 @@ Eric Christopher echristo@cygnus.com
Franz Sirl Franz.Sirl-kernel@lauterbach.com
Geoff Berry gcb@gnu.org
Gilles Zunino Gilles.Zunino@hei.fr
-Per Bothner per@bother.com
+Kresten Krab Thorup krab@gnu.org
+Per Bothner per@bothner.com
Rainer Orth ro@TechFak.Uni-Bielefeld.DE
-Stu Grossman grossman@cygnus.com
+Stu Grossman grossman@juniper.com
Tom Tromey tromey@cygnus.com
Urban Widmark urban@svenskatest.se
Warren Levy warrenl@cygnus.com
diff --git a/libjava/acconfig.h b/libjava/acconfig.h
index daddbb1..1bd5025 100644
--- a/libjava/acconfig.h
+++ b/libjava/acconfig.h
@@ -93,3 +93,6 @@
#undef HAVE_READDIR_R
#undef HAVE_GETHOSTBYNAME_R
#undef HAVE_GETHOSTBYADDR_R
+
+/* Define if you want a bytecode interpreter. */
+#undef INTERPRETER
diff --git a/libjava/boehm.cc b/libjava/boehm.cc
index f9e72ba..2e1b5f2 100644
--- a/libjava/boehm.cc
+++ b/libjava/boehm.cc
@@ -16,6 +16,7 @@ details. */
#include <java/lang/Class.h>
#include <jvm.h>
#include <java-field.h>
+#include <java-interp.h>
// We need to include gc_priv.h. However, it tries to include
// config.h if it hasn't already been included. So we force the
@@ -97,8 +98,14 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
{
jclass c = (jclass) addr;
+#if 0
+ // The next field should probably not be marked, since this is
+ // only used in the class hash table. Marking this field
+ // basically prohibits class unloading. --Kresten
w = (word) c->next;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c2label);
+#endif
+
w = (word) c->name;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c3label);
w = (word) c->superclass;
@@ -109,12 +116,23 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5label);
}
+#ifdef INTERPRETER
+ if (_Jv_IsInterpretedClass (c))
+ {
+ w = (word) c->constants.tags;
+ MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5alabel);
+ w = (word) c->constants.data;
+ MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5blabel);
+ }
+#endif
+
// If the class is an array, then the methods field holds a
// pointer to the element class. If the class is primitive,
// then the methods field holds a pointer to the array class.
w = (word) c->methods;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c6label);
+
if (! c->isArray() && ! c->isPrimitive())
{
// Scan each method in the cases where `methods' really
@@ -127,7 +145,19 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
w = (word) c->methods[i].signature;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
cm2label);
+
// FIXME: `ncode' entry?
+
+#ifdef INTERPRETER
+ // The interpreter installs a heap-allocated
+ // trampoline here, so we'll mark it.
+ if (_Jv_IsInterpretedClass (c))
+ {
+ w = (word) c->methods[i].ncode;
+ MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
+ cm3label);
+ }
+#endif
}
}
@@ -136,12 +166,34 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8label);
for (int i = 0; i < c->field_count; ++i)
{
+ _Jv_Field* field = &c->fields[i];
+
#ifndef COMPACT_FIELDS
- w = (word) c->fields[i].name;
+ w = (word) field->name;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8alabel);
#endif
- w = (word) c->fields[i].type;
+ w = (word) field->type;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8blabel);
+
+ // For the interpreter, we also need to mark the memory
+ // containing static members
+ if (field->flags & 0x0008)
+ {
+ w = (word) field->u.addr;
+ MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8clabel);
+
+ // also, if the static member is a reference,
+ // mark also the value pointed to. We check for isResolved
+ // since marking can happen before memory is allocated for
+ // static members.
+ if (JvFieldIsRef (field) && field->isResolved())
+ {
+ jobject val = *(jobject*) field->u.addr;
+ w = (word) val;
+ MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
+ c, c8elabel);
+ }
+ }
}
w = (word) c->vtable;
@@ -155,6 +207,28 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
}
w = (word) c->loader;
MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cBlabel);
+
+#ifdef INTERPRETER
+ if (_Jv_IsInterpretedClass (c))
+ {
+ _Jv_InterpClass* ic = (_Jv_InterpClass*)c;
+
+ w = (word) ic->interpreted_methods;
+ MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, cElabel);
+
+ for (int i = 0; i < c->method_count; i++)
+ {
+ w = (word) ic->interpreted_methods[i];
+ MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, \
+ cFlabel);
+ }
+
+ w = (word) ic->field_initializers;
+ MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, cGlabel);
+
+ }
+#endif
+
}
else
{
diff --git a/libjava/configure b/libjava/configure
index a08e388..eac0e54 100755
--- a/libjava/configure
+++ b/libjava/configure
@@ -35,6 +35,8 @@ ac_help="$ac_help
ac_help="$ac_help
--enable-libgcj-debug Enable runtime debugging code"
ac_help="$ac_help
+ --enable-interpreter Enable interpreter"
+ac_help="$ac_help
--with-ecos Enable runtime eCos target support."
ac_help="$ac_help
--with-system-zlib Use installed libz"
@@ -59,6 +61,7 @@ program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
+sitefile=
srcdir=
target=NONE
verbose=
@@ -173,6 +176,7 @@ Configuration:
--help print this message
--no-create do not create output files
--quiet, --silent do not print \`checking...' messages
+ --site-file=FILE use FILE as the site file
--version print the version of autoconf that created configure
Directory and file names:
--prefix=PREFIX install architecture-independent files in PREFIX
@@ -343,6 +347,11 @@ EOF
-site=* | --site=* | --sit=*)
site="$ac_optarg" ;;
+ -site-file | --site-file | --site-fil | --site-fi | --site-f)
+ ac_prev=sitefile ;;
+ -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*)
+ sitefile="$ac_optarg" ;;
+
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
@@ -508,12 +517,16 @@ fi
srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+if test -z "$sitefile"; then
+ if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
fi
+else
+ CONFIG_SITE="$sitefile"
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
@@ -601,7 +614,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:605: checking host system type" >&5
+echo "configure:618: checking host system type" >&5
host_alias=$host
case "$host_alias" in
@@ -622,7 +635,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6
echo $ac_n "checking target system type""... $ac_c" 1>&6
-echo "configure:626: checking target system type" >&5
+echo "configure:639: checking target system type" >&5
target_alias=$target
case "$target_alias" in
@@ -640,7 +653,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6
echo $ac_n "checking build system type""... $ac_c" 1>&6
-echo "configure:644: checking build system type" >&5
+echo "configure:657: checking build system type" >&5
build_alias=$build
case "$build_alias" in
@@ -688,7 +701,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:692: checking for a BSD compatible install" >&5
+echo "configure:705: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -741,7 +754,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
-echo "configure:745: checking whether build environment is sane" >&5
+echo "configure:758: checking whether build environment is sane" >&5
# Just in case
sleep 1
echo timestamp > conftestfile
@@ -798,7 +811,7 @@ test "$program_suffix" != NONE &&
test "$program_transform_name" = "" && program_transform_name="s,x,x,"
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:802: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:815: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -831,12 +844,12 @@ else
fi
echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
-echo "configure:835: checking for Cygwin environment" >&5
+echo "configure:848: checking for Cygwin environment" >&5
if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 840 "configure"
+#line 853 "configure"
#include "confdefs.h"
int main() {
@@ -847,7 +860,7 @@ int main() {
return __CYGWIN__;
; return 0; }
EOF
-if { (eval echo configure:851: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:864: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_cygwin=yes
else
@@ -864,19 +877,19 @@ echo "$ac_t""$ac_cv_cygwin" 1>&6
CYGWIN=
test "$ac_cv_cygwin" = yes && CYGWIN=yes
echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
-echo "configure:868: checking for mingw32 environment" >&5
+echo "configure:881: checking for mingw32 environment" >&5
if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 873 "configure"
+#line 886 "configure"
#include "confdefs.h"
int main() {
return __MINGW32__;
; return 0; }
EOF
-if { (eval echo configure:880: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:893: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_mingw32=yes
else
@@ -924,7 +937,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:928: checking host system type" >&5
+echo "configure:941: checking host system type" >&5
host_alias=$host
case "$host_alias" in
@@ -966,7 +979,7 @@ EOF
missing_dir=`cd $ac_aux_dir && pwd`
echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
-echo "configure:970: checking for working aclocal" >&5
+echo "configure:983: checking for working aclocal" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -979,7 +992,7 @@ else
fi
echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
-echo "configure:983: checking for working autoconf" >&5
+echo "configure:996: checking for working autoconf" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -992,7 +1005,7 @@ else
fi
echo $ac_n "checking for working automake""... $ac_c" 1>&6
-echo "configure:996: checking for working automake" >&5
+echo "configure:1009: checking for working automake" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -1005,7 +1018,7 @@ else
fi
echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
-echo "configure:1009: checking for working autoheader" >&5
+echo "configure:1022: checking for working autoheader" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -1018,7 +1031,7 @@ else
fi
echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
-echo "configure:1022: checking for working makeinfo" >&5
+echo "configure:1035: checking for working makeinfo" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@@ -1043,7 +1056,7 @@ fi
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1047: checking for $ac_word" >&5
+echo "configure:1060: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1073,7 +1086,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1077: checking for $ac_word" >&5
+echo "configure:1090: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1122,7 +1135,7 @@ fi
fi
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:1126: checking whether we are using GNU C" >&5
+echo "configure:1139: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1131,7 +1144,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1135: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1148: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -1146,7 +1159,7 @@ if test $ac_cv_prog_gcc = yes; then
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:1150: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:1163: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1182,7 +1195,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1186: checking for $ac_word" >&5
+echo "configure:1199: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1215,7 +1228,7 @@ test -n "$CXX" || CXX="gcc"
test -z "$CXX" && { echo "configure: error: no acceptable c++ found in \$PATH" 1>&2; exit 1; }
echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
-echo "configure:1219: checking whether we are using GNU C++" >&5
+echo "configure:1232: checking whether we are using GNU C++" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1224,7 +1237,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1228: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1241: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gxx=yes
else
ac_cv_prog_gxx=no
@@ -1239,7 +1252,7 @@ if test $ac_cv_prog_gxx = yes; then
ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=
echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
-echo "configure:1243: checking whether ${CXX-g++} accepts -g" >&5
+echo "configure:1256: checking whether ${CXX-g++} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1272,7 +1285,7 @@ fi
# LIBGCJ_CONFIGURE, which doesn't work because that means that it will
# be run before AC_CANONICAL_HOST.
echo $ac_n "checking build system type""... $ac_c" 1>&6
-echo "configure:1276: checking build system type" >&5
+echo "configure:1289: checking build system type" >&5
build_alias=$build
case "$build_alias" in
@@ -1293,7 +1306,7 @@ echo "$ac_t""$build" 1>&6
# Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
set dummy ${ac_tool_prefix}as; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1297: checking for $ac_word" >&5
+echo "configure:1310: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1325,7 +1338,7 @@ fi
# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1329: checking for $ac_word" >&5
+echo "configure:1342: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1357,7 +1370,7 @@ fi
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1361: checking for $ac_word" >&5
+echo "configure:1374: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1389,7 +1402,7 @@ if test -n "$ac_tool_prefix"; then
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1393: checking for $ac_word" >&5
+echo "configure:1406: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1434,7 +1447,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1438: checking for a BSD compatible install" >&5
+echo "configure:1451: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1488,7 +1501,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
-echo "configure:1492: checking whether to enable maintainer-specific portions of Makefiles" >&5
+echo "configure:1505: checking whether to enable maintainer-specific portions of Makefiles" >&5
# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
if test "${enable_maintainer_mode+set}" = set; then
enableval="$enable_maintainer_mode"
@@ -1522,7 +1535,7 @@ if false; then
echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
-echo "configure:1526: checking for executable suffix" >&5
+echo "configure:1539: checking for executable suffix" >&5
if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1532,7 +1545,7 @@ else
rm -f conftest*
echo 'int main () { return 0; }' > conftest.$ac_ext
ac_cv_exeext=
- if { (eval echo configure:1536: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ if { (eval echo configure:1549: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
for file in conftest.*; do
case $file in
*.c | *.o | *.obj | *.ilk | *.pdb) ;;
@@ -1654,7 +1667,7 @@ fi
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1658: checking for $ac_word" >&5
+echo "configure:1671: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1684,7 +1697,7 @@ fi
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1688: checking for $ac_word" >&5
+echo "configure:1701: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1714,7 +1727,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1718: checking for $ac_word" >&5
+echo "configure:1731: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1765,7 +1778,7 @@ fi
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1769: checking for $ac_word" >&5
+echo "configure:1782: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1797,7 +1810,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:1801: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:1814: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -1808,12 +1821,12 @@ cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext << EOF
-#line 1812 "configure"
+#line 1825 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-if { (eval echo configure:1817: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1830: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -1839,12 +1852,12 @@ if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:1843: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:1856: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:1848: checking whether we are using GNU C" >&5
+echo "configure:1861: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1853,7 +1866,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1857: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1870: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -1872,7 +1885,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:1876: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:1889: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1915,7 +1928,7 @@ ac_prog=ld
if test "$ac_cv_prog_gcc" = yes; then
# Check if gcc -print-prog-name=ld gives a path.
echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
-echo "configure:1919: checking for ld used by GCC" >&5
+echo "configure:1932: checking for ld used by GCC" >&5
ac_prog=`($CC -print-prog-name=ld) 2>&5`
case "$ac_prog" in
# Accept absolute paths.
@@ -1939,10 +1952,10 @@ echo "configure:1919: checking for ld used by GCC" >&5
esac
elif test "$with_gnu_ld" = yes; then
echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
-echo "configure:1943: checking for GNU ld" >&5
+echo "configure:1956: checking for GNU ld" >&5
else
echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
-echo "configure:1946: checking for non-GNU ld" >&5
+echo "configure:1959: checking for non-GNU ld" >&5
fi
if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1978,7 +1991,7 @@ fi
test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
-echo "configure:1982: checking if the linker ($LD) is GNU ld" >&5
+echo "configure:1995: checking if the linker ($LD) is GNU ld" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1994,7 +2007,7 @@ echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6
echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
-echo "configure:1998: checking for BSD-compatible nm" >&5
+echo "configure:2011: checking for BSD-compatible nm" >&5
if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2031,7 +2044,7 @@ echo "$ac_t""$NM" 1>&6
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:2035: checking whether ln -s works" >&5
+echo "configure:2048: checking whether ln -s works" >&5
if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2075,8 +2088,8 @@ test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
case "$host" in
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 2079 "configure"' > conftest.$ac_ext
- if { (eval echo configure:2080: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ echo '#line 2092 "configure"' > conftest.$ac_ext
+ if { (eval echo configure:2093: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
case "`/usr/bin/file conftest.o`" in
*32-bit*)
LD="${LD-ld} -32"
@@ -2097,19 +2110,19 @@ case "$host" in
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -belf"
echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
-echo "configure:2101: checking whether the C compiler needs -belf" >&5
+echo "configure:2114: checking whether the C compiler needs -belf" >&5
if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2106 "configure"
+#line 2119 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:2113: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2126: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
lt_cv_cc_needs_belf=yes
else
@@ -2253,6 +2266,21 @@ EOF
fi
+# Check whether --enable-interpreter or --disable-interpreter was given.
+if test "${enable_interpreter+set}" = set; then
+ enableval="$enable_interpreter"
+ if test "$enable_interpreter" = yes; then
+ cat >> confdefs.h <<\EOF
+#define INTERPRETER 1
+EOF
+
+ fi
+fi
+
+
+INTERPSPEC=
+
+
TARGET_ECOS="no"
# Check whether --with-ecos or --without-ecos was given.
if test "${with_ecos+set}" = set; then
@@ -2278,7 +2306,7 @@ EOF
esac
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:2282: checking how to run the C preprocessor" >&5
+echo "configure:2310: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@@ -2293,13 +2321,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 2297 "configure"
+#line 2325 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2303: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2331: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -2310,13 +2338,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 2314 "configure"
+#line 2342 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2320: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2348: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -2327,13 +2355,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
-#line 2331 "configure"
+#line 2359 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2337: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2365: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -2358,7 +2386,7 @@ fi
echo "$ac_t""$CPP" 1>&6
cat > conftest.$ac_ext <<EOF
-#line 2362 "configure"
+#line 2390 "configure"
#include "confdefs.h"
#include <stdint.h>
EOF
@@ -2373,7 +2401,7 @@ fi
rm -f conftest*
cat > conftest.$ac_ext <<EOF
-#line 2377 "configure"
+#line 2405 "configure"
#include "confdefs.h"
#include <inttypes.h>
EOF
@@ -2388,7 +2416,7 @@ fi
rm -f conftest*
cat > conftest.$ac_ext <<EOF
-#line 2392 "configure"
+#line 2420 "configure"
#include "confdefs.h"
#include <sys/types.h>
EOF
@@ -2403,7 +2431,7 @@ fi
rm -f conftest*
cat > conftest.$ac_ext <<EOF
-#line 2407 "configure"
+#line 2435 "configure"
#include "confdefs.h"
#include <sys/config.h>
EOF
@@ -2420,7 +2448,7 @@ rm -f conftest*
cat > conftest.$ac_ext <<EOF
-#line 2424 "configure"
+#line 2452 "configure"
#include "confdefs.h"
#include <time.h>
EOF
@@ -2435,7 +2463,7 @@ fi
rm -f conftest*
cat > conftest.$ac_ext <<EOF
-#line 2439 "configure"
+#line 2467 "configure"
#include "confdefs.h"
#include <time.h>
EOF
@@ -2473,7 +2501,7 @@ ZLIBSPEC=
libsubdir=.libs
echo $ac_n "checking for garbage collector to use""... $ac_c" 1>&6
-echo "configure:2477: checking for garbage collector to use" >&5
+echo "configure:2505: checking for garbage collector to use" >&5
# Check whether --enable-java-gc or --disable-java-gc was given.
if test "${enable_java_gc+set}" = set; then
enableval="$enable_java_gc"
@@ -2523,7 +2551,7 @@ esac
echo $ac_n "checking for threads package to use""... $ac_c" 1>&6
-echo "configure:2527: checking for threads package to use" >&5
+echo "configure:2555: checking for threads package to use" >&5
# Check whether --enable-threads or --disable-threads was given.
if test "${enable_threads+set}" = set; then
enableval="$enable_threads"
@@ -2715,12 +2743,12 @@ else
for ac_func in strerror ioctl select open fsync sleep
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2719: checking for $ac_func" >&5
+echo "configure:2747: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2724 "configure"
+#line 2752 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2743,7 +2771,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2775: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2770,12 +2798,12 @@ done
for ac_func in ctime_r ctime
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2774: checking for $ac_func" >&5
+echo "configure:2802: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2779 "configure"
+#line 2807 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2798,7 +2826,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2802: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2830: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2825,12 +2853,12 @@ done
for ac_func in gmtime_r localtime_r readdir_r getpwuid_r
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2829: checking for $ac_func" >&5
+echo "configure:2857: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2834 "configure"
+#line 2862 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2853,7 +2881,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2857: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2885: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2880,12 +2908,12 @@ done
for ac_func in access stat mkdir rename rmdir unlink realpath
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2884: checking for $ac_func" >&5
+echo "configure:2912: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2889 "configure"
+#line 2917 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2908,7 +2936,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2912: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2935,12 +2963,12 @@ done
for ac_func in inet_aton inet_addr
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2939: checking for $ac_func" >&5
+echo "configure:2967: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2944 "configure"
+#line 2972 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2963,7 +2991,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2967: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2995: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2990,12 +3018,12 @@ done
for ac_func in inet_pton uname inet_ntoa
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2994: checking for $ac_func" >&5
+echo "configure:3022: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2999 "configure"
+#line 3027 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3018,7 +3046,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3022: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3050: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3046,12 +3074,12 @@ done
for ac_func in gethostbyname_r
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3050: checking for $ac_func" >&5
+echo "configure:3078: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3055 "configure"
+#line 3083 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3074,7 +3102,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3078: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3106: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3101,7 +3129,7 @@ EOF
# We look for the one that returns `int'.
# Hopefully this check is robust enough.
cat > conftest.$ac_ext <<EOF
-#line 3105 "configure"
+#line 3133 "configure"
#include "confdefs.h"
#include <netdb.h>
EOF
@@ -3121,7 +3149,7 @@ rm -f conftest*
*" -D_REENTRANT "*) ;;
*)
echo $ac_n "checking whether gethostbyname_r declaration requires -D_REENTRANT""... $ac_c" 1>&6
-echo "configure:3125: checking whether gethostbyname_r declaration requires -D_REENTRANT" >&5
+echo "configure:3153: checking whether gethostbyname_r declaration requires -D_REENTRANT" >&5
if eval "test \"`echo '$''{'libjava_cv_gethostbyname_r_needs_reentrant'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3134,14 +3162,14 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
cat > conftest.$ac_ext <<EOF
-#line 3138 "configure"
+#line 3166 "configure"
#include "confdefs.h"
#include <netdb.h>
int main() {
gethostbyname_r("", 0, 0);
; return 0; }
EOF
-if { (eval echo configure:3145: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3173: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
libjava_cv_gethostbyname_r_needs_reentrant=no
else
@@ -3151,14 +3179,14 @@ else
CPPFLAGS_SAVE="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -D_REENTRANT"
cat > conftest.$ac_ext <<EOF
-#line 3155 "configure"
+#line 3183 "configure"
#include "confdefs.h"
#include <netdb.h>
int main() {
gethostbyname_r("", 0, 0);
; return 0; }
EOF
-if { (eval echo configure:3162: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3190: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
libjava_cv_gethostbyname_r_needs_reentrant=yes
else
@@ -3193,12 +3221,12 @@ EOF
esac
echo $ac_n "checking for struct hostent_data""... $ac_c" 1>&6
-echo "configure:3197: checking for struct hostent_data" >&5
+echo "configure:3225: checking for struct hostent_data" >&5
if eval "test \"`echo '$''{'libjava_cv_struct_hostent_data'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3202 "configure"
+#line 3230 "configure"
#include "confdefs.h"
#if GETHOSTBYNAME_R_NEEDS_REENTRANT && !defined(_REENTRANT)
@@ -3209,7 +3237,7 @@ int main() {
struct hostent_data data;
; return 0; }
EOF
-if { (eval echo configure:3213: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3241: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
libjava_cv_struct_hostent_data=yes
else
@@ -3238,12 +3266,12 @@ done
for ac_func in gethostbyaddr_r
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3242: checking for $ac_func" >&5
+echo "configure:3270: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3247 "configure"
+#line 3275 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3266,7 +3294,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3270: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3298: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3293,7 +3321,7 @@ EOF
# We look for the one that returns `int'.
# Hopefully this check is robust enough.
cat > conftest.$ac_ext <<EOF
-#line 3297 "configure"
+#line 3325 "configure"
#include "confdefs.h"
#include <netdb.h>
EOF
@@ -3317,12 +3345,12 @@ done
for ac_func in gethostname
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3321: checking for $ac_func" >&5
+echo "configure:3349: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3326 "configure"
+#line 3354 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3345,7 +3373,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3349: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3377: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3369,7 +3397,7 @@ EOF
EOF
cat > conftest.$ac_ext <<EOF
-#line 3373 "configure"
+#line 3401 "configure"
#include "confdefs.h"
#include <unistd.h>
EOF
@@ -3396,12 +3424,12 @@ done
for ac_func in pthread_mutexattr_settype pthread_mutexattr_setkind_np
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3400: checking for $ac_func" >&5
+echo "configure:3428: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3405 "configure"
+#line 3433 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3424,7 +3452,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3428: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3456: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3454,12 +3482,12 @@ done
for ac_func in sched_yield
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3458: checking for $ac_func" >&5
+echo "configure:3486: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3463 "configure"
+#line 3491 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3482,7 +3510,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3486: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3514: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3504,7 +3532,7 @@ EOF
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for sched_yield in -lposix4""... $ac_c" 1>&6
-echo "configure:3508: checking for sched_yield in -lposix4" >&5
+echo "configure:3536: checking for sched_yield in -lposix4" >&5
ac_lib_var=`echo posix4'_'sched_yield | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -3512,7 +3540,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lposix4 $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3516 "configure"
+#line 3544 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -3523,7 +3551,7 @@ int main() {
sched_yield()
; return 0; }
EOF
-if { (eval echo configure:3527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3555: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3548,7 +3576,7 @@ else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for sched_yield in -lrt""... $ac_c" 1>&6
-echo "configure:3552: checking for sched_yield in -lrt" >&5
+echo "configure:3580: checking for sched_yield in -lrt" >&5
ac_lib_var=`echo rt'_'sched_yield | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -3556,7 +3584,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lrt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3560 "configure"
+#line 3588 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -3567,7 +3595,7 @@ int main() {
sched_yield()
; return 0; }
EOF
-if { (eval echo configure:3571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3599: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3604,12 +3632,12 @@ done
for ac_func in gettimeofday time ftime
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3608: checking for $ac_func" >&5
+echo "configure:3636: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3613 "configure"
+#line 3641 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3632,7 +3660,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3636: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3664: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3663,12 +3691,12 @@ done
for ac_func in memmove
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3667: checking for $ac_func" >&5
+echo "configure:3695: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3672 "configure"
+#line 3700 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3691,7 +3719,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3695: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3723: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3721,12 +3749,12 @@ done
for ac_func in memcpy
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3725: checking for $ac_func" >&5
+echo "configure:3753: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3730 "configure"
+#line 3758 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3749,7 +3777,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3753: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3797,7 +3825,7 @@ done
#--------------------------------------------------------------------
echo $ac_n "checking for socket libraries""... $ac_c" 1>&6
-echo "configure:3801: checking for socket libraries" >&5
+echo "configure:3829: checking for socket libraries" >&5
if eval "test \"`echo '$''{'gcj_cv_lib_sockets'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3805,12 +3833,12 @@ else
gcj_checkBoth=0
unset ac_cv_func_connect
echo $ac_n "checking for connect""... $ac_c" 1>&6
-echo "configure:3809: checking for connect" >&5
+echo "configure:3837: checking for connect" >&5
if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3814 "configure"
+#line 3842 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char connect(); below. */
@@ -3833,7 +3861,7 @@ connect();
; return 0; }
EOF
-if { (eval echo configure:3837: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3865: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_connect=yes"
else
@@ -3856,7 +3884,7 @@ fi
if test "$gcj_checkSocket" = 1; then
unset ac_cv_func_connect
echo $ac_n "checking for main in -lsocket""... $ac_c" 1>&6
-echo "configure:3860: checking for main in -lsocket" >&5
+echo "configure:3888: checking for main in -lsocket" >&5
ac_lib_var=`echo socket'_'main | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -3864,14 +3892,14 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lsocket $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3868 "configure"
+#line 3896 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:3875: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3903: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3898,12 +3926,12 @@ fi
LIBS="$LIBS -lsocket -lnsl"
unset ac_cv_func_accept
echo $ac_n "checking for accept""... $ac_c" 1>&6
-echo "configure:3902: checking for accept" >&5
+echo "configure:3930: checking for accept" >&5
if eval "test \"`echo '$''{'ac_cv_func_accept'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3907 "configure"
+#line 3935 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char accept(); below. */
@@ -3926,7 +3954,7 @@ accept();
; return 0; }
EOF
-if { (eval echo configure:3930: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_accept=yes"
else
@@ -3953,12 +3981,12 @@ fi
gcj_oldLibs=$LIBS
LIBS="$LIBS $gcj_cv_lib_sockets"
echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6
-echo "configure:3957: checking for gethostbyname" >&5
+echo "configure:3985: checking for gethostbyname" >&5
if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3962 "configure"
+#line 3990 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char gethostbyname(); below. */
@@ -3981,7 +4009,7 @@ gethostbyname();
; return 0; }
EOF
-if { (eval echo configure:3985: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4013: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_gethostbyname=yes"
else
@@ -3999,7 +4027,7 @@ if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6
-echo "configure:4003: checking for main in -lnsl" >&5
+echo "configure:4031: checking for main in -lnsl" >&5
ac_lib_var=`echo nsl'_'main | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -4007,14 +4035,14 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lnsl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4011 "configure"
+#line 4039 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:4018: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4046: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -4044,9 +4072,13 @@ fi
echo "$ac_t""$gcj_cv_lib_sockets" 1>&6
SYSTEMSPEC="$SYSTEMSPEC $gcj_cv_lib_sockets"
+ if test "$enable_interpreter" = yes; then
+ INTERPSPEC=
+ fi
+
if test "$with_system_zlib" = yes; then
echo $ac_n "checking for deflate in -lz""... $ac_c" 1>&6
-echo "configure:4050: checking for deflate in -lz" >&5
+echo "configure:4082: checking for deflate in -lz" >&5
ac_lib_var=`echo z'_'deflate | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -4054,7 +4086,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lz $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4058 "configure"
+#line 4090 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -4065,7 +4097,7 @@ int main() {
deflate()
; return 0; }
EOF
-if { (eval echo configure:4069: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4101: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -4094,7 +4126,7 @@ fi
# requires -ldl.
if test "$GC" = boehm; then
echo $ac_n "checking for main in -ldl""... $ac_c" 1>&6
-echo "configure:4098: checking for main in -ldl" >&5
+echo "configure:4130: checking for main in -ldl" >&5
ac_lib_var=`echo dl'_'main | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -4102,14 +4134,14 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4106 "configure"
+#line 4138 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:4113: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4145: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -4219,17 +4251,17 @@ for ac_hdr in unistd.h bstring.h sys/time.h sys/types.h fcntl.h sys/ioctl.h sys/
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4223: checking for $ac_hdr" >&5
+echo "configure:4255: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4228 "configure"
+#line 4260 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4233: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4265: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -4259,17 +4291,17 @@ for ac_hdr in dirent.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4263: checking for $ac_hdr" >&5
+echo "configure:4295: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4268 "configure"
+#line 4300 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4273: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4305: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -4297,16 +4329,16 @@ done
echo $ac_n "checking whether struct sockaddr_in6 is in netinet/in.h""... $ac_c" 1>&6
-echo "configure:4301: checking whether struct sockaddr_in6 is in netinet/in.h" >&5
+echo "configure:4333: checking whether struct sockaddr_in6 is in netinet/in.h" >&5
cat > conftest.$ac_ext <<EOF
-#line 4303 "configure"
+#line 4335 "configure"
#include "confdefs.h"
#include <netinet/in.h>
int main() {
struct sockaddr_in6 addr6;
; return 0; }
EOF
-if { (eval echo configure:4310: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4342: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
cat >> confdefs.h <<\EOF
#define HAVE_INET6 1
@@ -4322,16 +4354,16 @@ fi
rm -f conftest*
echo $ac_n "checking for socklen_t in sys/socket.h""... $ac_c" 1>&6
-echo "configure:4326: checking for socklen_t in sys/socket.h" >&5
+echo "configure:4358: checking for socklen_t in sys/socket.h" >&5
cat > conftest.$ac_ext <<EOF
-#line 4328 "configure"
+#line 4360 "configure"
#include "confdefs.h"
#include <sys/socket.h>
int main() {
socklen_t x = 5;
; return 0; }
EOF
-if { (eval echo configure:4335: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4367: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
cat >> confdefs.h <<\EOF
#define HAVE_SOCKLEN_T 1
@@ -4347,16 +4379,16 @@ fi
rm -f conftest*
echo $ac_n "checking for tm_gmtoff in struct tm""... $ac_c" 1>&6
-echo "configure:4351: checking for tm_gmtoff in struct tm" >&5
+echo "configure:4383: checking for tm_gmtoff in struct tm" >&5
cat > conftest.$ac_ext <<EOF
-#line 4353 "configure"
+#line 4385 "configure"
#include "confdefs.h"
#include <time.h>
int main() {
struct tm tim; tim.tm_gmtoff = 0;
; return 0; }
EOF
-if { (eval echo configure:4360: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4392: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
cat >> confdefs.h <<\EOF
#define STRUCT_TM_HAS_GMTOFF 1
@@ -4369,16 +4401,16 @@ else
rm -rf conftest*
echo "$ac_t""no" 1>&6
echo $ac_n "checking for global timezone variable""... $ac_c" 1>&6
-echo "configure:4373: checking for global timezone variable" >&5
+echo "configure:4405: checking for global timezone variable" >&5
cat > conftest.$ac_ext <<EOF
-#line 4375 "configure"
+#line 4407 "configure"
#include "confdefs.h"
#include <time.h>
int main() {
long z2 = timezone;
; return 0; }
EOF
-if { (eval echo configure:4382: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4414: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
cat >> confdefs.h <<\EOF
#define HAVE_TIMEZONE 1
@@ -4398,19 +4430,19 @@ rm -f conftest*
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:4402: checking for working alloca.h" >&5
+echo "configure:4434: checking for working alloca.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4407 "configure"
+#line 4439 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() {
char *p = alloca(2 * sizeof(int));
; return 0; }
EOF
-if { (eval echo configure:4414: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4446: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_header_alloca_h=yes
else
@@ -4431,12 +4463,12 @@ EOF
fi
echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:4435: checking for alloca" >&5
+echo "configure:4467: checking for alloca" >&5
if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4440 "configure"
+#line 4472 "configure"
#include "confdefs.h"
#ifdef __GNUC__
@@ -4464,7 +4496,7 @@ int main() {
char *p = (char *) alloca(1);
; return 0; }
EOF
-if { (eval echo configure:4468: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4500: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_func_alloca_works=yes
else
@@ -4496,12 +4528,12 @@ EOF
echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:4500: checking whether alloca needs Cray hooks" >&5
+echo "configure:4532: checking whether alloca needs Cray hooks" >&5
if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4505 "configure"
+#line 4537 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
@@ -4526,12 +4558,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
if test $ac_cv_os_cray = yes; then
for ac_func in _getb67 GETB67 getb67; do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4530: checking for $ac_func" >&5
+echo "configure:4562: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4535 "configure"
+#line 4567 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -4554,7 +4586,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:4558: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4590: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -4581,7 +4613,7 @@ done
fi
echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:4585: checking stack direction for C alloca" >&5
+echo "configure:4617: checking stack direction for C alloca" >&5
if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -4589,7 +4621,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
-#line 4593 "configure"
+#line 4625 "configure"
#include "confdefs.h"
find_stack_direction ()
{
@@ -4608,7 +4640,7 @@ main ()
exit (find_stack_direction() < 0);
}
EOF
-if { (eval echo configure:4612: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_stack_direction=1
else
@@ -4635,7 +4667,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:4639: checking for $ac_word" >&5
+echo "configure:4671: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_PERL'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -4868,6 +4900,7 @@ s%@LIBTOOL@%$LIBTOOL%g
s%@COMPPATH@%$COMPPATH%g
s%@TESTSUBDIR_TRUE@%$TESTSUBDIR_TRUE%g
s%@TESTSUBDIR_FALSE@%$TESTSUBDIR_FALSE%g
+s%@INTERPSPEC@%$INTERPSPEC%g
s%@CPP@%$CPP%g
s%@SYSTEMSPEC@%$SYSTEMSPEC%g
s%@ZLIBSPEC@%$ZLIBSPEC%g
diff --git a/libjava/configure.in b/libjava/configure.in
index 4549889..861530a 100644
--- a/libjava/configure.in
+++ b/libjava/configure.in
@@ -42,6 +42,17 @@ AC_ARG_ENABLE(libgcj-debug,
AC_DEFINE(DEBUG)
fi)
+dnl See if the user has the enterpreter included.
+AC_ARG_ENABLE(interpreter,
+[ --enable-interpreter Enable interpreter],
+ if test "$enable_interpreter" = yes; then
+ AC_DEFINE(INTERPRETER)
+ fi)
+
+dnl This becomes -lffi if the interpreter is enables
+INTERPSPEC=
+AC_SUBST(INTERPSPEC)
+
dnl If the target is an eCos system, use the appropriate eCos
dnl I/O routines.
dnl FIXME: this should not be a local option but a global target
@@ -447,6 +458,10 @@ else
])
SYSTEMSPEC="$SYSTEMSPEC $gcj_cv_lib_sockets"
+ if test "$enable_interpreter" = yes; then
+ INTERPSPEC=
+ fi
+
if test "$with_system_zlib" = yes; then
AC_CHECK_LIB(z, deflate, ZLIBSPEC=-lz, ZLIBSPEC=-lzgcj)
else
diff --git a/libjava/defineclass.cc b/libjava/defineclass.cc
new file mode 100644
index 0000000..09f8f47
--- /dev/null
+++ b/libjava/defineclass.cc
@@ -0,0 +1,1556 @@
+// defineclass.cc - defining a class from .class format.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/*
+ Author: Kresten Krab Thorup <krab@gnu.org>
+
+ Written using the online versions of Java Language Specification (1st
+ ed.) and The Java Virtual Machine Specification (2nd ed.).
+
+ Future work may include reading (and handling) attributes which are
+ currently being ignored ("InnerClasses", "LineNumber", etc...).
+*/
+
+#include <java-interp.h>
+
+#ifdef INTERPRETER
+
+#include <java-cpool.h>
+#include <cni.h>
+
+#include <java/lang/Class.h>
+#include <java/lang/Float.h>
+#include <java/lang/Double.h>
+#include <java/lang/Character.h>
+#include <java/lang/LinkageError.h>
+#include <java/lang/InternalError.h>
+#include <java/lang/ClassFormatError.h>
+#include <java/lang/NoClassDefFoundError.h>
+#include <java/lang/ClassCircularityError.h>
+#include <java/lang/ClassNotFoundException.h>
+#include <java/lang/IncompatibleClassChangeError.h>
+
+#define ClassClass _CL_Q34java4lang5Class
+extern java::lang::Class ClassClass;
+#define StringClass _CL_Q34java4lang6String
+extern java::lang::Class StringClass;
+#define ClassObject _CL_Q34java4lang6Object
+extern java::lang::Class ClassObject;
+
+// we don't verify method names that match these.
+static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
+static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
+
+
+// these go in some seperate functions, to avoid having _Jv_InitClass
+// inserted all over the place.
+static void throw_internal_error (char *msg)
+ __attribute__ ((__noreturn__));
+static void throw_no_class_def_found_error (jstring msg)
+ __attribute__ ((__noreturn__));
+static void throw_no_class_def_found_error (char *msg)
+ __attribute__ ((__noreturn__));
+static void throw_class_format_error (jstring msg)
+ __attribute__ ((__noreturn__));
+static void throw_class_format_error (char *msg)
+ __attribute__ ((__noreturn__));
+static void throw_incompatible_class_change_error (jstring msg)
+ __attribute__ ((__noreturn__));
+static void throw_class_circularity_error (jstring msg)
+ __attribute__ ((__noreturn__));
+
+static jdouble long_bits_to_double (jlong);
+static jfloat int_bits_to_float (jint);
+
+/**
+ * We define class reading using a class. It is practical, since then
+ * the entire class-reader can be a friend of class Class (it needs to
+ * write all it's different structures); but also because this makes it
+ * easy to make class definition reentrant, and thus two threads can be
+ * defining classes at the same time. This class (_Jv_ClassReader) is
+ * never exposed outside this file, so we don't have to worry about
+ * public or private members here.
+ */
+
+struct _Jv_ClassReader {
+
+ // do verification? Currently, there is no option to disable this.
+ // This flag just controls the verificaiton done by the class loader;
+ // i.e., checking the integrity of the constant pool; and it is
+ // allways on. You always want this as far as I can see, but it also
+ // controls weither identifiers and type descriptors/signatures are
+ // verified as legal. This could be somewhat more expensive since it
+ // will call Characher.isJavaIdentifier{Start,Part} for each character
+ // in any identifier (field name or method name) it comes by. Thus,
+ // it might be useful to turn off this verification for classes that
+ // come from a trusted source. However, for GCJ, trusted classes are
+ // most likely to be linked in.
+
+ bool verify;
+
+ // input data.
+ unsigned char *bytes;
+ int len;
+
+ // current input position
+ int pos;
+
+ // the constant pool data
+ int pool_count;
+ unsigned char *tags;
+ unsigned int *offsets;
+
+ // the class to define (see java-interp.h)
+ _Jv_InterpClass *def;
+
+ /* check that the given number of input bytes are available */
+ inline void check (int num)
+ {
+ if (pos + num > len)
+ throw_class_format_error ("Premature end of data");
+ }
+
+ /* skip a given number of bytes in input */
+ inline void skip (int num)
+ {
+ check (num);
+ pos += num;
+ }
+
+ /* read an unsignend 1-byte unit */
+ inline static jint get1u (unsigned char* bytes)
+ {
+ return bytes[0];
+ }
+
+ /* read an unsigned 1-byte unit */
+ inline jint read1u ()
+ {
+ skip (1);
+ return get1u (bytes+pos-1);
+ }
+
+ /* read an unsigned 2-byte unit */
+ inline static jint get2u (unsigned char *bytes)
+ {
+ return (((jint)bytes[0]) << 8) | ((jint)bytes[1]);
+ }
+
+ /* read an unsigned 2-byte unit */
+ inline jint read2u ()
+ {
+ skip (2);
+ return get2u (bytes+pos-2);
+ }
+
+ /* read a 4-byte unit */
+ static jint get4 (unsigned char *bytes)
+ {
+ return (((jint)bytes[0]) << 24)
+ | (((jint)bytes[1]) << 16)
+ | (((jint)bytes[2]) << 8)
+ | (((jint)bytes[3]) << 0);
+ }
+
+ /* read a 4-byte unit, (we don't do that quite so often) */
+ inline jint read4 ()
+ {
+ skip (4);
+ return get4 (bytes+pos-4);
+ }
+
+ /* read a 8-byte unit */
+ static jlong get8 (unsigned char* bytes)
+ {
+ return (((jlong)bytes[0]) << 56)
+ | (((jlong)bytes[1]) << 48)
+ | (((jlong)bytes[2]) << 40)
+ | (((jlong)bytes[3]) << 32)
+ | (((jlong)bytes[4]) << 24)
+ | (((jlong)bytes[5]) << 16)
+ | (((jlong)bytes[6]) << 8)
+ | (((jlong)bytes[7]) << 0);
+ }
+
+ /* read a 8-byte unit */
+ inline jlong read8 ()
+ {
+ skip (8);
+ return get8 (bytes+pos-8);
+ }
+
+ inline void check_tag (int index, char expected_tag)
+ {
+ if (index < 0
+ || index > pool_count
+ || tags[index] != expected_tag)
+ throw_class_format_error ("erroneous constant pool tag");
+ }
+
+ _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length)
+ {
+ if (klass == 0 || length < 0 || offset+length > data->length)
+ throw_internal_error ("arguments to _Jv_DefineClass");
+
+ verify = true;
+ bytes = (unsigned char*) (elements (data)+offset);
+ len = length;
+ pos = 0;
+ def = (_Jv_InterpClass*) klass;
+ }
+
+ /** and here goes the parser members defined out-of-line */
+ void parse ();
+ void read_constpool ();
+ void prepare_pool_entry (int index, unsigned char tag);
+ void read_fields ();
+ void read_methods ();
+ void read_one_class_attribute ();
+ void read_one_method_attribute (int method);
+ void read_one_code_attribute (int method);
+ void read_one_field_attribute (int field);
+
+ /** check an utf8 entry, without creating a Utf8Const object */
+ bool is_attribute_name (int index, char *name);
+
+ /** here goes the class-loader members defined out-of-line */
+ void handleConstantPool ();
+ void handleClassBegin (int, int, int);
+ void handleInterfacesBegin (int);
+ void handleInterface (int, int);
+ void handleFieldsBegin (int);
+ void handleField (int, int, int, int);
+ void handleFieldsEnd ();
+ void handleConstantValueAttribute (int,int);
+ void handleMethodsBegin (int);
+ void handleMethod (int, int, int, int);
+ void handleMethodsEnd ();
+ void handleCodeAttribute (int, int, int, int, int, int);
+ void handleExceptionTableEntry (int, int, int, int, int, int);
+
+ void checkExtends (jclass sub, jclass super);
+ void checkImplements (jclass sub, jclass super);
+
+ /*
+ * FIXME: we should keep a hash table of utf8-strings, since many will
+ * be the same. It's a little tricky, however, because the hash table
+ * needs to interact gracefully with the garbage collector. Much
+ * memory is to be saved by this, however! perhaps the improvement
+ * could be implemented in prims.cc (_Jv_makeUtf8Const), since it
+ * computes the hash value anyway.
+ */
+
+ static const int PUBLIC = 0x001;
+ static const int PRIVATE = 0x002;
+ static const int PROTECTED = 0x004;
+ static const int STATIC = 0x008;
+ static const int FINAL = 0x010;
+ static const int SYNCHRONIZED = 0x020;
+ static const int VOLATILE = 0x040;
+ static const int TRANSIENT = 0x080;
+ static const int NATIVE = 0x100;
+ static const int INTERFACE = 0x200;
+ static const int ABSTRACT = 0x400;
+ static const int ALL_FLAGS = 0x7FF;
+
+};
+
+/* This is used for the isJavaIdentifierStart & isJavaIdentifierPart
+ methods, so we avoid doing _Jv_InitClass all the time */
+
+static const java::lang::Character *character = 0;
+static void prepare_character ();
+
+void
+_Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length)
+{
+ if (character == 0)
+ prepare_character ();
+
+ _Jv_ClassReader reader (klass, data, offset, length);
+ reader.parse();
+
+ /* that's it! */
+}
+
+/** put it after _Jv_DefineClass, so it doesn't get inlined */
+static void prepare_character ()
+{
+ character = new java::lang::Character ('!');
+}
+
+
+/** This section defines the parsing/scanning of the class data */
+
+void
+_Jv_ClassReader::parse ()
+{
+ int magic = read4 ();
+
+ /* FIXME: Decide which range of version numbers to allow */
+
+ /* int minor_version = */ read2u ();
+ /* int major_verson = */ read2u ();
+
+ if (magic != (int) 0xCAFEBABE)
+ throw_class_format_error ("bad magic number");
+
+ pool_count = read2u ();
+
+ read_constpool ();
+
+ int access_flags = read2u ();
+ int this_class = read2u ();
+ int super_class = read2u ();
+
+ check_tag (this_class, JV_CONSTANT_Class);
+ if (super_class != 0)
+ check_tag (super_class, JV_CONSTANT_Class);
+
+ handleClassBegin (access_flags, this_class, super_class);
+
+ int interfaces_count = read2u ();
+
+ handleInterfacesBegin (interfaces_count);
+
+ for (int i = 0; i < interfaces_count; i++)
+ {
+ int iface = read2u ();
+ check_tag (iface, JV_CONSTANT_Class);
+ handleInterface (i, iface);
+ }
+
+ read_fields ();
+ read_methods ();
+
+ int attributes_count = read2u ();
+
+ for (int i = 0; i < attributes_count; i++)
+ {
+ read_one_class_attribute ();
+ }
+
+ if (pos != len)
+ throw_class_format_error ("unused data before end of file");
+
+ // tell everyone we're done.
+ def->state = JV_STATE_LOADED;
+ def->notifyAll ();
+
+}
+
+void _Jv_ClassReader::read_constpool ()
+{
+ tags = (unsigned char*) _Jv_AllocBytesChecked (pool_count);
+ offsets = (unsigned int *) _Jv_AllocBytesChecked (sizeof (int)
+ * pool_count) ;
+
+ /** first, we scan the constant pool, collecting tags and offsets */
+ tags[0] = JV_CONSTANT_Undefined;
+ offsets[0] = pos;
+ for (int c = 1; c < pool_count; c++)
+ {
+ tags[c] = read1u ();
+ offsets[c] = pos;
+
+ switch (tags[c])
+ {
+ case JV_CONSTANT_String:
+ case JV_CONSTANT_Class:
+ skip (2);
+ break;
+
+ case JV_CONSTANT_Fieldref:
+ case JV_CONSTANT_Methodref:
+ case JV_CONSTANT_InterfaceMethodref:
+ case JV_CONSTANT_NameAndType:
+ case JV_CONSTANT_Integer:
+ case JV_CONSTANT_Float:
+ skip (4);
+ break;
+
+ case JV_CONSTANT_Double:
+ case JV_CONSTANT_Long:
+ skip (8);
+ tags[++c] = JV_CONSTANT_Undefined;
+ break;
+
+ case JV_CONSTANT_Utf8:
+ {
+ int len = read2u ();
+ skip (len);
+ }
+ break;
+
+ case JV_CONSTANT_Unicode:
+ throw_class_format_error ("unicode not supported");
+ break;
+
+ default:
+ throw_class_format_error ("erroneous constant pool tag");
+ }
+ }
+
+ handleConstantPool ();
+}
+
+
+void _Jv_ClassReader::read_fields ()
+{
+ int fields_count = read2u ();
+ handleFieldsBegin (fields_count);
+
+ for (int i = 0; i < fields_count; i++)
+ {
+ int access_flags = read2u ();
+ int name_index = read2u ();
+ int descriptor_index = read2u ();
+ int attributes_count = read2u ();
+
+ check_tag (name_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
+
+ check_tag (descriptor_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
+
+ handleField (i, access_flags, name_index, descriptor_index);
+
+ for (int j = 0; j < attributes_count; j++)
+ {
+ read_one_field_attribute (i);
+ }
+ }
+
+ handleFieldsEnd ();
+}
+
+bool
+_Jv_ClassReader::is_attribute_name (int index, char *name)
+{
+ check_tag (index, JV_CONSTANT_Utf8);
+ int len = get2u (bytes+offsets[index]);
+ if (len != (int) strlen (name))
+ return false;
+ else
+ return !memcmp (bytes+offsets[index]+2, name, len);
+}
+
+void _Jv_ClassReader::read_one_field_attribute (int field_index)
+{
+ int name = read2u ();
+ int length = read4 ();
+
+ if (is_attribute_name (name, "ConstantValue"))
+ {
+ int cv = read2u ();
+
+ if (cv < pool_count
+ && cv > 0
+ && (tags[cv] == JV_CONSTANT_Integer
+ || tags[cv] == JV_CONSTANT_Float
+ || tags[cv] == JV_CONSTANT_Long
+ || tags[cv] == JV_CONSTANT_Double
+ || tags[cv] == JV_CONSTANT_String))
+ {
+ handleConstantValueAttribute (field_index, cv);
+ }
+ else
+ {
+ throw_class_format_error ("erroneous ConstantValue attribute");
+ }
+
+ if (length != 2)
+ throw_class_format_error ("erroneous ConstantValue attribute");
+ }
+
+ else
+ {
+ skip (length);
+ }
+}
+
+void _Jv_ClassReader::read_methods ()
+{
+ int methods_count = read2u ();
+
+ handleMethodsBegin (methods_count);
+
+ for (int i = 0; i < methods_count; i++)
+ {
+ int access_flags = read2u ();
+ int name_index = read2u ();
+ int descriptor_index = read2u ();
+ int attributes_count = read2u ();
+
+ check_tag (name_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
+
+ check_tag (name_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
+
+ handleMethod (i, access_flags, name_index,
+ descriptor_index);
+
+ for (int j = 0; j < attributes_count; j++)
+ {
+ read_one_method_attribute (i);
+ }
+ }
+
+ handleMethodsEnd ();
+}
+
+void _Jv_ClassReader::read_one_method_attribute (int method_index)
+{
+ int name = read2u ();
+ int length = read4 ();
+
+ if (is_attribute_name (name, "Exceptions"))
+ {
+ /* we ignore this for now */
+ skip (length);
+ }
+
+ else if (is_attribute_name (name, "Code"))
+ {
+ int start_off = pos;
+ int max_stack = read2u ();
+ int max_locals = read2u ();
+ int code_length = read4 ();
+
+ int code_start = pos;
+ skip (code_length);
+ int exception_table_length = read2u ();
+
+ handleCodeAttribute (method_index,
+ max_stack, max_locals,
+ code_start, code_length,
+ exception_table_length);
+
+
+ for (int i = 0; i < exception_table_length; i++)
+ {
+ int start_pc = read2u ();
+ int end_pc = read2u ();
+ int handler_pc = read2u ();
+ int catch_type = read2u ();
+
+ if (start_pc > end_pc
+ || start_pc < 0
+ || end_pc >= code_length
+ || handler_pc >= code_length)
+ throw_class_format_error ("erroneous exception handler info");
+
+ if (! (tags[catch_type] == JV_CONSTANT_Class
+ || tags[catch_type] == 0))
+ {
+ throw_class_format_error ("erroneous exception handler info");
+ }
+
+ handleExceptionTableEntry (method_index,
+ i,
+ start_pc,
+ end_pc,
+ handler_pc,
+ catch_type);
+
+ }
+
+ int attributes_count = read2u ();
+
+ for (int i = 0; i < attributes_count; i++)
+ {
+ read_one_code_attribute (method_index);
+ }
+
+ if ((pos - start_off) != length)
+ throw_class_format_error ("code attribute too short");
+ }
+
+ else
+ {
+ /* ignore unknown attributes */
+ skip (length);
+ }
+}
+
+void _Jv_ClassReader::read_one_code_attribute (int /*method*/)
+{
+ /* ignore for now, ... later we may want to pick up
+ line number information, for debugging purposes;
+ in fact, the whole debugger issue is open! */
+
+ /* int name = */ read2u ();
+ int length = read4 ();
+ skip (length);
+
+}
+
+void _Jv_ClassReader::read_one_class_attribute ()
+{
+ /* we also ignore the class attributes, ...
+ some day we'll add inner-classes support. */
+
+ /* int name = */ read2u ();
+ int length = read4 ();
+ skip (length);
+}
+
+
+
+
+/* this section defines the semantic actions of the parser */
+
+void _Jv_ClassReader::handleConstantPool ()
+{
+ /** now, we actually define the class' constant pool */
+
+ // the pool is scanned explicitly by the collector
+ jbyte *pool_tags = (jbyte*) _Jv_AllocBytesChecked (pool_count);
+ void **pool_data = (void**) _Jv_AllocBytesChecked (pool_count * sizeof (void*));
+
+ def->constants.tags = pool_tags;
+ def->constants.data = pool_data;
+ def->constants.size = pool_count;
+
+ // Here we make a pass to collect the strings! We do this, because
+ // internally in the GCJ runtime, classes are encoded with .'s not /'s.
+ // Therefore, we first collect the strings, and then translate the rest
+ // of the utf8-entries (thus not representing strings) from /-notation
+ // to .-notation.
+ for (int i = 1; i < pool_count; i++)
+ {
+ if (tags[i] == JV_CONSTANT_String)
+ {
+ unsigned char* str_data = bytes + offsets [i];
+ int utf_index = get2u (str_data);
+ check_tag (utf_index, JV_CONSTANT_Utf8);
+ unsigned char *utf_data = bytes + offsets[utf_index];
+ int len = get2u (utf_data);
+ pool_data[i] = (void*)_Jv_makeUtf8Const ((char*)(utf_data+2), len);
+ pool_tags[i] = JV_CONSTANT_String;
+ }
+ else
+ {
+ pool_tags[i] = JV_CONSTANT_Undefined;
+ }
+ }
+
+ // and now, we scan everything else but strings & utf8-entries. This
+ // leaves out those utf8-entries which are not used; which will be left
+ // with a tag of JV_CONSTANT_Undefined in the class definition.
+ for (int index = 1; index < pool_count; index++)
+ {
+ switch (tags[index])
+ {
+ case JV_CONSTANT_Undefined:
+ case JV_CONSTANT_String:
+ case JV_CONSTANT_Utf8:
+ continue;
+
+ default:
+ prepare_pool_entry (index, tags[index]);
+ }
+ }
+
+}
+
+/* this is a recursive procedure, which will prepare pool entries as needed.
+ Which is how we avoid initializing those entries which go unused. */
+void
+_Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
+{
+ /* these two, pool_data and pool_tags, point into the class
+ structure we are currently defining */
+
+ unsigned char *pool_tags = (unsigned char*) def->constants.tags;
+ void **pool_data = (void**) def->constants.data;
+
+ /* this entry was already prepared */
+ if (pool_tags[index] == this_tag)
+ return;
+
+ /* this_data points to the constant-pool information for the current
+ constant-pool entry */
+
+ unsigned char *this_data = bytes + offsets[index];
+
+ switch (this_tag)
+ {
+ case JV_CONSTANT_Utf8:
+ {
+ // If we came here, it is because some other tag needs this
+ // utf8-entry for type information! Thus, we translate /'s to .'s in
+ // order to accomondate gcj's internal representation.
+
+ int len = get2u (this_data);
+ char *buffer = (char*) alloca (len);
+ char *s = ((char*) this_data)+2;
+
+ /* FIXME: avoid using a buffer here */
+ for (int i = 0; i < len; i++)
+ {
+ if (s[i] == '/')
+ buffer[i] = '.';
+ else
+ buffer[i] = (char) s[i];
+ }
+
+ pool_data[index] = (void*)_Jv_makeUtf8Const (buffer, len);
+ pool_tags[index] = JV_CONSTANT_Utf8;
+ }
+ break;
+
+ case JV_CONSTANT_Class:
+ {
+ int utf_index = get2u (this_data);
+ check_tag (utf_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (utf_index, JV_CONSTANT_Utf8);
+
+ if (verify)
+ _Jv_VerifyClassName ((_Jv_Utf8Const*)pool_data[utf_index]);
+
+ pool_data[index] = pool_data[utf_index];
+ pool_tags[index] = JV_CONSTANT_Class;
+ }
+ break;
+
+ case JV_CONSTANT_String:
+ // already handled before...
+ break;
+
+ case JV_CONSTANT_Fieldref:
+ case JV_CONSTANT_Methodref:
+ case JV_CONSTANT_InterfaceMethodref:
+ {
+ int class_index = get2u (this_data);
+ int nat_index = get2u (this_data+2);
+
+ check_tag (class_index, JV_CONSTANT_Class);
+ prepare_pool_entry (class_index, JV_CONSTANT_Class);
+
+ check_tag (nat_index, JV_CONSTANT_NameAndType);
+ prepare_pool_entry (nat_index, JV_CONSTANT_NameAndType);
+
+ // here, verify the signature and identifier name
+ if (verify)
+ {
+ _Jv_ushort name_index, type_index;
+ _Jv_loadIndexes ((const void**)&pool_data[nat_index],
+ name_index, type_index);
+
+ if (this_tag == JV_CONSTANT_Fieldref)
+ _Jv_VerifyFieldSignature
+ ((_Jv_Utf8Const*)pool_data[type_index]);
+ else
+ _Jv_VerifyMethodSignature
+ ((_Jv_Utf8Const*)pool_data[type_index]);
+
+ _Jv_Utf8Const* name = (_Jv_Utf8Const*)pool_data[name_index];
+
+ if (this_tag != JV_CONSTANT_Fieldref
+ && ( _Jv_equalUtf8Consts (name, clinit_name)
+ || _Jv_equalUtf8Consts (name, init_name)))
+ /* ignore */;
+ else
+ _Jv_VerifyIdentifier ((_Jv_Utf8Const*)pool_data[name_index]);
+ }
+
+ _Jv_storeIndexes (&pool_data[index], class_index, nat_index);
+ pool_tags[index] = this_tag;
+ }
+ break;
+
+ case JV_CONSTANT_NameAndType:
+ {
+ _Jv_ushort name_index = get2u (this_data);
+ _Jv_ushort type_index = get2u (this_data+2);
+
+ check_tag (name_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
+
+ check_tag (type_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (type_index, JV_CONSTANT_Utf8);
+
+ _Jv_storeIndexes (&pool_data[index], name_index, type_index);
+ pool_tags[index] = JV_CONSTANT_NameAndType;
+ }
+ break;
+
+ case JV_CONSTANT_Float:
+ {
+ jfloat f = int_bits_to_float ((jint) get4 (this_data));
+ _Jv_storeFloat (&pool_data[index], f);
+ pool_tags[index] = JV_CONSTANT_Float;
+ }
+ break;
+
+ case JV_CONSTANT_Integer:
+ {
+ int i = get4 (this_data);
+ _Jv_storeInt (&pool_data[index], i);
+ pool_tags[index] = JV_CONSTANT_Integer;
+ }
+ break;
+
+ case JV_CONSTANT_Double:
+ {
+ jdouble d = long_bits_to_double ((jlong) get8 (this_data));
+ _Jv_storeDouble (&pool_data[index], d);
+ pool_tags[index] = JV_CONSTANT_Double;
+ }
+ break;
+
+ case JV_CONSTANT_Long:
+ {
+ jlong i = get8 (this_data);
+ _Jv_storeLong (&pool_data[index], i);
+ pool_tags[index] = JV_CONSTANT_Long;
+ }
+ break;
+
+ default:
+ throw_class_format_error ("erroneous constant pool tag");
+ }
+}
+
+
+void
+_Jv_ClassReader::handleClassBegin
+ (int access_flags, int this_class, int super_class)
+{
+ unsigned char *pool_tags = (unsigned char*) def->constants.tags;
+ void **pool_data = (void**) def->constants.data;
+
+ check_tag (this_class, JV_CONSTANT_Class);
+ _Jv_Utf8Const *loadedName = (_Jv_Utf8Const*)pool_data[this_class];
+
+ // was ClassLoader.defineClass called with an expected class name?
+ if (def->name == 0)
+ {
+ jclass orig = _Jv_FindClassInCache (loadedName, def->loader);
+
+ if (orig == 0)
+ {
+ def->name = loadedName;
+ }
+ else
+ {
+ jstring msg = JvNewStringUTF ("anonymous "
+ "class data denotes "
+ "existing class ");
+ msg = msg->concat (orig->getName ());
+
+ throw_no_class_def_found_error (msg);
+ }
+ }
+
+ // assert that the loaded class has the expected name, 5.3.5
+ else if (! _Jv_equalUtf8Consts (loadedName, def->name))
+ {
+ jstring msg = JvNewStringUTF ("loaded class ");
+ msg = msg->concat (def->getName ());
+ msg = msg->concat (_Jv_NewStringUTF (" was in fact named "));
+ jstring klass_name = _Jv_NewStringUTF (loadedName->data);
+ msg = msg->concat (klass_name);
+
+ throw_no_class_def_found_error (msg);
+ }
+
+ def->accflags = access_flags;
+ pool_data[this_class] = (void*)def;
+ pool_tags[this_class] = JV_CONSTANT_ResolvedClass;
+
+ if (super_class == 0)
+ {
+ // interfaces have java.lang.Object as super.
+ if (access_flags & INTERFACE)
+ {
+ def->superclass = (jclass)&ClassObject;
+ }
+
+ // FIXME: Consider this carefully!
+ else if (!_Jv_equalUtf8Consts (def->name, ClassObject.name))
+ {
+ throw_no_class_def_found_error ("loading java.lang.Object");
+ }
+ }
+
+ // In the pre-loading state, it can be looked up in the
+ // cache only by this thread! This allows the super-class
+ // to include references to this class.
+
+ def->state = JV_STATE_PRELOADING;
+ _Jv_RegisterClass (def);
+
+ if (super_class != 0)
+ {
+ // load the super class
+ check_tag (super_class, JV_CONSTANT_Class);
+ _Jv_Utf8Const* super_name =
+ (_Jv_Utf8Const*)pool_data[super_class];
+
+ // load the super class using our defining loader
+ jclass the_super = _Jv_FindClass (super_name,
+ def->loader);
+
+ // This will establish that we are allowed to be a subclass,
+ // and check for class circularity error
+ checkExtends (def, the_super);
+
+ def->superclass = the_super;
+ pool_data[super_class] = (void*) the_super;
+ pool_tags[super_class] = JV_CONSTANT_ResolvedClass;
+ }
+
+ // now we've come past the circularity problem, we can
+ // now say that we're loading...
+
+ def->state = JV_STATE_LOADING;
+ def->notifyAll ();
+}
+
+///// implements the checks described in sect. 5.3.5.3
+void
+_Jv_ClassReader::checkExtends (jclass sub, jclass super)
+{
+ // having an interface or a final class as a superclass is no good
+ if ((super->accflags & (INTERFACE | FINAL)) != 0)
+ {
+ throw_incompatible_class_change_error (sub->getName ());
+ }
+
+ // if the super class is not public, we need to check some more
+ if ((super->accflags & PUBLIC) == 0)
+ {
+ // With package scope, the classes must have the same
+ // class loader.
+ if ( sub->loader != super->loader
+ || !_Jv_ClassNameSamePackage (sub->name, super->name))
+ {
+ throw_incompatible_class_change_error (sub->getName ());
+ }
+ }
+
+ for (; super != 0; super = super->superclass)
+ {
+ if (super == sub)
+ throw_class_circularity_error (sub->getName ());
+ }
+}
+
+
+
+void _Jv_ClassReader::handleInterfacesBegin (int count)
+{
+ def->interfaces = (jclass*) _Jv_AllocBytesChecked (count*sizeof (jclass));
+ def->interface_count = count;
+}
+
+void _Jv_ClassReader::handleInterface (int if_number, int offset)
+{
+ void ** pool_data = def->constants.data;
+ unsigned char * pool_tags = (unsigned char*) def->constants.tags;
+
+ jclass the_interface;
+
+ if (pool_tags[offset] == JV_CONSTANT_Class)
+ {
+ _Jv_Utf8Const* name = (_Jv_Utf8Const*) pool_data[offset];
+ the_interface = _Jv_FindClass (name, def->loader);
+ }
+ else if (pool_tags[offset] == JV_CONSTANT_ResolvedClass)
+ {
+ the_interface = (jclass)pool_data[offset];
+ }
+ else
+ {
+ throw_no_class_def_found_error ("erroneous constant pool tag");
+ }
+
+ // checks the validity of the_interface, and that we are in fact
+ // allowed to implement that interface.
+ checkImplements (def, the_interface);
+
+ pool_data[offset] = (void*)the_interface;
+ pool_tags[offset] = JV_CONSTANT_ResolvedClass;
+
+ def->interfaces[if_number] = the_interface;
+}
+
+void
+_Jv_ClassReader::checkImplements (jclass sub, jclass super)
+{
+ // well, it *must* be an interface
+ if ((super->accflags & INTERFACE) == 0)
+ {
+ throw_incompatible_class_change_error (sub->getName ());
+ }
+
+ // if it has package scope, it must also be defined by the
+ // same loader.
+ if ((super->accflags & PUBLIC) == 0)
+ {
+ if ( sub->loader != super->loader
+ || !_Jv_ClassNameSamePackage (sub->name, super->name))
+ {
+ throw_incompatible_class_change_error (sub->getName ());
+ }
+ }
+
+ // FIXME: add interface circularity check here
+ if (sub == super)
+ {
+ throw_class_circularity_error (sub->getName ());
+ }
+}
+
+void _Jv_ClassReader::handleFieldsBegin (int count)
+{
+ def->fields = (_Jv_Field*)
+ _Jv_AllocBytesChecked (count * sizeof (_Jv_Field));
+ def->field_count = count;
+ def->field_initializers = (_Jv_ushort*)
+ _Jv_AllocBytesChecked (count * sizeof (_Jv_ushort));
+ for (int i = 0; i < count; i++)
+ def->field_initializers[i] = (_Jv_ushort) 0;
+}
+
+void _Jv_ClassReader::handleField (int field_no,
+ int flags,
+ int name,
+ int desc)
+{
+ void **const pool_data = def->constants.data;
+
+ _Jv_Field *field = &def->fields[field_no];
+ _Jv_Utf8Const *field_name = (_Jv_Utf8Const*) pool_data[name];
+
+#ifndef COMPACT_FIELDS
+ field->name = field_name;
+#else
+ field->nameIndex = name;
+#endif
+
+ if (verify)
+ _Jv_VerifyIdentifier (field_name);
+
+ // ignore flags we don't know about.
+ field->flags = flags & ALL_FLAGS;
+
+ if (verify)
+ {
+ if (field->flags & (SYNCHRONIZED|NATIVE|INTERFACE|ABSTRACT))
+ throw_class_format_error ("erroneous field access flags");
+
+ if (1 < ( ((field->flags & PUBLIC) ? 1 : 0)
+ +((field->flags & PRIVATE) ? 1 : 0)
+ +((field->flags & PROTECTED) ? 1 : 0)))
+ throw_class_format_error ("erroneous field access flags");
+ }
+
+ _Jv_Utf8Const* sig = (_Jv_Utf8Const*) pool_data[desc];
+
+ if (verify)
+ _Jv_VerifyFieldSignature (sig);
+
+ // field->type is really a jclass, but while it is still
+ // unresolved we keep an _Jv_Utf8Const* instead.
+ field->type = (jclass) sig;
+ field->flags |= _Jv_FIELD_UNRESOLVED_FLAG;
+ field->u.boffset = 0;
+}
+
+
+void _Jv_ClassReader::handleConstantValueAttribute (int field_index,
+ int value)
+{
+ _Jv_Field *field = &def->fields[field_index];
+
+ if ((field->flags & (STATIC|FINAL|PRIVATE)) == 0)
+ {
+ // Ignore, as per vmspec #4.7.2
+ return;
+ }
+
+ // do not allow multiple constant fields!
+ if (field->flags & _Jv_FIELD_CONSTANT_VALUE)
+ throw_class_format_error ("field has multiple ConstantValue attributes");
+
+ field->flags |= _Jv_FIELD_CONSTANT_VALUE;
+ def->field_initializers[field_index] = value;
+
+ /* type check the initializer */
+
+ if (value <= 0 || value >= pool_count)
+ throw_class_format_error ("erroneous ConstantValue attribute");
+
+ /* FIXME: do the rest */
+}
+
+void _Jv_ClassReader::handleFieldsEnd ()
+{
+ // We need to reorganize the fields so that the static ones are first,
+ // to conform to GCJ class layout.
+
+ int low = 0;
+ int high = def->field_count-1;
+ _Jv_Field *fields = def->fields;
+ _Jv_ushort *inits = def->field_initializers;
+
+ // this is kind of a raw version of quicksort.
+ while (low < high)
+ {
+ // go forward on low, while it's a static
+ while (low < high && (fields[low].flags & STATIC) != 0)
+ low++;
+
+ // go backwards on high, while it's a non-static
+ while (low < high && (fields[high].flags & STATIC) == 0)
+ high--;
+
+ if (low==high)
+ break;
+
+ _Jv_Field tmp = fields[low];
+ _Jv_ushort itmp = inits[low];
+
+ fields[low] = fields[high];
+ inits[low] = inits[high];
+
+ fields[high] = tmp;
+ inits[high] = itmp;
+
+ high -= 1;
+ low += 1;
+ }
+
+ if ((fields[low].flags & STATIC) != 0)
+ low += 1;
+
+ def->static_field_count = low;
+}
+
+
+
+void _Jv_ClassReader::handleMethodsBegin (int count)
+{
+ def->methods = (_Jv_Method*)
+ _Jv_AllocBytesChecked (sizeof (_Jv_Method)*count);
+
+ def->interpreted_methods = (_Jv_InterpMethod**)
+ _Jv_AllocBytesChecked (sizeof (_Jv_InterpMethod*) * count);
+
+ for (int i = 0; i < count; i++)
+ def->interpreted_methods[i] = 0;
+
+ def->method_count = count;
+}
+
+
+void _Jv_ClassReader::handleMethod
+ (int mth_index, int accflags, int name, int desc)
+{
+ void **const pool_data = def->constants.data;
+ _Jv_Method *method = &def->methods[mth_index];
+
+ check_tag (name, JV_CONSTANT_Utf8);
+ prepare_pool_entry (name, JV_CONSTANT_Utf8);
+ method->name = (_Jv_Utf8Const*)pool_data[name];
+
+ check_tag (desc, JV_CONSTANT_Utf8);
+ prepare_pool_entry (desc, JV_CONSTANT_Utf8);
+ method->signature = (_Jv_Utf8Const*)pool_data[desc];
+
+ // ignore unknown flags
+ method->accflags = accflags & ALL_FLAGS;
+
+ // intialize...
+ method->ncode = 0;
+
+ if (verify)
+ {
+ if (_Jv_equalUtf8Consts (method->name, clinit_name)
+ || _Jv_equalUtf8Consts (method->name, init_name))
+ /* ignore */;
+ else
+ _Jv_VerifyIdentifier (method->name);
+
+ _Jv_VerifyMethodSignature (method->signature);
+
+ if (method->accflags & (VOLATILE|TRANSIENT|INTERFACE))
+ throw_class_format_error ("erroneous method access flags");
+
+ if (1 < ( ((method->accflags & PUBLIC) ? 1 : 0)
+ +((method->accflags & PRIVATE) ? 1 : 0)
+ +((method->accflags & PROTECTED) ? 1 : 0)))
+ throw_class_format_error ("erroneous method access flags");
+ }
+}
+
+void _Jv_ClassReader::handleCodeAttribute
+ (int method_index, int max_stack, int max_locals,
+ int code_start, int code_length, int exc_table_length)
+{
+ int size = _Jv_InterpMethod::size (exc_table_length, code_length);
+ _Jv_InterpMethod *method =
+ (_Jv_InterpMethod*) (_Jv_AllocBytesChecked (size));
+
+ method->max_stack = max_stack;
+ method->max_locals = max_locals;
+ method->code_length = code_length;
+ method->exc_count = exc_table_length;
+ method->defining_class = def;
+ method->self = &def->methods[method_index];
+
+ // grab the byte code!
+ memcpy ((void*) method->bytecode (),
+ (void*) (bytes+code_start),
+ code_length);
+
+ def->interpreted_methods[method_index] = method;
+
+ /* that's all we do for now */
+}
+
+void _Jv_ClassReader::handleExceptionTableEntry
+ (int method_index, int exc_index,
+ int start_pc, int end_pc, int handler_pc, int catch_type)
+{
+ _Jv_InterpMethod *method = def->interpreted_methods[method_index];
+ _Jv_InterpException *exc = method->exceptions ();
+
+ exc[exc_index].start_pc = start_pc;
+ exc[exc_index].end_pc = end_pc;
+ exc[exc_index].handler_pc = handler_pc;
+ exc[exc_index].handler_type = catch_type;
+}
+
+void _Jv_ClassReader::handleMethodsEnd ()
+{
+ for (int i = 0; i < def->method_count; i++)
+ {
+ _Jv_Method *method = &def->methods[i];
+ if (method->accflags & (NATIVE|ABSTRACT))
+ {
+ if (def->interpreted_methods[i] != 0)
+ throw_class_format_error ("code provided "
+ "for abstract or native method");
+ }
+ else
+ {
+ if (def->interpreted_methods[i] == 0)
+ throw_class_format_error ("abstract or native method "
+ "with no code");
+ }
+ }
+
+}
+
+
+/** This section takes care of verifying integrity of identifiers,
+ signatures, field ddescriptors, and class names */
+
+#define UTF8_PEEK(PTR, LIMIT) \
+ ({ unsigned char* xxkeep = (PTR); \
+ int xxch = UTF8_GET(PTR,LIMIT); \
+ PTR = xxkeep; xxch; })
+
+/* verify one element of a type descriptor or signature */
+static unsigned char*
+_Jv_VerifyOne (unsigned char* ptr, unsigned char* limit, bool void_ok)
+{
+ if (ptr >= limit)
+ return 0;
+
+ int ch = UTF8_GET (ptr, limit);
+
+ switch (ch)
+ {
+ case 'V':
+ if (! void_ok) return 0;
+
+ case 'S': case 'B': case 'I': case 'J':
+ case 'Z': case 'C': case 'F': case 'D':
+ break;
+
+ case 'L':
+ {
+ unsigned char *start = ptr, *end;
+ do {
+ if (ptr > limit)
+ return 0;
+
+ end = ptr;
+
+ if ((ch = UTF8_GET (ptr, limit)) == -1)
+ return 0;
+
+ } while (ch != ';');
+ _Jv_VerifyClassName (start, (unsigned short) (end-start));
+ }
+ break;
+
+ case '[':
+ return _Jv_VerifyOne (ptr, limit, false);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return ptr;
+
+}
+
+
+/** verification and loading procedures **/
+
+void
+_Jv_VerifyFieldSignature (_Jv_Utf8Const*sig)
+{
+ unsigned char* ptr = (unsigned char*) sig->data;
+ unsigned char* limit = ptr + sig->length;
+
+ ptr = _Jv_VerifyOne (ptr, limit, false);
+
+ if (ptr != limit)
+ throw_class_format_error ("erroneous type descriptor");
+}
+
+void
+_Jv_VerifyMethodSignature (_Jv_Utf8Const*sig)
+{
+ unsigned char* ptr = (unsigned char*) sig->data;
+ unsigned char* limit = ptr + sig->length;
+
+ if (ptr == limit)
+ throw_class_format_error ("erroneous type descriptor");
+
+ if (UTF8_GET(ptr,limit) != '(')
+ throw_class_format_error ("erroneous type descriptor");
+
+ while (ptr && UTF8_PEEK (ptr, limit) != ')')
+ ptr = _Jv_VerifyOne (ptr, limit, false);
+
+ if (UTF8_GET (ptr, limit) != ')')
+ throw_class_format_error ("erroneous type descriptor");
+
+ // get the return type
+ ptr = _Jv_VerifyOne (ptr, limit, true);
+
+ if (ptr != limit)
+ throw_class_format_error ("erroneous type descriptor");
+
+ return;
+
+}
+
+/* we try to avoid calling the Character methods all the time,
+ in fact, they will only be called for non-standard things */
+
+static __inline__ int
+is_identifier_start (int c)
+{
+ unsigned int ch = (unsigned)c;
+
+ if ((ch - 0x41U) < 29U) /* A ... Z */
+ return 1;
+ if ((ch - 0x61U) < 29U) /* a ... z */
+ return 1;
+ if (ch == 0x5FU) /* _ */
+ return 1;
+
+ return character->isJavaIdentifierStart ((jchar) ch);
+}
+
+static __inline__ int
+is_identifier_part (int c)
+{
+ unsigned int ch = (unsigned)c;
+
+ if ((ch - 0x41U) < 29U) /* A ... Z */
+ return 1;
+ if ((ch - 0x61U) < 29U) /* a ... z */
+ return 1;
+ if ((ch - 0x30) < 10U) /* 0 .. 9 */
+ return 1;
+ if (ch == 0x5FU || ch == 0x24U) /* _ $ */
+ return 1;
+
+ return character->isJavaIdentifierStart ((jchar) ch);
+}
+
+void
+_Jv_VerifyIdentifier (_Jv_Utf8Const* name)
+{
+ unsigned char *ptr = (unsigned char*) name->data;
+ unsigned char *limit = ptr + name->length;
+ int ch;
+
+ if ((ch = UTF8_GET (ptr, limit))==-1
+ || ! is_identifier_start (ch))
+ throw_class_format_error ("erroneous identifier");
+
+ while (ptr != limit)
+ {
+ if ((ch = UTF8_GET (ptr, limit))==-1
+ || ! is_identifier_part (ch))
+ throw_class_format_error ("erroneous identifier");
+ }
+}
+
+
+void
+_Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length)
+{
+ unsigned char *limit = ptr+length;
+ int ch;
+
+ next_level:
+ do {
+ if ((ch = UTF8_GET (ptr, limit))==-1)
+ throw_class_format_error ("erroneous class name");
+ if (! is_identifier_start (ch))
+ throw_class_format_error ("erroneous class name");
+ do {
+ if (ptr == limit)
+ return;
+ else if ((ch = UTF8_GET (ptr, limit))==-1)
+ throw_class_format_error ("erroneous class name");
+ else if (ch == '.')
+ goto next_level;
+ else if (! is_identifier_part (ch))
+ throw_class_format_error ("erroneous class name");
+ } while (true);
+ } while (true);
+
+}
+
+void
+_Jv_VerifyClassName (_Jv_Utf8Const *name)
+{
+ _Jv_VerifyClassName ((unsigned char*)&name->data[0],
+ (_Jv_ushort) name->length);
+}
+
+
+/** returns true, if name1 and name2 represents classes in the same
+ package. */
+
+bool
+_Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2)
+{
+ unsigned char* ptr1 = (unsigned char*) name1->data;
+ unsigned char* limit1 = ptr1 + name1->length;
+
+ unsigned char* last1 = ptr1;
+
+ // scan name1, and find the last occurrence of '.'
+ while (ptr1 < limit1) {
+ int ch1 = UTF8_GET (ptr1, limit1);
+
+ if (ch1 == '.')
+ last1 = ptr1;
+
+ else if (ch1 == -1)
+ return false;
+ }
+
+ // now the length of name1's package name is len
+ int len = last1 - (unsigned char*) name1->data;
+
+ // if this is longer than name2, then we're off
+ if (len > name2->length)
+ return false;
+
+ // then compare the first len bytes for equality
+ if (memcmp ((void*) name1->data, (void*) name2->data, len) == 0)
+ {
+ // check that there are no .'s after position len in name2
+
+ unsigned char* ptr2 = (unsigned char*) name2->data + len;
+ unsigned char* limit2 =
+ (unsigned char*) name2->data + name2->length;
+
+ while (ptr2 < limit2)
+ {
+ int ch2 = UTF8_GET (ptr2, limit2);
+ if (ch2 == -1 || ch2 == '.')
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+
+
+/** Here we define the exceptions that can be thrown */
+
+static void
+throw_no_class_def_found_error (jstring msg)
+{
+ if (msg == 0)
+ JvThrow (new java::lang::NoClassDefFoundError);
+ else
+ JvThrow (new java::lang::NoClassDefFoundError (msg));
+}
+
+static void
+throw_no_class_def_found_error (char *msg)
+{
+ throw_no_class_def_found_error (JvNewStringLatin1 (msg));
+}
+
+static void
+throw_class_format_error (jstring msg)
+{
+ if (msg == 0)
+ JvThrow (new java::lang::ClassFormatError);
+ else
+ JvThrow (new java::lang::ClassFormatError (msg));
+}
+
+static void
+throw_class_format_error (char *msg)
+{
+ throw_class_format_error (JvNewStringLatin1 (msg));
+}
+
+static void
+throw_internal_error (char *msg)
+{
+ JvThrow
+ (new java::lang::InternalError (JvNewStringLatin1 (msg)));
+}
+
+static jfloat int_bits_to_float (jint value)
+{
+ return java::lang::Float::intBitsToFloat (value);
+}
+
+static jdouble long_bits_to_double (jlong value)
+{
+ return java::lang::Double::longBitsToDouble (value);
+}
+
+static void throw_incompatible_class_change_error (jstring msg)
+{
+ JvThrow (new java::lang::IncompatibleClassChangeError (msg));
+}
+
+static void throw_class_circularity_error (jstring msg)
+{
+ JvThrow (new java::lang::ClassCircularityError (msg));
+}
+
+#endif /* INTERPRETER */
+
diff --git a/libjava/gij.cc b/libjava/gij.cc
new file mode 100644
index 0000000..f29e825
--- /dev/null
+++ b/libjava/gij.cc
@@ -0,0 +1,27 @@
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+#include <jvm.h>
+#include <cni.h>
+#include <stdio.h>
+
+#include <java/lang/System.h>
+#include <java/util/Properties.h>
+
+int main (int argc, const char **argv)
+{
+ if (argc < 2)
+ {
+ printf ("usage: %s <class name> args\n", argv[0]);
+ exit (1);
+ }
+
+ JvRunMain (0, argc, argv);
+}
diff --git a/libjava/gnu/gcj/runtime/MethodInvocation.java b/libjava/gnu/gcj/runtime/MethodInvocation.java
new file mode 100644
index 0000000..d1664ba
--- /dev/null
+++ b/libjava/gnu/gcj/runtime/MethodInvocation.java
@@ -0,0 +1,32 @@
+// MethodInvocation.java - wrapper used by the interpreter.
+// (the native method is implemented in interpret.cc)
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+package gnu.gcj.runtime;
+
+import gnu.gcj.RawData;
+
+final class MethodInvocation {
+
+ private static Throwable continue0 (RawData meth, RawData inv)
+ {
+ try {
+ continue1 (meth, inv);
+ } catch (Throwable ex) {
+ return ex;
+ }
+ return null;
+ }
+
+ private static native void continue1 (RawData meth, RawData inv);
+
+}
diff --git a/libjava/gnu/gcj/util/path/CacheEntry.java b/libjava/gnu/gcj/util/path/CacheEntry.java
new file mode 100644
index 0000000..949200b
--- /dev/null
+++ b/libjava/gnu/gcj/util/path/CacheEntry.java
@@ -0,0 +1,65 @@
+// CacheEntry.java -- directory cache
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+package gnu.gcj.util.path;
+
+import java.util.*;
+import java.util.zip.*;
+import java.io.*;
+import java.net.*;
+
+
+final class CacheEntry {
+ String dir;
+ String[] files;
+ long time;
+
+ CacheEntry (String d)
+ {
+ dir = d;
+ files = new File(dir).list();
+ time = System.currentTimeMillis ();
+ }
+
+ void touch ()
+ {
+ time = System.currentTimeMillis ();
+ }
+
+ final long EXPIRATION_TIME_MS = 1000;
+
+ boolean is_old () {
+ return (System.currentTimeMillis () - time) > EXPIRATION_TIME_MS;
+ }
+
+ public int hashCode () { return dir.hashCode(); }
+ boolean contains (String file) {
+ if (files == null)
+ return false;
+
+ int index = file.lastIndexOf(SearchPath.file_seperator_char);
+ String f;
+
+ if (index == -1)
+ f = file;
+ else
+ f = file.substring (index+1);
+
+ for (int i = 0; i < files.length; i++)
+ {
+ if (f.equals (files[i])) return true;
+ }
+
+ return false;
+ }
+}
+
diff --git a/libjava/gnu/gcj/util/path/DirectoryPathEntry.java b/libjava/gnu/gcj/util/path/DirectoryPathEntry.java
new file mode 100644
index 0000000..a9ca602
--- /dev/null
+++ b/libjava/gnu/gcj/util/path/DirectoryPathEntry.java
@@ -0,0 +1,136 @@
+// DirectoryPathEntry.java -- search path element for directories
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+package gnu.gcj.util.path;
+
+import java.util.*;
+import java.util.zip.*;
+import java.io.*;
+import java.net.*;
+
+final class DirectoryPathEntry extends PathEntry
+{
+ final File dir;
+ final String base_canon;
+
+ public String toString () { return base_canon; }
+
+ DirectoryPathEntry (File f)
+ throws java.io.IOException
+ {
+ if (!f.isAbsolute ())
+ throw new IllegalArgumentException ();
+
+ dir = f;
+ base_canon = dir.getCanonicalPath ();
+ }
+
+ /*
+ * We maintain a cache of files, so that we
+ * can avoid many calls to stat(), which are
+ * very expensive.
+ *
+ * seen_cache contains (as keys) the directories
+ * which we have visited so far. The values are
+ * instances of CacheEntry, containing a time stamp,
+ * and a list of files in that directory.
+ *
+ */
+
+ private Hashtable seen_cache = new Hashtable ();
+
+ private boolean in_cache (File f)
+ {
+ String rel_dir = f.getParent ();
+ CacheEntry ent;
+
+ if (rel_dir == null)
+ throw new IllegalArgumentException ();
+
+ ent = (CacheEntry) seen_cache.get (rel_dir);
+ if (ent == null)
+ {
+ ent = new CacheEntry (rel_dir);
+ seen_cache.put (rel_dir, ent);
+ }
+
+ if (ent.contains (f.getPath ()))
+ {
+ return true;
+ }
+
+ if ( ent.is_old () )
+ {
+ if (f.exists ())
+ {
+ seen_cache.remove (rel_dir);
+ return true;
+ }
+ else
+ {
+ ent.touch ();
+ }
+ }
+
+ return false;
+ }
+
+ URL getURL (String file) {
+ try {
+ File f = new File((new File (dir, file).getCanonicalPath ()));
+
+ if (! f.getCanonicalPath ().startsWith (base_canon))
+ throw new IllegalArgumentException (file);
+
+
+ if (in_cache (f))
+ return new URL ("file", "", f.getPath ());
+ else
+ return null;
+
+ } catch (IOException x) {
+ return null;
+ }
+ }
+
+ InputStream getStream (String file) {
+ try {
+ File f = new File((new File (dir, file)).getCanonicalPath ());
+
+ if (! f.getCanonicalPath ().startsWith (base_canon))
+ throw new IllegalArgumentException (file);
+
+ if (in_cache (f))
+ return new FileInputStream (f);
+ else
+ return null;
+ } catch (IOException x) {
+ return null;
+ }
+ }
+
+ byte[] getBytes (String file) {
+ File f = new File (dir, file);
+
+ try {
+ if (in_cache (f))
+ return readbytes (new FileInputStream (f),
+ (int) f.length ());
+ else
+ return null;
+ } catch (IOException x) {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/gnu/gcj/util/path/PathEntry.java b/libjava/gnu/gcj/util/path/PathEntry.java
new file mode 100644
index 0000000..f83fc17
--- /dev/null
+++ b/libjava/gnu/gcj/util/path/PathEntry.java
@@ -0,0 +1,55 @@
+// PathEntry.java -- abstract element of search paths
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+package gnu.gcj.util.path;
+
+import java.util.*;
+import java.util.zip.*;
+import java.io.*;
+import java.net.*;
+
+abstract class PathEntry {
+ abstract URL getURL (String file);
+ abstract InputStream getStream (String file);
+ abstract byte[] getBytes (String file);
+
+ /**
+ * Utility routine like InputStream.read(byte[], 0, len), but will
+ * read fully, even if all the data is not available at once.
+ */
+ protected static byte[] readbytes (InputStream is, int length)
+ {
+ try {
+
+ byte[] data = new byte[length];
+ int read;
+ int off = 0;
+
+ while (off != length)
+ {
+ read = is.read (data, off, (int) (length-off));
+
+ if (read == -1)
+ return null;
+
+ off += read;
+ }
+
+ return data;
+ } catch (IOException x) {
+ return null;
+ }
+ }
+
+}
+
+
diff --git a/libjava/gnu/gcj/util/path/SearchPath.java b/libjava/gnu/gcj/util/path/SearchPath.java
new file mode 100644
index 0000000..ffc2ca8
--- /dev/null
+++ b/libjava/gnu/gcj/util/path/SearchPath.java
@@ -0,0 +1,205 @@
+// SearchPath.java -- generic search path utility
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+
+package gnu.gcj.util.path;
+
+import java.util.*;
+import java.util.zip.*;
+import java.io.*;
+import java.net.*;
+
+final public class SearchPath {
+
+ final static String path_seperator
+ = System.getProperty ("path.separator");
+ final static char path_seperator_char
+ = path_seperator.charAt (0);
+ final static String file_seperator
+ = System.getProperty ("file.separator");
+ final static char file_seperator_char
+ = file_seperator.charAt (0);
+
+ private Vector path;
+
+ /**
+ * Constructs a SearchPath object, given a system path.
+ * The system path is expected to be seperated by the string
+ * defined by the <code>path.seperator</code> property.
+ * (<code>":"</code> on unix, <code>;</code> on Windows, etc.).
+ * The path may contain names of directories, or names of
+ * .zip or .jar files. Elements that are neither of these
+ * are ignored.
+ * @param sys_path the search path
+ */
+
+ SearchPath (String sys_path)
+ {
+ StringTokenizer st = new StringTokenizer (sys_path, path_seperator);
+ init (st);
+ }
+
+ /**
+ * Constructs a SearchPath object, given a Vector of
+ * <code>String</code>, <code>File</code> or <code>URL</code>
+ * objects.
+ * The path may contain names of directories, or names of
+ * .zip or .jar files. Elements that are neither of these
+ * are ignored.
+ * @param p the vector of search path elements
+ */
+
+ SearchPath (Vector p)
+ {
+ init (p.elements ());
+ }
+
+ public URL getURL (String element)
+ {
+ URL result;
+
+ Enumeration e = path.elements ();
+ while (e.hasMoreElements ())
+ {
+ PathEntry ent = (PathEntry) e.nextElement ();
+
+ result = ent.getURL (element);
+
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+
+ public InputStream getStream (String element)
+ {
+ InputStream result;
+
+ Enumeration e = path.elements ();
+ while (e.hasMoreElements ())
+ {
+ PathEntry ent = (PathEntry) e.nextElement ();
+
+ result = ent.getStream (element);
+
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+
+ public byte[] getBytes (String element)
+ {
+ byte[] result;
+
+ Enumeration e = path.elements ();
+ while (e.hasMoreElements ())
+ {
+ PathEntry ent = (PathEntry) e.nextElement ();
+ result = ent.getBytes (element);
+ if (result != null)
+ {
+ System.out.println ("loading " + ent
+ + "(" + element + ")");
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+
+
+ private void init (Enumeration st)
+ {
+ path = new Vector ();
+ while (st.hasMoreElements ())
+ {
+ Object e = st.nextElement ();
+
+ String elem;
+ File efile;
+
+ if (e instanceof URL)
+ {
+ path.addElement (new URLPathEntry ((URL) e));
+ continue;
+ }
+
+ if (e instanceof File)
+ {
+ efile = (File) e;
+ elem = efile.getPath ();
+ }
+
+ else if (e instanceof String)
+ {
+ elem = (String) e;
+ efile = new File (elem);
+ }
+
+ else
+ throw new IllegalArgumentException ();
+
+ // make sure it is absolute, so we won't get
+ // trouble if the cwd is changed...
+ if (! efile.isAbsolute ())
+ efile = new File (efile.getAbsolutePath ());
+
+ if (efile.isDirectory ())
+ {
+ try {
+ path.addElement(new DirectoryPathEntry (efile));
+ } catch (IOException x) {
+ /* ignore for now */
+ }
+ }
+
+ else if (efile.isFile ())
+ {
+ int ext = elem.lastIndexOf ('.');
+ if (ext == -1)
+ continue;
+
+ if (!elem.substring(ext+1).equalsIgnoreCase("zip"))
+ continue;
+
+ ZipPathEntry zpe = null;
+ try {
+ zpe = new ZipPathEntry (efile);
+ } catch (ZipException zx) {
+ System.err.println ("SearchPath::ZipException");
+ zpe = null;
+ } catch (MalformedURLException mx) {
+ System.err.println ("SearchPath::URLException");
+ zpe = null;
+ } catch (IOException iox) {
+ System.err.println ("SearchPath::IOException");
+ zpe = null;
+ }
+ if (zpe != null) path.addElement (zpe);
+ }
+ }
+
+ }
+
+
+}
+
diff --git a/libjava/gnu/gcj/util/path/URLPathEntry.java b/libjava/gnu/gcj/util/path/URLPathEntry.java
new file mode 100644
index 0000000..68f9200
--- /dev/null
+++ b/libjava/gnu/gcj/util/path/URLPathEntry.java
@@ -0,0 +1,67 @@
+// URLPathEntry.java -- search path element for URL's
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+package gnu.gcj.util.path;
+
+import java.util.*;
+import java.util.zip.*;
+import java.io.*;
+import java.net.*;
+
+final class URLPathEntry extends PathEntry {
+ final URL base;
+
+ URLPathEntry (URL f) {
+ base = f;
+ }
+
+ public String toString () { return base.toString (); }
+
+ URL getURL (String file) {
+
+ try {
+ URL res = new URL (base, file);
+ InputStream is = res.openStream (); // exc if not found
+ is.close ();
+ return res;
+ } catch (java.io.IOException x) {
+ return null;
+ }
+ }
+
+ InputStream getStream (String file) {
+
+ try {
+ URL res = new URL (base, file);
+ return res.openStream ();
+ } catch (java.io.IOException x) {
+ return null;
+ }
+
+ }
+
+ byte[] getBytes (String file) {
+
+ try {
+ URL res = new URL (base, file);
+ URLConnection conn = res.openConnection ();
+ int len = conn.getContentLength ();
+ if (len == -1) return null;
+ return readbytes (conn.getInputStream (), len);
+ } catch (java.io.IOException x) {
+ return null;
+ }
+
+ }
+
+}
+
diff --git a/libjava/gnu/gcj/util/path/ZipPathEntry.java b/libjava/gnu/gcj/util/path/ZipPathEntry.java
new file mode 100644
index 0000000..ac02262
--- /dev/null
+++ b/libjava/gnu/gcj/util/path/ZipPathEntry.java
@@ -0,0 +1,86 @@
+// ZipPathEntry.java -- search path element for directories
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+package gnu.gcj.util.path;
+
+import java.util.*;
+import java.util.zip.*;
+import java.io.*;
+import java.net.*;
+
+
+final class ZipPathEntry extends PathEntry {
+ final ZipFile zip;
+ final URL file;
+
+ public String toString () { return zip.getName (); }
+
+ ZipPathEntry (File f)
+ throws MalformedURLException, ZipException, IOException
+ {
+ file = new URL ("file", "", f.getPath ());
+ zip = new ZipFile (f);
+ zip.readDirectory ();
+ }
+
+ /*
+ The url for a zip-file resource is,
+
+ <code>file:///path/file.zip#name</code>
+
+ Then, it is URLConnection's problem to handle that.
+ */
+
+ URL getURL (String f) {
+
+ ZipEntry ent = zip.getEntry (f);
+
+ try {
+ if (ent != null)
+ return new URL (file, "#"+f);
+ else
+ return null;
+ } catch (IOException x) {
+ return null;
+ }
+ }
+
+ InputStream getStream (String f) {
+
+ ZipEntry ent = zip.getEntry (f);
+
+ try {
+ if (ent != null)
+ return zip.getInputStream (ent);
+ else
+ return null;
+ } catch (IOException x) {
+ return null;
+ }
+ }
+
+ byte[] getBytes (String f) {
+ ZipEntry ent = zip.getEntry (f);
+
+ try {
+ if (ent != null)
+ return readbytes (zip.getInputStream (ent),
+ (int) ent.getSize ());
+ else
+ return null;
+ } catch (IOException x) {
+ return null;
+ }
+
+ }
+}
+
diff --git a/libjava/include/config.h.in b/libjava/include/config.h.in
index d9b9a0a..03f51ba 100644
--- a/libjava/include/config.h.in
+++ b/libjava/include/config.h.in
@@ -106,6 +106,9 @@
#undef HAVE_GETHOSTBYNAME_R
#undef HAVE_GETHOSTBYADDR_R
+/* Define if you want a bytecode interpreter. */
+#undef INTERPRETER
+
/* Define if you have the access function. */
#undef HAVE_ACCESS
diff --git a/libjava/include/java-cpool.h b/libjava/include/java-cpool.h
new file mode 100644
index 0000000..f4d7ef99
--- /dev/null
+++ b/libjava/include/java-cpool.h
@@ -0,0 +1,173 @@
+// java-cpool.h - Constant pool parsing header. -*- c++ -*-
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#ifndef __JAVA_CPOOL_H__
+#define __JAVA_CPOOL_H__
+
+#include <javaprims.h>
+
+// we rename these, to avoid polluting the name space
+#define JV_CONSTANT_Undefined (0L)
+#define JV_CONSTANT_Utf8 (1L)
+#define JV_CONSTANT_Unicode (2L)
+#define JV_CONSTANT_Integer (3L)
+#define JV_CONSTANT_Float (4L)
+#define JV_CONSTANT_Long (5L)
+#define JV_CONSTANT_Double (6L)
+#define JV_CONSTANT_Class (7L)
+#define JV_CONSTANT_String (8L)
+#define JV_CONSTANT_Fieldref (9L)
+#define JV_CONSTANT_Methodref (10L)
+#define JV_CONSTANT_InterfaceMethodref (11L)
+#define JV_CONSTANT_NameAndType (12L)
+#define JV_CONSTANT_ResolvedFlag (16L)
+#define JV_CONSTANT_ResolvedString (16L | 8L)
+#define JV_CONSTANT_ResolvedClass (16L | 7L)
+
+/* We use the following two operations uniformly for all put/get operations
+ * in the runtime system (constant pool & stack), to assure that we keep
+ * everything in the same format. The idea is, that these should be inlined
+ * away, into just a simple store (for small data types, and a pair of stores
+ * if double or long has alignment greater than void *. On an 64-bit
+ * architecture, all operations should be simple stores; on a 32-bit
+ * architecture it depends on the alignment requirement for the specific
+ * type. */
+
+template <class T>
+static inline void _Jv_put (void *dst, T value)
+{
+#if 0
+ if (sizeof (T) == 8 && __alignof__ (T) > __alignof__ (void*))
+ {
+ jint *v_dst = (jint*)(dst);
+ jint *v_src = (jint*)&value;
+
+ v_dst[0] = v_src[0];
+ v_dst[1] = v_src[1];
+ }
+ else
+#endif
+ {
+ *((T*) (dst)) = value;
+ }
+}
+
+template <class T>
+static inline T _Jv_get (void *src)
+{
+#if 0
+ if (sizeof (T) == 8 && __alignof__ (T) > __alignof__ (void*))
+ {
+ T value;
+ jint *v_dst = (jint*)&value;
+ jint *v_src = (jint*)src;
+
+ v_dst[0] = v_src[0];
+ v_dst[1] = v_src[1];
+
+ return value;
+ }
+ else
+#endif
+ {
+ return *((T*) (src));
+ }
+}
+
+/** needed to keep the CONSTANT_XXXRef & CONSTANT_NameAndType entries */
+extern inline void
+_Jv_storeIndexes (void **data,
+ _Jv_ushort index0,
+ _Jv_ushort index1)
+{
+ // accomodate 64bit machines...
+ if (sizeof (void*) == (2 * sizeof (jint)))
+ {
+ ((jint*)data)[0] = index0;
+ ((jint*)data)[1] = index0;
+ }
+ else
+ {
+ _Jv_put<jint>(data, ((jint)index0 << 16) | (jint)index1);
+ }
+}
+
+extern inline void
+_Jv_loadIndexes (const void **data,
+ _Jv_ushort& index0,
+ _Jv_ushort& index1)
+{
+ if (sizeof (void*) == (2*sizeof (jint)))
+ {
+ index0 = ((jint*)data)[0];
+ index0 = ((jint*)data)[1];
+ }
+ else
+ {
+ jint udata = _Jv_get<jint>(data);
+
+ _Jv_uint uindex0 = ((udata >> 16) & 0xffff);
+ _Jv_uint uindex1 = udata & 0xffff;
+
+ index0 = uindex0;
+ index1 = uindex1;
+ }
+}
+
+extern inline void
+_Jv_storeFloat (void **data, jfloat f)
+{
+ _Jv_put<jfloat>(data, f);
+}
+
+extern inline jfloat
+_Jv_loadFloat (void **data)
+{
+ return _Jv_get<jfloat>(data);
+}
+
+extern inline void
+_Jv_storeInt (void **data, jint i)
+{
+ _Jv_put<jint>(data, i);
+}
+
+extern inline jint
+_Jv_loadInt (void **data)
+{
+ return _Jv_get<jint>(data);
+}
+
+extern inline void
+_Jv_storeLong (void **data, jlong l)
+{
+ return _Jv_put<jlong>(data, l);
+}
+
+extern inline jlong
+_Jv_loadLong (void **data)
+{
+ return _Jv_get<jlong>(data);
+}
+
+extern inline void
+_Jv_storeDouble (void **data, jdouble d)
+{
+ _Jv_put<jdouble>(data, d);
+}
+
+extern inline jdouble
+_Jv_loadDouble (void **data)
+{
+ return _Jv_get<jdouble> (data);
+}
+
+
+#endif /* __JAVA_CPOOL_H__ */
diff --git a/libjava/include/java-field.h b/libjava/include/java-field.h
index b4529fc..d00d9ce 100644
--- a/libjava/include/java-field.h
+++ b/libjava/include/java-field.h
@@ -53,7 +53,18 @@ struct _Jv_Field
jfieldID getNextInstanceField () { return this + 1; }
- jboolean isRef () { return ! isResolved () || ! type->isPrimitive (); }
+ jboolean isRef ()
+ {
+ if (!isResolved ())
+ {
+ char first = ((_Jv_Utf8Const*)type)->data[0];
+ return first == '[' || first == 'L';
+ }
+ else
+ {
+ return ! type->isPrimitive ();
+ }
+ }
// FIXME - may need to mask off internal flags.
int getModifiers() { return flags; }
diff --git a/libjava/include/java-insns.h b/libjava/include/java-insns.h
new file mode 100644
index 0000000..8b19abd
--- /dev/null
+++ b/libjava/include/java-insns.h
@@ -0,0 +1,247 @@
+// java-insns.h - Instruction encodings. This is -*- c++ -*-
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+static const int op_nop = 0x00;
+static const int op_aconst_null = 0x01;
+static const int op_iconst_m1 = 0x02;
+static const int op_iconst_0 = 0x03;
+static const int op_iconst_1 = 0x04;
+static const int op_iconst_2 = 0x05;
+static const int op_iconst_3 = 0x06;
+static const int op_iconst_4 = 0x07;
+static const int op_iconst_5 = 0x08;
+static const int op_lconst_0 = 0x09;
+static const int op_lconst_1 = 0x0a;
+static const int op_fconst_0 = 0x0b;
+static const int op_fconst_1 = 0x0c;
+static const int op_fconst_2 = 0x0d;
+static const int op_dconst_0 = 0x0e;
+static const int op_dconst_1 = 0x0f;
+static const int op_bipush = 0x10;
+static const int op_sipush = 0x11;
+static const int op_ldc = 0x12;
+static const int op_ldc_w = 0x13;
+static const int op_ldc2_w = 0x14;
+static const int op_iload = 0x15;
+static const int op_lload = 0x16;
+static const int op_fload = 0x17;
+static const int op_dload = 0x18;
+static const int op_aload = 0x19;
+static const int op_iload_0 = 0x1a;
+static const int op_iload_1 = 0x1b;
+static const int op_iload_2 = 0x1c;
+static const int op_iload_3 = 0x1d;
+static const int op_lload_0 = 0x1e;
+static const int op_lload_1 = 0x1f;
+static const int op_lload_2 = 0x20;
+static const int op_lload_3 = 0x21;
+static const int op_fload_0 = 0x22;
+static const int op_fload_1 = 0x23;
+static const int op_fload_2 = 0x24;
+static const int op_fload_3 = 0x25;
+static const int op_dload_0 = 0x26;
+static const int op_dload_1 = 0x27;
+static const int op_dload_2 = 0x28;
+static const int op_dload_3 = 0x29;
+static const int op_aload_0 = 0x2a;
+static const int op_aload_1 = 0x2b;
+static const int op_aload_2 = 0x2c;
+static const int op_aload_3 = 0x2d;
+static const int op_iaload = 0x2e;
+static const int op_laload = 0x2f;
+static const int op_faload = 0x30;
+static const int op_daload = 0x31;
+static const int op_aaload = 0x32;
+static const int op_baload = 0x33;
+static const int op_caload = 0x34;
+static const int op_saload = 0x35;
+static const int op_istore = 0x36;
+static const int op_lstore = 0x37;
+static const int op_fstore = 0x38;
+static const int op_dstore = 0x39;
+static const int op_astore = 0x3a;
+static const int op_istore_0 = 0x3b;
+static const int op_istore_1 = 0x3c;
+static const int op_istore_2 = 0x3d;
+static const int op_istore_3 = 0x3e;
+static const int op_lstore_0 = 0x3f;
+static const int op_lstore_1 = 0x40;
+static const int op_lstore_2 = 0x41;
+static const int op_lstore_3 = 0x42;
+static const int op_fstore_0 = 0x43;
+static const int op_fstore_1 = 0x44;
+static const int op_fstore_2 = 0x45;
+static const int op_fstore_3 = 0x46;
+static const int op_dstore_0 = 0x47;
+static const int op_dstore_1 = 0x48;
+static const int op_dstore_2 = 0x49;
+static const int op_dstore_3 = 0x4a;
+static const int op_astore_0 = 0x4b;
+static const int op_astore_1 = 0x4c;
+static const int op_astore_2 = 0x4d;
+static const int op_astore_3 = 0x4e;
+static const int op_iastore = 0x4f;
+static const int op_lastore = 0x50;
+static const int op_fastore = 0x51;
+static const int op_dastore = 0x52;
+static const int op_aastore = 0x53;
+static const int op_bastore = 0x54;
+static const int op_castore = 0x55;
+static const int op_sastore = 0x56;
+static const int op_pop = 0x57;
+static const int op_pop2 = 0x58;
+static const int op_dup = 0x59;
+static const int op_dup_x1 = 0x5a;
+static const int op_dup_x2 = 0x5b;
+static const int op_dup2 = 0x5c;
+static const int op_dup2_x1 = 0x5d;
+static const int op_dup2_x2 = 0x5e;
+static const int op_swap = 0x5f;
+static const int op_iadd = 0x60;
+static const int op_ladd = 0x61;
+static const int op_fadd = 0x62;
+static const int op_dadd = 0x63;
+static const int op_isub = 0x64;
+static const int op_lsub = 0x65;
+static const int op_fsub = 0x66;
+static const int op_dsub = 0x67;
+static const int op_imul = 0x68;
+static const int op_lmul = 0x69;
+static const int op_fmul = 0x6a;
+static const int op_dmul = 0x6b;
+static const int op_idiv = 0x6c;
+static const int op_ldiv = 0x6d;
+static const int op_fdiv = 0x6e;
+static const int op_ddiv = 0x6f;
+static const int op_irem = 0x70;
+static const int op_lrem = 0x71;
+static const int op_frem = 0x72;
+static const int op_drem = 0x73;
+static const int op_ineg = 0x74;
+static const int op_lneg = 0x75;
+static const int op_fneg = 0x76;
+static const int op_dneg = 0x77;
+static const int op_ishl = 0x78;
+static const int op_lshl = 0x79;
+static const int op_ishr = 0x7a;
+static const int op_lshr = 0x7b;
+static const int op_iushr = 0x7c;
+static const int op_lushr = 0x7d;
+static const int op_iand = 0x7e;
+static const int op_land = 0x7f;
+static const int op_ior = 0x80;
+static const int op_lor = 0x81;
+static const int op_ixor = 0x82;
+static const int op_lxor = 0x83;
+static const int op_iinc = 0x84;
+static const int op_i2l = 0x85;
+static const int op_i2f = 0x86;
+static const int op_i2d = 0x87;
+static const int op_l2i = 0x88;
+static const int op_l2f = 0x89;
+static const int op_l2d = 0x8a;
+static const int op_f2i = 0x8b;
+static const int op_f2l = 0x8c;
+static const int op_f2d = 0x8d;
+static const int op_d2i = 0x8e;
+static const int op_d2l = 0x8f;
+static const int op_d2f = 0x90;
+static const int op_i2b = 0x91;
+static const int op_i2c = 0x92;
+static const int op_i2s = 0x93;
+static const int op_lcmp = 0x94;
+static const int op_fcmpl = 0x95;
+static const int op_fcmpg = 0x96;
+static const int op_dcmpl = 0x97;
+static const int op_dcmpg = 0x98;
+static const int op_ifeq = 0x99;
+static const int op_ifne = 0x9a;
+static const int op_iflt = 0x9b;
+static const int op_ifge = 0x9c;
+static const int op_ifgt = 0x9d;
+static const int op_ifle = 0x9e;
+static const int op_if_icmpeq = 0x9f;
+static const int op_if_icmpne = 0xa0;
+static const int op_if_icmplt = 0xa1;
+static const int op_if_icmpge = 0xa2;
+static const int op_if_icmpgt = 0xa3;
+static const int op_if_icmple = 0xa4;
+static const int op_if_acmpeq = 0xa5;
+static const int op_if_acmpne = 0xa6;
+static const int op_goto = 0xa7;
+static const int op_jsr = 0xa8;
+static const int op_ret = 0xa9;
+static const int op_tableswitch = 0xaa;
+static const int op_lookupswitch = 0xab;
+static const int op_ireturn = 0xac;
+static const int op_lreturn = 0xad;
+static const int op_freturn = 0xae;
+static const int op_dreturn = 0xaf;
+static const int op_areturn = 0xb0;
+static const int op_return = 0xb1;
+static const int op_getstatic = 0xb2;
+static const int op_putstatic = 0xb3;
+static const int op_getfield = 0xb4;
+static const int op_putfield = 0xb5;
+static const int op_invokevirtual = 0xb6;
+static const int op_invokespecial = 0xb7;
+static const int op_invokestatic = 0xb8;
+static const int op_invokeinterface = 0xb9;
+static const int op_xxxunusedxxx1 = 0xba;
+static const int op_new = 0xbb;
+static const int op_newarray = 0xbc;
+static const int op_anewarray = 0xbd;
+static const int op_arraylength = 0xbe;
+static const int op_athrow = 0xbf;
+static const int op_checkcast = 0xc0;
+static const int op_instanceof = 0xc1;
+static const int op_monitorenter = 0xc2;
+static const int op_monitorexit = 0xc3;
+static const int op_wide = 0xc4;
+static const int op_multianewarray = 0xc5;
+static const int op_ifnull = 0xc6;
+static const int op_ifnonnull = 0xc7;
+static const int op_goto_w = 0xc8;
+static const int op_jsr_w = 0xc9;
+
+// new opcodes
+
+static const int op_putfield_1 = 0xca;
+static const int op_putfield_2 = 0xcb;
+static const int op_putfield_4 = 0xcd;
+static const int op_putfield_8 = 0xce;
+static const int op_putfield_a = 0xcf;
+
+static const int op_putstatic_1 = 0xd0;
+static const int op_putstatic_2 = 0xd1;
+static const int op_putstatic_4 = 0xd2;
+static const int op_putstatic_8 = 0xd3;
+static const int op_putstatic_a = 0xd4;
+
+static const int op_getfield_1 = 0xd5;
+static const int op_getfield_2s = 0xd6;
+static const int op_getfield_2u = 0xd7;
+static const int op_getfield_4 = 0xd8;
+static const int op_getfield_8 = 0xd9;
+static const int op_getfield_a = 0xda;
+
+static const int op_getstatic_1 = 0xdb;
+static const int op_getstatic_2s = 0xdc;
+static const int op_getstatic_2u = 0xdd;
+static const int op_getstatic_4 = 0xde;
+static const int op_getstatic_8 = 0xdf;
+static const int op_getstatic_a = 0xe0;
+
+static const int op_invokefinal = 0xe1;
+static const int op_invokevtable = 0xe2;
+
+
+
+
diff --git a/libjava/include/java-interp.h b/libjava/include/java-interp.h
new file mode 100644
index 0000000..70feec1
--- /dev/null
+++ b/libjava/include/java-interp.h
@@ -0,0 +1,172 @@
+// java-interp.h - Header file for the bytecode interpreter. -*- c++ -*-
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#ifndef __JAVA_INTERP_H__
+#define __JAVA_INTERP_H__
+
+#include <config.h>
+
+#include <jvm.h>
+#include <java-cpool.h>
+
+#ifdef INTERPRETER
+
+#pragma interface
+
+#include <java/lang/Class.h>
+#include <java/lang/ClassLoader.h>
+#include <gnu/gcj/runtime/MethodInvocation.h>
+
+extern "C" {
+#include <ffi.h>
+}
+
+extern inline jboolean
+_Jv_IsInterpretedClass (jclass c)
+{
+ return (c->loader != 0);
+}
+
+struct _Jv_ResolvedMethod;
+
+void _Jv_VerifyFieldSignature (_Jv_Utf8Const*sig);
+void _Jv_VerifyMethodSignature (_Jv_Utf8Const*sig);
+void _Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length);
+void _Jv_VerifyClassName (_Jv_Utf8Const *name);
+void _Jv_VerifyIdentifier (_Jv_Utf8Const *);
+bool _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2);
+void _Jv_DefineClass (jclass, jbyteArray, jint, jint);
+void _Jv_ResolveField (_Jv_Field *, java::lang::ClassLoader*);
+
+void _Jv_InitField (jobject, jclass, int);
+void * _Jv_AllocMethodInvocation (jsize size);
+
+/* FIXME: this should really be defined in some more generic place */
+#define ROUND(V, A) (((((unsigned) (V))-1) | ((A)-1))+1)
+
+/* the interpreter is written in C++, primarily because it makes it easy for
+ * the entire thing to be "friend" with class Class. */
+
+class _Jv_InterpClass;
+class _Jv_InterpMethod;
+class _Jv_InterpMethodInvocation;
+
+class _Jv_InterpException {
+ int start_pc;
+ int end_pc;
+ int handler_pc;
+ int handler_type;
+
+ friend class _Jv_ClassReader;
+ friend class _Jv_InterpMethod;
+};
+
+class _Jv_InterpMethod {
+
+ _Jv_ushort max_stack;
+ _Jv_ushort max_locals;
+ int code_length;
+
+ _Jv_ushort exc_count;
+ _Jv_ushort args_raw_size;
+
+ _Jv_InterpClass *defining_class;
+ _Jv_Method *self;
+
+ unsigned char* bytecode ()
+ {
+ return
+ ((unsigned char*)this)
+ + ROUND((sizeof (_Jv_InterpMethod)
+ + exc_count*sizeof (_Jv_InterpException)), 4);
+ }
+
+ _Jv_InterpException * exceptions ()
+ {
+ return (_Jv_InterpException*) (this+1);
+ }
+
+ static size_t size (int exc_count, int code_length)
+ {
+ return
+ ROUND ((sizeof (_Jv_InterpMethod)
+ + (exc_count * sizeof (_Jv_InterpException))), 4)
+ + code_length;
+ }
+
+ // return the method's invocation pointer (a stub).
+ void *ncode ();
+ void continue1 (_Jv_InterpMethodInvocation *inv);
+
+ static void run_normal (ffi_cif*, void*, void**, void*);
+ static void run_synch_object (ffi_cif*, void*, void**, void*);
+ static void run_synch_class (ffi_cif*, void*, void**, void*);
+
+ inline jobject run (ffi_cif*, void*, void**,
+ _Jv_InterpMethodInvocation*);
+
+ bool find_exception (jobject ex,
+ _Jv_InterpMethodInvocation *inv);
+
+ public:
+ static void dump_object(jobject o);
+
+ friend class _Jv_ClassReader;
+ friend class _Jv_InterpMethodInvocation;
+ friend class gnu::gcj::runtime::MethodInvocation;
+
+ friend void _Jv_PrepareClass(jclass);
+
+ friend void _Jv_callInterpretedMethod (ffi_cif*,
+ void*,
+ void **,
+ void*);
+};
+
+class _Jv_InterpMethodInvocation {
+ _Jv_InterpMethod *running;
+ void **sp;
+ unsigned char *pc;
+ void* state[0];
+
+ void** stack_base () { return &state[0]; }
+ void** local_base () { return &state[running->max_stack]; }
+
+ friend class _Jv_InterpMethod;
+};
+
+class _Jv_InterpClass : public java::lang::Class
+{
+ _Jv_InterpMethod **interpreted_methods;
+ _Jv_ushort *field_initializers;
+
+ friend class _Jv_ClassReader;
+ friend class _Jv_InterpMethod;
+ friend void _Jv_PrepareClass(jclass);
+ friend void _Jv_InitField (jobject, jclass, int);
+ friend void* _Jv_MarkObj (void *, void *, void *, void *);
+};
+
+struct _Jv_ResolvedMethod {
+ jint stack_item_count;
+ jint vtable_index;
+ jclass klass;
+ _Jv_Method* method;
+
+ // a resolved method holds the cif in-line, so that _Jv_MarkObj just needs
+ // to mark the resolved method to hold on to the cif. Some memory could be
+ // saved by keeping a cache of cif's, since many will be the same.
+ ffi_cif cif;
+ ffi_type * arg_types[0];
+};
+
+#endif /* INTERPRETER */
+
+#endif /* __JAVA_INTERP_H__ */
diff --git a/libjava/include/javaprims.h b/libjava/include/javaprims.h
index 98781ad..9d8c0a6 100644
--- a/libjava/include/javaprims.h
+++ b/libjava/include/javaprims.h
@@ -162,6 +162,7 @@ extern "Java"
class VerifyError;
class VirtualMachineError;
class Void;
+ class VMClassLoader;
namespace reflect
{
class AccessibleObject;
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 75ca827..34da0ed 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -40,6 +40,8 @@ extern int _Jv_strLengthUtf8(char* str, int len);
typedef struct _Jv_Utf8Const Utf8Const;
_Jv_Utf8Const *_Jv_makeUtf8Const (char *s, int len);
+_Jv_Utf8Const *_Jv_makeUtf8TypeConst (char* s, int len);
+_Jv_Utf8Const *_Jv_makeUtf8Const (jstring string);
extern jboolean _Jv_equalUtf8Consts (_Jv_Utf8Const *, _Jv_Utf8Const *);
extern jboolean _Jv_equal (_Jv_Utf8Const *, jstring, jint);
@@ -91,6 +93,8 @@ extern "C" void *_Jv_LookupInterfaceMethod (jclass klass, Utf8Const *name,
extern "C" void _Jv_CheckArrayStore (jobject array, jobject obj);
extern "C" void _Jv_RegisterClass (jclass klass);
extern "C" void _Jv_RegisterClasses (jclass *classes);
+extern void _Jv_UnregisterClass (_Jv_Utf8Const*, java::lang::ClassLoader*);
+
extern jclass _Jv_FindClass (_Jv_Utf8Const *name,
java::lang::ClassLoader *loader);
extern jclass _Jv_FindClassFromSignature (char *,
diff --git a/libjava/interpret.cc b/libjava/interpret.cc
new file mode 100644
index 0000000..1b9b800
--- /dev/null
+++ b/libjava/interpret.cc
@@ -0,0 +1,2449 @@
+// interpret.cc - Code for the interpreter
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+/* define this to get instruction timings. */
+/* #define TIME_MAINLOOP */
+
+#include <config.h>
+
+#pragma implementation "java-interp.h"
+
+#include <cni.h>
+#include <jvm.h>
+#include <java-field.h>
+#include <java-cpool.h>
+#include <java-interp.h>
+#include <java/lang/fdlibm.h>
+#include <java/lang/System.h>
+#include <java/lang/String.h>
+#include <java/lang/Integer.h>
+#include <java/lang/StringBuffer.h>
+#include <java/io/PrintStream.h>
+#include <java/lang/Class.h>
+#include <java/lang/reflect/Modifier.h>
+#include <java/lang/ClassCastException.h>
+#include <java/lang/VirtualMachineError.h>
+#include <java/lang/InternalError.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/ArithmeticException.h>
+#include <java/lang/IncompatibleClassChangeError.h>
+#include <java-insns.h>
+#include <java-signal.h>
+#ifdef TIME_MAINLOOP
+#include <sys/time.h>
+#include <stdio.h>
+#endif
+
+#ifndef INTERPRETER
+
+#include <gnu/gcj/runtime/MethodInvocation.h>
+
+/* this is the exception handler hack, for the interpreter */
+void
+gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
+ gnu::gcj::RawData *)
+{
+ JvFail ("no interpreter");
+}
+
+#else
+
+#define ClassError _CL_Q34java4lang5Error
+extern java::lang::Class ClassError;
+
+static const int PUBLIC = 0x001;
+static const int PRIVATE = 0x002;
+static const int PROTECTED = 0x004;
+static const int STATIC = 0x008;
+static const int FINAL = 0x010;
+static const int SYNCHRONIZED = 0x020;
+static const int VOLATILE = 0x040;
+static const int TRANSIENT = 0x080;
+static const int NATIVE = 0x100;
+static const int INTERFACE = 0x200;
+static const int ABSTRACT = 0x400;
+static const int ALL_FLAGS = 0x7FF;
+
+static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
+
+static void throw_internal_error (char *msg)
+ __attribute__ ((__noreturn__));
+static void throw_incompatible_class_change_error (jstring msg)
+ __attribute__ ((__noreturn__));
+#if !HANDLE_SEGV
+static void throw_null_pointer_exception ()
+ __attribute__ ((__noreturn__));
+#endif
+#if !HANDLE_FPE
+static void throw_arithmetic_exception ()
+ __attribute__ ((__noreturn__));
+#endif
+
+
+static inline void dupx (void **&sp, int n, int x)
+{
+ // first "slide" n+x elements n to the right
+ int top = n-1;
+ for (int i = 0; i < n+x; i++)
+ {
+ sp[(top-i)] = sp[(top-i)-n];
+ }
+
+ // next, copy the n top elements, n+x down
+ for (int i = 0; i < n; i++)
+ {
+ sp[top-(n+x)-i] = sp[top-i];
+ }
+
+ // the net effect
+ sp += n;
+};
+
+
+#define PUSHA(V) \
+ ({ jobject __v=(V); *(jobject*)sp++ = __v; })
+#define PUSHI(V) \
+ ({ jint __v=(V); *(jint*)sp++ = __v; })
+#define PUSHF(V) \
+ ({ jfloat __v=(V); *(jfloat*)sp++ = __v; })
+#define PUSHL(V) \
+ ({ jlong __v=(V); memcpy ((void*)sp, (void*)&__v, 8); sp+=2; })
+#define PUSHD(V) \
+ ({ jdouble __v=(V); memcpy ((void*)sp, (void*)&__v, 8); sp+=2; })
+
+#define POPA() (*(jobject*)--sp)
+#define POPI() (*(jint*)--sp)
+#define POPF() (*(jfloat*)--sp)
+#define POPL() ({ jlong __r; sp-=2; memcpy ((void*)&__r, sp, 8); __r; })
+#define POPD() ({ jdouble __r; sp-=2; memcpy ((void*)&__r, sp, 8); __r; })
+
+#define LOADA(I) *sp++ = locals[I]
+#define LOADI(I) *sp++ = locals[I]
+#define LOADF(I) *sp++ = locals[I]
+#define LOADL(I) ({ memcpy (sp, locals+(I), 8); sp+=2; })
+#define LOADD(I) ({ memcpy (sp, locals+(I), 8); sp+=2; })
+
+#define STOREA(I) locals[I] = *--sp
+#define STOREI(I) locals[I] = *--sp
+#define STOREF(I) locals[I] = *--sp
+#define STOREL(I) ({ sp-=2; memcpy (locals+(I), sp, 8); })
+#define STORED(I) ({ sp-=2; memcpy (locals+(I), sp, 8); })
+
+#define PEEKI(I) (*(jint*) (locals+(I)))
+#define PEEKA(I) (*(jobject*) (locals+(I)))
+
+#define POKEI(I,V) (*(jint*) (locals+(I)) = (V))
+
+
+#define BINOPI(OP) { \
+ jint value2 = POPI(); \
+ jint value1 = POPI(); \
+ PUSHI(value1 OP value2); \
+}
+
+#define BINOPF(OP) { \
+ jfloat value2 = POPF(); \
+ jfloat value1 = POPF(); \
+ PUSHF(value1 OP value2); \
+}
+
+#define BINOPL(OP) { \
+ jlong value2 = POPL(); \
+ jlong value1 = POPL(); \
+ PUSHL(value1 OP value2); \
+}
+
+#define BINOPD(OP) { \
+ jdouble value2 = POPD(); \
+ jdouble value1 = POPD(); \
+ PUSHD(value1 OP value2); \
+}
+
+static inline jint get1s(unsigned char* loc) {
+ return *(signed char*)loc;
+}
+
+static inline jint get1u(unsigned char* loc) {
+ return *loc;
+}
+
+static inline jint get2s(unsigned char* loc) {
+ return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
+}
+
+static inline jint get2u(unsigned char* loc) {
+ return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
+}
+
+static jint get4(unsigned char* loc) {
+ return (((jint)(loc[0])) << 24)
+ | (((jint)(loc[1])) << 16)
+ | (((jint)(loc[2])) << 8)
+ | (((jint)(loc[3])) << 0);
+}
+
+
+#if HANDLE_SEGV
+#define NULLCHECK(X)
+#else
+#define NULLCHECK(X) \
+ do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
+#endif
+
+#if HANDLE_FPE
+#define ZEROCHECK(X)
+#else
+#define ZEROCHECK(X) \
+ do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
+#endif
+
+// this method starts the actual running of the method. It is inlined
+// in three different variants in the static methods run_normal,
+// run_sync_object and run_sync_class (see below). Those static methods
+// are installed directly in the stub for this method (by
+// _Jv_InterpMethod::ncode, in resolve.cc).
+
+inline jobject
+_Jv_InterpMethod::run (ffi_cif* cif,
+ void *retp,
+ void**args,
+ _Jv_InterpMethodInvocation *inv)
+{
+ inv->running = this;
+ inv->pc = bytecode ();
+ inv->sp = inv->stack_base ();
+ void **locals = inv->local_base ();
+
+ /* Go straight at it! the ffi raw format matches the internal
+ stack representation exactly!
+ */
+ memcpy ((void*) locals, (void*) args, args_raw_size);
+
+ next_segment:
+ /* this will call the method _Jv_InterpMethod::continue0, see below */
+ jobject ex =
+ gnu::gcj::runtime::MethodInvocation::continue0
+ ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
+
+ if (ex == 0) // no exception...
+ {
+ /* define sp locally, so the POP? macros will pick it up */
+ void **sp = (void**)inv->sp;
+ int rtype = cif->rtype->type;
+
+ if (rtype == FFI_TYPE_POINTER)
+ {
+ jobject r = POPA();
+ *(jobject*) retp = r;
+ return 0;
+ }
+ else if (rtype == FFI_TYPE_SINT32)
+ {
+ jint r = POPI();
+ *(jint*)retp = r;
+ return 0;
+ }
+ else if (rtype == FFI_TYPE_VOID)
+ {
+ return 0;
+ }
+ else switch (rtype)
+ {
+ case FFI_TYPE_FLOAT:
+ {
+ jfloat r = POPF();
+ *(jfloat*)retp = r;
+ return 0;
+ }
+
+ case FFI_TYPE_DOUBLE:
+ {
+ jdouble r = POPD();
+ *(jdouble*)retp = r;
+ return 0;
+ }
+
+ case FFI_TYPE_UINT8:
+ case FFI_TYPE_UINT16:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_SINT8:
+ case FFI_TYPE_SINT16:
+ {
+ jint r = POPI();
+ *(jint*)retp = r;
+ return 0;
+ }
+
+ case FFI_TYPE_SINT64:
+ {
+ jlong r = POPL();
+ *(jlong*)retp = r;
+ return 0;
+ }
+
+ default:
+ throw_internal_error ("unknown return type");
+ }
+
+ }
+
+ /** handle an exception */
+ if ( find_exception (ex, inv) )
+ goto next_segment;
+
+ java::lang::System::out->println
+ (_Jv_NewStringUTF (self->name->data));
+
+ return ex;
+}
+
+bool _Jv_InterpMethod::find_exception (jobject ex,
+ _Jv_InterpMethodInvocation *inv)
+{
+ int logical_pc = inv->pc - bytecode ();
+ _Jv_InterpException *exc = exceptions ();
+ jclass exc_class = ex->getClass ();
+
+ for (int i = 0; i < exc_count; i++)
+ {
+ if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
+ {
+ jclass handler;
+
+ if (exc[i].handler_type != 0)
+ handler = (jclass)
+ _Jv_ResolvePoolEntry (defining_class,
+ exc[i].handler_type);
+ else
+ handler = NULL;
+
+ if (handler==NULL || handler->isAssignableFrom (exc_class))
+ {
+ inv->pc = bytecode () + exc[i].handler_pc;
+ inv->sp = inv->stack_base (); // reset stack
+ *(jobject*) (inv->sp ++) = ex;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void _Jv_InterpMethod::run_normal (ffi_cif* cif,
+ void* ret,
+ void** args,
+ void* __this)
+{
+ _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
+
+ // we do the alloca of the method invocation here, to allow the method
+ // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
+ int storage_size = _this->max_stack+_this->max_locals;
+ _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
+ alloca (sizeof (_Jv_InterpMethodInvocation)
+ + storage_size * sizeof (void*));
+
+ jobject ex = _this->run (cif, ret, args, inv);
+ if (ex != 0) _Jv_Throw (ex);
+}
+
+void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
+ void* ret,
+ void** args,
+ void* __this)
+{
+ _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
+ jobject rcv = (jobject)args[0];
+
+ int storage_size = _this->max_stack+_this->max_locals;
+ _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
+ alloca (sizeof (_Jv_InterpMethodInvocation)
+ + storage_size * sizeof (void*));
+
+ _Jv_MonitorEnter (rcv);
+ jobject ex = _this->run (cif, ret, args, inv);
+ _Jv_MonitorExit (rcv);
+
+ if (ex != 0) _Jv_Throw (ex);
+}
+
+void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
+ void* ret,
+ void** args,
+ void* __this)
+{
+ _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
+ jclass sync = _this->defining_class;
+
+ int storage_size = _this->max_stack+_this->max_locals;
+ _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
+ alloca (sizeof (_Jv_InterpMethodInvocation)
+ + storage_size * sizeof (void*));
+
+ _Jv_MonitorEnter (sync);
+ jobject ex = _this->run (cif, ret, args, inv);
+ _Jv_MonitorExit (sync);
+
+ if (ex != 0) _Jv_Throw (ex);
+}
+
+/* this is the exception handler hack, for the interpreter */
+void
+gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
+ gnu::gcj::RawData *inv)
+{
+ _Jv_InterpMethod *meth0 = (_Jv_InterpMethod*)meth;
+ _Jv_InterpMethodInvocation *inv0 = (_Jv_InterpMethodInvocation*)inv;
+ meth0->continue1 (inv0);
+}
+
+/*
+ This proceeds execution, as designated in "inv". If an exception
+ happens, then it is simply thrown, and handled in Java. Thus, the pc
+ needs to be stored in the invocation at all times, so we can figure
+ out which handler (if any) to invoke.
+
+ One design issue, which I have not completely considered, is if it
+ should be possible to have interpreted classes linked in! Seldom used
+ (or non-critical) classes could reasonably be interpreted.
+*/
+
+
+#ifdef TIME_MAINLOOP
+static jlong insn_time [256] = { 0 };
+static jlong insn_count[256] = { 0 };
+
+static void
+dump_time ()
+{
+ double total_all = 0;
+ for (int i = 0; i < 256; i++)
+ {
+ total_all += insn_time[i];
+ }
+
+ for (int i = 0; i < 256; i++)
+ {
+ jlong total = insn_time[i];
+ jlong count = insn_count[i];
+
+ if (count == 0) continue;
+
+ jlong amount = total/count;
+
+ printf ("in 0x%02x: %7Li %7Li %7Li %2.1f%%\n", i,
+ (long long)count, (long long)total, (long long)amount,
+ (float) (100.0*(double)total/total_all)
+ );
+ }
+}
+#endif
+
+void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
+{
+ /* for some reason, which I do not understand, the compiler on x86
+ * allocates almost 4k stack space for this function! Even though
+ * there are many local variables, they are all nicely contained
+ * within a block scope, except for the few declared right below
+ * here. What's going on?? It could well be, that there in fact is
+ * on the order of 1000 local variables, including all those inlined
+ * and expanded from macros... Compiling with -O0, it allocates a
+ * "modest" 300 bytes of stack space. Among all those options of
+ * gcc, why isn't there a -fpack-stack, allowing reuse of stack
+ * locations? */
+
+ void** sp = inv->sp;
+ unsigned char *pc = inv->pc;
+ void** locals = inv->local_base ();
+ int opcode;
+
+ jclass defining_class = this->defining_class;
+ void **pool_data = defining_class->constants.data;
+
+ /* these two are used in the invokeXXX instructions */
+ void (*fun)(...);
+ _Jv_ResolvedMethod* rmeth;
+
+#ifdef TIME_MAINLOOP
+ struct timeval tv;
+ int last_opcode;
+ jlong last_time;
+ static jlong time_warp = 0;
+
+#define USEC(TV) \
+ ((jlong) (TV).tv_sec * 1000000LL + (jlong)(TV).tv_usec)
+
+
+ if (time_warp == 0)
+ {
+ struct timeval tv2;
+
+ gettimeofday (&tv, 0);
+ for (int i = 0; i < 100; i++)
+ gettimeofday (&tv2, 0);
+
+ jlong then = USEC(tv);
+ jlong now = USEC(tv2);
+ time_warp = (now - then) / 100;
+
+ if (time_warp == 0)
+ time_warp = 1;
+ }
+
+#define TIME_SUSPEND do { \
+ gettimeofday (&tv, 0); \
+ jlong now = USEC(tv); \
+ insn_time[last_opcode] += (now - last_time) - time_warp; \
+} while(0)
+
+#define TIME_RESUME do { \
+ gettimeofday (&tv, 0); \
+ last_time = USEC(tv); \
+} while(0)
+
+ last_opcode = 0;
+ gettimeofday (&tv, 0);
+ last_time = (jlong)tv.tv_sec * 1000000LL + (jlong)tv.tv_usec;
+
+#else
+
+#define TIME_SUSPEND
+#define TIME_RESUME
+
+#endif
+
+ next_insn:
+ inv->pc = pc;
+
+#ifdef TIME_MAINLOOP
+
+ gettimeofday (&tv, 0);
+ jlong now = USEC(tv);
+ insn_time[last_opcode] += (now - last_time) - time_warp;
+ last_time = now;
+ last_opcode = *pc;
+ insn_count[last_opcode] += 1;
+
+#endif
+ opcode = *pc++;
+
+ /* we special-case the single opcode aload_0 -- it makes
+ up 10% of the time spent in the main loop. */
+
+ switch (opcode)
+ {
+ case op_aload_0: // 0x2a
+ LOADA(0);
+ goto next_insn;
+
+ case op_iload: // 0x15
+ LOADI (get1u (pc++));
+ goto next_insn;
+
+ case op_getfield_4: // 0xd8
+ {
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ PUSHI (*(jint*) ((char*)obj + field_offset));
+ }
+ goto next_insn;
+
+ case op_iload_1: // 0x1b
+ LOADI (1);
+ goto next_insn;
+
+ case op_getfield_a: // 0xda
+ {
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ PUSHA(*(jobject*) ((char*)obj + field_offset));
+ }
+ goto next_insn;
+
+ case op_invokevirtual: // 0xb6
+ {
+ int index = get2u (pc); pc += 2;
+
+ /* _Jv_ResolvePoolEntry returns immediately if the value already
+ * is resolved. If we want to clutter up the code here to gain
+ * a little performance, then we can check the corresponding bit
+ * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
+ * don't think it is worth it. */
+
+ rmeth = (_Jv_ResolvedMethod*)
+ _Jv_ResolvePoolEntry (defining_class, index);
+
+ sp -= rmeth->stack_item_count;
+ NULLCHECK(sp[0]);
+
+ if (rmeth->vtable_index == -1)
+ {
+ // final methods do not appear in the vtable,
+ // if it does not appear in the superclass.
+ fun = (void (*) (...)) rmeth->method->ncode;
+ }
+ else
+ {
+ jobject rcv = (jobject)sp[0];
+ _Jv_VTable *table = *(_Jv_VTable**)rcv;
+ fun = (void (*) (...))table->method[rmeth->vtable_index];
+ }
+ }
+ goto perform_invoke;
+
+ perform_invoke:
+ {
+ /* here goes the magic again... */
+ ffi_cif *cif = &rmeth->cif;
+ void **raw = sp;
+
+ jdouble rvalue;
+
+ TIME_SUSPEND;
+ ffi_raw_call (cif, fun, (void*)&rvalue, (ffi_raw*) raw);
+ TIME_RESUME;
+
+ int rtype = cif->rtype->type;
+
+ /* the likelyhood of object, int, or void return is very high,
+ * so those are checked before the switch */
+ if (rtype == FFI_TYPE_POINTER)
+ {
+ PUSHA (*(jobject*)&rvalue);
+ }
+ else if (rtype == FFI_TYPE_SINT32)
+ {
+ PUSHI (*(jint*)&rvalue);
+ }
+ else if (rtype == FFI_TYPE_VOID)
+ {
+ /* skip */
+ }
+ else switch (rtype)
+ {
+ case FFI_TYPE_SINT8:
+ {
+ jbyte value = (*(jint*)&rvalue) & 0xff;
+ PUSHI (value);
+ }
+ break;
+
+ case FFI_TYPE_SINT16:
+ {
+ jshort value = (*(jint*)&rvalue) & 0xffff;
+ PUSHI (value);
+ }
+ break;
+
+ case FFI_TYPE_UINT16:
+ {
+ jint value = (*(jint*)&rvalue) & 0xffff;
+ PUSHI (value);
+ }
+ break;
+
+ case FFI_TYPE_FLOAT:
+ PUSHF (*(jfloat*)&rvalue);
+ break;
+
+ case FFI_TYPE_DOUBLE:
+ PUSHD (rvalue);
+ break;
+
+ case FFI_TYPE_SINT64:
+ PUSHL (*(jlong*)&rvalue);
+ break;
+
+ default:
+ throw_internal_error ("unknown return type in invokeXXX");
+ }
+
+ }
+ goto next_insn;
+
+
+ case op_nop:
+ goto next_insn;
+
+ case op_aconst_null:
+ PUSHA (NULL);
+ goto next_insn;
+
+ case op_iconst_m1:
+ case op_iconst_0:
+ case op_iconst_1:
+ case op_iconst_2:
+ case op_iconst_3:
+ case op_iconst_4:
+ case op_iconst_5:
+ PUSHI (opcode-op_iconst_0);
+ goto next_insn;
+
+ case op_lconst_0:
+ case op_lconst_1:
+ PUSHL ((jlong) (opcode-op_lconst_0));
+ goto next_insn;
+
+ case op_fconst_0:
+ case op_fconst_1:
+ case op_fconst_2:
+ PUSHF ((jfloat) (opcode-op_fconst_0));
+ goto next_insn;
+
+ case op_dconst_0:
+ case op_dconst_1:
+ PUSHD ((jdouble) (opcode-op_dconst_0));
+ goto next_insn;
+
+ case op_bipush:
+ PUSHI (get1s(pc++));
+ goto next_insn;
+
+ case op_sipush:
+ PUSHI (get2s(pc)); pc += 2;
+ goto next_insn;
+
+ case op_ldc:
+ {
+ int index = get1u (pc++);
+ PUSHA((jobject) pool_data[index]);
+ }
+ goto next_insn;
+
+ case op_ldc_w:
+ {
+ int index = get2u (pc); pc += 2;
+ PUSHA((jobject) pool_data[index]);
+ }
+ goto next_insn;
+
+ case op_ldc2_w:
+ {
+ int index = get2u (pc); pc += 2;
+ memcpy (sp, &pool_data[index], 8);
+ sp += 2;
+ }
+ goto next_insn;
+
+ case op_lload:
+ LOADL (get1u (pc++));
+ goto next_insn;
+
+ case op_fload:
+ LOADF (get1u (pc++));
+ goto next_insn;
+
+ case op_dload:
+ LOADD (get1u (pc++));
+ goto next_insn;
+
+ case op_aload:
+ LOADA (get1u (pc++));
+ goto next_insn;
+
+ case op_iload_0:
+ LOADI (0);
+ goto next_insn;
+
+ case op_iload_2:
+ LOADI (2);
+ goto next_insn;
+
+ case op_iload_3:
+ LOADI (3);
+ goto next_insn;
+
+ case op_lload_0:
+ case op_lload_1:
+ case op_lload_2:
+ case op_lload_3:
+ LOADL (opcode-op_lload_0);
+ goto next_insn;
+
+ case op_fload_0:
+ case op_fload_1:
+ case op_fload_2:
+ case op_fload_3:
+ LOADF (opcode-op_fload_0);
+ goto next_insn;
+
+ case op_dload_0:
+ case op_dload_1:
+ case op_dload_2:
+ case op_dload_3:
+ LOADD (opcode-op_dload_0);
+ goto next_insn;
+
+ case op_aload_1:
+ LOADA(1);
+ goto next_insn;
+
+ case op_aload_2:
+ LOADA(2);
+ goto next_insn;
+
+ case op_aload_3:
+ LOADA(3);
+ goto next_insn;
+
+ case op_iaload:
+ {
+ jint index = POPI();
+ jintArray arr = (jintArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ PUSHI( elements(arr)[index] );
+ }
+ goto next_insn;
+
+ case op_laload:
+ {
+ jint index = POPI();
+ jlongArray arr = (jlongArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ PUSHL( elements(arr)[index] );
+ }
+ goto next_insn;
+
+ case op_faload:
+ {
+ jint index = POPI();
+ jfloatArray arr = (jfloatArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ PUSHF( elements(arr)[index] );
+ }
+ goto next_insn;
+
+ case op_daload:
+ {
+ jint index = POPI();
+ jdoubleArray arr = (jdoubleArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ PUSHD( elements(arr)[index] );
+ }
+ goto next_insn;
+
+ case op_aaload:
+ {
+ jint index = POPI();
+ jobjectArray arr = (jobjectArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ PUSHA( elements(arr)[index] );
+ }
+ goto next_insn;
+
+ case op_baload:
+ {
+ jint index = POPI();
+ jbyteArray arr = (jbyteArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ PUSHI( elements(arr)[index] );
+ }
+ goto next_insn;
+
+ case op_caload:
+ {
+ jint index = POPI();
+ jcharArray arr = (jcharArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ PUSHI( elements(arr)[index] );
+ }
+ goto next_insn;
+
+ case op_saload:
+ {
+ jint index = POPI();
+ jshortArray arr = (jshortArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ PUSHI( elements(arr)[index] );
+ }
+ goto next_insn;
+
+ case op_istore:
+ STOREI (get1u (pc++));
+ goto next_insn;
+
+ case op_lstore:
+ STOREL (get1u (pc++));
+ goto next_insn;
+
+ case op_fstore:
+ STOREF (get1u (pc++));
+ goto next_insn;
+
+ case op_dstore:
+ STORED (get1u (pc++));
+ goto next_insn;
+
+ case op_astore:
+ STOREI (get1u (pc++));
+ goto next_insn;
+
+ case op_istore_0:
+ case op_istore_1:
+ case op_istore_2:
+ case op_istore_3:
+ STOREI (opcode-op_istore_0);
+ goto next_insn;
+
+ case op_lstore_0:
+ case op_lstore_1:
+ case op_lstore_2:
+ case op_lstore_3:
+ STOREL (opcode-op_lstore_0);
+ goto next_insn;
+
+ case op_fstore_0:
+ case op_fstore_1:
+ case op_fstore_2:
+ case op_fstore_3:
+ STOREF (opcode-op_fstore_0);
+ goto next_insn;
+
+ case op_dstore_0:
+ case op_dstore_1:
+ case op_dstore_2:
+ case op_dstore_3:
+ STORED (opcode-op_dstore_0);
+ goto next_insn;
+
+ case op_astore_0:
+ case op_astore_1:
+ case op_astore_2:
+ case op_astore_3:
+ STOREA (opcode-op_astore_0);
+ goto next_insn;
+
+ case op_iastore:
+ {
+ jint value = POPI();
+ jint index = POPI();
+ jintArray arr = (jintArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ elements(arr)[index] = value;
+ }
+ goto next_insn;
+
+ case op_lastore:
+ {
+ jlong value = POPL();
+ jint index = POPI();
+ jlongArray arr = (jlongArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ elements(arr)[index] = value;
+ }
+ goto next_insn;
+
+ case op_fastore:
+ {
+ jfloat value = POPF();
+ jint index = POPI();
+ jfloatArray arr = (jfloatArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ elements(arr)[index] = value;
+ }
+ goto next_insn;
+
+ case op_dastore:
+ {
+ jdouble value = POPD();
+ jint index = POPI();
+ jdoubleArray arr = (jdoubleArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ elements(arr)[index] = value;
+ }
+ goto next_insn;
+
+ case op_aastore:
+ {
+ jobject value = POPA();
+ jint index = POPI();
+ jobjectArray arr = (jobjectArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ _Jv_CheckArrayStore (arr, value);
+ elements(arr)[index] = value;
+ }
+ goto next_insn;
+
+ case op_bastore:
+ {
+ jbyte value = (jbyte) POPI();
+ jint index = POPI();
+ jbyteArray arr = (jbyteArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ elements(arr)[index] = value;
+ }
+ goto next_insn;
+
+ case op_castore:
+ {
+ jchar value = (jchar) POPI();
+ jint index = POPI();
+ jcharArray arr = (jcharArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ elements(arr)[index] = value;
+ }
+ goto next_insn;
+
+ case op_sastore:
+ {
+ jshort value = (jshort) POPI();
+ jint index = POPI();
+ jshortArray arr = (jshortArray) POPA();
+ NULLCHECK (arr);
+ if (index < 0 || index >= arr->length)
+ {
+ TIME_SUSPEND;
+ _Jv_ThrowBadArrayIndex (index);
+ }
+ elements(arr)[index] = value;
+ }
+ goto next_insn;
+
+ case op_pop:
+ sp -= 1;
+ goto next_insn;
+
+ case op_pop2:
+ sp -= 2;
+ goto next_insn;
+
+ case op_dup:
+ sp[0] = sp[-1];
+ sp += 1;
+ goto next_insn;
+
+ case op_dup_x1:
+ dupx (sp, 1, 1);
+ goto next_insn;
+
+ case op_dup_x2:
+ dupx (sp, 1, 2);
+ goto next_insn;
+
+ case op_dup2:
+ sp[0] = sp[-2];
+ sp[1] = sp[-1];
+ sp += 2;
+ goto next_insn;
+
+ case op_dup2_x1:
+ dupx (sp, 2, 1);
+ goto next_insn;
+
+ case op_dup2_x2:
+ dupx (sp, 2, 2);
+ goto next_insn;
+
+ case op_swap:
+ {
+ jobject tmp1 = POPA();
+ jobject tmp2 = POPA();
+ PUSHA (tmp1);
+ PUSHA (tmp2);
+ }
+ goto next_insn;
+
+ case op_iadd:
+ BINOPI(+);
+ goto next_insn;
+
+ case op_ladd:
+ BINOPL(+);
+ goto next_insn;
+
+ case op_fadd:
+ BINOPF(+);
+ goto next_insn;
+
+ case op_dadd:
+ BINOPD(+);
+ goto next_insn;
+
+ case op_isub:
+ BINOPI(-);
+ goto next_insn;
+
+ case op_lsub:
+ BINOPL(-);
+ goto next_insn;
+
+ case op_fsub:
+ BINOPF(-);
+ goto next_insn;
+
+ case op_dsub:
+ BINOPD(-);
+ goto next_insn;
+
+ case op_imul:
+ BINOPI(*);
+ goto next_insn;
+
+ case op_lmul:
+ BINOPL(*);
+ goto next_insn;
+
+ case op_fmul:
+ BINOPF(*);
+ goto next_insn;
+
+ case op_dmul:
+ BINOPD(*);
+ goto next_insn;
+
+ case op_idiv:
+ {
+ jint value2 = POPI();
+ jint value1 = POPI();
+ ZEROCHECK (value2);
+ jint res = value1 / value2;
+ PUSHI (res);
+ }
+ goto next_insn;
+
+ case op_ldiv:
+ {
+ jlong value2 = POPL();
+ jlong value1 = POPL();
+ ZEROCHECK (value2);
+ jlong res = value1 / value2;
+ PUSHL (res);
+ }
+ goto next_insn;
+
+ case op_fdiv:
+ {
+ jfloat value2 = POPF();
+ jfloat value1 = POPF();
+ ZEROCHECK (value2);
+ jfloat res = value1 / value2;
+ PUSHF (res);
+ }
+ goto next_insn;
+
+ case op_ddiv:
+ {
+ jdouble value2 = POPD();
+ jdouble value1 = POPD();
+ ZEROCHECK (value2);
+ jdouble res = value1 / value2;
+ PUSHD (res);
+ }
+ goto next_insn;
+
+ case op_irem:
+ {
+ jint value2 = POPI();
+ jint value1 = POPI();
+ ZEROCHECK (value2);
+ jint res = value1 % value2;
+ PUSHI (res);
+ }
+ goto next_insn;
+
+ case op_lrem:
+ {
+ jlong value2 = POPL();
+ jlong value1 = POPL();
+ ZEROCHECK (value2);
+ jlong res = value1 % value2;
+ PUSHL (res);
+ }
+ goto next_insn;
+
+ case op_frem:
+ {
+ jfloat value2 = POPF();
+ jfloat value1 = POPF();
+ ZEROCHECK (value2);
+ jfloat res = __ieee754_fmod (value1, value2);
+ PUSHF (res);
+ }
+ goto next_insn;
+
+ case op_drem:
+ {
+ jdouble value2 = POPD();
+ jdouble value1 = POPD();
+ ZEROCHECK (value2);
+ jdouble res = __ieee754_fmod (value1, value2);
+ PUSHD (res);
+ }
+ goto next_insn;
+
+ case op_ineg:
+ *(jint*) (sp-1) *= -1;
+ goto next_insn;
+
+ case op_lneg:
+ *(jlong*) (sp-1) *= -1;
+ goto next_insn;
+
+ case op_fneg:
+ *(jfloat*) (sp-1) *= -1;
+ goto next_insn;
+
+ case op_dneg:
+ *(jdouble*) (sp-1) *= -1;
+ goto next_insn;
+
+ case op_ishl:
+ {
+ jint shift = (POPI() & 0x1f);
+ jint value = POPI();
+ PUSHI (value << shift);
+ }
+ goto next_insn;
+
+ case op_lshl:
+ {
+ jint shift = (POPI() & 0x3f);
+ jlong value = POPL();
+ PUSHL (value << shift);
+ }
+ goto next_insn;
+
+ case op_ishr:
+ {
+ jint shift = (POPI() & 0x1f);
+ jint value = POPI();
+ PUSHI (value >> shift);
+ }
+ goto next_insn;
+
+ case op_lshr:
+ {
+ jint shift = (POPI() & 0x3f);
+ jlong value = POPL();
+ PUSHL (value >> shift);
+ }
+ goto next_insn;
+
+ case op_iushr:
+ {
+ jint shift = (POPI() & 0x1f);
+ unsigned long value = POPI();
+ PUSHI ((jint) (value >> shift));
+ }
+ goto next_insn;
+
+ case op_lushr:
+ {
+ jint shift = (POPI() & 0x3f);
+ UINT64 value = (UINT64) POPL();
+ PUSHL ((value >> shift));
+ }
+ goto next_insn;
+
+ case op_iand:
+ BINOPI (&);
+ goto next_insn;
+
+ case op_land:
+ BINOPL (&);
+ goto next_insn;
+
+ case op_ior:
+ BINOPI (|);
+ goto next_insn;
+
+ case op_lor:
+ BINOPL (|);
+ goto next_insn;
+
+ case op_ixor:
+ BINOPI (^);
+ goto next_insn;
+
+ case op_lxor:
+ BINOPL (^);
+ goto next_insn;
+
+ case op_iinc:
+ {
+ jint index = get1u (pc++);
+ jint amount = get1s (pc++);
+ *(jint*) (locals + index) += amount;
+ }
+ goto next_insn;
+
+ case op_i2l:
+ PUSHL ((jlong)POPI ());
+ goto next_insn;
+
+ case op_i2f:
+ PUSHF ((jfloat)POPI ());
+ goto next_insn;
+
+ case op_i2d:
+ PUSHD ((jdouble)POPI ());
+ goto next_insn;
+
+ case op_l2i:
+ PUSHI ((jint)POPL ());
+ goto next_insn;
+
+ case op_l2f:
+ PUSHF ((jfloat)POPL ());
+ goto next_insn;
+
+ case op_l2d:
+ PUSHD ((jdouble)POPL ());
+ goto next_insn;
+
+ case op_f2i:
+ PUSHI ((jint)POPF ());
+ goto next_insn;
+
+ case op_f2l:
+ PUSHL ((jlong)POPF ());
+ goto next_insn;
+
+ case op_f2d:
+ PUSHD ((jdouble)POPF ());
+ goto next_insn;
+
+ case op_d2i:
+ PUSHI ((jint)POPD ());
+ goto next_insn;
+
+ case op_d2l:
+ PUSHL ((jlong)POPD ());
+ goto next_insn;
+
+ case op_d2f:
+ PUSHF ((jfloat)POPD ());
+ goto next_insn;
+
+ case op_i2b:
+ PUSHI ((jbyte)POPI ());
+ goto next_insn;
+
+ case op_i2c:
+ PUSHI ((jchar)POPI ());
+ goto next_insn;
+
+ case op_i2s:
+ PUSHI ((jshort)POPI ());
+ goto next_insn;
+
+ case op_lcmp:
+ {
+ jlong value2 = POPL ();
+ jlong value1 = POPL ();
+ if (value1 > value2)
+ { PUSHI (1); }
+ else if (value1 == value2)
+ { PUSHI (0); }
+ else
+ { PUSHI (-1); }
+ }
+ goto next_insn;
+
+ case op_fcmpl:
+ case op_fcmpg:
+ {
+ jfloat value2 = POPF ();
+ jfloat value1 = POPF ();
+ if (value1 > value2)
+ PUSHI (1);
+ else if (value1 == value2)
+ PUSHI (0);
+ else if (value1 < value2)
+ PUSHI (-1);
+ else if (opcode == op_fcmpg)
+ PUSHI (1);
+ else
+ PUSHI (-1);
+ }
+ goto next_insn;
+
+ case op_dcmpl:
+ case op_dcmpg:
+ {
+ jdouble value2 = POPD ();
+ jdouble value1 = POPD ();
+ if (value1 > value2)
+ PUSHI (1);
+ else if (value1 == value2)
+ PUSHI (0);
+ else if (value1 < value2)
+ PUSHI (-1);
+ else if (opcode == op_dcmpg)
+ PUSHI (1);
+ else
+ PUSHI (-1);
+ }
+ goto next_insn;
+
+ case op_ifeq:
+ {
+ jint offset = get2s (pc);
+ if (POPI() == 0)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_ifne:
+ {
+ jint offset = get2s (pc);
+ if (POPI() != 0)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_iflt:
+ {
+ jint offset = get2s (pc);
+ if (POPI() < 0)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_ifge:
+ {
+ jint offset = get2s (pc);
+ if (POPI() >= 0)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_ifgt:
+ {
+ jint offset = get2s (pc);
+ if (POPI() > 0)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_ifle:
+ {
+ jint offset = get2s (pc);
+ if (POPI() <= 0)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_if_icmpeq:
+ {
+ jint offset = get2s (pc);
+ jint value2 = POPI();
+ jint value1 = POPI();
+ if (value1 == value2)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_if_icmpne:
+ {
+ jint offset = get2s (pc);
+ jint value2 = POPI();
+ jint value1 = POPI();
+ if (value1 != value2)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_if_icmplt:
+ {
+ jint offset = get2s (pc);
+ jint value2 = POPI();
+ jint value1 = POPI();
+ if (value1 < value2)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_if_icmpge:
+ {
+ jint offset = get2s (pc);
+ jint value2 = POPI();
+ jint value1 = POPI();
+ if (value1 >= value2)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_if_icmpgt:
+ {
+ jint offset = get2s (pc);
+ jint value2 = POPI();
+ jint value1 = POPI();
+ if (value1 > value2)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_if_icmple:
+ {
+ jint offset = get2s (pc);
+ jint value2 = POPI();
+ jint value1 = POPI();
+ if (value1 <= value2)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_if_acmpeq:
+ {
+ jint offset = get2s (pc);
+ jobject value2 = POPA();
+ jobject value1 = POPA();
+ if (value1 == value2)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_if_acmpne:
+ {
+ jint offset = get2s (pc);
+ jobject value2 = POPA();
+ jobject value1 = POPA();
+ if (value1 != value2)
+ pc = pc-1+offset;
+ else
+ pc = pc+2;
+ }
+ goto next_insn;
+
+ case op_goto:
+ {
+ jint offset = get2s (pc);
+ pc = pc-1+offset;
+ }
+ goto next_insn;
+
+ case op_jsr:
+ {
+ unsigned char *base_pc = pc-1;
+ jint offset = get2s (pc); pc += 2;
+ PUSHA ((jobject)pc);
+ pc = base_pc+offset;
+ }
+ goto next_insn;
+
+ case op_ret:
+ {
+ jint index = get1u (pc);
+ pc = (unsigned char*) PEEKA (index);
+ }
+ goto next_insn;
+
+ case op_tableswitch:
+ {
+ unsigned char *base_pc = pc-1;
+ int index = POPI();
+
+ unsigned char* base = bytecode ();
+ while ((pc-base) % 4 != 0)
+ pc++;
+
+ jint def = get4 (pc);
+ jint low = get4 (pc+4);
+ jint high = get4 (pc+8);
+
+ if (index < low || index > high)
+ pc = base_pc + def;
+ else
+ pc = base_pc + get4 (pc+4*(index-low+3));
+ }
+ goto next_insn;
+
+ case op_lookupswitch:
+ {
+ unsigned char *base_pc = pc-1;
+ int index = POPI();
+
+ unsigned char* base = bytecode ();
+ while ((pc-base) % 4 != 0)
+ pc++;
+
+ jint def = get4 (pc);
+ jint npairs = get4 (pc+4);
+
+ int max = npairs-1;
+ int min = 0;
+
+ // simple binary search...
+ while (min < max)
+ {
+ int half = (min+max)/2;
+ int match = get4 (pc+ 4*(2 + 2*half));
+
+ if (index == match)
+ min = max = half;
+
+ else if (index < match)
+ max = half-1;
+
+ else
+ min = half+1;
+ }
+
+ if (index == get4 (pc+ 4*(2 + 2*min)))
+ pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
+ else
+ pc = base_pc + def;
+ }
+ goto next_insn;
+
+ /* on return, just save the sp and return to caller */
+ case op_ireturn:
+ case op_lreturn:
+ case op_freturn:
+ case op_dreturn:
+ case op_areturn:
+ case op_return:
+ inv->sp = sp;
+ TIME_SUSPEND;
+ return;
+
+ case op_getstatic:
+ {
+ unsigned char *base_pc = pc-1;
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_ResolvePoolEntry (defining_class, fieldref_index);
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+
+ if ((field->flags & STATIC) == 0)
+ throw_incompatible_class_change_error
+ (JvNewStringLatin1 ("field no longer static"));
+
+ jclass type = field->type;
+
+ if (type->isPrimitive ())
+ {
+ switch (type->size_in_bytes)
+ {
+ case 1:
+ *base_pc = op_getstatic_1;
+ break;
+
+ case 2:
+ if (type == JvPrimClass (char))
+ *base_pc = op_getstatic_2u;
+ else
+ *base_pc = op_getstatic_2s;
+ break;
+
+ case 4:
+ *base_pc = op_getstatic_4;
+ break;
+
+ case 8:
+ *base_pc = op_getstatic_8;
+ break;
+ }
+ }
+ else
+ {
+ *base_pc = op_getstatic_a;
+ }
+
+ pc = base_pc;
+ }
+ goto next_insn;
+
+ case op_getfield:
+ {
+ unsigned char *base_pc = pc-1;
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_ResolvePoolEntry (defining_class, fieldref_index);
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+
+ if ((field->flags & STATIC) != 0)
+ throw_incompatible_class_change_error
+ (JvNewStringLatin1 ("field is static"));
+
+ jclass type = field->type;
+
+ if (type->isPrimitive ())
+ {
+ switch (type->size_in_bytes)
+ {
+ case 1:
+ *base_pc = op_getfield_1;
+ break;
+
+ case 2:
+ if (type == JvPrimClass (char))
+ *base_pc = op_getfield_2u;
+ else
+ *base_pc = op_getfield_2s;
+ break;
+
+ case 4:
+ *base_pc = op_getfield_4;
+ break;
+
+ case 8:
+ *base_pc = op_getfield_8;
+ break;
+ }
+ }
+ else
+ {
+ *base_pc = op_getfield_a;
+ }
+
+ if (field->u.boffset > 0xffff)
+ JvThrow (new java::lang::VirtualMachineError);
+
+ base_pc[1] = (field->u.boffset>>8) & 0xff;
+ base_pc[2] = field->u.boffset & 0xff;
+
+ pc = base_pc;
+ }
+ goto next_insn;
+
+ case op_putstatic:
+ {
+ unsigned char* base_pc = pc-1;
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_ResolvePoolEntry (defining_class, fieldref_index);
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+
+ jclass type = field->type;
+
+ // ResolvePoolEntry cannot check this
+ if ((field->flags & STATIC) == 0)
+ throw_incompatible_class_change_error
+ (JvNewStringLatin1 ("field no longer static"));
+
+ /* if this is patented, then maybe we could install
+ a function in the constant pool, to do the right thing */
+
+ if (type->isPrimitive ())
+ {
+ switch (type->size_in_bytes)
+ {
+ case 1:
+ *base_pc = op_putstatic_1;
+ break;
+
+ case 2:
+ *base_pc = op_putstatic_2;
+ break;
+
+ case 4:
+ *base_pc = op_putstatic_4;
+ break;
+
+ case 8:
+ *base_pc = op_putstatic_8;
+ break;
+ }
+ }
+ else
+ {
+ *base_pc = op_putstatic_a;
+ }
+
+ // do the instruction again!
+ pc = base_pc;
+ }
+ goto next_insn;
+
+
+ case op_putfield:
+ {
+ unsigned char* base_pc = pc-1;
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_ResolvePoolEntry (defining_class, fieldref_index);
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+
+ jclass type = field->type;
+
+ if ((field->flags & STATIC) != 0)
+ throw_incompatible_class_change_error
+ (JvNewStringLatin1 ("field is static"));
+
+ if (type->isPrimitive ())
+ {
+ switch (type->size_in_bytes)
+ {
+ case 1:
+ *base_pc = op_putfield_1;
+ break;
+
+ case 2:
+ *base_pc = op_putfield_2;
+ break;
+
+ case 4:
+ *base_pc = op_putfield_4;
+ break;
+
+ case 8:
+ *base_pc = op_putfield_8;
+ break;
+ }
+ }
+ else
+ {
+ *base_pc = op_putfield_a;
+ }
+
+ if (field->u.boffset > 0xffff)
+ JvThrow (new java::lang::VirtualMachineError);
+
+ base_pc[1] = (field->u.boffset>>8) & 0xff;
+ base_pc[2] = field->u.boffset & 0xff;
+
+ // do the instruction again!
+ pc = base_pc;
+ }
+ goto next_insn;
+
+
+ case op_getfield_1:
+ {
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ PUSHI (*(jbyte*) ((char*)obj + field_offset));
+ }
+ goto next_insn;
+
+ case op_getfield_2s:
+ {
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ PUSHI (*(jshort*) ((char*)obj + field_offset));
+ }
+ goto next_insn;
+
+ case op_getfield_2u:
+ {
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ PUSHI (*(jchar*) ((char*)obj + field_offset));
+ }
+ goto next_insn;
+
+ case op_getfield_8:
+ {
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ PUSHL(*(jlong*) ((char*)obj + field_offset));
+ }
+ goto next_insn;
+
+ case op_getstatic_1:
+ {
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ PUSHI (*(jbyte*) (field->u.addr));
+ }
+ goto next_insn;
+
+ case op_getstatic_2s:
+ {
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ PUSHI(*(jshort*) (field->u.addr));
+ }
+ goto next_insn;
+
+ case op_getstatic_2u:
+ {
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ PUSHI(*(jchar*) (field->u.addr));
+ }
+ goto next_insn;
+
+ case op_getstatic_4:
+ {
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ PUSHI(*(jint*) (field->u.addr));
+ }
+ goto next_insn;
+
+ case op_getstatic_8:
+ {
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ PUSHL(*(jlong*) (field->u.addr));
+ }
+ goto next_insn;
+
+ case op_getstatic_a:
+ {
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ PUSHA(*(jobject*) (field->u.addr));
+ }
+ goto next_insn;
+
+ case op_putfield_1:
+ {
+ jint value = POPI();
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ *(jbyte*) ((char*)obj + field_offset) = value;
+ }
+ goto next_insn;
+
+ case op_putfield_2:
+ {
+ jint value = POPI();
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ *(jchar*) ((char*)obj + field_offset) = value;
+ }
+ goto next_insn;
+
+ case op_putfield_4:
+ {
+ jint value = POPI();
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ *(jint*) ((char*)obj + field_offset) = value;
+ }
+ goto next_insn;
+
+ case op_putfield_8:
+ {
+ jlong value = POPL();
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ *(jlong*) ((char*)obj + field_offset) = value;
+ }
+ goto next_insn;
+
+ case op_putfield_a:
+ {
+ jobject value = POPA();
+ jobject obj = POPA();
+ NULLCHECK(obj);
+ jint field_offset = get2u (pc); pc += 2;
+ *(jobject*) ((char*)obj + field_offset) = value;
+ }
+ goto next_insn;
+
+ case op_putstatic_1:
+ {
+ jint value = POPI();
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ *(jbyte*) (field->u.addr) = value;
+ }
+ goto next_insn;
+
+ case op_putstatic_2:
+ {
+ jint value = POPI();
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ *(jchar*) (field->u.addr) = value;
+ }
+ goto next_insn;
+
+ case op_putstatic_4:
+ {
+ jint value = POPI();
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ *(jint*) (field->u.addr) = value;
+ }
+ goto next_insn;
+
+ case op_putstatic_8:
+ {
+ jlong value = POPL();
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ *(jlong*) (field->u.addr) = value;
+ }
+ goto next_insn;
+
+ case op_putstatic_a:
+ {
+ jobject value = POPA();
+ jint fieldref_index = get2u (pc); pc += 2;
+ _Jv_Field *field = (_Jv_Field*) pool_data[fieldref_index];
+ *(jobject*) (field->u.addr) = value;
+ }
+ goto next_insn;
+
+ case op_invokespecial:
+ {
+ int index = get2u (pc); pc += 2;
+
+ rmeth = (_Jv_ResolvedMethod*)
+ _Jv_ResolvePoolEntry (defining_class, index);
+
+ sp -= rmeth->stack_item_count;
+
+ NULLCHECK(sp[0]);
+
+ fun = (void (*) (...))rmeth->method->ncode;
+ }
+ goto perform_invoke;
+
+ case op_invokestatic:
+ {
+ int index = get2u (pc); pc += 2;
+
+ rmeth = (_Jv_ResolvedMethod*)
+ _Jv_ResolvePoolEntry (defining_class, index);
+
+ sp -= rmeth->stack_item_count;
+
+ _Jv_InitClass (rmeth->klass);
+ fun = (void (*) (...))rmeth->method->ncode;
+ }
+ goto perform_invoke;
+
+ case op_invokeinterface:
+ {
+ int index = get2u (pc); pc += 2;
+
+ // invokeinterface has two unused bytes...
+ pc += 2;
+
+ rmeth = (_Jv_ResolvedMethod*)
+ _Jv_ResolvePoolEntry (defining_class, index);
+
+ sp -= rmeth->stack_item_count;
+ NULLCHECK(sp[0]);
+
+ jobject rcv = (jobject)sp[0];
+
+ fun = (void (*) (...))
+ _Jv_LookupInterfaceMethod (rcv->getClass (),
+ rmeth->method->name,
+ rmeth->method->signature);
+ }
+ goto perform_invoke;
+
+
+ case op_new:
+ {
+ int index = get2u (pc); pc += 2;
+ jclass klass = (jclass) _Jv_ResolvePoolEntry (defining_class,
+ index);
+ _Jv_InitClass (klass);
+ jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
+ PUSHA (res);
+ }
+ goto next_insn;
+
+ case op_newarray:
+ {
+ int atype = get1u (pc++);
+ int size = POPI();
+ jobject result = _Jv_NewArray (atype, size);
+ PUSHA (result);
+ }
+ goto next_insn;
+
+ case op_anewarray:
+ {
+ int index = get2u (pc); pc += 2;
+ jclass klass = (jclass) _Jv_ResolvePoolEntry (defining_class, index);
+ int size = POPI();
+ _Jv_InitClass (klass);
+ jobject result = _Jv_NewObjectArray (size, klass, 0);
+ PUSHA (result);
+ }
+ goto next_insn;
+
+ case op_arraylength:
+ {
+ __JArray *arr = (__JArray*)POPA();
+ PUSHI (arr->length);
+ }
+ goto next_insn;
+
+ case op_athrow:
+ {
+ jobject value = POPA();
+ TIME_SUSPEND;
+ JvThrow (value);
+ }
+ goto next_insn;
+
+ case op_checkcast:
+ {
+ jobject value = POPA();
+ jint index = get2u (pc); pc += 2;
+ jclass to = (jclass)_Jv_ResolvePoolEntry (defining_class,
+ index);
+
+ if (value != NULL && ! to->isInstance (value))
+ {
+ TIME_SUSPEND;
+ JvThrow (new java::lang::ClassCastException
+ (to->getName()));
+ }
+
+ PUSHA (value);
+ }
+ goto next_insn;
+
+ case op_instanceof:
+ {
+ jobject value = POPA();
+ jint index = get2u (pc); pc += 2;
+ jclass to = (jclass)_Jv_ResolvePoolEntry (defining_class,
+ index);
+ PUSHI (to->isInstance (value));
+ }
+ goto next_insn;
+
+ case op_monitorenter:
+ {
+ jobject value = POPA();
+ NULLCHECK(value);
+ _Jv_MonitorEnter (value);
+ }
+ goto next_insn;
+
+ case op_monitorexit:
+ {
+ jobject value = POPA();
+ NULLCHECK(value);
+ _Jv_MonitorExit (value);
+ }
+ goto next_insn;
+
+ case op_ifnull:
+ {
+ unsigned char* base_pc = pc-1;
+ jint offset = get2s (pc); pc += 2;
+ jobject val = POPA();
+ if (val == NULL)
+ pc = base_pc+offset;
+ }
+ goto next_insn;
+
+ case op_ifnonnull:
+ {
+ unsigned char* base_pc = pc-1;
+ jint offset = get2s (pc); pc += 2;
+ jobject val = POPA();
+ if (val != NULL)
+ pc = base_pc+offset;
+ }
+ goto next_insn;
+
+ case op_wide:
+ {
+ jint the_mod_op = get1u (pc++);
+ jint wide = get2u (pc); pc += 2;
+
+ switch (the_mod_op)
+ {
+ case op_istore:
+ STOREI (wide);
+ goto next_insn;
+
+ case op_fstore:
+ STOREF (wide);
+ goto next_insn;
+
+ case op_astore:
+ STOREA (wide);
+ goto next_insn;
+
+ case op_lload:
+ LOADL (wide);
+ goto next_insn;
+
+ case op_dload:
+ LOADD (wide);
+ goto next_insn;
+
+ case op_iload:
+ LOADI (wide);
+ goto next_insn;
+
+ case op_aload:
+ LOADA (wide);
+ goto next_insn;
+
+ case op_lstore:
+ STOREL (wide);
+ goto next_insn;
+
+ case op_dstore:
+ STORED (wide);
+ goto next_insn;
+
+ case op_ret:
+ pc = (unsigned char*) PEEKA (wide);
+ goto next_insn;
+
+ case op_iinc:
+ {
+ jint amount = get2s (pc); pc += 2;
+ jint value = PEEKI (wide);
+ POKEI (wide, value+amount);
+ }
+ goto next_insn;
+
+ default:
+ throw_internal_error ("illegal bytecode modified by wide");
+ }
+
+ }
+
+ case op_multianewarray:
+ {
+ int kind_index = get2u (pc); pc += 2;
+ int dim = get1u (pc); pc += 1;
+
+ jclass type = (jclass) _Jv_ResolvePoolEntry (defining_class,
+ kind_index);
+ _Jv_InitClass (type);
+ jint *sizes = (jint*) alloca (sizeof (jint)*dim);
+
+ for (int i = dim - 1; i >= 0; i--)
+ {
+ sizes[i] = POPI ();
+ }
+
+ jobject res = _Jv_NewMultiArray (type,dim, sizes);
+
+ PUSHA (res);
+ }
+ goto next_insn;
+
+ case op_goto_w:
+ {
+ unsigned char* base_pc = pc-1;
+ int offset = get4 (pc); pc += 4;
+ pc = base_pc+offset;
+ }
+ goto next_insn;
+
+ case op_jsr_w:
+ {
+ unsigned char* base_pc = pc-1;
+ int offset = get4 (pc); pc += 4;
+ PUSHA((jobject)pc);
+ pc = base_pc+offset;
+ }
+ goto next_insn;
+
+ default:
+ throw_internal_error ("opcode not implemented");
+
+ }
+ goto next_insn;
+}
+
+
+static void
+throw_internal_error (char *msg)
+{
+ JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
+}
+
+static void
+throw_incompatible_class_change_error (jstring msg)
+{
+ JvThrow (new java::lang::IncompatibleClassChangeError (msg));
+}
+
+#if !HANDLE_SEGV
+static java::lang::NullPointerException *null_pointer_exc;
+static void
+throw_null_pointer_exception ()
+{
+ if (null_pointer_exc == NULL)
+ null_pointer_exc = new java::lang::NullPointerException;
+
+ JvThrow (null_pointer_exc);
+}
+#endif
+
+#if !HANDLE_FPE
+static java::lang::ArithmeticException *arithmetic_exc;
+static void
+throw_arithmetic_exception ()
+{
+ if (arithmetic_exc == NULL)
+ arithmetic_exc = new java::lang::ArithmeticException
+ (JvNewStringLatin1 ("/ by zero"));
+
+ JvThrow (arithmetic_exc);
+}
+#endif
+
+void
+jvdump(jobject o)
+{
+ _Jv_InterpMethod::dump_object(o);
+}
+
+/* FIXME: This is not finished! */
+void
+_Jv_InterpMethod::dump_object(jobject o)
+{
+ java::io::PrintStream *out = java::lang::System::out;
+
+ if (o == NULL)
+ {
+ out->println (JvNewStringLatin1 ("<null>"));
+ return;
+ }
+
+ jclass klass = o->getClass ();
+
+ out->print (klass->getName ());
+ out->print (JvNewStringLatin1 ("@0x"));
+ out->print (java::lang::Integer::toHexString ((jint)o));
+ out->print (JvNewStringLatin1 ("{"));
+#if 0
+ while (klass && klass != &ObjectClass)
+ {
+ _Jv_Field *fields = klass->fields;
+ int max = klass->field_count;
+
+ for (int i = 0; i < max; ++i)
+ {
+ out->print (_Jv_NewStringUTF (field->name->data));
+ out->print (JvNewStringLatin1 ("="));
+
+ if (JvFieldIsRef (field))
+ {
+ if (field->flags & STATIC)
+ out->print (JvGetSt)
+ }
+ field = field->getNextInstanceField ();
+
+ if (i+1 < max && klass->getSuperclass () != null)
+ out->print (JvNewStringLatin1 ("; "));
+ }
+
+ klass = klass->getSuperclass();
+ }
+#endif
+ out->print (JvNewStringLatin1 ("}\n"));
+
+}
+
+#endif // INTERPRETER
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index eb0a2f95..df55425 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -21,25 +21,30 @@ details. */
extern "C" void _Jv_InitClass (jclass klass);
extern "C" void _Jv_RegisterClasses (jclass *classes);
+// These are the possible values for the `state' field of the class
+// structure. Note that ordering is important here; in particular
+// `resolved' must come between `nothing' and the other states.
+// Whenever the state changes, one should notify all waiters of this
+// class.
+#define JV_STATE_NOTING 0 // set by compiler
+
+#define JV_STATE_PRELOADING 1 // can do _Jv_FindClass
+#define JV_STATE_LOADING 3 // has super installed
+#define JV_STATE_LOADED 5 // is complete
+
+#define JV_STATE_COMPILED 6 // this was a compiled class
+
+#define JV_STATE_PREPARED 7 // layout & static init done
+#define JV_STATE_LINKED 9 // strings interned
+
+#define JV_STATE_IN_PROGRESS 10 // <clinit> running
+#define JV_STATE_DONE 12 //
+
+#define JV_STATE_ERROR 14 // must be last
+
struct _Jv_Field;
struct _Jv_VTable;
-#define CONSTANT_Class 7
-#define CONSTANT_Fieldref 9
-#define CONSTANT_Methodref 10
-#define CONSTANT_InterfaceMethodref 11
-#define CONSTANT_String 8
-#define CONSTANT_Integer 3
-#define CONSTANT_Float 4
-#define CONSTANT_Long 5
-#define CONSTANT_Double 6
-#define CONSTANT_NameAndType 12
-#define CONSTANT_Utf8 1
-#define CONSTANT_Unicode 2
-#define CONSTANT_ResolvedFlag 16
-#define CONSTANT_ResolvedString (CONSTANT_String+CONSTANT_ResolvedFlag)
-#define CONSTANT_ResolvedClass (CONSTANT_Class+CONSTANT_ResolvedFlag)
-
struct _Jv_Constants
{
jint size;
@@ -134,9 +139,11 @@ public:
return size_in_bytes;
}
+ // finalization
+ void finalize ();
+
private:
void checkMemberAccess (jint flags);
- void resolveConstants (void);
// Various functions to handle class initialization.
java::lang::Throwable *hackTrampoline (jint, java::lang::Throwable *);
@@ -147,12 +154,6 @@ private:
friend _Jv_Method *_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
_Jv_Utf8Const *signature);
friend void _Jv_InitClass (jclass klass);
- friend void _Jv_RegisterClasses (jclass *classes);
- friend jclass _Jv_FindClassInCache (_Jv_Utf8Const *name,
- java::lang::ClassLoader *loader);
- friend jclass _Jv_FindArrayClass (jclass element);
- friend jclass _Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
- java::lang::ClassLoader *loader);
friend jfieldID JvGetFirstInstanceField (jclass);
friend jint JvNumInstanceFields (jclass);
@@ -165,6 +166,41 @@ private:
friend class _Jv_PrimClass;
+ // Friends classes and functions to implement the ClassLoader
+ friend class java::lang::ClassLoader;
+
+ friend void _Jv_WaitForState (jclass, int);
+ friend void _Jv_RegisterClasses (jclass *classes);
+ friend void _Jv_RegisterInitiatingLoader (jclass,java::lang::ClassLoader*);
+ friend void _Jv_UnregisterClass (jclass);
+ friend jclass _Jv_FindClass (_Jv_Utf8Const *name,
+ java::lang::ClassLoader *loader);
+ friend jclass _Jv_FindClassInCache (_Jv_Utf8Const *name,
+ java::lang::ClassLoader *loader);
+ friend jclass _Jv_FindArrayClass (jclass element,
+ java::lang::ClassLoader *loader);
+ friend jclass _Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
+ java::lang::ClassLoader *loader);
+
+ friend void _Jv_InternClassStrings (jclass);
+
+#ifdef INTERPRETER
+ friend jboolean _Jv_IsInterpretedClass (jclass);
+ friend void _Jv_InitField (jobject, jclass, _Jv_Field*);
+ friend _Jv_Method* _Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *,
+ _Jv_Utf8Const*);
+ friend int _Jv_DetermineVTableIndex (jclass, _Jv_Utf8Const *,
+ _Jv_Utf8Const*);
+ friend void _Jv_InitField (jobject, jclass, int);
+ friend void* _Jv_ResolvePoolEntry (jclass, int);
+ friend void _Jv_PrepareClass (jclass);
+
+ friend class _Jv_ClassReader;
+ friend class _Jv_InterpClass;
+ friend class _Jv_InterpMethod;
+ friend class _Jv_InterpMethodInvocation;
+#endif
+
#ifdef JV_MARKOBJ_DECL
friend JV_MARKOBJ_DECL;
#endif
diff --git a/libjava/java/lang/Class.java b/libjava/java/lang/Class.java
index 4ffccea..bc826e9 100644
--- a/libjava/java/lang/Class.java
+++ b/libjava/java/lang/Class.java
@@ -152,4 +152,7 @@ public final class Class implements Serializable
// Initialize the class.
private native void initializeClass ();
+
+ // finalization
+ protected native void finalize ();
}
diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java
index 048cea7..f0b533f 100644
--- a/libjava/java/lang/ClassLoader.java
+++ b/libjava/java/lang/ClassLoader.java
@@ -9,86 +9,394 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.lang;
+
import java.io.InputStream;
-import java.util.Hashtable;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Stack;
/**
- * @author Tom Tromey <tromey@cygnus.com>
- * @date October 28, 1998
+ * The class <code>ClassLoader</code> is intended to be subclassed by
+ * applications in order to describe new ways of loading classes,
+ * such as over the network.
+ *
+ * @author Kresten Krab Thorup
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* Status: Just a stub; not useful at all.
*/
-public abstract class ClassLoader
-{
- protected ClassLoader ()
- {
- cache = new Hashtable ();
- }
+public abstract class ClassLoader {
- protected final Class defineClass (String className, byte[] bytecode,
- int offset, int length)
- {
- throw new ClassFormatError ("defineClass unimplemented");
- }
+ static private ClassLoader system;
+
+ private static native ClassLoader getVMClassLoader0 ();
- protected final Class defineClass (byte[] bytecodes,
- int offset, int length)
- {
- return defineClass (null, bytecodes, offset, length);
- }
+ static public ClassLoader getSystemClassLoader () {
+ if (system == null)
+ system = getVMClassLoader0 ();
+ return system;
+ }
- protected final Class findLoadedClass (String className)
- {
- return (Class) cache.get(className);
- }
+ /**
+ * Creates a <code>ClassLoader</code>. The only thing this
+ * constructor does, is to call
+ * <code>checkCreateClassLoader</code> on the current
+ * security manager.
+ * @exception java.lang.SecurityException if not allowed
+ */
+ protected ClassLoader()
+ {
+ SecurityManager security = System.getSecurityManager ();
+ if (security != null)
+ security.checkCreateClassLoader ();
+ }
- protected final Class findSystemClass (String className)
- throws ClassNotFoundException
- {
- Class c = system.findLoadedClass(className);
- system.resolveClass(c);
- return c;
- }
+ /**
+ * Loads and link the class by the given name.
+ * @param name the name of the class.
+ * @return the class loaded.
+ * @see ClassLoader#loadClass(String,boolean)
+ * @exception java.lang.ClassNotFoundException
+ */
+ public Class loadClass(String name)
+ throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ {
+ return loadClass (name, true);
+ }
- // FIXME: Needs URL.
- // public URL getResource (String resName);
+ /**
+ * Loads the class by the given name.
+ * As per java 1.1, this has been deprecated. Use
+ * <code>loadClass(String)</code>
+ * instead.
+ * @param name the name of the class.
+ * @param link if the class should be linked.
+ * @return the class loaded.
+ * @exception java.lang.ClassNotFoundException
+ * @deprecated
+ */
+ protected abstract Class loadClass(String name, boolean link)
+ throws java.lang.ClassNotFoundException, java.lang.LinkageError;
- public InputStream getResourceAsStream (String resName)
- {
- return null;
- }
+ /**
+ * Defines a class, given the class-data. According to the JVM, this
+ * method should not be used; instead use the variant of this method
+ * in which the name of the class being defined is specified
+ * explicitly.
+ * <P>
+ * If the name of the class, as specified (implicitly) in the class
+ * data, denotes a class which has already been loaded by this class
+ * loader, an instance of
+ * <code>java.lang.ClassNotFoundException</code> will be thrown.
+ *
+ * @param data bytes in class file format.
+ * @param off offset to start interpreting data.
+ * @param len length of data in class file.
+ * @return the class defined.
+ * @exception java.lang.ClassNotFoundException
+ * @exception java.lang.LinkageError
+ * @see ClassLoader#defineClass(String,byte[],int,int) */
+ protected final Class defineClass(byte[] data, int off, int len)
+ throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ {
+ return defineClass (null, data, off, len);
+ }
- // FIXME: Needs URL.
- // public static final URL getSystemResource (String resName);
+ /**
+ * Defines a class, given the class-data. This is preferable
+ * over <code>defineClass(byte[],off,len)</code> since it is more
+ * secure. If the expected name does not match that of the class
+ * file, <code>ClassNotFoundException</code> is thrown. If
+ * <code>name</code> denotes the name of an already loaded class, a
+ * <code>LinkageError</code> is thrown.
+ * <p>
+ *
+ * FIXME: How do we assure that the class-file data is not being
+ * modified, simultaneously with the class loader running!? If this
+ * was done in some very clever way, it might break security.
+ * Right now I am thinking that defineclass should make sure never to
+ * read an element of this array more than once, and that that would
+ * assure the ``immutable'' appearance. It is still to be determined
+ * if this is in fact how defineClass operates.
+ *
+ * @param name the expected name.
+ * @param data bytes in class file format.
+ * @param off offset to start interpreting data.
+ * @param len length of data in class file.
+ * @return the class defined.
+ * @exception java.lang.ClassNotFoundException
+ * @exception java.lang.LinkageError
+ */
+ protected final synchronized Class defineClass(String name,
+ byte[] data,
+ int off,
+ int len)
+ throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ {
+ if (data==null || data.length < off+len || off<0 || len<0)
+ throw new ClassFormatError ("arguments to defineClass "
+ + "are meaningless");
- public static final InputStream getSystemResourceAsStream (String resName)
- {
- return null;
- }
+ // as per 5.3.5.1
+ if (name != null && findLoadedClass (name) != null)
+ throw new java.lang.LinkageError ("class "
+ + name
+ + " already loaded");
- protected abstract Class loadClass (String className, boolean resolve)
- throws ClassNotFoundException;
- public Class loadClass (String name) throws ClassNotFoundException
- {
- return loadClass (name, true);
- }
+ try {
+ // Since we're calling into native code here,
+ // we better make sure that any generated
+ // exception is to spec!
+
+ return defineClass0 (name, data, off, len);
+
+ } catch (java.lang.LinkageError x) {
+ throw x; // rethrow
+
+ } catch (java.lang.ClassNotFoundException x) {
+ throw x; // rethrow
+
+ } catch (java.lang.VirtualMachineError x) {
+ throw x; // rethrow
+
+ } catch (java.lang.Throwable x) {
+ // This should never happen, or we are beyond spec.
+
+ throw new InternalError ("Unexpected exception "
+ + "while defining class "
+ + name + ": "
+ + x.toString ());
+ }
+ }
+
+ /** This is the entry point of defineClass into the native code */
+ private native Class defineClass0 (String name,
+ byte[] data,
+ int off,
+ int len)
+ throws java.lang.ClassNotFoundException, java.lang.LinkageError;
- protected final void resolveClass (Class c)
- {
- // Nothing for now.
- }
- protected final void setSigners (Class cl, Object[] signers)
- {
- // Nothing for now.
+ /** This is called by defineClass0, once the "raw" and uninitialized
+ * class object has been created, and handles exceptions generated
+ * while actually defining the class (_Jv_DefineClass). defineClass0
+ * holds the lock on the new class object, so it needs to capture
+ * these exceptions. */
+
+ private static Throwable defineClass1 (Class klass, byte[] data,
+ int offset, int length)
+ {
+ try {
+ defineClass2 (klass, data, offset, length);
+ } catch (Throwable x) {
+ return x;
}
+ return null;
+ }
+
+ /** This is just a wrapper for _Jv_DefineClass */
+ private static native void defineClass2 (Class klass, byte[] data,
+ int offset, int length)
+ throws Throwable;
+
+ /**
+ * Link the given class. This will bring the class to a state where
+ * the class initializer can be run. Linking involves the following
+ * steps:
+ * <UL>
+ * <LI> Prepare (allocate and internalize) the constant strings that
+ * are used in this class.
+ * <LI> Allocate storage for static fields, and define the layout
+ * of instance fields.
+ * <LI> Perform static initialization of ``static final'' int,
+ * long, float, double and String fields for which there is a
+ * compile-time constant initializer.
+ * <LI> Create the internal representation of the ``vtable''.
+ * </UL>
+ * For <code>gcj</code>-compiled classes, only the first step is
+ * performed. The compiler will have done the rest already.
+ * <P>
+ * This is called by the system automatically,
+ * as part of class initialization; there is no reason to ever call
+ * this method directly.
+ * <P>
+ * For historical reasons, this method has a name which is easily
+ * misunderstood. Java classes are never ``resolved''. Classes are
+ * linked; whereas method and field references are resolved.
+ * <P>
+ * FIXME: The JDK documentation declares this method
+ * <code>final</code>, we declare it <code>static</code> -- any
+ * objections? This allows us to call it directly from native code
+ * with less hassle.
+ *
+ * @param clazz the class to link.
+ * @exception java.lang.LinkageError
+ */
+ protected static void resolveClass(Class clazz)
+ throws java.lang.LinkageError
+ {
+ synchronized (clazz)
+ {
+ try {
+ linkClass0 (clazz);
+ } catch (Throwable x) {
+ markClassErrorState0 (clazz);
+
+ if (x instanceof Error)
+ throw (Error)x;
+ else
+ throw new java.lang.InternalError
+ ("unexpected exception during linking: " + x);
+ }
+ }
+ }
+
+ /** Internal method. Calls _Jv_PrepareClass and
+ * _Jv_InternClassStrings. This is only called from resolveClass. */
+ private static native void linkClass0(Class clazz)
+ throws java.lang.LinkageError;
+
+ /** Internal method. Marks the given clazz to be in an erroneous
+ * state, and calls notifyAll() on the class object. This should only
+ * be called when the caller has the lock on the class object. */
+ private static native void markClassErrorState0(Class clazz);
+
+
+ /**
+ * Returns a class found in a system-specific way, typically
+ * via the <code>java.class.path</code> system property.
+ *
+ * @param name the class to resolve.
+ * @return the class loaded.
+ * @exception java.lang.LinkageError
+ * @exception java.lang.ClassNotFoundException
+ */
+ protected native static Class findSystemClass(String name)
+ throws java.lang.ClassNotFoundException, java.lang.LinkageError;
+
+ /*
+ * Does currently nothing.
+ */
+ protected final void setSigners(Class claz, Object[] signers) {
+ /* claz.setSigners (signers); */
+ }
+
+ /*
+ * If a class named <code>name</code> was previously loaded using
+ * this <code>ClassLoader</code>, then it is returned. Otherwise
+ * it returns <code>null</code>.
+ * @param name class to find.
+ * @return the class loaded, or null.
+ */
+ protected native Class findLoadedClass(String name);
- // Class cache.
- private Hashtable cache;
+ public static final InputStream getSystemResourceAsStream(String name) {
+ return system.getResourceAsStream (name);
+ }
- // The system class loader. FIXME: should have an actual value
- private static final ClassLoader system = null;
+ public static final URL getSystemResource(String name) {
+ return system.getResource (name);
+ }
+
+ public static final byte[] getSystemResourceAsBytes(String name) {
+ return system.getResourceAsBytes (name);
+ }
+
+ /**
+ * Return an InputStream representing the resource name.
+ * This is essentially like
+ * <code>getResource(name).openStream()</code>, except
+ * it masks out any IOException and returns null on failure.
+ * @param name resource to load
+ * @return an InputStream, or null
+ * @see java.lang.ClassLoader#getResource(String)
+ * @see java.lang.ClassLoader#getResourceAsBytes(String)
+ * @see java.io.InputStream
+ */
+ public InputStream getResourceAsStream(String name)
+ {
+ try {
+ URL res = getResource (name);
+ if (res == null) return null;
+ return res.openStream ();
+ } catch (java.io.IOException x) {
+ return null;
+ }
+ }
+
+ /**
+ * Return a byte array <code>byte[]</code> representing the
+ * resouce <code>name</code>. This only works for resources
+ * that have a known <code>content-length</code>, and
+ * it will block while loading the resource. Returns null
+ * for error conditions.<p>
+ * Since it is synchroneous, this is only convenient for
+ * resources that are "readily" available. System resources
+ * can conveniently be loaded this way, and the runtime
+ * system uses this to load class files. <p>
+ * To find the class data for a given class, use
+ * something like the following:
+ * <ul><code>
+ * String res = clazz.getName().replace ('.', '/')) + ".class";<br>
+ * byte[] data = getResourceAsBytes (res);
+ * </code></ul>
+ * @param name resource to load
+ * @return a byte array, or null
+ * @see java.lang.ClassLoader#getResource(String)
+ * @see java.lang.ClassLoader#getResourceAsStream(String)
+ */
+ public byte[] getResourceAsBytes(String name) {
+ try {
+ URL res = getResource (name);
+ if (res == null) return null;
+ URLConnection conn = res.openConnection ();
+ int len = conn.getContentLength ();
+ if (len == -1) return null;
+ return readbytes (conn.getInputStream (), len);
+ } catch (java.io.IOException x) {
+ return null;
+ }
+ }
+
+ /**
+ * Return an java.io.URL representing the resouce <code>name</code>.
+ * @param name resource to load
+ * @return a URL, or null if there is no such resource.
+ * @see java.lang.ClassLoader#getResourceAsBytes(String)
+ * @see java.lang.ClassLoader#getResourceAsStream(String)
+ * @see java.io.URL
+ */
+ public URL getResource(String name) {
+ return null;
+ }
+
+ /**
+ * Utility routine to read a resource fully, even if the given
+ * InputStream only provides partial results.
+ */
+ private static byte[] readbytes (InputStream is, int length)
+ {
+ try {
+
+ byte[] data = new byte[length];
+ int read;
+ int off = 0;
+
+ while (off != length)
+ {
+ read = is.read (data, off, (int) (length-off));
+
+ if (read == -1)
+ return null;
+
+ off += read;
+ }
+
+ return data;
+ } catch (java.io.IOException x) {
+ return null;
+ }
+ }
}
diff --git a/libjava/java/lang/FirstThread.java b/libjava/java/lang/FirstThread.java
index ec0f1db..0dd5c9c 100644
--- a/libjava/java/lang/FirstThread.java
+++ b/libjava/java/lang/FirstThread.java
@@ -19,12 +19,30 @@ package java.lang;
final class FirstThread extends Thread
{
- public native void run ();
+ public native void run0 ();
+ public void run ()
+ {
+ try {
+ run0 ();
+ } catch (Throwable ex) {
+ System.err.println ("uncaught exception at top level");
+ ex.printStackTrace ();
+ }
+ }
public FirstThread (ThreadGroup g, Class k, Object o)
{
super (g, null, "main");
klass = k;
+ klass_name = null;
+ args = o;
+ }
+
+ public FirstThread (ThreadGroup g, String class_name, Object o)
+ {
+ super (g, null, "main");
+ klass = null;
+ klass_name = class_name;
args = o;
}
@@ -36,5 +54,6 @@ final class FirstThread extends Thread
// Private data.
private Class klass;
+ private String klass_name;
private Object args;
}
diff --git a/libjava/java/lang/VMClassLoader.java b/libjava/java/lang/VMClassLoader.java
new file mode 100644
index 0000000..026f6d8
--- /dev/null
+++ b/libjava/java/lang/VMClassLoader.java
@@ -0,0 +1,117 @@
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+package java.lang;
+
+import java.io.*;
+import java.net.URL;
+import gnu.gcj.util.path.SearchPath;
+
+final class VMClassLoader extends java.lang.ClassLoader
+{
+ private SearchPath path;
+ private final String path_seperator;
+ private final String file_seperator;
+ private final char file_seperator_char;
+
+ private VMClassLoader () {
+ path_seperator = System.getProperty ("path.separator", ":");
+ file_seperator = System.getProperty ("file.separator", "/");
+
+ file_seperator_char = file_seperator.charAt (0);
+
+ String class_path = System.getProperty ("java.class.path", ".");
+ path = new SearchPath (class_path);
+ }
+
+ protected Class loadClass(String name,
+ boolean resolve)
+ throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ {
+ return loadClassInternal (name, resolve, false);
+ }
+
+ /** I'm a little in doubt here, if this method is
+ actually supposed to throw a LinkageError, or not.
+ The spec, 20.14.3, is a little unclear. It says:
+
+ `` The general contract of loadClass is that, given the name
+ of a class, it either returns the Class object for the class
+ or throws a ClassNotFoundException.''
+
+ However, by making LinkageError a checked exception,
+ i.e., mention it directly in the throws clause,
+ we'll force caller to consider that case as well.
+ **/
+
+ protected Class loadClassInternal(String name,
+ boolean resolve,
+ boolean fromBootLoader)
+ throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ {
+ Class clazz;
+
+ /** TODO: call _Jv_VerifyClassName **/
+ if ( (name.indexOf ('/') != -1)
+ || (name.charAt (0) == '.')
+ || (name.indexOf (file_seperator) != -1)
+ || (name.indexOf ("..") != -1))
+ {
+ throw new IllegalArgumentException (name);
+ }
+
+ // already loaded?
+ clazz = findLoadedClass (name);
+
+ // we need access to the boot class loader here
+ if (clazz == null && !fromBootLoader)
+ clazz = findBootClass (name);
+
+ if (clazz == null)
+ {
+ StringBuffer res = new StringBuffer ();
+
+ // here we do actually replace .'s with /'s because
+ // we're going to find something in the file system.
+ res.append (name.replace ('.', file_seperator_char));
+ res.append (".class");
+
+ byte[] data = getResourceAsBytes (res.toString ());
+
+ if (data == null)
+ throw new ClassNotFoundException (name);
+
+ clazz = defineClass (name, data, 0, data.length);
+
+ }
+
+ if (resolve && clazz != null)
+ resolveClass (clazz);
+
+ return clazz;
+ }
+
+ private native Class findBootClass (String name);
+
+ public InputStream getResourceAsStream(String name)
+ {
+ return path.getStream (name);
+ }
+
+ public URL getResource(String name)
+ {
+ return path.getURL (name);
+ }
+
+ public byte[] getResourceAsBytes(String name)
+ {
+ return path.getBytes (name);
+ }
+}
diff --git a/libjava/java/lang/VirtualMachineError.java b/libjava/java/lang/VirtualMachineError.java
index dcc907c..ee6d8e8 100644
--- a/libjava/java/lang/VirtualMachineError.java
+++ b/libjava/java/lang/VirtualMachineError.java
@@ -20,6 +20,11 @@ package java.lang;
* Status: Believed complete and correct.
*/
+/* FIXME: We should consider adding some special error message when this
+ * exception is thrown, or maybe if it being caught at top-level. Such
+ * a message would direct the user to send a bug report to
+ * gcj-bugs@cygnus.com, or something like that. --KKT */
+
public abstract class VirtualMachineError extends Error
{
public VirtualMachineError ()
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index 1768df5..367f14a 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -39,6 +39,8 @@ details. */
#include <java/lang/System.h>
#include <java/lang/SecurityManager.h>
+#include <java-cpool.h>
+
#define CloneableClass _CL_Q34java4lang9Cloneable
@@ -59,28 +61,6 @@ static _Jv_Utf8Const *void_signature = _Jv_makeUtf8Const ("()V", 3);
static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
-// These are the possible values for the `state' field. They more or
-// less follow the section numbers in the Java Language Spec. Right
-// now we don't bother to represent other interesting states, e.g. the
-// states a class might inhabit before it is prepared. Note that
-// ordering is important here; in particular `resolved' must come
-// between `nothing' and the other states.
-#define STATE_NOTHING 0
-#define STATE_RESOLVED 1
-#define STATE_IN_PROGRESS 6
-#define STATE_DONE 9
-#define STATE_ERROR 10
-
-// Size of local hash table.
-#define HASH_LEN 256
-
-// Hash function for Utf8Consts.
-#define HASH_UTF(Utf) (((Utf)->hash) % HASH_LEN)
-
-// This is the table we use to keep track of loaded classes. See Spec
-// section 12.2.
-static jclass loaded_classes[HASH_LEN];
-
jclass
@@ -111,6 +91,9 @@ java::lang::Class::forName (jstring className)
#endif
if (! klass)
JvThrow (new java::lang::ClassNotFoundException (className));
+
+ _Jv_InitClass (klass);
+
return klass;
}
@@ -380,33 +363,13 @@ java::lang::Class::newInstance (void)
return r;
}
-// Initialize the constants.
void
-java::lang::Class::resolveConstants (void)
+java::lang::Class::finalize (void)
{
- for (int i = 0; i < constants.size; ++i)
- {
- if (constants.tags[i] == CONSTANT_String)
- {
- jstring str;
- str = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) constants.data[i]);
- constants.data[i] = (void *) str;
- constants.tags[i] = CONSTANT_ResolvedString;
- }
- else if (constants.tags[i] == CONSTANT_Class)
- {
- _Jv_Utf8Const *name = (_Jv_Utf8Const *) constants.data[i];
- jclass klass = _Jv_FindClassFromSignature (name->data, loader);
- if (! klass)
- {
- jstring str = _Jv_NewStringUtf8Const (name);
- JvThrow (new java::lang::ClassNotFoundException (str));
- }
-
- constants.data[i] = (void *) klass;
- constants.tags[i] = CONSTANT_ResolvedClass;
- }
- }
+#ifdef INTERPRETER
+ JvAssert (_Jv_IsInterpretedClass (this));
+ _Jv_UnregisterClass (this);
+#endif
}
// FIXME.
@@ -424,38 +387,52 @@ void
java::lang::Class::initializeClass (void)
{
// Short-circuit to avoid needless locking.
- if (state == STATE_DONE)
+ if (state == JV_STATE_DONE)
return;
- // Step 1.
- _Jv_MonitorEnter (this);
+ // do this before we enter the monitor below, since this can cause
+ // exceptions. Here we assume, that reading "state" is an atomic
+ // operation, I pressume that is true? --Kresten
+ if (state < JV_STATE_LINKED)
+ {
+#ifdef INTERPRETER
+ if (_Jv_IsInterpretedClass (this))
+ {
+ java::lang::ClassLoader::resolveClass (this);
- // FIXME: This should actually be handled by calling into the class
- // loader. For now we put it here.
- if (state < STATE_RESOLVED)
+ // Step 1.
+ _Jv_MonitorEnter (this);
+ }
+ else
+#endif
+ {
+ // Step 1.
+ _Jv_MonitorEnter (this);
+ _Jv_InternClassStrings (this);
+ }
+ }
+ else
{
- // We set the state before calling resolveConstants to avoid
- // infinite recursion when processing String or Class.
- state = STATE_RESOLVED;
- resolveConstants ();
+ // Step 1.
+ _Jv_MonitorEnter (this);
}
// Step 2.
java::lang::Thread *self = java::lang::Thread::currentThread();
// FIXME: `self' can be null at startup. Hence this nasty trick.
self = (java::lang::Thread *) ((long) self | 1);
- while (state == STATE_IN_PROGRESS && thread && thread != self)
+ while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
wait ();
// Steps 3 & 4.
- if (state == STATE_DONE || state == STATE_IN_PROGRESS || thread == self)
+ if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS || thread == self)
{
_Jv_MonitorExit (this);
return;
}
// Step 5.
- if (state == STATE_ERROR)
+ if (state == JV_STATE_ERROR)
{
_Jv_MonitorExit (this);
JvThrow (new java::lang::NoClassDefFoundError);
@@ -463,7 +440,7 @@ java::lang::Class::initializeClass (void)
// Step 6.
thread = self;
- state = STATE_IN_PROGRESS;
+ state = JV_STATE_IN_PROGRESS;
_Jv_MonitorExit (this);
// Step 7.
@@ -477,7 +454,7 @@ java::lang::Class::initializeClass (void)
{
// Caught an exception.
_Jv_MonitorEnter (this);
- state = STATE_ERROR;
+ state = JV_STATE_ERROR;
notify ();
_Jv_MonitorExit (this);
JvThrow (except);
@@ -492,7 +469,7 @@ java::lang::Class::initializeClass (void)
if (! except)
{
_Jv_MonitorEnter (this);
- state = STATE_DONE;
+ state = JV_STATE_DONE;
}
else
{
@@ -503,7 +480,7 @@ java::lang::Class::initializeClass (void)
except = hackTrampoline(2, except);
}
_Jv_MonitorEnter (this);
- state = STATE_ERROR;
+ state = JV_STATE_ERROR;
}
notify ();
_Jv_MonitorExit (this);
@@ -530,6 +507,64 @@ _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
return NULL;
}
+#define MCACHE_SIZE 1013
+
+struct _Jv_mcache {
+ jclass klass;
+ _Jv_Method *method;
+};
+
+static _Jv_mcache method_cache[MCACHE_SIZE];
+static int method_cache_count;
+
+static void*
+_Jv_FindMethodInCache (jclass klass,
+ _Jv_Utf8Const *name,
+ _Jv_Utf8Const *signature)
+{
+ for (int index = name->hash % MCACHE_SIZE;
+ method_cache[index].klass != NULL;
+ index = (index+1) % MCACHE_SIZE)
+ {
+ _Jv_mcache *mc = (method_cache+index);
+ _Jv_Method *m = mc->method;
+
+ if (mc->klass == klass
+ && m != NULL // thread safe check
+ && _Jv_equalUtf8Consts (m->name, name)
+ && _Jv_equalUtf8Consts (m->signature, signature))
+ {
+ return mc->method->ncode;
+ }
+ }
+ return NULL;
+}
+
+static void
+_Jv_AddMethodToCache (jclass klass,
+ _Jv_Method *method)
+{
+ _Jv_MonitorEnter (&ClassClass);
+
+ if (method_cache_count > MCACHE_SIZE*2/3)
+ {
+ for (int i = 0; i < MCACHE_SIZE; i++)
+ method_cache[i].klass = 0;
+ }
+
+ for (int index = method->name->hash % MCACHE_SIZE;
+ method_cache[index].klass != NULL;
+ index = (index+1) % MCACHE_SIZE)
+ {
+ method_cache[index].method = method;
+ method_cache[index].klass = klass;
+ }
+
+ method_cache_count += 1;
+
+ _Jv_MonitorExit (&ClassClass);
+}
+
void *
_Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
_Jv_Utf8Const *signature)
@@ -539,6 +574,14 @@ _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
// call a method of a class until the class is linked. But this
// captures the general idea.
// klass->getClassLoader()->resolveClass(klass);
+ //
+ // KKT: This is unnessecary, exactly for the reason you present:
+ // _Jv_LookupInterfaceMethod is only called on object instances, and
+ // such have already been initialized (which includes resolving).
+
+ void *ncode = _Jv_FindMethodInCache (klass, name, signature);
+ if (ncode != 0)
+ return ncode;
for (; klass; klass = klass->getSuperclass())
{
@@ -553,6 +596,8 @@ _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
if (! java::lang::reflect::Modifier::isPublic(meth->accflags))
JvThrow (new java::lang::IllegalAccessError);
+ _Jv_AddMethodToCache (klass, meth);
+
return meth->ncode;
}
JvThrow (new java::lang::IncompatibleClassChangeError);
@@ -565,219 +610,6 @@ _Jv_InitClass (jclass klass)
klass->initializeClass();
}
-// This function is called many times during startup, before main() is
-// run. We do our runtime initialization here the very first time we
-// are called. At that point in time we know for certain we are
-// running single-threaded, so we don't need to lock when modifying
-// `init'. CLASSES is NULL-terminated.
-void
-_Jv_RegisterClasses (jclass *classes)
-{
- static bool init = false;
-
- if (! init)
- {
- init = true;
- _Jv_InitThreads ();
- _Jv_InitGC ();
- _Jv_InitializeSyncMutex ();
- }
-
- JvSynchronize sync (&ClassClass);
- for (; *classes; ++classes)
- {
- jclass klass = *classes;
- jint hash = HASH_UTF (klass->name);
- klass->next = loaded_classes[hash];
- loaded_classes[hash] = klass;
- }
-}
-
-void
-_Jv_RegisterClass (jclass klass)
-{
- jclass classes[2];
- classes[0] = klass;
- classes[1] = NULL;
- _Jv_RegisterClasses (classes);
-}
-
-jclass
-_Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
-{
- JvSynchronize sync (&ClassClass);
- jint hash = HASH_UTF (name);
- jclass klass;
- for (klass = loaded_classes[hash]; klass; klass = klass->next)
- {
- if (loader == klass->loader && _Jv_equalUtf8Consts (name, klass->name))
- break;
- }
- return klass;
-}
-
-#if 0
-jclass
-_Jv_FindClassInCache (jstring name, java::lang::ClassLoader *loader)
-{
- JvSynchronize sync (&ClassClass);
- jint hash = name->hashCode();
- jclass klass = loaded_classes[(_Jv_ushort) hash % HASH_LEN];
- for ( ; klass; klass = klass->next)
- {
- if (loader == klass->loader
- && _Jv_equalUtf8Consts (klass->name, name, hash))
- break;
- }
- return klass;
-}
-#endif
-
-jclass
-_Jv_FindClass (_Jv_Utf8Const* name, java::lang::ClassLoader *loader)
-{
- jclass klass = _Jv_FindClassInCache (name, loader);
- if (loader && ! klass)
- {
- klass = loader->loadClass(_Jv_NewStringUtf8Const (name));
- if (klass)
- _Jv_RegisterClass (klass);
- }
- return klass;
-}
-
-#if 0
-jclass
-_Jv_FindClass (jstring name, java::lang::ClassLoader *loader)
-{
- jclass klass = _Jv_FindClassInCache (name, loader);
- if (loader && ! klass)
- {
- klass = loader->loadClass(name);
- if (klass)
- _Jv_RegisterClass (klass);
- }
- return klass;
-}
-#endif
-
-jclass
-_Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
- java::lang::ClassLoader *loader)
-{
- jclass ret = (jclass) JvAllocObject (&ClassClass);
-
- ret->next = NULL;
- ret->name = name;
- ret->accflags = 0;
- ret->superclass = superclass;
- ret->constants.size = 0;
- ret->constants.tags = NULL;
- ret->constants.data = NULL;
- ret->methods = NULL;
- ret->method_count = 0;
- ret->vtable_method_count = 0;
- ret->fields = NULL;
- ret->size_in_bytes = 0;
- ret->field_count = 0;
- ret->static_field_count = 0;
- ret->vtable = NULL;
- ret->interfaces = NULL;
- ret->loader = loader;
- ret->interface_count = 0;
- ret->state = 0;
- ret->thread = NULL;
-
- _Jv_RegisterClass (ret);
-
- return ret;
-}
-
-jclass
-_Jv_FindArrayClass (jclass element)
-{
- _Jv_Utf8Const *array_name;
- int len;
- if (element->isPrimitive())
- {
- // For primitive types the array is cached in the class.
- jclass ret = (jclass) element->methods;
- if (ret)
- return ret;
- len = 3;
- }
- else
- len = element->name->length + 5;
-
- {
- char signature[len];
- int index = 0;
- signature[index++] = '[';
- // Compute name of array class to see if we've already cached it.
- if (element->isPrimitive())
- {
- signature[index++] = (char) element->method_count;
- }
- else
- {
- size_t length = element->name->length;
- const char *const name = element->name->data;
- if (name[0] != '[')
- signature[index++] = 'L';
- memcpy (&signature[index], name, length);
- index += length;
- if (name[0] != '[')
- signature[index++] = ';';
- }
- array_name = _Jv_makeUtf8Const (signature, index);
- }
-
- jclass array_class = _Jv_FindClassInCache (array_name, element->loader);
-
- if (! array_class)
- {
- // Create new array class.
- array_class = _Jv_NewClass (array_name, &ObjectClass, element->loader);
-
- // Note that `vtable_method_count' doesn't include the initial
- // NULL slot.
- int dm_count = ObjectClass.vtable_method_count + 1;
-
- // Create a new vtable by copying Object's vtable (except the
- // class pointer, of course). Note that we allocate this as
- // unscanned memory -- the vtables are handled specially by the
- // GC.
- int size = (sizeof (_Jv_VTable) +
- ((dm_count - 1) * sizeof (void *)));
- _Jv_VTable *vtable = (_Jv_VTable *) _Jv_AllocBytes (size);
- vtable->clas = array_class;
- memcpy (vtable->method, ObjectClass.vtable->method,
- dm_count * sizeof (void *));
- array_class->vtable = vtable;
- array_class->vtable_method_count = ObjectClass.vtable_method_count;
-
- // Stash the pointer to the element type.
- array_class->methods = (_Jv_Method *) element;
-
- // Register our interfaces.
- // FIXME: for JDK 1.2 we need Serializable.
- static jclass interfaces[] = { &CloneableClass };
- array_class->interfaces = interfaces;
- array_class->interface_count = 1;
-
- // FIXME: initialize other Class instance variables,
- // e.g. `fields'.
-
- array_class->state = STATE_DONE;
- }
-
- // For primitive types, point back at this array.
- if (element->isPrimitive())
- element->methods = (_Jv_Method *) array_class;
-
- return array_class;
-}
-
jboolean
_Jv_IsInstanceOf(jobject obj, jclass cl)
{
diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc
new file mode 100644
index 0000000..13452ec
--- /dev/null
+++ b/libjava/java/lang/natClassLoader.cc
@@ -0,0 +1,624 @@
+// natClassLoader.cc - Implementation of java.lang.ClassLoader native methods.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <cni.h>
+#include <jvm.h>
+#include <java/lang/Character.h>
+#include <java/lang/Thread.h>
+#include <java/lang/ClassLoader.h>
+#include <java/lang/VMClassLoader.h>
+#include <java/lang/InternalError.h>
+#include <java/lang/LinkageError.h>
+#include <java/lang/ClassFormatError.h>
+#include <java/lang/NoClassDefFoundError.h>
+#include <java/lang/ClassNotFoundException.h>
+#include <java/lang/ClassCircularityError.h>
+#include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/reflect/Modifier.h>
+
+#include <java-interp.h>
+
+#define CloneableClass _CL_Q34java4lang9Cloneable
+extern java::lang::Class CloneableClass;
+#define ObjectClass _CL_Q34java4lang6Object
+extern java::lang::Class ObjectClass;
+#define ClassClass _CL_Q34java4lang5Class
+extern java::lang::Class ClassClass;
+#define VMClassLoaderClass _CL_Q34java4lang17VMClassLoader
+extern java::lang::Class VMClassLoader;
+#define ClassLoaderClass _CL_Q34java4lang11ClassLoader
+extern java::lang::Class ClassLoaderClass;
+
+/////////// java.lang.ClassLoader native methods ////////////
+
+#ifdef INTERPRETER
+java::lang::VMClassLoader *redirect = 0;
+#endif
+
+java::lang::ClassLoader*
+java::lang::ClassLoader::getVMClassLoader0 ()
+{
+#ifdef INTERPRETER
+ if (redirect == 0)
+ redirect = new java::lang::VMClassLoader;
+ return redirect;
+#else
+ return 0;
+#endif
+}
+
+void
+java::lang::ClassLoader::defineClass2 (jclass klass, jbyteArray data,
+ jint offset, jint length)
+{
+#ifdef INTERPRETER
+ _Jv_DefineClass (klass, data, offset, length);
+#endif
+}
+
+java::lang::Class *
+java::lang::ClassLoader::defineClass0 (jstring name,
+ jbyteArray data,
+ jint offset,
+ jint length)
+{
+#ifdef INTERPRETER
+ jclass klass;
+ klass = (jclass) JvAllocObject (&ClassClass, sizeof (_Jv_InterpClass));
+
+ // synchronize on the class, so that it is not
+ // attempted initialized until we're done loading.
+ _Jv_MonitorEnter (klass);
+
+ // record which is the defining loader
+ klass->loader = this;
+
+ // register that we are the initiating loader...
+ if (name != 0)
+ {
+ _Jv_Utf8Const * name2 = _Jv_makeUtf8Const (name);
+
+ _Jv_VerifyClassName (name2);
+
+ klass->name = name2;
+ }
+
+ // this will do the magic. loadInto also operates
+ // as an exception trampoline for now...
+ Throwable *ex = defineClass1 (klass, data, offset, length);
+
+ if (ex) // we failed to load it
+ {
+ klass->state = JV_STATE_ERROR;
+ klass->notifyAll ();
+
+ _Jv_UnregisterClass (klass);
+
+ _Jv_MonitorExit (klass);
+
+ // FIXME: Here we may want to test that EX does
+ // indeed represent a valid exception. That is,
+ // anything but ClassNotFoundException,
+ // or some kind of Error.
+
+ JvThrow (ex);
+ }
+
+ // if everything proceeded sucessfully, we're loaded.
+ JvAssert (klass->state == JV_STATE_LOADED);
+
+ // if an exception is generated, this is initially missed.
+ // however, we come back here in handleException0 below...
+ _Jv_MonitorExit (klass);
+
+ return klass;
+
+#else // INTERPRETER
+
+ return 0;
+#endif
+}
+
+void
+_Jv_WaitForState (jclass klass, int state)
+{
+ if (klass->state >= state)
+ return;
+
+ _Jv_MonitorEnter (klass) ;
+
+ if (state == JV_STATE_LINKED)
+ {
+ _Jv_MonitorExit (klass);
+ _Jv_InternClassStrings (klass);
+ return;
+ }
+
+ java::lang::Thread *self = java::lang::Thread::currentThread();
+
+ // this is similar to the strategy for class initialization.
+ // if we already hold the lock, just leave.
+ while (klass->state <= state
+ && klass->thread
+ && klass->thread != self)
+ klass->wait ();
+
+ _Jv_MonitorExit (klass);
+
+ if (klass->state == JV_STATE_ERROR)
+ {
+ _Jv_Throw (new java::lang::LinkageError ());
+ }
+}
+
+// Finish linking a class. Only called from ClassLoader::resolveClass.
+void
+java::lang::ClassLoader::linkClass0 (java::lang::Class *klass)
+{
+ if (klass->state >= JV_STATE_LINKED)
+ return;
+
+#ifdef INTERPRETER
+ if (_Jv_IsInterpretedClass (klass))
+ {
+ _Jv_PrepareClass (klass);
+ }
+#endif
+
+ _Jv_InternClassStrings (klass);
+}
+
+void
+java::lang::ClassLoader::markClassErrorState0 (java::lang::Class *klass)
+{
+ klass->state = JV_STATE_ERROR;
+ klass->notifyAll ();
+}
+
+
+/** this is the only native method in VMClassLoader, so
+ we define it here. */
+jclass
+java::lang::VMClassLoader::findBootClass (jstring name)
+{
+ return _Jv_FindClassInCache (_Jv_makeUtf8Const (name), 0);
+}
+
+jclass
+java::lang::ClassLoader::findLoadedClass (jstring name)
+{
+ return _Jv_FindClassInCache (_Jv_makeUtf8Const (name), this);
+}
+
+jclass
+java::lang::ClassLoader::findSystemClass (jstring name)
+{
+ return _Jv_FindClass (_Jv_makeUtf8Const (name), 0);
+}
+
+
+/* This is the final step of linking, internalizing the constant strings
+ * of a class. This is called for both compiled and interpreted
+ * classes, and it is *only* called from ClassLoader::linkClass0,
+ * which is always in a context where the current thread has a lock on
+ * the class in question. We define it here, and not in resolve.cc, so that
+ * the entire resolve.cc can be #ifdef'ed away when not using the
+ * interpreter. */
+void
+_Jv_InternClassStrings(jclass klass)
+{
+ if (klass->state >= JV_STATE_LINKED)
+ return;
+
+ // short-circuit, so that mutually dependent classes are ok
+ klass->state = JV_STATE_LINKED;
+
+ _Jv_Constants *pool = &klass->constants;
+ for (int i = 1; i < pool->size; ++i)
+ {
+ if (pool->tags[i] == JV_CONSTANT_String)
+ {
+ jstring str;
+ str = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) pool->data[i]);
+ pool->data[i] = (void *) str;
+ pool->tags[i] |= JV_CONSTANT_ResolvedFlag;
+ }
+ }
+
+ klass->notifyAll ();
+}
+
+
+//
+// A single class can have many "initiating" class loaders,
+// and a single "defining" class loader. The Defining
+// class loader is what is returned from Class.getClassLoader()
+// and is used when loading dependent classes during resolution.
+// The set of initiating class loaders are used to ensure
+// safety of linking, and is maintained in the hash table
+// "initiated_classes". A defining classloader is by definition also
+// initiating, so we only store classes in this table, if they have more
+// than one class loader associated.
+//
+
+
+// Size of local hash table.
+#define HASH_LEN 1013
+
+// Hash function for Utf8Consts.
+#define HASH_UTF(Utf) (((Utf)->hash) % HASH_LEN)
+
+struct _Jv_LoaderInfo {
+ _Jv_LoaderInfo *next;
+ java::lang::Class *klass;
+ java::lang::ClassLoader *loader;
+};
+
+_Jv_LoaderInfo *initiated_classes[HASH_LEN];
+jclass loaded_classes[HASH_LEN];
+
+jclass
+_Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
+{
+ _Jv_MonitorEnter (&ClassClass);
+ jint hash = HASH_UTF (name);
+
+ // first, if LOADER is a defining loader, then it is also initiating
+ jclass klass;
+ for (klass = loaded_classes[hash]; klass; klass = klass->next)
+ {
+ if (loader == klass->loader && _Jv_equalUtf8Consts (name, klass->name))
+ break;
+ }
+
+ // otherwise, it may be that the class in question was defined
+ // by some other loader, but that the loading was initiated by
+ // the loader in question.
+ if (!klass)
+ {
+ _Jv_LoaderInfo *info;
+ for (info = initiated_classes[hash]; info; info = info->next)
+ {
+ if (loader == info->loader
+ && _Jv_equalUtf8Consts (name, info->klass->name))
+ {
+ klass = info->klass;
+ break;
+ }
+ }
+ }
+
+ _Jv_MonitorExit (&ClassClass);
+
+ return klass;
+}
+
+void
+_Jv_UnregisterClass (jclass the_class)
+{
+ _Jv_MonitorEnter (&ClassClass);
+ jint hash = HASH_UTF(the_class->name);
+
+ jclass *klass = &(loaded_classes[hash]);
+ for ( ; *klass; klass = &((*klass)->next))
+ {
+ if (*klass == the_class)
+ {
+ *klass = (*klass)->next;
+ break;
+ }
+ }
+
+ _Jv_LoaderInfo **info = &(initiated_classes[hash]);
+ for ( ; *info; info = &((*info)->next))
+ {
+ while ((*info)->klass == the_class)
+ {
+ *info = (*info)->next;
+ }
+ }
+
+ _Jv_MonitorExit (&ClassClass);
+}
+
+void
+_Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
+{
+ _Jv_LoaderInfo *info = new _Jv_LoaderInfo; // non-gc alloc!
+ jint hash = HASH_UTF(klass->name);
+
+ _Jv_MonitorEnter (&ClassClass);
+ info->loader = loader;
+ info->klass = klass;
+ info->next = initiated_classes[hash];
+ initiated_classes[hash] = info;
+ _Jv_MonitorExit (&ClassClass);
+
+}
+
+// This function is called many times during startup, before main() is
+// run. We do our runtime initialization here the very first time we
+// are called. At that point in time we know for certain we are
+// running single-threaded, so we don't need to lock when modifying
+// `init'. CLASSES is NULL-terminated.
+void
+_Jv_RegisterClasses (jclass *classes)
+{
+ static bool init = false;
+
+ if (! init)
+ {
+ init = true;
+ _Jv_InitThreads ();
+ _Jv_InitGC ();
+ _Jv_InitializeSyncMutex ();
+ }
+
+ JvSynchronize sync (&ClassClass);
+ for (; *classes; ++classes)
+ {
+ jclass klass = *classes;
+ jint hash = HASH_UTF (klass->name);
+ klass->next = loaded_classes[hash];
+ loaded_classes[hash] = klass;
+
+ // registering a compiled class causes
+ // it to be immediately "prepared".
+ if (klass->state == JV_STATE_NOTING)
+ klass->state = JV_STATE_COMPILED;
+ }
+}
+
+void
+_Jv_RegisterClass (jclass klass)
+{
+ jclass classes[2];
+ classes[0] = klass;
+ classes[1] = NULL;
+ _Jv_RegisterClasses (classes);
+}
+
+#if 0
+// NOTE: this one is out of date with the new loader stuff...
+jclass
+_Jv_FindClassInCache (jstring name, java::lang::ClassLoader *loader)
+{
+ JvSynchronize sync (&ClassClass);
+ jint hash = name->hashCode();
+ jclass klass = loaded_classes[(_Jv_ushort) hash % HASH_LEN];
+ for ( ; klass; klass = klass->next)
+ {
+ if (loader == klass->loader
+ && _Jv_equal (klass->name, name, hash))
+ break;
+ }
+ _Jv_MonitorExit (&ClassClass);
+ return klass;
+}
+#endif
+
+jclass _Jv_FindClass (_Jv_Utf8Const *name,
+ java::lang::ClassLoader *loader)
+{
+ jclass klass = _Jv_FindClassInCache (name, loader);
+
+#ifdef INTERPRETER
+ if (! klass)
+ {
+ jstring sname = _Jv_NewStringUTF (name->data);
+
+ if (loader)
+ {
+ // Load using a user-defined loader, jvmspec 5.3.2
+ klass = loader->loadClass(sname, false);
+
+ // if "loader" delegateted the loadClass operation
+ // to another loader, register explicitly
+ // that he is also an initiating loader of the
+ // given class.
+
+ if (klass && (klass->getClassLoader () != loader))
+ _Jv_RegisterInitiatingLoader (klass, 0);
+ }
+ else
+ {
+ if (redirect == NULL)
+ {
+ _Jv_InitClass (&ClassLoaderClass);
+ java::lang::ClassLoader::getSystemClassLoader ();
+ }
+
+ // Load using the bootstrap loader jmspec 5.3.1
+ klass = redirect -> loadClassInternal (sname, false, true);
+
+ // register that we're an initiating loader
+ if (klass)
+ {
+ _Jv_RegisterInitiatingLoader (klass, 0);
+ }
+ }
+ }
+ else
+ {
+ // we need classes to be in the hash while
+ // we're loading, so that they can refer to themselves.
+ _Jv_WaitForState (klass, JV_STATE_LOADED);
+ }
+#endif
+
+ return klass;
+}
+
+#if 0
+// NOTE: this one is out of date with the new class loader stuff...
+jclass
+_Jv_FindClass (jstring name, java::lang::ClassLoader *loader)
+{
+ jclass klass = _Jv_FindClassInCache (name, loader);
+ if (! klass)
+ {
+ if (loader)
+ {
+ klass = loader->loadClass(name);
+ }
+ else
+ {
+ // jmspec 5.3.1.2
+
+ // delegate to the system loader
+ klass = java::lang::ClassLoader::system.loadClass (sname);
+
+ // register that we're an initiating loader
+ if (klass)
+ _Jv_RegisterInitiatingLoader (klass, 0);
+ }
+ }
+ else
+ {
+ _Jv_WaitForState (klass, JV_STATE_LOADED);
+ }
+
+ return klass;
+}
+#endif
+
+jclass
+_Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
+ java::lang::ClassLoader *loader)
+{
+ jclass ret = (jclass) JvAllocObject (&ClassClass);
+
+ ret->next = NULL;
+ ret->name = name;
+ ret->accflags = 0;
+ ret->superclass = superclass;
+ ret->constants.size = 0;
+ ret->constants.tags = NULL;
+ ret->constants.data = NULL;
+ ret->methods = NULL;
+ ret->method_count = 0;
+ ret->vtable_method_count = 0;
+ ret->fields = NULL;
+ ret->size_in_bytes = 0;
+ ret->field_count = 0;
+ ret->static_field_count = 0;
+ ret->vtable = NULL;
+ ret->interfaces = NULL;
+ ret->loader = loader;
+ ret->interface_count = 0;
+ ret->state = 0;
+ ret->thread = NULL;
+
+ _Jv_RegisterClass (ret);
+
+ return ret;
+}
+
+jclass
+_Jv_FindArrayClass (jclass element, java::lang::ClassLoader *loader)
+{
+ _Jv_Utf8Const *array_name;
+ int len;
+ if (element->isPrimitive())
+ {
+ // For primitive types the array is cached in the class.
+ jclass ret = (jclass) element->methods;
+ if (ret)
+ return ret;
+ len = 3;
+ }
+ else
+ len = element->name->length + 5;
+
+ {
+ char signature[len];
+ int index = 0;
+ signature[index++] = '[';
+ // Compute name of array class to see if we've already cached it.
+ if (element->isPrimitive())
+ {
+ signature[index++] = (char) element->method_count;
+ }
+ else
+ {
+ size_t length = element->name->length;
+ const char *const name = element->name->data;
+ if (name[0] != '[')
+ signature[index++] = 'L';
+ memcpy (&signature[index], name, length);
+ index += length;
+ if (name[0] != '[')
+ signature[index++] = ';';
+ }
+ array_name = _Jv_makeUtf8Const (signature, index);
+ }
+
+ jclass array_class = _Jv_FindClassInCache (array_name, element->loader);
+
+ if (! array_class)
+ {
+ // Create new array class.
+ array_class = _Jv_NewClass (array_name, &ObjectClass, element->loader);
+
+ // Note that `vtable_method_count' doesn't include the initial
+ // NULL slot.
+ int dm_count = ObjectClass.vtable_method_count + 1;
+
+ // Create a new vtable by copying Object's vtable (except the
+ // class pointer, of course). Note that we allocate this as
+ // unscanned memory -- the vtables are handled specially by the
+ // GC.
+ int size = (sizeof (_Jv_VTable) +
+ ((dm_count - 1) * sizeof (void *)));
+ _Jv_VTable *vtable = (_Jv_VTable *) _Jv_AllocBytes (size);
+ vtable->clas = array_class;
+ memcpy (vtable->method, ObjectClass.vtable->method,
+ dm_count * sizeof (void *));
+ array_class->vtable = vtable;
+ array_class->vtable_method_count = ObjectClass.vtable_method_count;
+
+ // Stash the pointer to the element type.
+ array_class->methods = (_Jv_Method *) element;
+
+ // Register our interfaces.
+ // FIXME: for JDK 1.2 we need Serializable.
+ static jclass interfaces[] = { &CloneableClass };
+ array_class->interfaces = interfaces;
+ array_class->interface_count = 1;
+
+ // as per vmspec 5.3.3.2
+ array_class->accflags = element->accflags;
+
+ // FIXME: initialize other Class instance variables,
+ // e.g. `fields'.
+
+ // say this class is initialized and ready to go!
+ array_class->state = JV_STATE_DONE;
+
+ // vmspec, section 5.3.3 describes this
+ if (element->loader != loader)
+ _Jv_RegisterInitiatingLoader (array_class, loader);
+ }
+
+ // For primitive types, point back at this array.
+ if (element->isPrimitive())
+ element->methods = (_Jv_Method *) array_class;
+
+ return array_class;
+}
+
+
diff --git a/libjava/java/lang/natFirstThread.cc b/libjava/java/lang/natFirstThread.cc
index d47446b..319e487 100644
--- a/libjava/java/lang/natFirstThread.cc
+++ b/libjava/java/lang/natFirstThread.cc
@@ -27,7 +27,7 @@ details. */
typedef void main_func (jobject);
void
-java::lang::FirstThread::run (void)
+java::lang::FirstThread::run0 (void)
{
Utf8Const* main_signature = _Jv_makeUtf8Const ("([Ljava.lang.String;)V", 22);
Utf8Const* main_name = _Jv_makeUtf8Const ("main", 4);
@@ -41,6 +41,12 @@ java::lang::FirstThread::run (void)
DIE ("class must be public");
#endif
+ if (klass == NULL)
+ {
+ klass = java::lang::Class::forName (klass_name);
+ if (klass != NULL) _Jv_InitClass (klass);
+ }
+
_Jv_Method *meth = _Jv_GetMethodLocal (klass, main_name, main_signature);
// Some checks from Java Spec section 12.1.4.
diff --git a/libjava/java/lang/reflect/natArray.cc b/libjava/java/lang/reflect/natArray.cc
index 3da8b5c..2c951db 100644
--- a/libjava/java/lang/reflect/natArray.cc
+++ b/libjava/java/lang/reflect/natArray.cc
@@ -45,10 +45,11 @@ java::lang::reflect::Array::newInstance (jclass componentType, jintArray dimensi
if (ndims == 1)
return newInstance (componentType, dims[0]);
jclass arrayType = componentType;
- for (int i = 0; i < ndims; i++)
- arrayType = _Jv_FindArrayClass (arrayType);
- return _Jv_NewMultiArray (arrayType, ndims, dims);
+ for (int i = 0; i < ndims; i++) // FIXME 2nd arg should
+ // be "current" loader
+ arrayType = _Jv_FindArrayClass (arrayType, 0);
+ return _Jv_NewMultiArray (arrayType, ndims, dims);
}
jint
diff --git a/libjava/java/lang/reflect/natMethod.cc b/libjava/java/lang/reflect/natMethod.cc
index 720bbc3..a62d1ff 100644
--- a/libjava/java/lang/reflect/natMethod.cc
+++ b/libjava/java/lang/reflect/natMethod.cc
@@ -378,8 +378,10 @@ java::lang::reflect::Method::getType ()
while (*ptr != ';' && ptr[1] != '\0');
break;
}
+
+ // FIXME: 2'nd argument should be "current loader"
while (--num_arrays >= 0)
- type = _Jv_FindArrayClass (type);
+ type = _Jv_FindArrayClass (type, 0);
*argPtr++ = type;
}
parameter_types = args;
diff --git a/libjava/java/net/natPlainSocketImpl.cc b/libjava/java/net/natPlainSocketImpl.cc
index d42b821..e652ba7 100644
--- a/libjava/java/net/natPlainSocketImpl.cc
+++ b/libjava/java/net/natPlainSocketImpl.cc
@@ -354,7 +354,7 @@ java::net::PlainSocketImpl::getOption (jint optID)
if (l_val.l_onoff)
return new java::lang::Integer (l_val.l_linger);
else
- return new java::lang::Boolean (false);
+ return new java::lang::Boolean ((__java_boolean)false);
#else
JvThrow (new java::lang::InternalError (
JvNewStringUTF ("SO_LINGER not supported")));
diff --git a/libjava/libgcj.spec.in b/libjava/libgcj.spec.in
index a46acef..e9ee02d 100644
--- a/libjava/libgcj.spec.in
+++ b/libjava/libgcj.spec.in
@@ -4,7 +4,7 @@
# to link with libgcj.
#
%rename lib liborig
-*lib: -lgcj -lm @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(liborig)
+*lib: -lgcj -lm @INTERPSPEC@ @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(liborig)
%rename cc1 cc1orig
*cc1: @DIVIDESPEC@ %(cc1orig)
diff --git a/libjava/prims.cc b/libjava/prims.cc
index c26c299..90fd96d 100644
--- a/libjava/prims.cc
+++ b/libjava/prims.cc
@@ -180,6 +180,24 @@ _Jv_makeUtf8Const (char* s, int len)
return (m);
}
+_Jv_Utf8Const *
+_Jv_makeUtf8Const (jstring string)
+{
+ jint hash = string->hashCode ();
+ jint len = _Jv_GetStringUTFLength (string);
+
+ Utf8Const* m = (Utf8Const*)
+ _Jv_AllocBytesChecked (sizeof(Utf8Const) + len + 1);
+
+ m->hash = hash;
+ m->length = len;
+
+ _Jv_GetStringUTFRegion (string, 0, string->length (), m->data);
+ m->data[len] = 0;
+
+ return m;
+}
+
#ifdef DEBUG
@@ -298,7 +316,10 @@ _Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
JvThrow (no_memory);
size_t size = count * sizeof (jobject) + sizeof (__JArray);
- jclass clas = _Jv_FindArrayClass (elementClass);
+
+ // FIXME: second argument should be "current loader" //
+ jclass clas = _Jv_FindArrayClass (elementClass, 0);
+
jobjectArray obj = (jobjectArray) _Jv_AllocArray (size);
if (! obj)
JvThrow (no_memory);
@@ -338,7 +359,7 @@ _Jv_NewPrimArray (jclass eltype, jint count)
arr->length = count;
// Note that we assume we are given zeroed memory by the allocator.
- jclass klass = _Jv_FindArrayClass (eltype);
+ jclass klass = _Jv_FindArrayClass (eltype, 0);
// Set the vtbl last to avoid problems if the GC happens during the
// window in this function between the allocation and this
// assignment.
@@ -531,9 +552,11 @@ _Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader)
;
_Jv_Utf8Const *name = _Jv_makeUtf8Const (&sig[1], i - 1);
return _Jv_FindClass (name, loader);
+
}
case '[':
- return _Jv_FindArrayClass (_Jv_FindClassFromSignature (&sig[1], loader));
+ return _Jv_FindArrayClass (_Jv_FindClassFromSignature (&sig[1], loader),
+ loader);
}
JvFail ("couldn't understand class signature");
return NULL; // Placate compiler.
@@ -588,9 +611,20 @@ JvRunMain (jclass klass, int argc, const char **argv)
LTDL_SET_PRELOADED_SYMBOLS ();
#endif
- arg_vec = JvConvertArgv (argc - 1, argv + 1);
- main_group = new java::lang::ThreadGroup (23);
- main_thread = new java::lang::FirstThread (main_group, klass, arg_vec);
+ if (klass == NULL)
+ {
+ arg_vec = JvConvertArgv (argc - 2, argv + 2);
+ main_group = new java::lang::ThreadGroup (23);
+ main_thread = new java::lang::FirstThread (main_group,
+ JvNewStringLatin1 (argv[1]),
+ arg_vec);
+ }
+ else
+ {
+ arg_vec = JvConvertArgv (argc - 1, argv + 1);
+ main_group = new java::lang::ThreadGroup (23);
+ main_thread = new java::lang::FirstThread (main_group, klass, arg_vec);
+ }
main_thread->start();
_Jv_ThreadWait ();
@@ -598,6 +632,7 @@ JvRunMain (jclass klass, int argc, const char **argv)
java::lang::Runtime::getRuntime ()->exit (0);
}
+
void *
@@ -630,7 +665,7 @@ _Jv_divI (jint dividend, jint divisor)
if (divisor == 0)
_Jv_Throw (arithexception);
- if (dividend == 0x80000000L && divisor == -1)
+ if (dividend == (jint) 0x80000000L && divisor == -1)
return dividend;
return dividend / divisor;
@@ -642,7 +677,7 @@ _Jv_remI (jint dividend, jint divisor)
if (divisor == 0)
_Jv_Throw (arithexception);
- if (dividend == 0x80000000L && divisor == -1)
+ if (dividend == (jint) 0x80000000L && divisor == -1)
return 0;
return dividend % divisor;
@@ -654,7 +689,7 @@ _Jv_divJ (jlong dividend, jlong divisor)
if (divisor == 0)
_Jv_Throw (arithexception);
- if (dividend == 0x8000000000000000LL && divisor == -1)
+ if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
return dividend;
return dividend / divisor;
@@ -666,9 +701,15 @@ _Jv_remJ (jlong dividend, jlong divisor)
if (divisor == 0)
_Jv_Throw (arithexception);
- if (dividend == 0x8000000000000000LL && divisor == -1)
+ if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
return 0;
return dividend % divisor;
}
+
+
+
+
+
+
diff --git a/libjava/resolve.cc b/libjava/resolve.cc
new file mode 100644
index 0000000..a2d61c9
--- /dev/null
+++ b/libjava/resolve.cc
@@ -0,0 +1,1101 @@
+// resolve.cc - Code for linking and resolving classes and pool entries.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org> */
+
+#include <java-interp.h>
+
+#ifdef INTERPRETER
+
+#include <cni.h>
+#include <jvm.h>
+#include <string.h>
+#include <java-cpool.h>
+#include <java/lang/Class.h>
+#include <java/lang/String.h>
+#include <java/lang/Thread.h>
+#include <java/lang/InternalError.h>
+#include <java/lang/VirtualMachineError.h>
+#include <java/lang/NoSuchFieldError.h>
+#include <java/lang/ClassFormatError.h>
+#include <java/lang/IllegalAccessError.h>
+#include <java/lang/AbstractMethodError.h>
+#include <java/lang/ClassNotFoundException.h>
+#include <java/lang/IncompatibleClassChangeError.h>
+
+static void throw_internal_error (char *msg)
+ __attribute__ ((__noreturn__));
+static void throw_class_format_error (jstring msg)
+ __attribute__ ((__noreturn__));
+static void throw_class_format_error (char *msg)
+ __attribute__ ((__noreturn__));
+
+#define StringClass _CL_Q34java4lang6String
+extern java::lang::Class StringClass;
+#define ClassObject _CL_Q34java4lang6Object
+extern java::lang::Class ClassObject;
+#define ObjectClass _CL_Q34java4lang6Object
+extern java::lang::Class ObjectClass;
+
+
+static int get_alignment_from_class (jclass);
+
+static _Jv_ResolvedMethod*
+_Jv_BuildResolvedMethod (_Jv_Method*,
+ jclass,
+ jboolean,
+ jint);
+
+
+static const int PUBLIC = 0x001;
+static const int PRIVATE = 0x002;
+static const int PROTECTED = 0x004;
+static const int STATIC = 0x008;
+static const int FINAL = 0x010;
+static const int SYNCHRONIZED = 0x020;
+static const int VOLATILE = 0x040;
+static const int TRANSIENT = 0x080;
+static const int NATIVE = 0x100;
+static const int INTERFACE = 0x200;
+static const int ABSTRACT = 0x400;
+static const int ALL_FLAGS = 0x7FF;
+
+// We need to know the name of a constructor.
+static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
+
+static void throw_incompatible_class_change_error (jstring msg)
+{
+ JvThrow (new java::lang::IncompatibleClassChangeError (msg));
+}
+
+void*
+_Jv_ResolvePoolEntry (jclass klass, int index)
+{
+ _Jv_Constants *pool = &klass->constants;
+
+ if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
+ return pool->data[index];
+
+ switch (pool->tags[index]) {
+ case JV_CONSTANT_Class:
+ {
+ _Jv_Utf8Const *name = (_Jv_Utf8Const *) pool->data[index];
+
+ jclass found;
+ if (name->data[0] == '[')
+ found = _Jv_FindClassFromSignature (&name->data[0],
+ klass->loader);
+ else
+ found = _Jv_FindClass (name, klass->loader);
+
+ if (! found)
+ {
+ jstring str = _Jv_NewStringUTF (name->data);
+ JvThrow (new java::lang::ClassNotFoundException (str));
+ }
+
+ if ((found->accflags & PUBLIC) == PUBLIC
+ || (_Jv_ClassNameSamePackage (found->name,
+ klass->name)))
+ {
+ pool->data[index] = (void *) found;
+ pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+ }
+ else
+ {
+ JvThrow (new java::lang::IllegalAccessError (found->getName()));
+ }
+ }
+ break;
+
+ case JV_CONSTANT_String:
+ {
+ jstring str;
+ str = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) pool->data[index]);
+ pool->data[index] = (void *) str;
+ pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+ }
+ break;
+
+ case JV_CONSTANT_Fieldref:
+ {
+ _Jv_ushort class_index, name_and_type_index;
+ _Jv_loadIndexes ((const void**) &pool->data[index],
+ class_index,
+ name_and_type_index);
+ jclass owner = (jclass) _Jv_ResolvePoolEntry (klass, class_index);
+
+ if (owner != klass)
+ _Jv_InitClass (owner);
+
+ _Jv_ushort name_index, type_index;
+ _Jv_loadIndexes ((const void**) &pool->data[name_and_type_index],
+ name_index,
+ type_index);
+
+ _Jv_Utf8Const *field_name = (_Jv_Utf8Const*) pool->data[name_index];
+ _Jv_Utf8Const *field_type_name =
+ (_Jv_Utf8Const*) pool->data[type_index];
+
+ // FIXME: The implementation of this function
+ // (_Jv_FindClassFromSignature) will generate an instance of
+ // _Jv_Utf8Const for each call if the field type is a class name
+ // (Lxx.yy.Z;). This may be too expensive to do for each and
+ // every fieldref being resolved. For now, we fix the problem by
+ // only doing it when we have a loader different from the class
+ // declaring the field.
+
+ jclass field_type = 0;
+
+ if (owner->loader != klass->loader)
+ field_type = _Jv_FindClassFromSignature (field_type_name->data,
+ klass->loader);
+
+ _Jv_Field* the_field = 0;
+
+ for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ())
+ {
+ for (int i = 0; i < cls->field_count; i++)
+ {
+ _Jv_Field *field = &cls->fields[i];
+ if (! _Jv_equalUtf8Consts (field->name, field_name))
+ continue;
+
+ // now, check field access.
+
+ if ( (cls == klass)
+ || ((field->flags & PUBLIC) != 0)
+ || (((field->flags & PROTECTED) != 0)
+ && cls->isAssignableFrom (klass))
+ || (((field->flags & PRIVATE) == 0)
+ && _Jv_ClassNameSamePackage (cls->name,
+ klass->name)))
+ {
+ /* resove the field using the class' own loader
+ if necessary */
+
+ if (!field->isResolved ())
+ _Jv_ResolveField (field, cls->loader);
+
+ if (field_type != 0 && field->type != field_type)
+ JvThrow
+ (new java::lang::LinkageError
+ (JvNewStringLatin1
+ ("field type mismatch with different loaders")));
+
+ the_field = field;
+ goto end_of_field_search;
+ }
+ else
+ {
+ JvThrow (new java::lang::IllegalAccessError);
+ }
+ }
+ }
+
+ end_of_field_search:
+ if (the_field == 0)
+ {
+ jstring msg = JvNewStringLatin1 ("field ");
+ msg = msg->concat (owner->getName ());
+ msg = msg->concat (JvNewStringLatin1("."));
+ msg = msg->concat (_Jv_NewStringUTF (field_name->data));
+ msg = msg->concat (JvNewStringLatin1(" was not found."));
+ throw_incompatible_class_change_error (msg);
+ }
+
+ pool->data[index] = (void*)the_field;
+ pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+ }
+ break;
+
+ case JV_CONSTANT_Methodref:
+ case JV_CONSTANT_InterfaceMethodref:
+ {
+ _Jv_ushort class_index, name_and_type_index;
+ _Jv_loadIndexes ((const void**) &pool->data[index],
+ class_index,
+ name_and_type_index);
+ jclass owner = (jclass) _Jv_ResolvePoolEntry (klass, class_index);
+
+ if (owner != klass)
+ _Jv_InitClass (owner);
+
+ _Jv_ushort name_index, type_index;
+ _Jv_loadIndexes ((const void**) &pool->data[name_and_type_index],
+ name_index,
+ type_index);
+
+ _Jv_Utf8Const *method_name = (_Jv_Utf8Const*) pool->data[name_index];
+ _Jv_Utf8Const *method_signature =
+ (_Jv_Utf8Const*) pool->data[type_index];
+
+ int vtable_index = -1;
+ _Jv_Method *the_method = 0;
+ jclass found_class = 0;
+
+ // we make a loop here, because methods are allowed to be moved to
+ // a super class, and still be visible.. (binary compatibility).
+
+ for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ())
+ {
+ for (int i = 0; i < cls->method_count; i++)
+ {
+ _Jv_Method *method = &cls->methods[i];
+ if ( (!_Jv_equalUtf8Consts (method->name,
+ method_name))
+ || (!_Jv_equalUtf8Consts (method->signature,
+ method_signature)))
+ continue;
+
+ if (cls == klass
+ || ((method->accflags & PUBLIC) != 0)
+ || (((method->accflags & PROTECTED) != 0)
+ && cls->isAssignableFrom (klass))
+ || (((method->accflags & PRIVATE) == 0)
+ && _Jv_ClassNameSamePackage (cls->name,
+ klass->name)))
+ {
+ // FIXME: if (cls->loader != klass->loader), then we
+ // must actually check that the types of arguments
+ // correspond. That is, for each argument type, and
+ // the return type, doing _Jv_FindClassFromSignature
+ // with either loader should produce the same result,
+ // i.e., exactly the same jclass object. JVMS 5.4.3.3
+
+ the_method = method;
+ found_class = cls;
+
+
+ if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref)
+ vtable_index = -1;
+ else
+ vtable_index = _Jv_DetermineVTableIndex
+ (cls, method_name, method_signature);
+
+ if (vtable_index == 0)
+ throw_incompatible_class_change_error
+ (JvNewStringLatin1 ("method not found"));
+
+ goto end_of_method_search;
+ }
+ else
+ {
+ JvThrow (new java::lang::IllegalAccessError);
+ }
+ }
+ }
+
+ end_of_method_search:
+ if (the_method == 0)
+ {
+ jstring msg = JvNewStringLatin1 ("method ");
+ msg = msg->concat (owner->getName ());
+ msg = msg->concat (JvNewStringLatin1("."));
+ msg = msg->concat (_Jv_NewStringUTF (method_name->data));
+ msg = msg->concat (JvNewStringLatin1(" was not found."));
+ JvThrow(new java::lang::NoSuchFieldError (msg));
+ }
+
+ pool->data[index] = (void*)
+ _Jv_BuildResolvedMethod(the_method,
+ found_class,
+ ((the_method->accflags & STATIC) != 0),
+ vtable_index);
+ pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+ }
+ break;
+
+ }
+
+ return pool->data[index];
+}
+
+void
+_Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader)
+{
+ if (! field->isResolved ())
+ {
+ _Jv_Utf8Const *sig = (_Jv_Utf8Const*)field->type;
+ field->type = _Jv_FindClassFromSignature (sig->data, loader);
+ field->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG;
+ }
+}
+
+_Jv_Method*
+_Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
+ _Jv_Utf8Const *signature)
+{
+ for (; klass; klass = klass->getSuperclass())
+ {
+ _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
+
+ if (meth)
+ return meth;
+ }
+
+ return NULL;
+}
+
+/** FIXME: this is a terribly inefficient algorithm! It would improve
+ things if compiled classes to know vtable offset, and _Jv_Method had
+ a field for this.
+
+ Returns 0 if this class does not declare the given method.
+ Returns -1 if the given method does not appear in the vtable.
+ i.e., it is static, private, final or a constructor.
+ Otherwise, returns the vtable index. */
+int
+_Jv_DetermineVTableIndex (jclass klass,
+ _Jv_Utf8Const *name,
+ _Jv_Utf8Const *signature)
+{
+ jclass super_class = klass->getSuperclass ();
+
+ if (super_class != NULL)
+ {
+ int prev = _Jv_DetermineVTableIndex (super_class,
+ name,
+ signature);
+ if (prev != 0)
+ return prev;
+ }
+
+ /* at this point, we know that the super-class does not declare
+ * the method. Otherwise, the above call would have found it, and
+ * determined the result of this function (-1 or some positive
+ * number).
+ */
+
+ _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
+
+ /* now, if we do not declare this method, return zero */
+ if (meth == NULL)
+ return 0;
+
+ /* so now, we know not only that the super class does not declare the
+ * method, but we do! So, this is a first declaration of the method. */
+
+ /* now, the checks for things that are declared in this class, but do
+ * not go into the vtable. There are three cases.
+ * 1) the method is static, private or final
+ * 2) the class itself is final, or
+ * 3) it is the method <init>
+ */
+
+ if ( (meth->accflags & (STATIC|PRIVATE|FINAL)) != 0
+ || (klass->accflags & FINAL) != 0
+ || _Jv_equalUtf8Consts (name, init_name))
+ return -1;
+
+ /* reaching this point, we know for sure, that the method in question
+ * will be in the vtable. The question is where. */
+
+ /* the base offset, is where we will start assigning vtable
+ * indexes for this class. It is 1 for base classes
+ * (vtable->method[0] is unused), and for non-base classes it is the
+ * number of entries in the super class' vtable plus 1. */
+
+ int base_offset;
+ if (super_class == 0)
+ base_offset = 1;
+ else
+ base_offset = super_class->vtable_method_count+1;
+
+ /* we will consider methods 0..this_method_index-1. And for each one,
+ * determine if it is new (i.e., if it appears in the super class),
+ * and if it should go in the vtable. If so, increment base_offset */
+
+ int this_method_index = meth - (&klass->methods[0]);
+
+ for (int i = 0; i < this_method_index; i++)
+ {
+ _Jv_Method *m = &klass->methods[i];
+
+ /* fist some checks for things that surely do not go in the
+ * vtable */
+
+ if ((m->accflags & (STATIC|PRIVATE)) != 0)
+ continue;
+ if (_Jv_equalUtf8Consts (m->name, init_name))
+ continue;
+
+ /* Then, we need to know if this method appears in the
+ superclass. (This is where this function gets expensive) */
+ _Jv_Method *sm = _Jv_LookupDeclaredMethod (super_class,
+ m->name,
+ m->signature);
+
+ /* if it was somehow declared in the superclass, skip this */
+ if (sm != NULL)
+ continue;
+
+ /* but if it is final, and not declared in the super class,
+ * then we also skip it */
+ if ((m->accflags & FINAL) != 0)
+ continue;
+
+ /* finally, we can assign the index of this method */
+ /* m->vtable_index = base_offset */
+ base_offset += 1;
+ }
+
+ return base_offset;
+}
+
+/* this is installed in place of abstract methods */
+static void
+_Jv_abstractMethodError ()
+{
+ JvThrow (new java::lang::AbstractMethodError);
+}
+
+void
+_Jv_PrepareClass(jclass klass)
+{
+ /*
+ * The job of this function is to: 1) assign storage to fields, and 2)
+ * build the vtable. static fields are assigned real memory, instance
+ * fields are assigned offsets.
+ *
+ * NOTE: we have a contract with the garbage collector here. Static
+ * reference fields must not be resolved, until after they have storage
+ * assigned which is the check used by the collector to see if it
+ * should indirect the static field reference and mark the object
+ * pointed to.
+ *
+ * Most fields are resolved lazily (i.e. have their class-type
+ * assigned) when they are accessed the first time by calling as part
+ * of _Jv_ResolveField, which is allways called after _Jv_PrepareClass.
+ * Static fields with initializers are resolved as part of this
+ * function, as are fields with primitive types.
+ */
+
+ if (! _Jv_IsInterpretedClass (klass))
+ return;
+
+ if (klass->state >= JV_STATE_PREPARED)
+ return;
+
+ // make sure super-class is linked. This involves taking a lock on
+ // the super class, so we use the Java method resolveClass, which will
+ // unlock it properly, should an exception happen.
+
+ java::lang::ClassLoader::resolveClass (klass->superclass);
+
+ _Jv_InterpClass *clz = (_Jv_InterpClass*)klass;
+
+ /************ PART ONE: OBJECT LAYOUT ***************/
+
+ int instance_size;
+ int static_size;
+
+ // java.lang.Object is never interpreted!
+ instance_size = clz->superclass->size ();
+ static_size = 0;
+
+ for (int i = 0; i < clz->field_count; i++)
+ {
+ int field_size;
+ int field_align;
+
+ _Jv_Field *field = &clz->fields[i];
+
+ if (! field->isRef ())
+ {
+ // it's safe to resolve the field here, since it's
+ // a primitive class, which does not cause loading to happen.
+ _Jv_ResolveField (field, clz->loader);
+
+ field_size = field->type->size ();
+ field_align = get_alignment_from_class (field->type);
+ }
+ else
+ {
+ field_size = sizeof (jobject);
+ field_align = __alignof__ (jobject);
+ }
+
+#ifndef COMPACT_FIELDS
+ field->bsize = field_size;
+#endif
+
+ if (field->flags & STATIC)
+ {
+ /* this computes an offset into a region we'll allocate
+ shortly, and then add this offset to the start address */
+
+ static_size = ROUND (static_size, field_align);
+ field->u.boffset = static_size;
+ static_size += field_size;
+ }
+ else
+ {
+ instance_size = ROUND (instance_size, field_align);
+ field->u.boffset = instance_size;
+ instance_size += field_size;
+ }
+ }
+
+ // set the instance size for the class
+ clz->size_in_bytes = instance_size;
+
+ // allocate static memory
+ if (static_size != 0)
+ {
+ char *static_data = (char*)_Jv_AllocBytesChecked (static_size);
+
+ memset (static_data, 0, static_size);
+
+ for (int i = 0; i < clz->field_count; i++)
+ {
+ _Jv_Field *field = &clz->fields[i];
+
+ if ((field->flags & STATIC) != 0)
+ {
+ field->u.addr = static_data + field->u.boffset;
+
+ if (clz->field_initializers[i] != 0)
+ {
+ _Jv_ResolveField (field, clz->loader);
+ _Jv_InitField (0, clz, i);
+ }
+ }
+ }
+
+ // now we don't need the field_initializers anymore, so let the
+ // collector get rid of it!
+
+ clz->field_initializers = 0;
+ }
+
+ /************ PART TWO: VTABLE LAYOUT ***************/
+
+ /* preparation: build the vtable stubs (even interfaces can)
+ have code -- for static constructors. */
+ for (int i = 0; i < clz->method_count; i++)
+ {
+ _Jv_InterpMethod *imeth = clz->interpreted_methods[i];
+
+ if (imeth != 0) // it could be abstract or native
+ {
+ clz->methods[i].ncode = imeth->ncode ();
+ }
+ else
+ {
+ if ((clz->methods[i].accflags & NATIVE) != 0)
+ {
+ JvThrow
+ (new java::lang::VirtualMachineError
+ (JvNewStringLatin1
+ ("the interpreter does not support native methods")));
+ }
+ }
+ }
+
+ if (clz->accflags & INTERFACE)
+ {
+ clz->state = JV_STATE_PREPARED;
+ clz->notifyAll ();
+ return;
+ }
+
+ /* FIXME: native methods for interpreted classes should be handled, I
+ * dunno exactly how, but it seems that we should try to find them at
+ * this point, and if we fail, try again after <clinit>, since it
+ * could have caused additional code to be loaded. Interfaces cannot
+ * have native methods (not even for static initialization). */
+
+
+ /* Now onto the actual job: vtable layout. First, count how many new
+ methods we have */
+ int new_method_count = 0;
+
+ jclass super_class = clz->getSuperclass ();
+
+ if (super_class == 0)
+ throw_internal_error ("cannot handle interpreted base classes");
+
+ for (int i = 0; i < clz->method_count; i++)
+ {
+ _Jv_Method *this_meth = &clz->methods[i];
+
+ if ((this_meth->accflags & (STATIC|PRIVATE)) != 0
+ || _Jv_equalUtf8Consts (this_meth->name, init_name))
+ {
+ /* skip this, it doesn't go in the vtable */
+ continue;
+ }
+
+ _Jv_Method *orig_meth = _Jv_LookupDeclaredMethod (super_class,
+ this_meth->name,
+ this_meth->signature);
+
+ if (orig_meth == 0)
+ {
+ // new methods that are final, also don't go in the vtable
+ if ((this_meth->accflags & FINAL) != 0)
+ continue;
+
+ new_method_count += 1;
+ continue;
+ }
+
+ if ((orig_meth->accflags & (STATIC|PRIVATE|FINAL)) != 0
+ || ((orig_meth->accflags & ABSTRACT) == 0
+ && (this_meth->accflags & ABSTRACT) != 0
+ && (klass->accflags & ABSTRACT) == 0))
+ {
+ clz->state = JV_STATE_ERROR;
+ clz->notifyAll ();
+ JvThrow (new java::lang::IncompatibleClassChangeError
+ (clz->getName ()));
+ }
+
+ /* FIXME: At this point, if (loader != super_class->loader), we
+ * need to "impose class loader constraints" for the types
+ * involved in the signature of this method */
+ }
+
+ /* determine size */
+ int vtable_count = (super_class->vtable_method_count) + new_method_count;
+ clz->vtable_method_count = vtable_count;
+
+ /* allocate vtable structure */
+ _Jv_VTable *vtable = (_Jv_VTable*)
+ _Jv_AllocBytesChecked (sizeof (_Jv_VTable)
+ + (sizeof (void*) * (vtable_count)));
+ vtable->clas = clz;
+
+ /* copy super class' vtable entries (index 0 goes unused). */
+ memcpy ((void*)&vtable->method[1],
+ (void*)&super_class->vtable->method[1],
+ sizeof (void*) * super_class->vtable_method_count);
+
+ /* now, install our own vtable entries, reprise... */
+ for (int i = 0; i < clz->method_count; i++)
+ {
+ _Jv_Method *this_meth = &clz->methods[i];
+
+ int index = _Jv_DetermineVTableIndex (clz,
+ this_meth->name,
+ this_meth->signature);
+
+ if (index == 0)
+ throw_internal_error ("method now found in own class");
+
+ if (index != -1)
+ {
+ if (index > clz->vtable_method_count+1)
+ throw_internal_error ("vtable problem...");
+
+ if (clz->interpreted_methods[i] == 0)
+ vtable->method[index] = (void*)&_Jv_abstractMethodError;
+ else
+ vtable->method[index] = this_meth->ncode;
+ }
+ }
+
+ /* finally, assign the vtable! */
+ clz->vtable = vtable;
+
+ /* wooha! we're done. */
+ clz->state = JV_STATE_PREPARED;
+ clz->notifyAll ();
+}
+
+/** Do static initialization for fields with a constant initializer */
+void
+_Jv_InitField (jobject obj, jclass klass, int index)
+{
+ if (obj != 0 && klass == 0)
+ klass = obj->getClass ();
+
+ if (!_Jv_IsInterpretedClass (klass))
+ return;
+
+ _Jv_InterpClass *clz = (_Jv_InterpClass*)klass;
+
+ _Jv_Field * field = (&clz->fields[0]) + index;
+
+ if (index > clz->field_count)
+ throw_internal_error ("field out of range");
+
+ int init = clz->field_initializers[index];
+ if (init == 0)
+ return;
+
+ _Jv_Constants *pool = &clz->constants;
+ int tag = pool->tags[init];
+
+ if (! field->isResolved ())
+ throw_internal_error ("initializing unresolved field");
+
+ if (obj==0 && ((field->flags & STATIC) == 0))
+ throw_internal_error ("initializing non-static field with no object");
+
+ void *addr = 0;
+
+ if ((field->flags & STATIC) != 0)
+ addr = (void*) field->u.addr;
+ else
+ addr = (void*) (((char*)obj) + field->u.boffset);
+
+ switch (tag)
+ {
+ case JV_CONSTANT_String:
+ {
+ _Jv_MonitorEnter (clz);
+ jstring str;
+ str = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) pool->data[init]);
+ pool->data[init] = (void *) str;
+ pool->tags[init] = JV_CONSTANT_ResolvedString;
+ _Jv_MonitorExit (clz);
+ }
+ /* fall through */
+
+ case JV_CONSTANT_ResolvedString:
+ if (! (field->type == &StringClass || field->type == &ObjectClass))
+ throw_class_format_error ("string initialiser to non-string field");
+
+ *(jstring*)addr = *(jstring*) (pool->data + init);
+ break;
+
+ case JV_CONSTANT_Integer:
+ {
+ int value = *(jint*)(pool->data + init);
+
+ if (field->type == JvPrimClass (boolean))
+ *(jboolean*)addr = (jboolean)value;
+
+ else if (field->type == JvPrimClass (byte))
+ *(jbyte*)addr = (jbyte)value;
+
+ else if (field->type == JvPrimClass (char))
+ *(jchar*)addr = (jchar)value;
+
+ else if (field->type == JvPrimClass (short))
+ *(jshort*)addr = (jshort)value;
+
+ else if (field->type == JvPrimClass (int))
+ *(jint*)addr = (jint)value;
+
+ else
+ throw_class_format_error ("erroneous field initializer");
+ }
+ break;
+
+ case JV_CONSTANT_Long:
+ if (field->type != JvPrimClass (long))
+ throw_class_format_error ("erroneous field initializer");
+
+ memcpy (addr, pool->data+init, 8);
+ break;
+
+ case JV_CONSTANT_Float:
+ if (field->type != JvPrimClass (float))
+ throw_class_format_error ("erroneous field initializer");
+
+ memcpy (addr, pool->data+init, 4);
+ break;
+
+ case JV_CONSTANT_Double:
+ if (field->type != JvPrimClass (double))
+ throw_class_format_error ("erroneous field initializer");
+
+ memcpy (addr, pool->data+init, 8);
+ break;
+
+ default:
+ throw_class_format_error ("erroneous field initializer");
+ }
+}
+
+static int
+get_alignment_from_class (jclass klass)
+{
+ if (klass == JvPrimClass (byte))
+ return __alignof__ (jbyte);
+ else if (klass == JvPrimClass (short))
+ return __alignof__ (jshort);
+ else if (klass == JvPrimClass (int))
+ return __alignof__ (jint);
+ else if (klass == JvPrimClass (long))
+ return __alignof__ (jlong);
+ else if (klass == JvPrimClass (boolean))
+ return __alignof__ (jboolean);
+ else if (klass == JvPrimClass (char))
+ return __alignof__ (jchar);
+ else if (klass == JvPrimClass (float))
+ return __alignof__ (jfloat);
+ else if (klass == JvPrimClass (double))
+ return __alignof__ (jdouble);
+ else
+ return __alignof__ (jobject);
+}
+
+
+inline static unsigned char*
+skip_one_type (unsigned char* ptr)
+{
+ int ch = *ptr++;
+
+ while (ch == '[')
+ {
+ ch = *ptr++;
+ }
+
+ if (ch == 'L')
+ {
+ do { ch = *ptr++; } while (ch != ';');
+ }
+
+ return ptr;
+}
+
+static ffi_type*
+get_ffi_type_from_signature (unsigned char* ptr)
+{
+ switch (*ptr)
+ {
+ case 'L':
+ case '[':
+ return &ffi_type_pointer;
+ break;
+
+ case 'Z':
+ case 'B':
+ return &ffi_type_sint8;
+ break;
+
+ case 'C':
+ return &ffi_type_uint16;
+ break;
+
+ case 'S':
+ return &ffi_type_sint16;
+ break;
+
+ case 'I':
+ return &ffi_type_sint32;
+ break;
+
+ case 'J':
+ return &ffi_type_sint64;
+ break;
+
+ case 'F':
+ return &ffi_type_float;
+ break;
+
+ case 'D':
+ return &ffi_type_double;
+ break;
+
+ case 'V':
+ return &ffi_type_void;
+ break;
+ }
+
+ throw_internal_error ("unknown type in signature");
+}
+
+/* this function yields the number of actual arguments, that is, if the
+ * function is non-static, then one is added to the number of elements
+ * found in the signature */
+
+static int
+count_arguments (_Jv_Utf8Const *signature,
+ jboolean staticp)
+{
+ unsigned char *ptr = (unsigned char*) signature->data;
+ int arg_count = staticp ? 0 : 1;
+
+ /* first, count number of arguments */
+
+ // skip '('
+ ptr++;
+
+ // count args
+ while (*ptr != ')')
+ {
+ ptr = skip_one_type (ptr);
+ arg_count += 1;
+ }
+
+ return arg_count;
+}
+
+/* This beast will build a cif, given the signature. Memory for
+ * the cif itself and for the argument types must be allocated by the
+ * caller.
+ */
+
+static int
+init_cif (_Jv_Utf8Const* signature,
+ int arg_count,
+ jboolean staticp,
+ ffi_cif *cif,
+ ffi_type **arg_types)
+{
+ unsigned char *ptr = (unsigned char*) signature->data;
+
+ int arg_index = 0; // arg number
+ int item_count = 0; // stack-item count
+
+ // setup receiver
+ if (!staticp)
+ {
+ arg_types[arg_index++] = &ffi_type_pointer;
+ item_count += 1;
+ }
+
+ // skip '('
+ ptr++;
+
+ // assign arg types
+ while (*ptr != ')')
+ {
+ arg_types[arg_index++] = get_ffi_type_from_signature (ptr);
+
+ if (*ptr == 'J' || *ptr == 'D')
+ item_count += 2;
+ else
+ item_count += 1;
+
+ ptr = skip_one_type (ptr);
+ }
+
+ // skip ')'
+ ptr++;
+ ffi_type *rtype = get_ffi_type_from_signature (ptr);
+
+ ptr = skip_one_type (ptr);
+ if (ptr != (unsigned char*)signature->data + signature->length)
+ throw_internal_error ("did not find end of signature");
+
+ if (ffi_prep_cif (cif, FFI_DEFAULT_ABI,
+ arg_count, rtype, arg_types) != FFI_OK)
+ throw_internal_error ("ffi_prep_cif failed");
+
+ return item_count;
+}
+
+
+/* we put this one here, and not in interpret.cc because it
+ * calls the utility routines count_arguments
+ * which are static to this module. The following struct defines the
+ * layout we use for the stubs, it's only used in the ncode method. */
+
+typedef struct {
+ ffi_raw_closure closure;
+ ffi_cif cif;
+ ffi_type *arg_types[0];
+} ncode_closure;
+
+typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*);
+
+void* _Jv_InterpMethod::ncode ()
+{
+ if (self->ncode != 0)
+ return self->ncode;
+
+ jboolean staticp = (self->accflags & STATIC) != 0;
+ int arg_count = count_arguments (self->signature, staticp);
+
+ ncode_closure *closure =
+ (ncode_closure*)_Jv_AllocBytesChecked (sizeof (ncode_closure)
+ + arg_count * sizeof (ffi_type*));
+
+ init_cif (self->signature,
+ arg_count,
+ staticp,
+ &closure->cif,
+ &closure->arg_types[0]);
+
+ ffi_closure_fun fun;
+
+ args_raw_size = ffi_raw_size (&closure->cif);
+
+ if ((self->accflags & SYNCHRONIZED) != 0)
+ {
+ if (staticp)
+ fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+ else
+ fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object;
+ }
+ else
+ {
+ fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+ }
+
+ ffi_prep_raw_closure (&closure->closure,
+ &closure->cif,
+ fun,
+ (void*)this);
+
+ self->ncode = (void*)closure;
+ return self->ncode;
+}
+
+
+/* A _Jv_ResolvedMethod is what is put in the constant pool for a
+ * MethodRef or InterfacemethodRef. */
+static _Jv_ResolvedMethod*
+_Jv_BuildResolvedMethod (_Jv_Method* method,
+ jclass klass,
+ jboolean staticp,
+ jint vtable_index)
+{
+ int arg_count = count_arguments (method->signature, staticp);
+
+ _Jv_ResolvedMethod* result = (_Jv_ResolvedMethod*)
+ _Jv_AllocBytesChecked (sizeof (_Jv_ResolvedMethod)
+ + arg_count*sizeof (ffi_type*));
+
+ result->stack_item_count
+ = init_cif (method->signature,
+ arg_count,
+ staticp,
+ &result->cif,
+ &result->arg_types[0]);
+
+ result->vtable_index = vtable_index;
+ result->method = method;
+ result->klass = klass;
+
+ return result;
+}
+
+
+static void
+throw_class_format_error (jstring msg)
+{
+ if (msg == 0)
+ JvThrow (new java::lang::ClassFormatError);
+ else
+ JvThrow (new java::lang::ClassFormatError (msg));
+}
+
+static void
+throw_class_format_error (char *msg)
+{
+ throw_class_format_error (JvNewStringLatin1 (msg));
+}
+
+static void
+throw_internal_error (char *msg)
+{
+ JvThrow
+ (new java::lang::InternalError (JvNewStringLatin1 (msg)));
+}
+
+
+#endif
diff --git a/libjava/testsuite/Makefile.in b/libjava/testsuite/Makefile.in
index 139abea..ac2e92d 100644
--- a/libjava/testsuite/Makefile.in
+++ b/libjava/testsuite/Makefile.in
@@ -71,6 +71,7 @@ COMPPATH = @COMPPATH@
CPP = @CPP@
CXX = @CXX@
CXXCPP = @CXXCPP@
+DIVIDESPEC = @DIVIDESPEC@
DLLTOOL = @DLLTOOL@
EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
EXEEXT = @EXEEXT@
@@ -79,6 +80,7 @@ GCINCS = @GCINCS@
GCLIBS = @GCLIBS@
GCOBJS = @GCOBJS@
GCSPEC = @GCSPEC@
+INTERPSPEC = @INTERPSPEC@
LD = @LD@
LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@
LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@