⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 support.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * support.c * Native language support (excluding string routines). * * Copyright (c) 1996, 1997 *	Transvirtual Technologies, Inc.  All rights reserved. * * See the file "license.terms" for information on usage and redistribution  * of this file.  */#include "debug.h"#include "config.h"#include "config-std.h"#include "config-mem.h"#include "jni.h"#include <stdarg.h>#include "errors.h"#include "kaffe/jtypes.h"#include "gtypes.h"#include "access.h"#include "object.h"#include "constants.h"#include "baseClasses.h"#include "stringSupport.h"#include "lookup.h"#include "exception.h"#include "slots.h"#include "support.h"#ifndef HAVE_LIBFFI# define NEED_sysdepCallMethod 1#endif /* HAVE_LIBFFI */#include "classMethod.h"#include "machine.h"#include "md.h"#include "itypes.h"#include "external.h"#include "thread.h"#include "jthread.h"#include "locks.h"#if !defined(HAVE_GETTIMEOFDAY)#include <sys/timeb.h>#endif#define	MAXEXCEPTIONLEN		200#define	ERROR_SIGNATURE0	"()V"#define	ERROR_SIGNATURE		"(Ljava/lang/String;)V"/* Anchor point for user defined properties */userProperty* userProperties;#if defined(NO_SHARED_LIBRARIES)/* Internal native functions */static nativeFunction null_funcs[1];nativeFunction* native_funcs = null_funcs;#endif#ifdef HAVE_LIBFFI#include <ffi.h>static inline ffi_type *j2ffi(char type){	ffi_type *ftype;	switch (type) {	case 'J':		ftype = &ffi_type_sint64;		break;	case 'D':		ftype = &ffi_type_double;		break;	case 'F':		ftype = &ffi_type_float;		break;	default:		ftype = &ffi_type_uint;	}	return ftype;}#define sysdepCallMethod(CALL)						\do {									\	int i;								\	ffi_cif cif;							\	ffi_type *rtype;						\	ffi_type *argtypes[(CALL)->nrargs + 1];				\	void *argvals[(CALL)->nrargs + 1];				\	int fargs = 0;							\	for (i = 0; i < (CALL)->nrargs; i++) {				\		switch ((CALL)->callsize[i]) {				\		case 1:							\			argtypes[fargs] = j2ffi((CALL)->calltype[i]);	\			argvals[fargs] = &((CALL)->args[i].i);		\			fargs++;					\			break;						\		case 2:							\			argtypes[fargs] = j2ffi((CALL)->calltype[i]);	\			argvals[fargs] = &((CALL)->args[i].j);		\			fargs++;					\		default:						\			break;						\		}							\	}								\	rtype = j2ffi ((CALL)->rettype);				\	if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, fargs,			\	    rtype, argtypes) == FFI_OK) {				\		ffi_call(&cif, (CALL)->function, (CALL)->ret, argvals);	\	}								\	else								\		ABORT();						\} while (0);#endif /* HAVE_LIBFFI *//** * Call a Java method from native code. * * @param obj the obj or 0 if the method is static * @param method_name the name of the method to be called * @param signature the signature of the method to be called * @param mb pointer to the struct _methods of the method to be called * @param isStaticCall true if the call is static, otherwise false * @param argptr va_list of the arguments to be passed to the method * * @throws NoSuchMethodError method was not found * @throws NullPointerException if obj is 0 but method is not static * * @return the return value of the method to be called */jvaluedo_execute_java_method_v(void* obj, const char* method_name, const char* signature, Method* mb, int isStaticCall, va_list argptr){	jvalue retval;	errorInfo info;	if (obj == 0 && (! isStaticCall || ! mb)) {		throwException(NullPointerException);	}	if (mb == 0) {		assert(method_name != 0 && signature != 0);		if (isStaticCall) {			mb = lookupClassMethod((Hjava_lang_Class*)obj, method_name, signature, &info);		}		else {			mb = lookupObjectMethod((Hjava_lang_Object*)obj, method_name, signature, &info);		}	}	/* No method or wrong type - throw exception */	if (mb == 0) {		throwError(&info);	}	else if (isStaticCall && (mb->accflags & ACC_STATIC) == 0) {		throwException(NoSuchMethodError(method_name));	}	else if (!isStaticCall && (mb->accflags & ACC_STATIC) != 0) {		throwException(NoSuchMethodError(method_name));	}	callMethodV(mb, METHOD_INDIRECTMETHOD(mb), obj, argptr, &retval);	return (retval);}/** * Call a Java method from native code. * * @param obj the obj or 0 if the method is static * @param method_name the name of the method to be called * @param signature the signature of the method to be called * @param mb pointer to the struct _methods of the method to be called * @param isStaticCall true if the call is static, otherwise false * @param ... the arguments to be passed to the method * * @return the return value of the method to be called */jvaluedo_execute_java_method(void* obj, const char* method_name, const char* signature, Method* mb, int isStaticCall, ...){	va_list argptr;	jvalue retval;	assert(method_name != 0 || mb != 0);	va_start(argptr, isStaticCall);	retval = do_execute_java_method_v(obj, method_name, signature, mb, isStaticCall, argptr);	va_end(argptr);	return (retval);}/** * Call a Java static method on a class from native code. * * @param cname name of the class whose method is to be called * @param loader the class loader that's to be used to lookup the class * @param method_name the name of the method to be called * @param signature the signature of the method to be called * @param argptr the arguments to be passed to the method * * @throws NuSuchMethodError if method cannot be found *  * @return the return value of the method */jvaluedo_execute_java_class_method_v(const char* cname,	Hjava_lang_ClassLoader* loader, const char* method_name,	const char* signature, va_list argptr){	Hjava_lang_Class* clazz;	errorInfo info;	Method* mb = 0;	jvalue retval;	char *buf;	/* Convert "." to "/" and lookup class */	buf = checkPtr(KMALLOC(strlen(cname) + 1));	classname2pathname(cname, buf);	clazz = lookupClass(buf, loader, &info);	KFREE(buf);	/* Get method */	if (clazz != 0) {		mb = lookupClassMethod(clazz, method_name, signature, &info);	}	if (mb == 0) {		throwError(&info);	}	/* Method must be static to invoke it here */	if ((mb->accflags & ACC_STATIC) == 0) {		throwException(NoSuchMethodError(method_name));	}	/* Make the call */	callMethodV(mb, METHOD_INDIRECTMETHOD(mb), 0, argptr, &retval);	return (retval);}/** * Call a Java static method on a class from native code. * * @param cname name of the class whose method is to be called * @param loader the class loader that's to be used to lookup the class * @param method_name the name of the method to be called * @param signature the signature of the method to be called * @param ... the arguments to be passed to the method * * @return the return value of the method */jvaluedo_execute_java_class_method(const char* cname, Hjava_lang_ClassLoader*loader,	const char* method_name, const char* signature, ...){	va_list argptr;	jvalue retval;	va_start(argptr, signature);	retval = do_execute_java_class_method_v(cname, loader, method_name, signature, argptr);	va_end(argptr);	return (retval);}/** * Allocate an object and execute the constructor. * * @param cname the name of the class to be instantiated (may be 0 if cc is != 0) * @param loader the class loader that's to be used to lookup the class * @param cc the class to be instantiated (may be 0 if cname is != 0) * @param signature the signature of the constructor to be executed * @param argptr arguments to be passed to the constructor * * @throws InstantiationException if class is an interface or abstract * @throws NoSuchMethodError if the specified constructor cannot be found * * @return the newly allocated object */Hjava_lang_Object*execute_java_constructor_v(const char* cname, Hjava_lang_ClassLoader* loader,	Hjava_lang_Class* cc, const char* signature, va_list argptr){	Hjava_lang_Object* obj;	Method* mb;	jvalue retval;	errorInfo info;	Utf8Const* sig;	if (cc == 0) {		char *buf;		/* Convert "." to "/" and lookup class */		buf = checkPtr(KMALLOC(strlen(cname) + 1));		classname2pathname(cname, buf);		cc = lookupClass(buf, loader, &info);		KFREE(buf);		if (!cc) {			throwError(&info);		}	}	/* We cannot construct interfaces or abstract classes */	if (CLASS_IS_INTERFACE(cc) || CLASS_IS_ABSTRACT(cc)) {		throwException(InstantiationException(cc->name->data));	}	if (cc->state < CSTATE_USABLE) {		if (processClass(cc, CSTATE_COMPLETE, &info) == false) {			throwError(&info);		}	}	sig = checkPtr(utf8ConstNew(signature, -1));	mb = findMethodLocal(cc, constructor_name, sig);	utf8ConstRelease(sig);	if (mb == 0) {		throwException(NoSuchMethodError(constructor_name->data));	}	obj = newObject(cc);	assert(obj != 0);	/* Make the call */	callMethodV(mb, METHOD_INDIRECTMETHOD(mb), obj, argptr, &retval);	return (obj);}/** * Allocate an object and execute the constructor. * * @param cname the name of the class to be instantiated * @param loader the class loader that's to be used to lookup the class * @param cc the class to be instantiated * @param signature the signature of the constructor to be executed * @param ... arguments to be passed to the constructor * * @return the new allocated object */Hjava_lang_Object*execute_java_constructor(const char* cname, Hjava_lang_ClassLoader* loader,	Hjava_lang_Class* cc, const char* signature, ...){	va_list argptr;	Hjava_lang_Object* obj;	va_start(argptr, signature);	obj = execute_java_constructor_v(cname, loader, cc, signature, argptr);	va_end(argptr);	return (obj);}/* This is defined in the alpha port.  It causes all integer arguments   to be promoted to jlong, and all jfloats to be promoted to jdouble,   unless explicitly overridden.  It implies NO_HOLES, unless   explicitly defined otherwise.  */#if PROMOTE_TO_64bits# ifndef PROMOTE_jint2jlong#  define PROMOTE_jint2jlong 1# endif# ifndef PROMOTE_jfloat2jdouble#  define PROMOTE_jfloat2jdouble 1# endif/* NO_HOLES causes all types to occupy only one slot in callargs, but   not affecting their callsizes, that can still be used to   distinguish among types.  */# ifndef NO_HOLES#  define NO_HOLES 1# endif#endif/* If PROMOTE_jint2jlong is enabled, all integer values are to be   passed as jlongs.  It is only set by PROMOTE_TO_64bits.  */#if PROMOTE_jint2jlong# define PROM_i j#else# define PROM_i i#endif/* If PROMOTE_jfloat2jdouble is enabled, jfloats are to be passed as   jdoubles.  Note that, when a jfloat is promoted, its calltype will   be marked as 'D'.  No known port uses this.  In fact, alpha must   explicitly set it to 0, to prevent PROMOTE_TO_64bits from enabling   it.  */#if PROMOTE_jfloat2jdouble# define PROM_f d#else# define PROM_f f#endif/* This is currently defined in the MIPS O32 port.  It causes jlongs   and jdoubles to be forced into even arguments, by introducing a   padding integer argument. The argument DO is used to adjust the   input argument list.  */#if ALIGN_AT_64bits# if NO_HOLES#  error "ALIGN_AT_64bits is incompatible with NO_HOLES"# endif# define ENSURE_ALIGN64(DO) do { \		if (call.callsize[i] == 2 && (i & 1)) { \			char tmptype = call.calltype[i]; \			call.callsize[i] = 0; \			call.calltype[i] = 'I'; \			DO; \			++i; ++s; \			call.calltype[i] = tmptype; \			call.callsize[i] = 2; \		} \	} while (0)#else# define ENSURE_ALIGN64(DO) do {} while (0)#endif/** * Generic routine to call a native or Java method (array style). * * @param meth the struct _methods of the method to be executed * @param func the code that's to be executed * @param obj  the object whose method is to be called (my be 0 iff method is static) * @param args the arguments to be passed to the method * @param ret  buffer for the return value of the method (may be 0 iff return type is void) * @param promoted true iff 64 bit values occupy two entries in args, otherwise false */voidcallMethodA(Method* meth, void* func, void* obj, jvalue* args, jvalue* ret,	    int promoted){	int i;	int j;	int s;	/* XXX call.callsize and call.calltype arrays are statically sized 	   and are not checked for running out of bounds */	callMethodInfo call;		jvalue in[MAXMARGS];	jvalue tmp;	if (ret == 0) {		ret = &tmp;	}	i = 0;	s = 0;#if defined(INTERPRETER)	/*	 * If the method is native, we must find it so that we know whether	 * it is a JNI method or not.  If it is one, ACC_JNI will be set	 * upon return from native and we will add additional parameters 	 * according to the JNI calling convention.	 */	meth = (Method*)func;	if (meth->accflags & ACC_NATIVE) {		if (!METHOD_TRANSLATED(meth)) {			errorInfo info;			if (native(meth, &info) == false) {				throwError(&info);			}		}		call.function = METHOD_NATIVECODE(meth);	}	/* Insert the JNI environment */	if (meth->accflags & ACC_JNI) {		call.callsize[i] = PTR_TYPE_SIZE / SIZEOF_INT;		call.calltype[i] = 'L';		in[i].l = THREAD_JNIENV(); 		s += call.callsize[i];		i++;		/* If method is static we must insert the class as an argument */		if (meth->accflags & ACC_STATIC) {			call.callsize[i] = PTR_TYPE_SIZE / SIZEOF_INT;			s += call.callsize[i];			call.calltype[i] = 'L';			in[i].l = meth->class;			i++;		}	} #endif	/* If this method isn't static, we must insert the object as	 * an argument. 	 */	if ((meth->accflags & ACC_STATIC) == 0) {		call.callsize[i] = PTR_TYPE_SIZE / SIZEOF_INT;		s += call.callsize[i];		call.calltype[i] = 'L';		in[i].l = obj;		i++;	}	for (j = 0; j < METHOD_NARGS(meth); i++, j++) {		call.calltype[i] = *METHOD_ARG_TYPE(meth, j);		switch (call.calltype[i]) {		case 'Z':			if (promoted) goto use_int;			call.callsize[i] = 1;			in[i].PROM_i = args[j].z;			break;		case 'S':			if (promoted) goto use_int;			call.callsize[i] = 1;			in[i].PROM_i = args[j].s;			break;		case 'B':			if (promoted) goto use_int;			call.callsize[i] = 1;			in[i].PROM_i = args[j].b;			break;		case 'C':			if (promoted) goto use_int;			call.callsize[i] = 1;			in[i].PROM_i = args[j].c;			break;		case 'F':			call.callsize[i] = 1;			in[i].PROM_f = args[j].f;#if PROMOTE_jfloat2jdouble			call.calltype[i] = 'D';#endif			break;		case 'I':		use_int:			call.callsize[i] = 1;			in[i].PROM_i = args[j].i;			break;		case 'D':		case 'J':			call.callsize[i] = 2;			ENSURE_ALIGN64({});			in[i] = args[j];			if (promoted) { /* compensate for the second array element by incrementing args */			  args++;			}#if ! NO_HOLES			s += call.callsize[i];			in[i+1].i = (&in[i].i)[1];			i++; 			call.calltype[i] = 0;			call.callsize[i] = 0;#endif			break;		case '[':			call.calltype[i] = 'L';			/* fall through */		case 'L':			call.callsize[i] = PTR_TYPE_SIZE / SIZEOF_INT;			in[i] = args[j];			break;		default:			ABORT();		}		s += call.callsize[i];	}#if defined(STACK_LIMIT)	call.calltype[i] = 'L';	call.callsize[i] = PTR_TYPE_SIZE / SIZEOF_INT;	in[i].l = jthread_stacklimit();	s += PTR_TYPE_SIZE / SIZEOF_INT;	i++;#endif	/* Return info */	call.rettype = *METHOD_RET_TYPE(meth);	switch (call.rettype) {	case '[':		call.rettype = 'L';		/* fall through */	case 'L':		call.retsize = PTR_TYPE_SIZE / SIZEOF_INT;		break;	case 'V':		call.retsize = 0;		break;	case 'D':	case 'J':		call.retsize = 2;		break;	default:		call.retsize = 1;		break;	}	/* Call info and arguments */	call.nrargs = i;	call.argsize = s;	call.args = in;	call.ret = ret;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -