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

📄 machine.c

📁 java virtual machince kaffe
💻 C
字号:
/* * machine.c * Java virtual machine interpreter. * * Copyright (c) 1996, 1997 *	Transvirtual Technologies, Inc.  All rights reserved. * * Copyright (c) 2004 *	Kaffe.org contributors, see ChangeLog for details.  All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "debug.h"#define	CDBG(s) 	DBG(INT_VMCALL, s)#define	RDBG(s) 	DBG(INT_RETURN, s)#define	NDBG(s) 	DBG(INT_NATIVE, s)#define	IDBG(s)		DBG(INT_INSTR, s)#define	CHDBG(s)	DBG(INT_CHECKS, s)#include "config.h"#include "config-std.h"#include "config-math.h"#include "config-mem.h"#include "config-setjmp.h"#include "access.h"#include "baseClasses.h"#include "bytecode.h"#include "checks.h"#include "code-analyse.h"#include "constants.h"#include "classMethod.h"#include "errors.h"#include "exception.h"#include "external.h"#include "gc.h"#include "gtypes.h"#include "icode.h"#include "jthread.h"#include "locks.h"#include "lookup.h"#include "machine.h"#include "md.h"#include "object.h"#include "slots.h"#include "soft.h"#include "support.h"#include "thread.h"/* * Define information about this engine. */const char* engine_name = "Interpreter";#define EXPLICIT_CHECK_NULL(_i, _s, _n)                       \      cbranch_ref_const_ne((_s), 0, reference_label(_i, _n)); \      softcall_nullpointer();                                 \      set_label(_i, _n)/* Define CREATE_NULLPOINTER_CHECKS in md.h when your machine cannot use the * MMU for detecting null pointer accesses */#if defined(CREATE_NULLPOINTER_CHECKS)#define CHECK_NULL(_i, _s, _n)                                  \    EXPLICIT_CHECK_NULL(_i, _s, _n)#else#define CHECK_NULL(_i, _s, _n)#endif/* For JIT3 compatibility */#define check_array_store(a,b)		softcall_checkarraystore(a,b)#define explicit_check_null(x,obj,y)	EXPLICIT_CHECK_NULL(x,obj,y)#if defined(KAFFE_VMDEBUG)#define check_null(x,obj,y)		EXPLICIT_CHECK_NULL(x,obj,y)#else#define check_null(x,obj,y)		CHECK_NULL(x,obj,y)#endif#define check_div(x,obj,y)#define check_div_long(x,obj,y)#ifdef DIRECT_THREADING#define	define_insn(code)	INSN_LBL_##code: \				IDBG( dprintf("%03ld: %s\n", (long) pc, #code); );#define	define_insn_alias(code)	INSN_LBL_##code: \				IDBG( dprintf("%03ld: %s\n", (long) pc, #code); );#define	define_wide_insn(code)	break;					\				case code:				\				IDBG( dprintf("%03ld: %s\n", (long) pc, #code); );#define define_insn_fini { \		pc = npc; \		assert(npc < (uintp)(meth->c.bcode.codelen)); \		vmExcept_setPC(mjbuf, pc); \		npc = pc + insnLen[code[pc]]; \		goto *insn_handlers[code[pc]]; \	}	#define INTRP_SW_HEAD() goto *insn_handlers[code[pc]];#define INTRP_SW_PROLOG() \INSN_LBL_INVALID: { \	CHDBG(dprintf("Unknown bytecode %d\n", code[pc]); ); \		throwException(NEW_LANG_EXCEPTION(VerifyError)); \		goto *insn_handlers[code[npc]]; }#else#define	define_insn(code)	case code:				\				IDBG( dprintf("%03ld: %s\n", (long) pc, #code); );#define	define_insn_alias(code)	case code:				\				IDBG( dprintf("%03ld: %s\n", (long) pc, #code); );#define	define_wide_insn(code)	break;					\				case code:				\				IDBG( dprintf("%03ld: %s\n", (long) pc, #code); );#define define_insn_fini		break;#define INTRP_SW_HEAD() switch(code[pc])#define INTRP_SW_PROLOG() \		default: \			CHDBG(dprintf("Unknown bytecode %d\n", code[pc]); ); \			throwException(NEW_LANG_EXCEPTION(VerifyError)); \			break#endif#if defined(KAFFE_PROFILER)int profFlag;			 /* flag to control profiling */#endifvoid runVirtualMachine(methods *meth, slots *lcl, slots *sp, uintp npc, slots *retval, volatile VmExceptHandler *mjbuf, threadData *thread_data);voidvirtualMachine(methods*volatile meth, slots* volatile arg, slots* volatile retval, threadData* volatile thread_data){	methods *volatile const vmeth = meth;	Hjava_lang_Object* volatile mobj;	VmExceptHandler mjbuf;	accessFlags methaccflags;	kaffeClassFlags methkflags;	slots* lcl;	slots* sp;	uintp npc;	int32 idx;	jint low;	errorInfo einfo;	/* implement stack overflow check */	if (KTHREAD(stackcheck)(thread_data->needOnStack) == false) {		if (thread_data->needOnStack == STACK_LOW) {			CHDBG(			    dprintf(			    "Panic: unhandled StackOverflowError()\n");			);			KAFFEVM_ABORT();		}			{			Hjava_lang_Throwable *th;			errorInfo soeinfo;			thread_data->needOnStack = STACK_LOW;			th = (Hjava_lang_Throwable *)newObjectChecked (javaLangStackOverflowError, &soeinfo);			thread_data->needOnStack = STACK_HIGH;					throwException(th);		}	}CDBG(	dprintf("Call: %s.%s%s.\n", meth->class->name->data, meth->name->data, METHOD_SIGD(meth)); );	/* If this is native, then call the real function */	methaccflags = meth->accflags;	methkflags = meth->kFlags;#if defined(ENABLE_JVMPI)	if (methaccflags & ACC_STATIC)	  soft_enter_method(NULL, meth);	else	  soft_enter_method(((jvalue*)arg)[0].l, meth);#endif	if (methodIsNative(meth)) {NDBG(		dprintf("Call to native %s.%s%s.\n", meth->class->name->data, meth->name->data, METHOD_SIGD(meth)); );		if (methaccflags & ACC_STATIC) {			KaffeVM_callMethodA(meth, meth, 0, (jvalue*)arg, (jvalue*)retval, 1);		}		else {			KaffeVM_callMethodA(meth, meth, ((jvalue*)arg)[0].l, &((jvalue*)arg)[1], (jvalue*)retval, 1);		}#if defined(ENABLE_JVMPI)		soft_exit_method(meth);#endif		return;	}	/* Analyze method if required */	if ((methkflags & KFLAG_VERIFIED) == 0) {		codeinfo* codeInfo;		bool success = analyzeMethod(meth, &codeInfo, &einfo);		tidyAnalyzeMethod(&codeInfo);		if (success == false) {			throwError(&einfo);		}	}	/* Allocate stack space and locals. */	lcl = alloca(sizeof(slots) * (meth->localsz + meth->stacksz));#if defined(KAFFE_VMDEBUG)	{	    int32 *p = (int32 *) &lcl[meth->localsz + meth->stacksz];	    while (p-- > (int32*)lcl)		*p = UNINITIALIZED_STACK_SLOT;	}#endif	mobj = 0;	npc = 0;	/* If we have any exception handlers we must prepare to catch them.	 * We also need to catch if we are synchronised (so we can release it).	 */	setupExceptionHandling(&mjbuf, meth, mobj, thread_data);	if (meth->exception_table != 0) {		if (JTHREAD_SETJMP(mjbuf.jbuf) != 0) {			meth = vmeth;			thread_data->exceptPtr = &mjbuf;			npc = vmExcept_getPC(&mjbuf);			sp = &lcl[meth->localsz];#if defined(KAFFE_VMDEBUG)			{			    int32 *p = (int32 *) &lcl[meth->localsz + meth->stacksz];			    while (p-- > (int32*)sp)				*p = 0xdeadbeef;			}#endif			sp->v.taddr = (void*)thread_data->exceptObj;			thread_data->exceptObj = 0;			runVirtualMachine(meth, lcl, sp, npc, retval, &mjbuf, thread_data);			goto end;		}	}	/* Calculate number of arguments */	idx = sizeofSigMethod(meth, false);	if (idx == -1) {	  postException(&einfo,  JAVA_LANG(InternalError));	  throwError(&einfo);	}	idx += (methaccflags & ACC_STATIC ? 0 : 1);	/* Copy in the arguments */	sp = lcl;	for (low = 0; low < idx; low++) {		*(sp++) = *(arg++);	}	/* Sync. if required */	if (methaccflags & ACC_SYNCHRONISED) {		if (methaccflags & ACC_STATIC) {			mobj = &meth->class->head;		}		else {			mobj = (Hjava_lang_Object*)lcl[0].v.taddr;		}		/* this lock is safe for Thread.stop() */		locks_internal_lockMutex(&mobj->lock, 0);		/*		 * We must store the object on which we synchronized		 * in the mjbuf chain for the exception handler		 * routine to find it (and unlock it when unwinding).		 */		vmExcept_setSyncObj(&mjbuf, mobj);	}	sp = &lcl[meth->localsz - 1];	runVirtualMachine(meth, lcl, sp, npc, retval, &mjbuf, thread_data); end:	/* Unsync. if required */	if (mobj != 0) {		locks_internal_unlockMutex(&mobj->lock, NULL); 	}	cleanupExceptionHandling(&mjbuf, thread_data);#if defined(ENABLE_JVMPI)	soft_exit_method(meth);#endifRDBG(	dprintf("Returning from method %s%s.\n", meth->name->data, METHOD_SIGD(meth)); );}void runVirtualMachine(methods *meth, slots *lcl, slots *sp, uintp npc, slots *retval, volatile VmExceptHandler *mjbuf, threadData *thread_data) {	bytecode *code = (bytecode*)meth->c.bcode.code;#ifdef DIRECT_THREADING#define IH(name) &&INSN_LBL_##name#define IH_INVALID &&INSN_LBL_INVALIDstatic const void *insn_handlers[] = {                                                  	/* opcodes */    IH(NOP),		IH(ACONST_NULL),	IH(ICONST_M1), 		IH(ICONST_0),		/* 0-3 */    IH(ICONST_1),	IH(ICONST_2),		IH(ICONST_3),		IH(ICONST_4),		/* 4-7 */    IH(ICONST_5),	IH(LCONST_0),		IH(LCONST_1),		IH(FCONST_0),		/* 8-11 */    IH(FCONST_1),	IH(FCONST_2),		IH(DCONST_0),		IH(DCONST_1),		/* 12-15 */    IH(BIPUSH),		IH(SIPUSH),		IH(LDC1),		IH(LDC2),		/* 16-19 */    IH(LDC2W),		IH(ILOAD),		IH(LLOAD),		IH(FLOAD),		/* 20-23 */    IH(DLOAD),		IH(ALOAD),		IH(ILOAD_0),		IH(ILOAD_1),		/* 24-27 */    IH(ILOAD_2),	IH(ILOAD_3),		IH(LLOAD_0),		IH(LLOAD_1),		/* 28-31 */    IH(LLOAD_2),	IH(LLOAD_3),		IH(FLOAD_0),		IH(FLOAD_1),		/* 32-35 */    IH(FLOAD_2),	IH(FLOAD_3),		IH(DLOAD_0),		IH(DLOAD_1),		/* 36-39 */    IH(DLOAD_2),	IH(DLOAD_3),		IH(ALOAD_0),		IH(ALOAD_1),		/* 40-43 */    IH(ALOAD_2),	IH(ALOAD_3),		IH(IALOAD),		IH(LALOAD),		/* 44-47 */    IH(FALOAD),		IH(DALOAD),		IH(AALOAD),		IH(BALOAD),		/* 48-51 */    IH(CALOAD),		IH(SALOAD),		IH(ISTORE),		IH(LSTORE),		/* 52-55 */    IH(FSTORE),		IH(DSTORE),		IH(ASTORE),		IH(ISTORE_0),		/* 56-59 */    IH(ISTORE_1),	IH(ISTORE_2),		IH(ISTORE_3),		IH(LSTORE_0),		/* 60-63 */    IH(LSTORE_1),	IH(LSTORE_2),		IH(LSTORE_3),		IH(FSTORE_0),		/* 64-67 */    IH(FSTORE_1),	IH(FSTORE_2),		IH(FSTORE_3),		IH(DSTORE_0),   	/* 68-71 */    IH(DSTORE_1),	IH(DSTORE_2),		IH(DSTORE_3),		IH(ASTORE_0),   	/* 72-75 */    IH(ASTORE_1),	IH(ASTORE_2),		IH(ASTORE_3),		IH(IASTORE),		/* 76-79 */    IH(LASTORE),	IH(FASTORE),		IH(DASTORE),		IH(AASTORE),		/* 80-83 */    IH(BASTORE),	IH(CASTORE),		IH(SASTORE),		IH(POP),		/* 84-87 */    IH(POP2),		IH(DUP),		IH(DUP_X1),		IH(DUP_X2),		/* 88-91 */    IH(DUP2),		IH(DUP2_X1),		IH(DUP2_X2),		IH(SWAP),		/* 92-95 */    IH(IADD),		IH(LADD),		IH(FADD),		IH(DADD),		/* 96-99 */    IH(ISUB),		IH(LSUB),		IH(FSUB),		IH(DSUB),		/* 100-103 */    IH(IMUL),		IH(LMUL),		IH(FMUL),		IH(DMUL),		/* 104-107 */    IH(IDIV),		IH(LDIV),		IH(FDIV),		IH(DDIV),		/* 108-111 */    IH(IREM),		IH(LREM),		IH(FREM),		IH(DREM),		/* 112-115 */    IH(INEG),		IH(LNEG),		IH(FNEG),		IH(DNEG),		/* 116-119 */    IH(ISHL),		IH(LSHL),		IH(ISHR),		IH(LSHR),		/* 120-123 */    IH(IUSHR),		IH(LUSHR),		IH(IAND),		IH(LAND),		/* 124-127 */    IH(IOR),		IH(LOR),		IH(IXOR),		IH(LXOR),		/* 128-131 */    IH(IINC),		IH(I2L),		IH(I2F),		IH(I2D),		/* 132-135 */    IH(L2I),		IH(L2F),		IH(L2D),		IH(F2I),		/* 136-139 */    IH(F2L),		IH(F2D),		IH(D2I),		IH(D2L),		/* 140-143 */    IH(D2F),		IH(INT2BYTE),		IH(INT2CHAR),		IH(INT2SHORT),		/* 144-147 */    IH(LCMP),		IH(FCMPL),		IH(FCMPG),		IH(DCMPL),		/* 148-151 */    IH(DCMPG),		IH(IFEQ),		IH(IFNE),		IH(IFLT),		/* 152-155 */    IH(IFGE),		IH(IFGT),		IH(IFLE),		IH(IF_ICMPEQ),		/* 156-159 */    IH(IF_ICMPNE),	IH(IF_ICMPLT),		IH(IF_ICMPGE),		IH(IF_ICMPGT),		/* 160-163 */    IH(IF_ICMPLE),	IH(IF_ACMPEQ),		IH(IF_ACMPNE),		IH(GOTO),		/* 164-167 */    IH(JSR),		IH(RET),		IH(TABLESWITCH),	IH(LOOKUPSWITCH), 	/* 168-171 */    IH(IRETURN),	IH(LRETURN),		IH(FRETURN),		IH(DRETURN),		/* 172-175 */    IH(ARETURN),	IH(RETURN),		IH(GETSTATIC),		IH(PUTSTATIC),		/* 176-179 */    IH(GETFIELD),	IH(PUTFIELD),		IH(INVOKEVIRTUAL),	IH(INVOKESPECIAL), 	/* 180-183 */    IH(INVOKESTATIC),	IH(INVOKEINTERFACE),	IH_INVALID,		IH(NEW),		/* 184-187 */    IH(NEWARRAY),	IH(ANEWARRAY),		IH(ARRAYLENGTH),	IH(ATHROW),		/* 188-191 */    IH(CHECKCAST),	IH(INSTANCEOF),		IH(MONITORENTER),	IH(MONITOREXIT),	/* 192-195 */    IH(WIDE),		IH(MULTIANEWARRAY),	IH(IFNULL),		IH(IFNONNULL),		/* 196-199 */    IH(GOTO_W),		IH(JSR_W),		IH(BREAKPOINT),		IH_INVALID,		/* 200-203 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 204-207 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 208-211 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 212-215 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 216-219 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 220-223 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 224-227 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 228-231 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 232-235 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 236-239 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 240-243 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 244-247 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID,		/* 248-251 */    IH_INVALID,		IH_INVALID,		IH_INVALID,		IH_INVALID		/* 252-255 */};#undef IH#endif	/* Misc machine variables */	jvalue tmpl;	slots tmp[1];	slots tmp2[1];	slots mtable[1];	/* Variables used directly in the machine */	int32 idx;	jint low;	jint high;	/* Call, field and creation information */	callInfo cinfo;	fieldInfo finfo;	Hjava_lang_Class* crinfo;	errorInfo einfo;	/* Finally we get to actually execute the machine */	for (;;) {		register uintp pc = npc;		assert(npc < (uintp)(meth->c.bcode.codelen));		vmExcept_setPC(mjbuf, pc);		npc = pc + insnLen[code[pc]];		INTRP_SW_HEAD() {		    INTRP_SW_PROLOG();#include "kaffe.def"		} // INTRP_SW_HEAD()	} end:	return;}/* * say what engine we're using */const char*getEngine(void){	return "kaffe.intr";}void initEngine(void){}static inline void setFrame(VmExceptHandler* eh,	 struct _jmethodID* meth,	 struct Hjava_lang_Object* syncobj){	assert(eh);	assert(meth);		eh->meth = meth;	eh->frame.intrp.pc = 0;	eh->frame.intrp.syncobj = syncobj;}voidsetupExceptionHandling(VmExceptHandler* eh,		       struct _jmethodID* meth,		       struct Hjava_lang_Object* syncobj,		       threadData*	thread_data){  setFrame(eh, meth, syncobj);  eh->prev = thread_data->exceptPtr;  thread_data->exceptPtr = eh;}voidcleanupExceptionHandling(VmExceptHandler* eh,			 threadData* thread_data) {  thread_data->exceptPtr = eh->prev;}

⌨️ 快捷键说明

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