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

📄 machine.c

📁 kaffe是一个java虚拟机的源代码。里面包含了一些java例程和标准的java包。
💻 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 "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"/* * Define information about this engine. */char* engine_name = "Just-in-time";char* engine_version = KVER;iLock* 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), 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/* * 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;#if defined(KAFFE_PROFILER)int profFlag; /* flag to control profiling */Method *globalMethod;static void printProfilerStats(void);#endifstruct {	int time;} jitStats;static void generateInsnSequence(codeinfo* codeInfo);static void checkCaughtExceptions(Method* meth, int pc);void	endBlock(sequence*);void	startBlock(sequence*);void	endSubBlock(sequence*);void	startSubBlock(sequence*);void	cancelNoWriteback(void);jlong	currentTime(void);/* * 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){	Hjava_lang_Throwable* overflow;	/* XXX fix this.  	 * We should not have to access current just to do the stack check	 */	Hjava_lang_Thread* current = getCurrentThread();	jint *needOnStack;	if (current == 0) {		return;	}	needOnStack = &unhand(current)->needOnStack;	if (jthread_stackcheck(*needOnStack)) {		return;	}	overflow = (Hjava_lang_Throwable*)unhand(current)->stackOverflowError;	if (overflow != 0) {		if (*needOnStack == STACK_LOW) {			dprintf(				"Panic: unhandled StackOverflowError()\n");			ABORT();		}		*needOnStack = STACK_LOW;		throwException(overflow);	}}#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;	int len;	callInfo cinfo;	fieldInfo finfo;	Hjava_lang_Class* crinfo;	bool success = true;	nativeCodeInfo ncode;	codeinfo* codeInfo;	int64 tms = 0;	int64 tme;	int iLockRoot;	static Method* jitting = 0;	/* DEBUG */	/* lock class to protect the method.  Even though meth->class	   is a Java Object, this lock is not in the Java abstraction	   layer; it is just a detail of implementation, so we must	   use lockMutex instead of lockObject.  */	lockMutex(&meth->class->head);	/* Must check the translation	 * hasn't been done by someone else once we get it.	 */	if (METHOD_TRANSLATED(meth)) {		goto done3;	}	if (Kaffe_JavaVMArgs[0].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 ((meth->accflags & ACC_NATIVE) != 0) {		success = native(meth, einfo);		if (success == false) {			goto done3;		}		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 = verifyMethod(meth, &codeInfo, einfo);	if (success == false) {		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 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:	tidyVerifyMethod(&codeInfo);DBG(JIT,	dprintf("Translated %s.%s%s (%s) %p\n", meth->class->name->data, 		meth->name->data, METHOD_SIGD(meth), 		isStatic ? "static" : "normal", meth->ncode);	    )	if (Kaffe_JavaVMArgs[0].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 = 0;	}#endifdone2:	jitting = 0;	/* DEBUG */	stopTiming(&jit_time);	leaveTranslator();done3:	unlockMutex(&meth->class->head);	return (success);}/* * Generate the code. */boolfinishInsnSequence(codeinfo* codeInfo, nativeCodeInfo* code, errorInfo *einfo){#if defined(CALLTARGET_ALIGNMENT)	int align = CALLTARGET_ALIGNMENT;#else	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	uint32 constlen;	nativecode* methblock;	nativecode* codebase;	/* Emit pending instructions */	generateInsnSequence(codeInfo);	/* Okay, put this into malloc'ed memory */	constlen = nConst * sizeof(union _constpoolval);	/* Allocate some padding to align codebase if so desired 	 * NB: we assume the allocator returns at least 8-byte aligned 	 * addresses.   XXX: this should really be gc_memalign	 */  	methblock = gc_malloc(exc_len + constlen + CODEPC + (align ? (align - 8) : 0), GC_ALLOC_JITCODE);	if (methblock == 0) {		postOutOfMemory(einfo);		return (false);	}	codebase = methblock + exc_len + constlen;	/* align entry point if so desired */	if (align != 0 && (unsigned long)codebase % align != 0) {		int pad = (align - (unsigned long)codebase % align);		/* assert the allocator indeed returned 8 bytes aligned addrs */		assert(pad <= align - 8);			codebase = (char*)codebase + pad;	}	memcpy(codebase, codeblock, CODEPC);	addToCounter(&jitcodeblock, "jitmem-codeblock", 1,		-(jlong)GCSIZEOF(codeblock));	gc_free(codeblock);	/* Establish any code constants */	establishConstants(methblock + exc_len);	/* Link it */	linkLabels(codeInfo, (uintp)codebase);	/* Note info on the compiled code for later installation */	code->mem = methblock;	code->memlen = exc_len + constlen + CODEPC;	code->code = codebase;	code->codelen = CODEPC;	return (true);}

⌨️ 快捷键说明

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