* Merged gcj-abi-2-dev-branch to trunk.
(Actual changes too large to list in the commit message; see ChangeLog.) From-SVN: r91270
This commit is contained in:
+73
-66
@@ -42,13 +42,15 @@ enum
|
||||
|
||||
JV_STATE_PRELOADING = 1, // Can do _Jv_FindClass.
|
||||
JV_STATE_LOADING = 3, // Has super installed.
|
||||
JV_STATE_COMPILED = 5, // This was a compiled class.
|
||||
JV_STATE_READ = 4, // Has been completely defined.
|
||||
JV_STATE_LOADED = 5, // Has Miranda methods defined.
|
||||
|
||||
JV_STATE_COMPILED = 6, // This was a compiled class.
|
||||
|
||||
JV_STATE_LOADED = 6, // Is complete.
|
||||
JV_STATE_PREPARED = 7, // Layout & static init done.
|
||||
JV_STATE_LINKED = 9, // Strings interned.
|
||||
|
||||
JV_STATE_IN_PROGRESS = 10, // <Clinit> running.
|
||||
JV_STATE_IN_PROGRESS = 10, // <clinit> running.
|
||||
|
||||
JV_STATE_ERROR = 12,
|
||||
|
||||
@@ -59,6 +61,9 @@ struct _Jv_Field;
|
||||
struct _Jv_VTable;
|
||||
union _Jv_word;
|
||||
struct _Jv_ArrayVTable;
|
||||
class _Jv_ExecutionEngine;
|
||||
class _Jv_CompiledEngine;
|
||||
class _Jv_InterpreterEngine;
|
||||
|
||||
struct _Jv_Constants
|
||||
{
|
||||
@@ -106,7 +111,7 @@ union _Jv_IDispatchTable
|
||||
} iface;
|
||||
};
|
||||
|
||||
// Used by _Jv_GetInterfaces ()
|
||||
// Used by _Jv_Linker::get_interfaces ()
|
||||
struct _Jv_ifaces
|
||||
{
|
||||
jclass *list;
|
||||
@@ -139,6 +144,23 @@ struct _Jv_CatchClass
|
||||
_Jv_Utf8Const *classname;
|
||||
};
|
||||
|
||||
// Possible values for the assertion_code field in the type assertion table.
|
||||
enum
|
||||
{
|
||||
JV_ASSERT_END_OF_TABLE = 0,
|
||||
JV_ASSERT_TYPES_COMPATIBLE = 1,
|
||||
JV_ASSERT_IS_INSTANTIABLE = 2
|
||||
};
|
||||
|
||||
// Entry in the type assertion table, used to validate type constraints
|
||||
// for binary compatibility.
|
||||
struct _Jv_TypeAssertion
|
||||
{
|
||||
jint assertion_code;
|
||||
_Jv_Utf8Const *op1;
|
||||
_Jv_Utf8Const *op2;
|
||||
};
|
||||
|
||||
#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
|
||||
|
||||
#define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
|
||||
@@ -149,11 +171,11 @@ struct _Jv_CatchClass
|
||||
_Jv_Method *_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
|
||||
_Jv_Utf8Const *signature);
|
||||
jboolean _Jv_IsAssignableFrom (jclass, jclass);
|
||||
jboolean _Jv_IsAssignableFromSlow (jclass, jclass);
|
||||
jboolean _Jv_InterfaceAssignableFrom (jclass, jclass);
|
||||
void _Jv_InitClass (jclass klass);
|
||||
|
||||
_Jv_Method* _Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *,
|
||||
_Jv_Utf8Const*);
|
||||
_Jv_Utf8Const*, jclass * = NULL);
|
||||
jfieldID JvGetFirstInstanceField (jclass);
|
||||
jint JvNumInstanceFields (jclass);
|
||||
jfieldID JvGetFirstStaticField (jclass);
|
||||
@@ -183,10 +205,6 @@ class java::io::ObjectOutputStream;
|
||||
class java::io::ObjectInputStream;
|
||||
class java::io::ObjectStreamClass;
|
||||
|
||||
void _Jv_WaitForState (jclass, int);
|
||||
void _Jv_RegisterClasses (const jclass *classes);
|
||||
void _Jv_RegisterClasses_Counted (const jclass *classes,
|
||||
size_t count);
|
||||
void _Jv_RegisterClassHookDefault (jclass klass);
|
||||
void _Jv_RegisterInitiatingLoader (jclass,java::lang::ClassLoader*);
|
||||
void _Jv_UnregisterClass (jclass);
|
||||
@@ -205,19 +223,7 @@ void _Jv_InitNewClassFields (jclass klass);
|
||||
|
||||
// Friend functions and classes in prims.cc
|
||||
void _Jv_InitPrimClass (jclass, char *, char, int);
|
||||
void _Jv_PrepareCompiledClass (jclass);
|
||||
void _Jv_PrepareConstantTimeTables (jclass);
|
||||
jshort _Jv_GetInterfaces (jclass, _Jv_ifaces *);
|
||||
void _Jv_GenerateITable (jclass, _Jv_ifaces *, jshort *);
|
||||
jstring _Jv_GetMethodString (jclass, _Jv_Utf8Const *);
|
||||
jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort);
|
||||
jshort _Jv_FindIIndex (jclass *, jshort *, jshort);
|
||||
void _Jv_LinkSymbolTable (jclass);
|
||||
void _Jv_LayoutInterfaceMethods (jclass);
|
||||
void _Jv_LayoutVTableMethods (jclass klass);
|
||||
void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
|
||||
void _Jv_MakeVTable (jclass);
|
||||
void _Jv_linkExceptionClassTable (jclass);
|
||||
|
||||
jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
|
||||
jint flags);
|
||||
@@ -225,25 +231,14 @@ jclass _Jv_GetArrayClass (jclass klass, java::lang::ClassLoader *loader);
|
||||
|
||||
#ifdef INTERPRETER
|
||||
jboolean _Jv_IsInterpretedClass (jclass);
|
||||
void _Jv_InitField (jobject, jclass, _Jv_Field*);
|
||||
void _Jv_InitField (jobject, jclass, int);
|
||||
_Jv_word _Jv_ResolvePoolEntry (jclass, int);
|
||||
_Jv_Method *_Jv_SearchMethodInClass (jclass cls, jclass klass,
|
||||
_Jv_Utf8Const *method_name,
|
||||
_Jv_Utf8Const *method_signature);
|
||||
|
||||
void _Jv_PrepareClass (jclass);
|
||||
void _Jv_PrepareMissingMethods (jclass base, jclass iface_class);
|
||||
|
||||
void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
|
||||
|
||||
class _Jv_ClassReader;
|
||||
class _Jv_InterpClass;
|
||||
class _Jv_InterpMethod;
|
||||
#endif
|
||||
|
||||
class _Jv_BytecodeVerifier;
|
||||
class _Jv_StackTrace;
|
||||
class gnu::gcj::runtime::StackTrace;
|
||||
class java::io::VMObjectStreamClass;
|
||||
|
||||
@@ -316,9 +311,14 @@ public:
|
||||
void setSigners(JArray<jobject> *);
|
||||
|
||||
inline jclass getSuperclass (void)
|
||||
{
|
||||
return superclass;
|
||||
}
|
||||
{
|
||||
return superclass;
|
||||
}
|
||||
|
||||
inline jclass getInterface (jint n)
|
||||
{
|
||||
return interfaces[n];
|
||||
}
|
||||
|
||||
inline jboolean isArray (void)
|
||||
{
|
||||
@@ -351,9 +351,16 @@ public:
|
||||
|
||||
// FIXME: this probably shouldn't be public.
|
||||
jint size (void)
|
||||
{
|
||||
return size_in_bytes;
|
||||
}
|
||||
{
|
||||
return size_in_bytes;
|
||||
}
|
||||
|
||||
// The index of the first method we declare ourself (as opposed to
|
||||
// inheriting).
|
||||
inline jint firstMethodIndex (void)
|
||||
{
|
||||
return vtable_method_count - method_count;
|
||||
}
|
||||
|
||||
// finalization
|
||||
void finalize ();
|
||||
@@ -372,10 +379,17 @@ private:
|
||||
|
||||
static jstring getPackagePortion (jstring);
|
||||
|
||||
void set_state (jint nstate)
|
||||
{
|
||||
state = nstate;
|
||||
notifyAll ();
|
||||
}
|
||||
|
||||
// Friend functions implemented in natClass.cc.
|
||||
friend _Jv_Method *::_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
|
||||
_Jv_Utf8Const *signature);
|
||||
friend jboolean (::_Jv_IsAssignableFrom) (jclass, jclass);
|
||||
friend jboolean (::_Jv_IsAssignableFromSlow) (jclass, jclass);
|
||||
friend jboolean (::_Jv_InterfaceAssignableFrom) (jclass, jclass);
|
||||
friend void *::_Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface,
|
||||
int method_idx);
|
||||
@@ -383,7 +397,7 @@ private:
|
||||
friend void ::_Jv_InitClass (jclass klass);
|
||||
|
||||
friend _Jv_Method* ::_Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *,
|
||||
_Jv_Utf8Const*);
|
||||
_Jv_Utf8Const*, jclass *);
|
||||
friend jfieldID (::JvGetFirstInstanceField) (jclass);
|
||||
friend jint (::JvNumInstanceFields) (jclass);
|
||||
friend jfieldID (::JvGetFirstStaticField) (jclass);
|
||||
@@ -413,7 +427,6 @@ private:
|
||||
friend class java::io::ObjectInputStream;
|
||||
friend class java::io::ObjectStreamClass;
|
||||
|
||||
friend void ::_Jv_WaitForState (jclass, int);
|
||||
friend void ::_Jv_RegisterClasses (const jclass *classes);
|
||||
friend void ::_Jv_RegisterClasses_Counted (const jclass *classes,
|
||||
size_t count);
|
||||
@@ -436,40 +449,22 @@ private:
|
||||
// in prims.cc
|
||||
friend void ::_Jv_InitPrimClass (jclass, char *, char, int);
|
||||
|
||||
friend void ::_Jv_PrepareCompiledClass (jclass);
|
||||
friend void ::_Jv_PrepareConstantTimeTables (jclass);
|
||||
friend jshort (::_Jv_GetInterfaces) (jclass, _Jv_ifaces *);
|
||||
friend void ::_Jv_GenerateITable (jclass, _Jv_ifaces *, jshort *);
|
||||
friend jstring (::_Jv_GetMethodString) (jclass, _Jv_Utf8Const *);
|
||||
friend jshort (::_Jv_AppendPartialITable) (jclass, jclass, void **, jshort);
|
||||
friend jshort (::_Jv_FindIIndex) (jclass *, jshort *, jshort);
|
||||
friend void ::_Jv_LinkSymbolTable (jclass);
|
||||
friend void ::_Jv_LayoutInterfaceMethods (jclass);
|
||||
friend void ::_Jv_LayoutVTableMethods (jclass klass);
|
||||
friend void ::_Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
|
||||
friend void ::_Jv_MakeVTable (jclass);
|
||||
friend void ::_Jv_linkExceptionClassTable (jclass);
|
||||
|
||||
friend jboolean (::_Jv_CheckAccess) (jclass self_klass, jclass other_klass,
|
||||
jint flags);
|
||||
|
||||
friend bool _Jv_getInterfaceMethod(jclass, jclass&, int&,
|
||||
const _Jv_Utf8Const*,
|
||||
const _Jv_Utf8Const*);
|
||||
|
||||
friend jclass (::_Jv_GetArrayClass) (jclass klass,
|
||||
java::lang::ClassLoader *loader);
|
||||
|
||||
#ifdef INTERPRETER
|
||||
friend jboolean (::_Jv_IsInterpretedClass) (jclass);
|
||||
friend void ::_Jv_InitField (jobject, jclass, _Jv_Field*);
|
||||
friend void ::_Jv_InitField (jobject, jclass, int);
|
||||
friend _Jv_word (::_Jv_ResolvePoolEntry) (jclass, int);
|
||||
friend _Jv_Method *::_Jv_SearchMethodInClass (jclass cls, jclass klass,
|
||||
_Jv_Utf8Const *method_name,
|
||||
_Jv_Utf8Const *method_signature);
|
||||
|
||||
friend void ::_Jv_PrepareClass (jclass);
|
||||
friend void ::_Jv_PrepareMissingMethods (jclass base, jclass iface_class);
|
||||
|
||||
friend void ::_Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
|
||||
|
||||
friend class ::_Jv_ClassReader;
|
||||
friend class ::_Jv_InterpClass;
|
||||
friend class ::_Jv_InterpMethod;
|
||||
@@ -480,10 +475,14 @@ private:
|
||||
#endif
|
||||
|
||||
friend class ::_Jv_BytecodeVerifier;
|
||||
friend class ::_Jv_StackTrace;
|
||||
friend class gnu::gcj::runtime::StackTrace;
|
||||
friend class java::io::VMObjectStreamClass;
|
||||
|
||||
friend class _Jv_Linker;
|
||||
friend class _Jv_ExecutionEngine;
|
||||
friend class _Jv_CompiledEngine;
|
||||
friend class _Jv_InterpreterEngine;
|
||||
|
||||
friend void ::_Jv_sharedlib_register_hook (jclass klass);
|
||||
|
||||
// Chain for class pool.
|
||||
@@ -518,8 +517,12 @@ private:
|
||||
_Jv_OffsetTable *otable;
|
||||
// Offset table symbols.
|
||||
_Jv_MethodSymbol *otable_syms;
|
||||
// Address table
|
||||
_Jv_AddressTable *atable;
|
||||
_Jv_MethodSymbol *atable_syms;
|
||||
// Interface table
|
||||
_Jv_AddressTable *itable;
|
||||
_Jv_MethodSymbol *itable_syms;
|
||||
_Jv_CatchClass *catch_classes;
|
||||
// Interfaces implemented by this class.
|
||||
jclass *interfaces;
|
||||
@@ -542,13 +545,17 @@ private:
|
||||
jclass arrayclass;
|
||||
// Security Domain to which this class belongs (or null).
|
||||
java::security::ProtectionDomain *protectionDomain;
|
||||
// Pointer to the type assertion table for this class.
|
||||
_Jv_TypeAssertion *assertion_table;
|
||||
// Signers of this class (or null).
|
||||
JArray<jobject> *hack_signers;
|
||||
// Used by Jv_PopClass and _Jv_PushClass to communicate with StackTrace.
|
||||
jclass chain;
|
||||
// Additional data, specific to the generator (JIT, native, interpreter) of this
|
||||
// class.
|
||||
// Additional data, specific to the generator (JIT, native,
|
||||
// interpreter) of this class.
|
||||
void *aux_info;
|
||||
// Execution engine.
|
||||
_Jv_ExecutionEngine *engine;
|
||||
};
|
||||
|
||||
// Inline functions that are friends of java::lang::Class
|
||||
|
||||
@@ -288,6 +288,8 @@ public abstract class ClassLoader
|
||||
if (c != null)
|
||||
return c;
|
||||
|
||||
ClassNotFoundException ex = null;
|
||||
|
||||
// Can the class be loaded by a parent?
|
||||
try
|
||||
{
|
||||
@@ -304,9 +306,20 @@ public abstract class ClassLoader
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
ex = e;
|
||||
}
|
||||
// Still not found, we have to do it ourself.
|
||||
c = findClass(name);
|
||||
try
|
||||
{
|
||||
c = findClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException cause)
|
||||
{
|
||||
if (ex != null)
|
||||
throw new ClassNotFoundException(ex.toString(), cause);
|
||||
else
|
||||
throw cause;
|
||||
}
|
||||
if (resolve)
|
||||
resolveClass(c);
|
||||
return c;
|
||||
@@ -435,8 +448,9 @@ public abstract class ClassLoader
|
||||
domain = defaultProtectionDomain;
|
||||
if (! initialized)
|
||||
throw new SecurityException("attempt to define class from uninitialized class loader");
|
||||
|
||||
Class retval = VMClassLoader.defineClass(this, name, data,
|
||||
offset, len, domain);
|
||||
offset, len, domain);
|
||||
loadedClasses.put(retval.getName(), retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Compiler.java -- placeholder for Java-to-native runtime compilers
|
||||
Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -76,8 +76,7 @@ public final class Compiler
|
||||
*/
|
||||
public static boolean compileClass(Class oneClass)
|
||||
{
|
||||
// Never succeed.
|
||||
return false;
|
||||
return VMCompiler.compileClass(oneClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,8 +89,7 @@ public final class Compiler
|
||||
*/
|
||||
public static boolean compileClasses(String classNames)
|
||||
{
|
||||
// Note the incredibly lame interface. Always fail.
|
||||
return false;
|
||||
return VMCompiler.compileClasses(classNames);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,8 +103,7 @@ public final class Compiler
|
||||
*/
|
||||
public static Object command(Object arg)
|
||||
{
|
||||
// Our implementation defines this to a no-op.
|
||||
return null;
|
||||
return VMCompiler.command(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,6 +113,7 @@ public final class Compiler
|
||||
*/
|
||||
public static void enable()
|
||||
{
|
||||
VMCompiler.enable();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,5 +122,6 @@ public final class Compiler
|
||||
*/
|
||||
public static void disable()
|
||||
{
|
||||
VMCompiler.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ public class SecurityManager
|
||||
public void checkPermission(Permission perm)
|
||||
{
|
||||
// XXX Should be: AccessController.checkPermission(perm);
|
||||
throw new SecurityException("Operation not allowed");
|
||||
//.throw new SecurityException("Operation not allowed");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -553,7 +553,7 @@ public class SecurityManager
|
||||
// throw new SecurityException("Missing context");
|
||||
// AccessControlContext ac = (AccessControlContext) context;
|
||||
// ac.checkPermission(new FilePermission(filename, "read"));
|
||||
throw new SecurityException("Cannot read files via file names.");
|
||||
// throw new SecurityException("Cannot read files via file names.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -677,7 +677,7 @@ public class SecurityManager
|
||||
// // Use the toString() hack to do the null check.
|
||||
// ac.checkPermission(new SocketPermission(host.toString + ":" +port,
|
||||
// "connect"));
|
||||
throw new SecurityException("Cannot make network connections.");
|
||||
// throw new SecurityException("Cannot make network connections.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -97,44 +97,31 @@ final class VMClassLoader
|
||||
ProtectionDomain pd)
|
||||
throws ClassFormatError;
|
||||
|
||||
static final native void linkClass0 (Class klass);
|
||||
static final native void markClassErrorState0 (Class klass);
|
||||
|
||||
/**
|
||||
* Helper to resolve all references to other classes from this class.
|
||||
*
|
||||
* @param c the class to resolve
|
||||
*/
|
||||
static final void resolveClass(Class clazz)
|
||||
{
|
||||
synchronized (clazz)
|
||||
{
|
||||
try
|
||||
{
|
||||
linkClass0 (clazz);
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
markClassErrorState0 (clazz);
|
||||
static final native void resolveClass(Class clazz);
|
||||
|
||||
LinkageError e;
|
||||
if (x instanceof LinkageError)
|
||||
e = (LinkageError) x;
|
||||
else if (x instanceof ClassNotFoundException)
|
||||
{
|
||||
e = new NoClassDefFoundError("while resolving class: "
|
||||
+ clazz.getName());
|
||||
e.initCause (x);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = new LinkageError ("unexpected exception during linking: "
|
||||
+ clazz.getName());
|
||||
e.initCause (x);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
static final void transformException(Class clazz, Throwable x)
|
||||
{
|
||||
LinkageError e;
|
||||
if (x instanceof LinkageError)
|
||||
e = (LinkageError) x;
|
||||
else if (x instanceof ClassNotFoundException)
|
||||
{
|
||||
e = new NoClassDefFoundError("while resolving class: "
|
||||
+ clazz.getName());
|
||||
e.initCause (x);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = new LinkageError ("unexpected exception during linking: "
|
||||
+ clazz.getName());
|
||||
e.initCause (x);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
/* VMClassLoader.java -- Reference implementation of compiler interface
|
||||
Copyright (C) 2004 Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package java.lang;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Enumeration;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Vector;
|
||||
import gnu.gcj.runtime.SharedLibHelper;
|
||||
import gnu.gcj.runtime.PersistentByteMap;
|
||||
|
||||
/**
|
||||
* This class is just a per-VM reflection of java.lang.Compiler.
|
||||
* All methods are defined identically.
|
||||
*/
|
||||
final class VMCompiler
|
||||
{
|
||||
// True if we want to use gcj-jit.
|
||||
public static boolean useCompiler = true;
|
||||
|
||||
// True if we're able to use gcj-jit.
|
||||
public static final boolean canUseCompiler;
|
||||
|
||||
// Compiler to use.
|
||||
public static String gcjJitCompiler;
|
||||
|
||||
// Compiler options.
|
||||
public static String gcjJitCompilerOptions;
|
||||
|
||||
// Temporary directory to use.
|
||||
public static String gcjJitTmpdir;
|
||||
|
||||
// This maps a ClassLoader to a set of SharedLibHelper objects that
|
||||
// it has used. We do things this way to ensure that a
|
||||
// SharedLibHelper is collected if and only if the ClassLoader is.
|
||||
private static WeakHashMap sharedHelperMap = new WeakHashMap();
|
||||
|
||||
private static Vector precompiledMapFiles;
|
||||
|
||||
static
|
||||
{
|
||||
gcjJitCompiler = System.getProperty("gnu.gcj.jit.compiler");
|
||||
if (gcjJitCompiler == null)
|
||||
canUseCompiler = false;
|
||||
else
|
||||
{
|
||||
gcjJitCompilerOptions = System.getProperty("gnu.gcj.jit.options",
|
||||
"-g");
|
||||
gcjJitTmpdir = System.getProperty("gnu.gcj.jit.cachedir");
|
||||
// Note that we *don't* choose java.io.tmpdir as a default --
|
||||
// that would allow easy attacks against the VM.
|
||||
if (gcjJitTmpdir == null)
|
||||
canUseCompiler = false;
|
||||
else
|
||||
canUseCompiler = true;
|
||||
}
|
||||
|
||||
String prop = System.getProperty ("gnu.gcj.precompiled.db.path");
|
||||
if (prop != null)
|
||||
{
|
||||
precompiledMapFiles = new Vector();
|
||||
// Add the
|
||||
StringTokenizer st
|
||||
= new StringTokenizer (prop,
|
||||
System.getProperty ("path.separator", ":"));
|
||||
{
|
||||
while (st.hasMoreElements ())
|
||||
{
|
||||
String e = st.nextToken ();
|
||||
try
|
||||
{
|
||||
PersistentByteMap map
|
||||
= new PersistentByteMap
|
||||
(e, PersistentByteMap.AccessMode.READ_ONLY);
|
||||
precompiledMapFiles.add(map);
|
||||
}
|
||||
catch (IllegalArgumentException _)
|
||||
{
|
||||
// Not a map file
|
||||
}
|
||||
catch (java.io.IOException _)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't allow new `Compiler's to be made.
|
||||
*/
|
||||
private VMCompiler()
|
||||
{
|
||||
}
|
||||
|
||||
private static Class loadSharedLibrary(ClassLoader loader,
|
||||
String fileName,
|
||||
ProtectionDomain domain,
|
||||
String className)
|
||||
{
|
||||
Class c = null;
|
||||
SharedLibHelper helper
|
||||
= SharedLibHelper.findHelper (loader, fileName, domain.getCodeSource());
|
||||
c = helper.findClass (className);
|
||||
if (c != null)
|
||||
{
|
||||
HashSet hs = (HashSet) sharedHelperMap.get(loader);
|
||||
if (hs == null)
|
||||
{
|
||||
hs = new HashSet();
|
||||
sharedHelperMap.put(loader, hs);
|
||||
}
|
||||
hs.add(helper);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a class given the bytes for it. Returns the Class, or
|
||||
* null if compilation failed or otherwise could not be done.
|
||||
*/
|
||||
public static Class compileClass(ClassLoader loader,
|
||||
String name, byte[] data,
|
||||
int offset, int len,
|
||||
ProtectionDomain domain)
|
||||
{
|
||||
if (precompiledMapFiles == null
|
||||
&& (! useCompiler || ! canUseCompiler))
|
||||
return null;
|
||||
|
||||
byte digest[];
|
||||
|
||||
try
|
||||
{
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
digest = md.digest(data);
|
||||
}
|
||||
catch (NoSuchAlgorithmException _)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// We use lookaside cache files to determine whether these bytes
|
||||
// correspond to a class file that is part of a precompiled DSO.
|
||||
if (precompiledMapFiles != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Enumeration elements = precompiledMapFiles.elements();
|
||||
while (elements.hasMoreElements())
|
||||
{
|
||||
PersistentByteMap map = (PersistentByteMap)elements.nextElement();
|
||||
byte[] soName = map.get(digest);
|
||||
if (soName != null)
|
||||
return loadSharedLibrary(loader,
|
||||
new String(soName),
|
||||
domain, name);
|
||||
}
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (! useCompiler || ! canUseCompiler)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
// FIXME: Make sure that the class represented by the
|
||||
// bytes in DATA really is the class named in NAME. Make
|
||||
// sure it's not "java.*".
|
||||
StringBuffer hexBytes = new StringBuffer(gcjJitTmpdir);
|
||||
hexBytes.append(File.separatorChar);
|
||||
int digestLength = digest.length;
|
||||
for (int i = 0; i < digestLength; ++i)
|
||||
hexBytes.append(Integer.toHexString(digest[i] & 0xff));
|
||||
|
||||
// FIXME: use System.mapLibraryName?
|
||||
// I'm thinking we should use that, plus a class specified
|
||||
// via a property that determines lookup policy.
|
||||
File soFile = new File(hexBytes + ".so");
|
||||
if (soFile.isFile())
|
||||
return loadSharedLibrary (loader, soFile.toString(), domain,
|
||||
name);
|
||||
|
||||
File classFile = new File(hexBytes + ".class");
|
||||
classFile.delete();
|
||||
if (classFile.createNewFile() != true)
|
||||
return null;
|
||||
|
||||
FileOutputStream f = new FileOutputStream (classFile);
|
||||
// FIXME: race condition if bytes change... ?
|
||||
f.write(data, offset, len);
|
||||
|
||||
// Invoke the compiler.
|
||||
StringBuffer command = new StringBuffer(gcjJitCompiler);
|
||||
command.append(" ");
|
||||
command.append(classFile);
|
||||
command.append(" ");
|
||||
command.append(gcjJitCompilerOptions);
|
||||
// These options are required.
|
||||
command.append(" -findirect-dispatch -fjni -shared -fPIC -o ");
|
||||
command.append(soFile);
|
||||
Process p = Runtime.getRuntime().exec(command.toString());
|
||||
|
||||
// Read the process' stderr into a string.
|
||||
StringBuffer err = new StringBuffer();
|
||||
InputStreamReader stderr = new InputStreamReader (p.getErrorStream());
|
||||
char[] inBuf = new char[500];
|
||||
int bytesRead;
|
||||
while ((bytesRead = stderr.read (inBuf)) != -1)
|
||||
err.append(inBuf, 0, bytesRead);
|
||||
|
||||
if (p.waitFor() != 0)
|
||||
{
|
||||
// FIXME: we could log err.toString() somewhere...
|
||||
return null;
|
||||
}
|
||||
|
||||
return loadSharedLibrary(loader, soFile.toString(), domain, name);
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the class named by <code>oneClass</code>.
|
||||
*
|
||||
* @param oneClass the class to compile
|
||||
* @return <code>false</code> if no compiler is available or
|
||||
* compilation failed, <code>true</code> if compilation succeeded
|
||||
* @throws NullPointerException if oneClass is null
|
||||
*/
|
||||
public static boolean compileClass(Class oneClass)
|
||||
{
|
||||
// Never succeed.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the classes whose name matches <code>classNames</code>.
|
||||
*
|
||||
* @param classNames the name of classes to compile
|
||||
* @return <code>false</code> if no compiler is available or
|
||||
* compilation failed, <code>true</code> if compilation succeeded
|
||||
* @throws NullPointerException if classNames is null
|
||||
*/
|
||||
public static boolean compileClasses(String classNames)
|
||||
{
|
||||
// Note the incredibly lame interface. Always fail.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method examines the argument and performs an operation
|
||||
* according to the compilers documentation. No specific operation
|
||||
* is required.
|
||||
*
|
||||
* @param arg a compiler-specific argument
|
||||
* @return a compiler-specific value, including null
|
||||
* @throws NullPointerException if the compiler doesn't like a null arg
|
||||
*/
|
||||
public static Object command(Object arg)
|
||||
{
|
||||
// Our implementation defines this to a no-op.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling <code>Compiler.enable()</code> will cause the compiler
|
||||
* to resume operation if it was previously disabled; provided that a
|
||||
* compiler even exists.
|
||||
*/
|
||||
public static void enable()
|
||||
{
|
||||
useCompiler = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling <code>Compiler.disable()</code> will cause the compiler
|
||||
* to be suspended; provided that a compiler even exists.
|
||||
*/
|
||||
public static void disable()
|
||||
{
|
||||
useCompiler = false;
|
||||
}
|
||||
}
|
||||
@@ -54,11 +54,12 @@ class VMSecurityManager
|
||||
// The docs above are wrong. See the online docs.
|
||||
// FIXME this implementation is a bit wrong too -- the docs say we
|
||||
// must also consider ancestors of the system class loader.
|
||||
ClassLoader systemClassLoader = VMClassLoader.getSystemClassLoader();
|
||||
Class[] classStack = getClassContext ();
|
||||
for (int i = 0; i < classStack.length; i++)
|
||||
{
|
||||
ClassLoader loader = classStack[i].getClassLoader();
|
||||
if (loader != null)
|
||||
if (loader != null && loader != systemClassLoader)
|
||||
return loader;
|
||||
}
|
||||
|
||||
|
||||
+195
-946
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@ details. */
|
||||
|
||||
#include <gcj/cni.h>
|
||||
#include <jvm.h>
|
||||
#include <execution.h>
|
||||
|
||||
#include <java-threads.h>
|
||||
#include <java-interp.h>
|
||||
@@ -33,6 +34,7 @@ details. */
|
||||
#include <java/lang/ClassNotFoundException.h>
|
||||
#include <java/lang/ClassCircularityError.h>
|
||||
#include <java/lang/IncompatibleClassChangeError.h>
|
||||
#include <java/lang/ClassFormatError.h>
|
||||
#include <java/lang/VirtualMachineError.h>
|
||||
#include <java/lang/VMClassLoader.h>
|
||||
#include <java/lang/reflect/Modifier.h>
|
||||
@@ -41,156 +43,6 @@ details. */
|
||||
#include <java/io/Serializable.h>
|
||||
#include <java/lang/Cloneable.h>
|
||||
|
||||
void
|
||||
_Jv_WaitForState (jclass klass, int state)
|
||||
{
|
||||
if (klass->state >= state)
|
||||
return;
|
||||
|
||||
_Jv_MonitorEnter (klass) ;
|
||||
|
||||
if (klass->state == JV_STATE_COMPILED)
|
||||
{
|
||||
klass->state = JV_STATE_LOADED;
|
||||
if (gcj::verbose_class_flag)
|
||||
fprintf (stderr, "[Loaded (pre-compiled) %s]\n", klass->name->chars());
|
||||
}
|
||||
if (state == JV_STATE_LINKED)
|
||||
{
|
||||
// Must call _Jv_PrepareCompiledClass while holding the class
|
||||
// mutex.
|
||||
#ifdef INTERPRETER
|
||||
if (_Jv_IsInterpretedClass (klass))
|
||||
_Jv_PrepareClass (klass);
|
||||
#endif
|
||||
_Jv_PrepareCompiledClass (klass);
|
||||
_Jv_MonitorExit (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)
|
||||
throw new java::lang::LinkageError;
|
||||
}
|
||||
|
||||
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
|
||||
|
||||
/** This function does class-preparation for compiled classes.
|
||||
NOTE: It contains replicated functionality from
|
||||
_Jv_ResolvePoolEntry, and this is intentional, since that function
|
||||
lives in resolve.cc which is entirely conditionally compiled.
|
||||
*/
|
||||
void
|
||||
_Jv_PrepareCompiledClass (jclass klass)
|
||||
{
|
||||
jint state = klass->state;
|
||||
if (state >= JV_STATE_LINKED)
|
||||
return;
|
||||
|
||||
// Short-circuit, so that mutually dependent classes are ok.
|
||||
klass->state = JV_STATE_LINKED;
|
||||
|
||||
_Jv_Constants *pool = &klass->constants;
|
||||
|
||||
// Resolve class constants first, since other constant pool
|
||||
// entries may rely on these.
|
||||
for (int index = 1; index < pool->size; ++index)
|
||||
{
|
||||
if (pool->tags[index] == JV_CONSTANT_Class)
|
||||
{
|
||||
_Jv_Utf8Const *name = pool->data[index].utf8;
|
||||
|
||||
jclass found;
|
||||
if (name->first() == '[')
|
||||
found = _Jv_FindClassFromSignature (name->chars(),
|
||||
klass->loader);
|
||||
else
|
||||
found = _Jv_FindClass (name, klass->loader);
|
||||
|
||||
if (! found)
|
||||
{
|
||||
jstring str = name->toString();
|
||||
throw new java::lang::NoClassDefFoundError (str);
|
||||
}
|
||||
|
||||
pool->data[index].clazz = found;
|
||||
pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
|
||||
}
|
||||
}
|
||||
|
||||
// If superclass looks like a constant pool entry,
|
||||
// resolve it now.
|
||||
if ((uaddr) klass->superclass < pool->size)
|
||||
klass->superclass = pool->data[(uaddr) klass->superclass].clazz;
|
||||
|
||||
// Likewise for interfaces.
|
||||
for (int i = 0; i < klass->interface_count; i++)
|
||||
if ((uaddr) klass->interfaces[i] < pool->size)
|
||||
klass->interfaces[i] = pool->data[(uaddr) klass->interfaces[i]].clazz;
|
||||
|
||||
// Resolve the remaining constant pool entries.
|
||||
for (int index = 1; index < pool->size; ++index)
|
||||
{
|
||||
if (pool->tags[index] == JV_CONSTANT_String)
|
||||
{
|
||||
jstring str;
|
||||
|
||||
str = _Jv_NewStringUtf8Const (pool->data[index].utf8);
|
||||
pool->data[index].o = str;
|
||||
pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INTERPRETER
|
||||
// FIXME: although the comment up top says that this function is
|
||||
// only called for compiled classes, it is actually called for every
|
||||
// class.
|
||||
if (! _Jv_IsInterpretedClass (klass))
|
||||
{
|
||||
#endif /* INTERPRETER */
|
||||
jfieldID f = JvGetFirstStaticField (klass);
|
||||
for (int n = JvNumStaticFields (klass); n > 0; --n)
|
||||
{
|
||||
int mod = f->getModifiers ();
|
||||
// If we have a static String field with a non-null initial
|
||||
// value, we know it points to a Utf8Const.
|
||||
_Jv_ResolveField(f, klass->loader);
|
||||
if (f->getClass () == &java::lang::String::class$
|
||||
&& java::lang::reflect::Modifier::isStatic (mod))
|
||||
{
|
||||
jstring *strp = (jstring *) f->u.addr;
|
||||
if (*strp)
|
||||
*strp = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) *strp);
|
||||
}
|
||||
f = f->getNextField ();
|
||||
}
|
||||
#ifdef INTERPRETER
|
||||
}
|
||||
#endif /* INTERPRETER */
|
||||
|
||||
if (klass->isInterface ())
|
||||
_Jv_LayoutInterfaceMethods (klass);
|
||||
|
||||
if (state == JV_STATE_COMPILED && gcj::verbose_class_flag)
|
||||
fprintf (stderr, "[Loaded (pre-compiled) %s]\n",
|
||||
klass->name->chars());
|
||||
|
||||
klass->notifyAll ();
|
||||
|
||||
_Jv_PushClass (klass);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A single class can have many "initiating" class loaders,
|
||||
// and a single "defining" class loader. The Defining
|
||||
@@ -221,6 +73,8 @@ static _Jv_LoaderInfo *initiated_classes[HASH_LEN];
|
||||
static jclass loaded_classes[HASH_LEN];
|
||||
|
||||
// This is the root of a linked list of classes
|
||||
static jclass stack_head;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -323,11 +177,6 @@ _Jv_RegisterClasses (const jclass *classes)
|
||||
jclass klass = *classes;
|
||||
|
||||
(*_Jv_RegisterClassHook) (klass);
|
||||
|
||||
// registering a compiled class causes
|
||||
// it to be immediately "prepared".
|
||||
if (klass->state == JV_STATE_NOTHING)
|
||||
klass->state = JV_STATE_COMPILED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,11 +190,6 @@ _Jv_RegisterClasses_Counted (const jclass * classes, size_t count)
|
||||
jclass klass = classes[i];
|
||||
|
||||
(*_Jv_RegisterClassHook) (klass);
|
||||
|
||||
// registering a compiled class causes
|
||||
// it to be immediately "prepared".
|
||||
if (klass->state == JV_STATE_NOTHING)
|
||||
klass->state = JV_STATE_COMPILED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,8 +198,10 @@ _Jv_RegisterClassHookDefault (jclass klass)
|
||||
{
|
||||
jint hash = HASH_UTF (klass->name);
|
||||
|
||||
jclass check_class = loaded_classes[hash];
|
||||
|
||||
// The BC ABI makes this check unnecessary: we always resolve all
|
||||
// data references via the appropriate class loader, so the kludge
|
||||
// that required this check has gone.
|
||||
#if 0
|
||||
// If the class is already registered, don't re-register it.
|
||||
while (check_class != NULL)
|
||||
{
|
||||
@@ -381,7 +227,11 @@ _Jv_RegisterClassHookDefault (jclass klass)
|
||||
|
||||
check_class = check_class->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
// FIXME: this is really bogus!
|
||||
if (! klass->engine)
|
||||
klass->engine = &_Jv_soleCompiledEngine;
|
||||
klass->next = loaded_classes[hash];
|
||||
loaded_classes[hash] = klass;
|
||||
}
|
||||
@@ -442,7 +292,7 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
|
||||
{
|
||||
// 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);
|
||||
_Jv_Linker::wait_for_state (klass, JV_STATE_LOADED);
|
||||
}
|
||||
|
||||
return klass;
|
||||
@@ -555,7 +405,7 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
|
||||
// cache one and reuse it. It is not necessary to synchronize this.
|
||||
if (!array_idt)
|
||||
{
|
||||
_Jv_PrepareConstantTimeTables (array_class);
|
||||
_Jv_Linker::wait_for_state(array_class, JV_STATE_PREPARED);
|
||||
array_idt = array_class->idt;
|
||||
array_depth = array_class->depth;
|
||||
array_ancestors = array_class->ancestors;
|
||||
@@ -569,19 +419,19 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
|
||||
|
||||
using namespace java::lang::reflect;
|
||||
{
|
||||
// Array classes are "abstract final"...
|
||||
_Jv_ushort accflags = Modifier::FINAL | Modifier::ABSTRACT;
|
||||
// ... and inherit accessibility from element type, per vmspec 5.3.3.2
|
||||
accflags |= (element->accflags & Modifier::PUBLIC);
|
||||
accflags |= (element->accflags & Modifier::PROTECTED);
|
||||
accflags |= (element->accflags & Modifier::PRIVATE);
|
||||
// Array classes are "abstract final" and inherit accessibility
|
||||
// from element type, per vmspec 5.3.3.2
|
||||
_Jv_ushort accflags = (Modifier::FINAL | Modifier::ABSTRACT
|
||||
| (element->accflags
|
||||
& (Modifier::PUBLIC | Modifier::PROTECTED
|
||||
| Modifier::PRIVATE)));
|
||||
array_class->accflags = accflags;
|
||||
}
|
||||
|
||||
// An array class has no visible instance fields. "length" is invisible to
|
||||
// reflection.
|
||||
|
||||
// say this class is initialized and ready to go!
|
||||
// Say this class is initialized and ready to go!
|
||||
array_class->state = JV_STATE_DONE;
|
||||
|
||||
// vmspec, section 5.3.3 describes this
|
||||
@@ -591,8 +441,6 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
|
||||
element->arrayclass = array_class;
|
||||
}
|
||||
|
||||
static jclass stack_head;
|
||||
|
||||
// These two functions form a stack of classes. When a class is loaded
|
||||
// it is pushed onto the stack by the class loader; this is so that
|
||||
// StackTrace can quickly determine which classes have been loaded.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// natRuntime.cc - Implementation of native side of Runtime class.
|
||||
|
||||
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
|
||||
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
@@ -388,8 +388,11 @@ java::lang::Runtime::insertSystemProperties (java::util::Properties *newprops)
|
||||
newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
|
||||
|
||||
// A mixture of the Java Product Versioning Specification
|
||||
// (introduced in 1.2), and earlier versioning properties.
|
||||
SET ("java.version", GCJVERSION);
|
||||
// (introduced in 1.2), and earlier versioning properties. Some
|
||||
// programs rely on seeing values that they expect, so we claim to
|
||||
// be a 1.4-ish VM for their sake.
|
||||
SET ("java.version", "1.4.2");
|
||||
SET ("java.runtime.version", "1.4.2");
|
||||
SET ("java.vendor", "Free Software Foundation, Inc.");
|
||||
SET ("java.vendor.url", "http://gcc.gnu.org/java/");
|
||||
SET ("java.class.version", "46.0");
|
||||
@@ -399,7 +402,7 @@ java::lang::Runtime::insertSystemProperties (java::util::Properties *newprops)
|
||||
SET ("java.vm.version", __VERSION__);
|
||||
SET ("java.vm.vendor", "Free Software Foundation, Inc.");
|
||||
SET ("java.vm.name", "GNU libgcj");
|
||||
SET ("java.specification.version", "1.3");
|
||||
SET ("java.specification.version", "1.4");
|
||||
SET ("java.specification.name", "Java(tm) Platform API Specification");
|
||||
SET ("java.specification.vendor", "Sun Microsystems Inc.");
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// natString.cc - Implementation of java.lang.String native methods.
|
||||
|
||||
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation
|
||||
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
@@ -57,7 +56,7 @@ static int strhash_size = 0; /* Number of slots available in strhash.
|
||||
jstring*
|
||||
_Jv_StringFindSlot (jchar* data, jint len, jint hash)
|
||||
{
|
||||
JvSynchronize sync (&StringClass);
|
||||
JvSynchronize sync (&java::lang::String::class$);
|
||||
|
||||
int start_index = hash & (strhash_size - 1);
|
||||
int deleted_index = -1;
|
||||
@@ -120,7 +119,7 @@ _Jv_StringGetSlot (jstring str)
|
||||
static void
|
||||
rehash ()
|
||||
{
|
||||
JvSynchronize sync (&StringClass);
|
||||
JvSynchronize sync (&java::lang::String::class$);
|
||||
|
||||
if (strhash == NULL)
|
||||
{
|
||||
@@ -167,7 +166,7 @@ rehash ()
|
||||
jstring
|
||||
java::lang::String::intern()
|
||||
{
|
||||
JvSynchronize sync (&StringClass);
|
||||
JvSynchronize sync (&java::lang::String::class$);
|
||||
if (3 * strhash_count >= 2 * strhash_size)
|
||||
rehash();
|
||||
jstring* ptr = _Jv_StringGetSlot(this);
|
||||
@@ -194,7 +193,7 @@ java::lang::String::intern()
|
||||
void
|
||||
_Jv_FinalizeString (jobject obj)
|
||||
{
|
||||
JvSynchronize sync (&StringClass);
|
||||
JvSynchronize sync (&java::lang::String::class$);
|
||||
|
||||
// We might not actually have intern()d any strings at all, if
|
||||
// we're being called from Reference.
|
||||
@@ -286,9 +285,9 @@ _Jv_NewStringUtf8Const (Utf8Const* str)
|
||||
}
|
||||
chrs -= length;
|
||||
|
||||
JvSynchronize sync (&StringClass);
|
||||
JvSynchronize sync (&java::lang::String::class$);
|
||||
if (3 * strhash_count >= 2 * strhash_size)
|
||||
rehash ();
|
||||
rehash();
|
||||
jstring* ptr = _Jv_StringFindSlot (chrs, length, hash);
|
||||
if (*ptr != NULL && *ptr != DELETED_STRING)
|
||||
return (jstring) UNMASK_PTR (*ptr);
|
||||
@@ -527,7 +526,7 @@ java::lang::String::equals(jobject anObject)
|
||||
return false;
|
||||
if (anObject == this)
|
||||
return true;
|
||||
if (anObject->getClass() != &StringClass)
|
||||
if (anObject->getClass() != &java::lang::String::class$)
|
||||
return false;
|
||||
jstring other = (jstring) anObject;
|
||||
if (count != other->count)
|
||||
|
||||
@@ -22,6 +22,7 @@ details. */
|
||||
#include <java-interp.h>
|
||||
|
||||
#include <java/lang/VMClassLoader.h>
|
||||
#include <java/lang/VMCompiler.h>
|
||||
#include <gnu/gcj/runtime/VMClassLoader.h>
|
||||
#include <java/lang/ClassLoader.h>
|
||||
#include <java/lang/Class.h>
|
||||
@@ -29,6 +30,21 @@ details. */
|
||||
#include <java/security/ProtectionDomain.h>
|
||||
#include <java/lang/ClassFormatError.h>
|
||||
|
||||
void
|
||||
java::lang::VMClassLoader::resolveClass (jclass klass)
|
||||
{
|
||||
JvSynchronize sync (klass);
|
||||
try
|
||||
{
|
||||
_Jv_Linker::wait_for_state (klass, JV_STATE_LINKED);
|
||||
}
|
||||
catch (java::lang::Throwable *x)
|
||||
{
|
||||
klass->set_state(JV_STATE_ERROR);
|
||||
transformException(klass, x);
|
||||
}
|
||||
}
|
||||
|
||||
java::lang::Class *
|
||||
java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader,
|
||||
jstring name,
|
||||
@@ -37,72 +53,61 @@ java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader,
|
||||
jint length,
|
||||
java::security::ProtectionDomain *pd)
|
||||
{
|
||||
jclass klass = VMCompiler::compileClass(loader, name, data,
|
||||
offset, length, pd);
|
||||
|
||||
if (klass != NULL)
|
||||
{
|
||||
JvSynchronize sync (&java::lang::Class::class$);
|
||||
_Jv_RegisterClass (klass);
|
||||
}
|
||||
#ifdef INTERPRETER
|
||||
jclass klass;
|
||||
klass = new java::lang::Class ();
|
||||
klass->aux_info = (void *) _Jv_AllocBytes (sizeof (_Jv_InterpClass));
|
||||
|
||||
// Synchronize on the class, so that it is not attempted initialized
|
||||
// until we're done loading.
|
||||
JvSynchronize sync (klass);
|
||||
|
||||
// Record the defining loader. For the system class loader, we
|
||||
// record NULL.
|
||||
if (loader != java::lang::ClassLoader::getSystemClassLoader())
|
||||
klass->loader = loader;
|
||||
|
||||
if (name != 0)
|
||||
else
|
||||
{
|
||||
_Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
|
||||
klass = new java::lang::Class ();
|
||||
|
||||
if (! _Jv_VerifyClassName (name2))
|
||||
throw new java::lang::ClassFormatError
|
||||
(JvNewStringLatin1 ("erroneous class name"));
|
||||
// Synchronize on the class, so that it is not attempted initialized
|
||||
// until we're done loading.
|
||||
JvSynchronize sync (klass);
|
||||
|
||||
klass->name = name2;
|
||||
// Record the defining loader. For the system class loader, we
|
||||
// record NULL.
|
||||
if (loader != java::lang::ClassLoader::getSystemClassLoader())
|
||||
klass->loader = loader;
|
||||
|
||||
if (name != 0)
|
||||
{
|
||||
_Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
|
||||
|
||||
if (! _Jv_VerifyClassName (name2))
|
||||
throw new java::lang::ClassFormatError
|
||||
(JvNewStringLatin1 ("erroneous class name"));
|
||||
|
||||
klass->name = name2;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_Jv_DefineClass (klass, data, offset, length, pd);
|
||||
}
|
||||
catch (java::lang::Throwable *ex)
|
||||
{
|
||||
klass->state = JV_STATE_ERROR;
|
||||
klass->notifyAll ();
|
||||
|
||||
_Jv_UnregisterClass (klass);
|
||||
|
||||
// If EX is not a ClassNotFoundException, that's ok, because we
|
||||
// account for the possibility in defineClass().
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// if everything proceeded sucessfully, we're loaded.
|
||||
JvAssert (klass->state == JV_STATE_LOADED);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_Jv_DefineClass (klass, data, offset, length);
|
||||
}
|
||||
catch (java::lang::Throwable *ex)
|
||||
{
|
||||
klass->state = JV_STATE_ERROR;
|
||||
klass->notifyAll ();
|
||||
|
||||
_Jv_UnregisterClass (klass);
|
||||
|
||||
// If EX is not a ClassNotFoundException, that's ok, because we
|
||||
// account for the possibility in defineClass().
|
||||
throw ex;
|
||||
}
|
||||
|
||||
klass->protectionDomain = pd;
|
||||
|
||||
// if everything proceeded sucessfully, we're loaded.
|
||||
JvAssert (klass->state == JV_STATE_LOADED);
|
||||
#endif // INTERPRETER
|
||||
|
||||
return klass;
|
||||
|
||||
#else // INTERPRETER
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Finish linking a class. Only called from ClassLoader::resolveClass.
|
||||
void
|
||||
java::lang::VMClassLoader::linkClass0 (java::lang::Class *klass)
|
||||
{
|
||||
_Jv_WaitForState (klass, JV_STATE_LINKED);
|
||||
}
|
||||
|
||||
void
|
||||
java::lang::VMClassLoader::markClassErrorState0 (java::lang::Class *klass)
|
||||
{
|
||||
klass->state = JV_STATE_ERROR;
|
||||
klass->notifyAll ();
|
||||
}
|
||||
|
||||
java::lang::ClassLoader *
|
||||
@@ -125,9 +130,16 @@ jclass
|
||||
java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve)
|
||||
{
|
||||
_Jv_Utf8Const *utf = _Jv_makeUtf8Const (name);
|
||||
// FIXME: we culd make _Jv_FindClassFromSignature a template.
|
||||
jclass klass = _Jv_FindClassInCache (utf, NULL);
|
||||
if (klass && resolve)
|
||||
_Jv_InitClass (klass);
|
||||
if (klass)
|
||||
{
|
||||
// We never want to return a class without its supers linked.
|
||||
// It isn't clear from the spec, but this is what other
|
||||
// implementations do in practice.
|
||||
if (resolve)
|
||||
_Jv_InitClass (klass);
|
||||
else
|
||||
_Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
|
||||
}
|
||||
return klass;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// natField.cc - Implementation of java.lang.reflect.Field native methods.
|
||||
|
||||
/* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation
|
||||
/* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
@@ -47,7 +47,7 @@ java::lang::reflect::Field::getType ()
|
||||
{
|
||||
jfieldID fld = _Jv_FromReflectedField (this);
|
||||
JvSynchronize sync (declaringClass);
|
||||
_Jv_ResolveField (fld, declaringClass->getClassLoaderInternal ());
|
||||
_Jv_Linker::resolve_field (fld, declaringClass->getClassLoaderInternal ());
|
||||
return fld->type;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// natMethod.cc - Native code for Method class.
|
||||
|
||||
/* Copyright (C) 1998, 1999, 2000, 2001 , 2002, 2003 Free Software Foundation
|
||||
/* Copyright (C) 1998, 1999, 2000, 2001 , 2002, 2003, 2004 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
@@ -149,7 +149,6 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
|
||||
getType ();
|
||||
|
||||
jmethodID meth = _Jv_FromReflectedMethod (this);
|
||||
jclass objClass;
|
||||
|
||||
if (Modifier::isStatic(meth->accflags))
|
||||
{
|
||||
@@ -157,12 +156,10 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
|
||||
// here and not in _Jv_CallAnyMethodA because JNI initializes a
|
||||
// class whenever a method lookup is done.
|
||||
_Jv_InitClass (declaringClass);
|
||||
objClass = declaringClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
objClass = JV_CLASS (obj);
|
||||
|
||||
jclass objClass = JV_CLASS (obj);
|
||||
if (! _Jv_IsAssignableFrom (declaringClass, objClass))
|
||||
throw new java::lang::IllegalArgumentException;
|
||||
}
|
||||
@@ -184,7 +181,7 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
|
||||
{
|
||||
}
|
||||
|
||||
if (! _Jv_CheckAccess(caller, objClass, meth->accflags))
|
||||
if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags))
|
||||
throw new IllegalAccessException;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user