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

📄 machine.c

📁 java virtual machince kaffe
💻 C
📖 第 1 页 / 共 2 页
字号:
/* machine.c * Translate the Kaffe instruction set to the native one. * * 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 "config.h"#include "debug.h"#include "config-std.h"#include "config-mem.h"#include "classMethod.h"#include "gtypes.h"#include "kaffe/jmalloc.h"#include "bytecode.h"#include "slots.h"#include "registers.h"#include "seq.h"#include "gc.h"#include "machine.h"#include "basecode.h"#include "icode.h"#include "icode_internal.h"#include "labels.h"#include "constpool.h"#include "codeproto.h"#include "checks.h"#include "access.h"#include "object.h"#include "constants.h"#include "baseClasses.h"#include "code.h"#include "access.h"#include "lookup.h"#include "exception.h"#include "errors.h"#include "md.h"#include "locks.h"#include "code-analyse.h"#include "external.h"#include "soft.h"#include "stringSupport.h"#include "jni.h"#include "thread.h"#include "jthread.h"#include "stats.h"#include "support.h"#include "native-wrapper.h"#include "jvmpi_kaffe.h"/* * Define information about this engine. */char* engine_name = "Just-in-time";iStaticLock	translatorlock;		/* lock to protect the variables below */int stackno;int maxStack;int maxLocal;int maxTemp;int maxArgs;int maxPush;int isStatic;int tmpslot;int argcount = 0;		/* Function call argument count */uint32 pc;uint32 npc;jitflags willcatch;#define EXPLICIT_CHECK_NULL(_i, _s, _n)                       \      cbranch_ref_const_ne((_s), NULL, 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/* * If we rely on the MMU to catch null pointer accesses, we must spill * the registers to their home locations if that exception can be caught, * since the exception handler will load its registers from there. * For now, we use prepare_function_call() to do that. (Tim?) */#define CHECK_NULL(_i, _s, _n)	\	if (canCatch(NULLPOINTER)) {		\		prepare_function_call();  	\	}#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)#define check_null(x,obj,y)		CHECK_NULL(x,obj,y)#define check_div(x,obj,y)#define check_div_long(x,obj,y)/* Unit in which code block is increased when overrun */#define	ALLOCCODEBLOCKSZ	8192/* Codeblock redzone - allows for safe overrun when generating instructions */#define	CODEBLOCKREDZONE	256nativecode* codeblock;int codeblock_size;static int code_generated;static int bytecode_processed;static int codeperbytecode;int CODEPC;Method *globalMethod;#if defined(KAFFE_PROFILER)int profFlag; /* flag to control profiling */static void printProfilerStats(void);#endifstruct {	int time;} jitStats;static void generateInsnSequence(codeinfo* codeInfo);static void checkCaughtExceptions(Method* meth, unsigned int pc);void	endBlock(sequence*);void	startBlock(sequence*);void	endSubBlock(sequence*);void	startSubBlock(sequence*);void	cancelNoWriteback(void);jlong	currentTime(void);static JTHREAD_JMPBUF JIT_jumpExitWithOOM;void KaffeJIT_exitWithOOM(){  JTHREAD_LONGJMP(JIT_jumpExitWithOOM, 1);}bool KaffeJIT_setupExitWithOOM(struct _errorInfo* einfo){  if (!JTHREAD_SETJMP(JIT_jumpExitWithOOM))    return false;  postOutOfMemory(einfo);  return true;}/* * By default, we comply with the Java spec and turn stack overflow checks * on.  Note that this involves a noticeable performance penalty.  If you * feel adventurous, undef this. */#define CHECK_STACKOVERFLOW#if defined(CHECK_STACKOVERFLOW)static void checkStackOverflow(void){	/* XXX fix this.  	 * We should not have to access current just to do the stack check	 */	threadData *thread_data = KTHREAD(get_data)(KTHREAD(current)());	if (KTHREAD(stackcheck)(thread_data->needOnStack)) {		return;	}		if (thread_data->needOnStack == STACK_LOW) {		dprintf(			"Panic: unhandled StackOverflowError()\n");		KAFFEVM_ABORT();	}		{		Hjava_lang_Throwable *th;		errorInfo einfo;		thread_data->needOnStack = STACK_LOW;		th = (Hjava_lang_Throwable *)newObjectChecked (javaLangStackOverflowError, &einfo);		thread_data->needOnStack = STACK_HIGH;		throwException(th);	}}#endif /* CHECK_STACKOVERFLOW *//* * Translate a method into native code. * * Return true if successful, false otherwise. */booltranslate(Method* meth, errorInfo *einfo){	jint low;	jint high;	jvalue tmpl;	int idx;	SlotInfo* tmp;	SlotInfo* tmp2;	SlotInfo* mtable;	bytecode* base;	unsigned int len;	callInfo cinfo;	fieldInfo finfo;	Hjava_lang_Class* crinfo;	bool success = true;	nativeCodeInfo ncode;	codeinfo* codeInfo;	int64 tms = 0;	int64 tme;	static Method* jitting = NULL;	/* DEBUG */	lockClass(meth->class);	/* Must check the translation	 * hasn't been done by someone else once we get it.	 */	if (METHOD_TRANSLATED(meth)) {		goto done3;	}	if (Kaffe_JavaVMArgs.enableVerboseJIT) {		tms = currentTime();	}DBG(MOREJIT,	dprintf("asked to translate = %s.%s(%s)\n", 	    meth->class->name->data, meth->name->data, METHOD_SIGD(meth));	    );	/* If this code block is native, then just set it up and return */	if (methodIsNative(meth)) {		void *func = native(meth, einfo);		if (func == NULL) {			success = false;			goto done3;		}		engine_create_wrapper(meth, func);		KAFFEJIT_TO_NATIVE(meth);		/* Note that this is a real function not a trampoline.  */		if (meth->c.ncode.ncode_end == 0)			meth->c.ncode.ncode_end = METHOD_NATIVECODE(meth);		goto done3;	}	/* Scan the code and determine the basic blocks */	success = analyzeMethod(meth, &codeInfo, einfo); 	if (success == false) {		if (METHOD_TRANSLATED(meth))			success = true;		goto done3;	}DBG(MOREJIT,	dprintf("successfully verified = %s.%s(%s)\n", 	    meth->class->name->data, meth->name->data, METHOD_SIGD(meth));	    );	/* Only one in the translator at once. */	enterTranslator();	startTiming(&jit_time, "jittime");	if (KaffeJIT_setupExitWithOOM(einfo))	  {	    success = false;	    goto done2;	  }#if defined(KAFFE_PROFILER)	if (profFlag) {		static int init = 0;		if (!init) {			atexit(printProfilerStats);			init = 1;		}		profiler_get_clicks(meth->jitClicks);		meth->callsCount = 0;		meth->totalClicks = 0;		meth->totalChildrenClicks = 0;		globalMethod = meth;	}#endifDBG(MOREJIT,	if (jitting) {		dprintf("but still jitting = %s.%s(%s)\n", 			jitting->class->name->data, jitting->name->data, 			METHOD_SIGD(jitting));		}    );	/* start modifying global variables now */	assert(jitting == 0 || !!!"reentered jitter");	/* DEBUG */	jitting = meth;					/* DEBUG */	maxLocal = meth->localsz;	maxStack = meth->stacksz;        maxArgs = sizeofSigMethod(meth, false);	if (maxArgs == -1) {		goto done2;	}	if (meth->accflags & ACC_STATIC) {		isStatic = 1;	}	else {		isStatic = 0;		maxArgs += 1;	}	base = (bytecode*)meth->c.bcode.code;	len = meth->c.bcode.codelen;	/***************************************/	/* Next reduce bytecode to native code */	/***************************************/	if (!(success = initInsnSequence(meth, codeperbytecode * len, meth->localsz,					 meth->stacksz, einfo))) {		goto done1;	}	start_basic_block();	start_function();#if defined(CHECK_STACKOVERFLOW)	prepare_function_call();	call_soft(checkStackOverflow);	fixup_function_call();#endif	monitor_enter();	if (IS_STARTOFBASICBLOCK(0)) {		end_basic_block();		start_basic_block();	}	for (pc = 0; pc < len; pc = npc) {		assert(stackno <= maxStack+maxLocal);		npc = pc + insnLen[base[pc]];		/* Skip over the generation of any unreachable basic blocks */		if (IS_UNREACHABLE(pc)) {			while (npc < len && !IS_STARTOFBASICBLOCK(npc) && !IS_STARTOFEXCEPTION(npc)) {				npc = npc + insnLen[base[npc]];			}DBG(JIT,		dprintf("unreachable basic block pc [%d:%d]\n", pc, npc - 1);   );			if (IS_STARTOFBASICBLOCK(npc)) {				end_basic_block();				start_basic_block();				stackno = STACKPOINTER(npc);			}			continue;		}DBG(JIT,	dprintf("pc = %d, npc = %d\n", pc, npc);	);		/* Determine various exception conditions */		checkCaughtExceptions(meth, pc);		start_instruction();		/* Note start of exception handling blocks */		if (IS_STARTOFEXCEPTION(pc)) {			stackno = meth->localsz + meth->stacksz - 1;			start_exception_block();		}		switch (base[pc]) {		default:			dprintf("Unknown bytecode %d\n", base[pc]);			postException(einfo, JAVA_LANG(VerifyError));			success = false;			goto done;#include "kaffe.def"		}		/* Note maximum number of temp slots used and reset it */		if (tmpslot > maxTemp) {			maxTemp = tmpslot;		}		tmpslot = 0;		cancelNoWriteback();		if (IS_STARTOFBASICBLOCK(npc)) {			end_basic_block();			start_basic_block();			stackno = STACKPOINTER(npc);		}		generateInsnSequence(codeInfo);	}	end_function();	assert(maxTemp < MAXTEMPS);	if (finishInsnSequence(codeInfo, &ncode, einfo) == false) {		success = false;		goto done;	}	installMethodCode(codeInfo, meth, &ncode);done:	tidyAnalyzeMethod(&codeInfo);DBG(JIT,	dprintf("Translated %s.%s%s (%s) %p\n", meth->class->name->data, 		meth->name->data, METHOD_SIGD(meth), 		isStatic ? "static" : "normal", METHOD_NATIVECODE(meth));	    );	if (Kaffe_JavaVMArgs.enableVerboseJIT) {		tme = currentTime();		jitStats.time += (tme - tms);		printf("<JIT: %s.%s%s time %dms (%dms) @ %p>\n",		       CLASS_CNAME(meth->class),		       meth->name->data, METHOD_SIGD(meth),		       (int)(tme - tms), jitStats.time,		       METHOD_NATIVECODE(meth));	}done1:#if defined(KAFFE_PROFILER)	if (profFlag) {		profiler_click_t end;		profiler_get_clicks(end);		meth->jitClicks = end - meth->jitClicks;		globalMethod = NULL;	}#endifdone2:	jitting = NULL;	/* DEBUG */	stopTiming(&jit_time);	leaveTranslator();done3:	unlockClass(meth->class);	#if defined(ENABLE_JVMPI)	if (success && JVMPI_EVENT_ISENABLED(JVMPI_EVENT_COMPILED_METHOD_LOAD) )	  {	    JVMPI_Event ev;	    jvmpiFillMethodLoad(&ev, meth);	    jvmpiPostEvent(&ev);	  }#endif	return (success);}#ifndef ALIGNMENT_OF_SIZE#define ALIGNMENT_OF_SIZE(S)	(S)#endif/* * Generate the code. */boolfinishInsnSequence(codeinfo* codeInfo, nativeCodeInfo* code, errorInfo *einfo){#if defined(CALLTARGET_ALIGNMENT)	unsigned int align = CALLTARGET_ALIGNMENT;#else	unsigned int align = 0;#endif#if defined(MD_JIT_EXCEPTION_INFO_LENGTH)	int exc_len = MD_JIT_EXCEPTION_INFO_LENGTH;#else	int exc_len = 0;#endif	uintp const_align = sizeof(union _constpoolval) - 1;	uint32 constlen;	jitCodeHeader *jch;	nativecode* methblock;	/* Emit pending instructions */	generateInsnSequence(codeInfo);	/* Okay, put this into malloc'ed memory. We have to align the pool for	 * some double-word aligned instructions. */	constlen = KaffeJIT_getNumberOfConstants() * sizeof(union _constpoolval);	/* Allocate some padding to align codebase if so desired 	 */	methblock = gc_malloc(sizeof(jitCodeHeader) + exc_len + constlen + const_align + CODEPC + (align ? (align - ALIGNMENT_OF_SIZE(sizeof(jdouble))) : 0), KGC_ALLOC_JITCODE);	if (methblock == 0) {		postOutOfMemory(einfo);		return (false);	}	jch = (jitCodeHeader *)methblock;	jch->pool = (void *)((char *)(jch + 1)) + exc_len;	jch->pool = (void *)(((uintp)jch->pool + const_align) & ~const_align );	jch->code_start = ((nativecode *)jch->pool) + constlen;	jch->code_len = CODEPC;	/* align entry point if so desired */	if (align != 0 && (unsigned long)jch->code_start % align != 0) {		unsigned int pad = (align - (unsigned long)jch->code_start % align);				assert(pad <= align - ALIGNMENT_OF_SIZE(sizeof(jdouble)));				jch->code_start = jch->code_start + pad;	}	memcpy(jch->code_start, codeblock, CODEPC);	addToCounter(&jitcodeblock, "jitmem-codeblock", 1,		-(jlong)GCSIZEOF(codeblock));	KFREE(codeblock);	/* Establish any code constants */	KaffeJIT_establishConstants(jch->pool);	/* Link it */

⌨️ 快捷键说明

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