gcc/libjava/java/lang/reflect/natField.cc
Bryce McKinlay 18744d9b72 New Stack Trace infrastructure.
2005-03-10  Bryce McKinlay  <mckinlay@redhat.com>

	New Stack Trace infrastructure.
	* Makefile.am (libgcj0_convenience_la_SOURCES): Add stacktrace.cc.
	(gnu/gcj/runtime/StackTrace.lo): Removed.
	(ordinary_java_source_files): Remove obsolete files.
	(nat_source_files): Remove obsolete files. Add natVMThrowable.cc.
	* configure.host (fallback_backtrace_h): Set backtrace header
	for mingw and cygwin targets.
	* configure.ac: Make symlink for fallback backtrace headers.
	* Makefile.in, configure: Rebuilt.
	* defineclass.cc (_Jv_ClassReader::read_one_code_attribute):
	Read 'LineNumberTable' attribute.
	(_Jv_ClassReader::read_one_class_attribute): Read 'SourceFile'
	attribute.
	(_Jv_ClassReader::handleCodeAttribute): Initialize method line
	table fields.
	* exception.cc: Remove unused include.
	* interpret.cc (DIRECT_THREADED, insn_slot): Moved to java-interp.h.
	(SAVE_PC): New macro. Save current PC in the interpreter frame.
	(NULLCHECK, NULLARRAYCHECK): Use SAVE_PC.
	(_Jv_InterpMethod::compile): Translate bytecode PC values in the line
	table to direct threaded instruction values.
	(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): Removed.
	(_Jv_InterpMethod::run): No longer member function. All
	callers updated. Remove _Unwind calls. Call SAVE_PC whenever a call
	is made or where an instruction could throw.
	(_Jv_InterpMethod::get_source_line): New. Look up source line numbers
	in line_table.
	* prims.cc (catch_segv): Construct exception after MAKE_THROW_FRAME.
	(catch_fpe): Likewise.
	* stacktrace.cc: New file. Stack trace code now here.
	* gnu/gcj/runtime/MethodRef.java:
	* gnu/gcj/runtime/NameFinder.java: Mostly reimplemented. Now simply
	calls addr2line to look up PC addresses in a given binary or shared
	library.
	* gnu/gcj/runtime/StackTrace.java, gnu/gcj/runtime/natNameFinder.cc,
	gnu/gcj/runtime/natStackTrace.cc: Removed.
	* gnu/java/lang/MainThread.java (call_main): Add comment warning that
	this function name is specially recognised by the stack trace code
	and shouldn't be changed.
	* include/java-interp.h (DIRECT_THREADED, insn_slot): Moved here.
	(struct  _Jv_LineTableEntry, line_table, line_table_len): New.
	(_Jv_InterpMethod::run): Update declaration.
	(_Jv_StackTrace_): New friend. NameFinder and StackTrace no longer
	friends.
	(_Jv_InterpFrame): Renamed from _Jv_MethodChain. Add PC field.
	* include/java-stack.h: New file. Declarations for stack tracing.
	* include/jvm.h (_Jv_Frame_info): Removed.
	* java/lang/Class.h: Update friend declarations.
	* java/lang/VMClassLoader.java (getSystemClassLoader): Simplify
	exception message.
	* java/lang/VMThrowable.java (fillInStackTrace): Now native.
	(getStackTrace): Now native.
	(data): New RawDataManaged field.
	* java/lang/natClass.cc: Update includes.
	(forName): Use _Jv_StackTrace::GetCallingClass for
	calling-classloader check.
	(getClassLoader): Likewise.
	* java/lang/natRuntime.cc: Update includes.
	(_load): Use _Jv_StackTrace::GetFirstNonSystemClassLoader.
	* java/lang/natVMSecurityManager.cc: Update includes.
	(getClassContext): Use _Jv_StackTrace::GetClassContext.
	* java/lang/natVMThrowable.cc: New file. Native methods for
	VMThrowable.
	* java/lang/reflect/natArray.cc: Update includes.
	(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/lang/reflect/natConstructor.cc: Update includes.
	(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/lang/reflect/natField.cc: Update includes.
	(getAddr): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/lang/reflect/natMethod.cc: Update includes.
	(invoke): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/util/natResourceBundle.cc: Update includes.
	(getCallingClassLoader): Use _Jv_StackTrace::GetCallingClass.
	* java/util/logging/natLogger.cc: Update includes. Use
	_Jv_StackTrace::GetCallerInfo to get call-site info.
	* sysdep/generic/backtrace.h: Fallback backtrace code. Stub
	implementation.
	* sysdep/i386/backtrace.h: New. Fallback backtrace code. i386
	implementation.

From-SVN: r96253
2005-03-10 19:02:21 +00:00

436 lines
11 KiB
C++

// natField.cc - Implementation of java.lang.reflect.Field native methods.
/* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation
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. */
#include <config.h>
#include <stdlib.h>
#include <jvm.h>
#include <java-stack.h>
#include <java/lang/reflect/Field.h>
#include <java/lang/reflect/Modifier.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/IllegalArgumentException.h>
#include <java/lang/IllegalAccessException.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/Byte.h>
#include <java/lang/Short.h>
#include <java/lang/Integer.h>
#include <java/lang/Long.h>
#include <java/lang/Float.h>
#include <java/lang/Double.h>
#include <java/lang/Boolean.h>
#include <java/lang/Character.h>
jint
java::lang::reflect::Field::getModifiers ()
{
return _Jv_FromReflectedField (this)->getModifiers ();
}
jstring
java::lang::reflect::Field::getName ()
{
if (name == NULL)
name = _Jv_NewStringUtf8Const (_Jv_FromReflectedField (this)->name);
return name;
}
jclass
java::lang::reflect::Field::getType ()
{
if (type == NULL)
{
jfieldID fld = _Jv_FromReflectedField (this);
JvSynchronize sync (declaringClass);
_Jv_Linker::resolve_field (fld, declaringClass->getClassLoaderInternal ());
type = fld->type;
}
return type;
}
static void*
getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj,
jboolean checkFinal)
{
// FIXME: we know CALLER is NULL here. At one point we planned to
// have the compiler insert the caller as a hidden argument in some
// calls. However, we never implemented that, so we have to find
// the caller by hand instead.
using namespace java::lang::reflect;
jfieldID fld = _Jv_FromReflectedField (field);
_Jv_ushort flags = fld->getModifiers();
// Setting a final field is usually not allowed.
if (checkFinal
&& field->getModifiers() & java::lang::reflect::Modifier::FINAL)
throw new java::lang::IllegalAccessException(JvNewStringUTF
("Field is final"));
// Check accessibility, if required.
if (! (Modifier::isPublic (flags) || field->isAccessible()))
{
caller = _Jv_StackTrace::GetCallingClass (&Field::class$);
if (! _Jv_CheckAccess (caller, field->getDeclaringClass(), flags))
throw new java::lang::IllegalAccessException;
}
if (flags & Modifier::STATIC)
{
jclass fldClass = field->getDeclaringClass ();
JvInitClass(fldClass);
return fld->u.addr;
}
else
{
if (obj == NULL)
throw new java::lang::NullPointerException;
if (! _Jv_IsInstanceOf (obj, field->getDeclaringClass()))
throw new java::lang::IllegalArgumentException;
return (void*) ((char*) obj + fld->getOffset ());
}
}
static jboolean
getBoolean (jclass cls, void* addr)
{
if (cls == JvPrimClass (boolean))
return * (jboolean *) addr;
throw new java::lang::IllegalArgumentException;
}
static jchar
getChar (jclass cls, void* addr)
{
if (cls == JvPrimClass (char))
return * (jchar *) addr;
throw new java::lang::IllegalArgumentException;
}
static jbyte
getByte (jclass cls, void* addr)
{
if (cls == JvPrimClass (byte))
return * (jbyte *) addr;
throw new java::lang::IllegalArgumentException;
}
static jshort
getShort (jclass cls, void* addr)
{
if (cls == JvPrimClass (short))
return * (jshort *) addr;
if (cls == JvPrimClass (byte))
return * (jbyte *) addr;
throw new java::lang::IllegalArgumentException;
}
static jint
getInt (jclass cls, void* addr)
{
if (cls == JvPrimClass (int))
return * (jint *) addr;
if (cls == JvPrimClass (short))
return * (jshort *) addr;
if (cls == JvPrimClass (char))
return * (jchar *) addr;
if (cls == JvPrimClass (byte))
return * (jbyte *) addr;
throw new java::lang::IllegalArgumentException;
}
static jlong
getLong (jclass cls, void* addr)
{
if (cls == JvPrimClass (long))
return * (jlong *) addr;
return ::getInt(cls, addr);
}
static jfloat
getFloat (jclass cls, void* addr)
{
if (cls == JvPrimClass (float))
return * (jfloat *) addr;
if (cls == JvPrimClass (long))
return * (jlong *) addr;
return ::getInt(cls, addr);
}
static jdouble
getDouble (jclass cls, void* addr)
{
if (cls == JvPrimClass (double))
return * (jdouble *) addr;
if (cls == JvPrimClass (float))
return * (jfloat *) addr;
if (cls == JvPrimClass (long))
return * (jlong *) addr;
return ::getInt(cls, addr);
}
jboolean
java::lang::reflect::Field::getBoolean (jclass caller, jobject obj)
{
return ::getBoolean (this->getType(), getAddr (this, caller, obj, false));
}
jchar
java::lang::reflect::Field::getChar (jclass caller, jobject obj)
{
return ::getChar (this->getType(), getAddr (this, caller, obj, false));
}
jbyte
java::lang::reflect::Field::getByte (jclass caller, jobject obj)
{
return ::getByte (this->getType(), getAddr (this, caller, obj, false));
}
jshort
java::lang::reflect::Field::getShort (jclass caller, jobject obj)
{
return ::getShort (this->getType(), getAddr (this, caller, obj, false));
}
jint
java::lang::reflect::Field::getInt (jclass caller, jobject obj)
{
return ::getInt (this->getType(), getAddr (this, caller, obj, false));
}
jlong
java::lang::reflect::Field::getLong (jclass caller, jobject obj)
{
return ::getLong (this->getType(), getAddr (this, caller, obj, false));
}
jfloat
java::lang::reflect::Field::getFloat (jclass caller, jobject obj)
{
return ::getFloat (this->getType(), getAddr (this, caller, obj, false));
}
jdouble
java::lang::reflect::Field::getDouble (jclass caller, jobject obj)
{
return ::getDouble (this->getType(), getAddr (this, caller, obj, false));
}
jobject
java::lang::reflect::Field::get (jclass caller, jobject obj)
{
jclass type = this->getType();
void* addr = getAddr (this, caller, obj, false);
if (! type->isPrimitive ())
return * (jobject*) addr;
if (type == JvPrimClass (double))
return new java::lang::Double (* (jdouble*) addr);
if (type == JvPrimClass (float))
return new java::lang::Float (* (jfloat*) addr);
if (type == JvPrimClass (long))
return new java::lang::Long (* (jlong*) addr);
if (type == JvPrimClass (int))
return new java::lang::Integer (* (jint*) addr);
if (type == JvPrimClass (short))
return new java::lang::Short (* (jshort*) addr);
if (type == JvPrimClass (byte))
return new java::lang::Byte (* (jbyte*) addr);
if (type == JvPrimClass (char))
return new java::lang::Character (* (jchar*) addr);
if (type == JvPrimClass (boolean))
{
_Jv_InitClass (&java::lang::Boolean::class$);
if (* (jboolean*) addr)
return java::lang::Boolean::TRUE;
else
return java::lang::Boolean::FALSE;
}
throw new java::lang::IllegalArgumentException;
}
static void
setBoolean (jclass type, void *addr, jboolean value)
{
if (type == JvPrimClass (boolean))
* (jboolean *) addr = value;
else
throw new java::lang::IllegalArgumentException;
}
static void
setChar (jclass type, void *addr, jchar value)
{
if (type == JvPrimClass (char))
* (jchar *) addr = value;
else if (type == JvPrimClass (int))
* (jint *) addr = value;
else if (type == JvPrimClass (long))
* (jlong *) addr = value;
else if (type == JvPrimClass (float))
* (jfloat *) addr = value;
else if (type == JvPrimClass (double))
* (jdouble *) addr = value;
else
throw new java::lang::IllegalArgumentException;
}
static void
setByte (jclass type, void *addr, jbyte value)
{
if (type == JvPrimClass (byte))
* (jbyte *) addr = value;
else if (type == JvPrimClass (short))
* (jshort *) addr = value;
else if (type == JvPrimClass (int))
* (jint *) addr = value;
else if (type == JvPrimClass (long))
* (jlong *) addr = value;
else if (type == JvPrimClass (float))
* (jfloat *) addr = value;
else if (type == JvPrimClass (double))
* (jdouble *) addr = value;
else
throw new java::lang::IllegalArgumentException;
}
static void
setShort (jclass type, void *addr, jshort value)
{
if (type == JvPrimClass (short))
* (jshort *) addr = value;
else if (type == JvPrimClass (int))
* (jint *) addr = value;
else if (type == JvPrimClass (long))
* (jlong *) addr = value;
else if (type == JvPrimClass (float))
* (jfloat *) addr = value;
else if (type == JvPrimClass (double))
* (jdouble *) addr = value;
else
throw new java::lang::IllegalArgumentException;
}
static void
setInt (jclass type, void *addr, jint value)
{
if (type == JvPrimClass (int))
* (jint *) addr = value;
else if (type == JvPrimClass (long))
* (jlong *) addr = value;
else if (type == JvPrimClass (float))
* (jfloat *) addr = value;
else if (type == JvPrimClass (double))
* (jdouble *) addr = value;
else
throw new java::lang::IllegalArgumentException;
}
static void
setLong (jclass type, void *addr, jlong value)
{
if (type == JvPrimClass (long))
* (jlong *) addr = value;
else if (type == JvPrimClass (float))
* (jfloat *) addr = value;
else if (type == JvPrimClass (double))
* (jdouble *) addr = value;
else
throw new java::lang::IllegalArgumentException;
}
static void
setFloat (jclass type, void *addr, jfloat value)
{
if (type == JvPrimClass (float))
* (jfloat *) addr = value;
else if (type == JvPrimClass (double))
* (jdouble *) addr = value;
else
throw new java::lang::IllegalArgumentException;
}
static void
setDouble (jclass type, void *addr, jdouble value)
{
if (type == JvPrimClass (double))
* (jdouble *) addr = value;
else
throw new java::lang::IllegalArgumentException;
}
void
java::lang::reflect::Field::setBoolean (jclass caller, jobject obj, jboolean b,
jboolean checkFinal)
{
::setBoolean (this->getType(), getAddr (this, caller, obj, checkFinal), b);
}
void
java::lang::reflect::Field::setChar (jclass caller, jobject obj, jchar c,
jboolean checkFinal)
{
::setChar (this->getType(), getAddr (this, caller, obj, checkFinal), c);
}
void
java::lang::reflect::Field::setByte (jclass caller, jobject obj, jbyte b,
jboolean checkFinal)
{
::setByte (this->getType(), getAddr (this, caller, obj, checkFinal), b);
}
void
java::lang::reflect::Field::setShort (jclass caller, jobject obj, jshort s,
jboolean checkFinal)
{
::setShort (this->getType(), getAddr (this, caller, obj, checkFinal), s);
}
void
java::lang::reflect::Field::setInt (jclass caller, jobject obj, jint i,
jboolean checkFinal)
{
::setInt (this->getType(), getAddr (this, caller, obj, checkFinal), i);
}
void
java::lang::reflect::Field::setLong (jclass caller, jobject obj, jlong l,
jboolean checkFinal)
{
::setLong (this->getType(), getAddr (this, caller, obj, checkFinal), l);
}
void
java::lang::reflect::Field::setFloat (jclass caller, jobject obj, jfloat f,
jboolean checkFinal)
{
::setFloat (this->getType(), getAddr (this, caller, obj, checkFinal), f);
}
void
java::lang::reflect::Field::setDouble (jclass caller, jobject obj, jdouble d,
jboolean checkFinal)
{
::setDouble (this->getType(), getAddr (this, caller, obj, checkFinal), d);
}
void
java::lang::reflect::Field::set (jclass caller, jobject object, jobject value,
jclass type, jboolean checkFinal)
{
void* addr = getAddr (this, caller, object, checkFinal);
if (value != NULL && ! _Jv_IsInstanceOf (value, type))
throw new java::lang::IllegalArgumentException;
* (jobject*) addr = value;
}