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

📄 machine.c

📁 kaffe是一个java虚拟机的源代码。里面包含了一些java例程和标准的java包。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* machine.c * Translate the Kaffe instruction set to the native one. * * Copyright (c) 1996-1999 *	Transvirtual Technologies, Inc.  All rights reserved. * * Cross-language profiling changes contributed by * the Flux Research Group, Department of Computer Science, * University of Utah, http://www.cs.utah.edu/flux/ * * See the file "license.terms" for information on usage and redistribution * of this file. */#define SCHK(s) s#define	SUSE(s)#include "config.h"#include "config-std.h"#include "config-mem.h"#include "gtypes.h"#include "md.h"#include "classMethod.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 "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 "locks.h"#include "code-analyse.h"#include "external.h"#include "soft.h"#include "thread.h"#include "itypes.h"#include "methodCache.h"#include "support.h"#include "xprofiler.h"#include "feedback.h"#include "debugFile.h"#include "fileSections.h"#include "mangle.h"char* engine_name = "Just-in-time v3";char* engine_version = KAFFEVERSION;int stackno;int maxStack;int maxLocal;int maxTemp;int maxArgs;int maxPush;int isStatic;codeinfo* codeInfo;int tmpslot;int argcount = 0;		/* Function call argument count */uint32 pc;uint32 npc;/* Various exception related things */jitflags willcatch;/* jit3 specific prototypes from icode.c */void explicit_check_null (int x, SlotInfo* obj, int y);void check_null (int x, SlotInfo* obj, int y);void check_div (int x, SlotInfo* obj, int y);void check_div_long (int x, SlotInfo* obj, int y);void softcall_fakecall (label* from,label* to, void* func);/* Unit in which code block is increased when overrun */#define	ALLOCCODEBLOCKSZ	8192/* Codeblock redzone - allows for safe overrun when generating instructions */#define	CODEBLOCKREDZONE	256int codeblock_size;static int code_generated;static int bytecode_processed;static int codeperbytecode;iLock *translatorlock;struct {	int time;} jitStats;static jboolean generateInsnSequence(errorInfo*);static void nullCall(void);static void makeFakeCalls(void);/* Desktop edition */#include "debug.h"#if defined(KAFFE_PROFILER)int profFlag;Method *globalMethod;static void printProfilerStats(void);#endif/* * Translate a method into native code. */jbooleantranslate(Method* xmeth, errorInfo* einfo){	int i;	jint low;	jint high;	jvalue tmpl;	int idx;	SlotInfo* tmp;	SlotInfo* tmp2;	SlotInfo* mtable;	bytecode* base;	uint32 len;	callInfo cinfo;	fieldInfo finfo;	Hjava_lang_Class* crinfo;	codeinfo* mycodeInfo;	nativeCodeInfo ncode;	int64 tms = 0;	int64 tme;	static bool reinvoke = false;	jboolean success = true;	int iLockRoot;	lockMutex(xmeth->class->centry);	if (METHOD_TRANSLATED(xmeth)) {		goto done3;	}	/* If this code block is native, then just set it up and return */	if ((xmeth->accflags & ACC_NATIVE) != 0) {		success = native(xmeth, einfo);		if (success == true) {			KAFFEJIT_TO_NATIVE(xmeth);		}		goto done3;	}	/* Scan the code and determine the basic blocks */	success = verifyMethod(xmeth, &mycodeInfo, einfo);	if (success == false) {		goto done3;	}#if defined(KAFFE_FEEDBACK)	if( kaffe_feedback_file )		lockMutex(kaffe_feedback_file);#endif	/* Only one in the translator at once. Must check the translation	 * hasn't been done by someone else once we get it.	 */	enterTranslator();	if (Kaffe_JavaVMArgs[0].enableVerboseJIT) {		tms = currentTime();	}DBG(MOREJIT,    dprintf("callinfo = %p\n", &cinfo);    )#if defined(KAFFE_PROFILER)	if (profFlag) {		static int init = 0;		if (!init) {			atexit(printProfilerStats);			init = 1;		}		profiler_get_clicks(xmeth->jitClicks);		xmeth->callsCount = 0;		xmeth->totalClicks = 0;		xmeth->totalChildrenClicks = 0;		globalMethod = xmeth;	}#endif	codeInfo = mycodeInfo;	/* Handle null calls specially */	if (METHOD_BYTECODE_LEN(xmeth) == 1 && METHOD_BYTECODE_CODE(xmeth)[0] == RETURN) {		/* 'nc' is a Workaround for KFREE ? : bug in gcc 2.7.2 */		void *nc = METHOD_NATIVECODE(xmeth);		KFREE(nc);		SET_METHOD_NATIVECODE(xmeth, (nativecode*)nullCall);		goto done;	}	assert(reinvoke == false);	reinvoke = true;	maxLocal = xmeth->localsz;	maxStack = xmeth->stacksz;        maxArgs = sizeofSigMethod(xmeth, false);	if (maxArgs == -1) {		goto done;	}	if (xmeth->accflags & ACC_STATIC) {		isStatic = 1;	}	else {		isStatic = 0;		maxArgs += 1;	}DBG(MOREJIT,	dprintf("Method: %s.%s%s\n", CLASS_CNAME(xmeth->class), xmeth->name->data, METHOD_SIGD(xmeth));	for (i = 0; i < maxLocal; i++) {		dprintf(" L%d: %2d", i, codeInfo->localuse[i].use);	}	dprintf("\n");)	base = (bytecode*)METHOD_BYTECODE_CODE(xmeth);	len = METHOD_BYTECODE_LEN(xmeth);	willcatch.ANY = false;	willcatch.BADARRAYINDEX = false;	/* Deterimine various exception conditions */	if (xmeth->exception_table != 0) {		willCatch(ANY);		for (i = 0; i < (int)xmeth->exception_table->length; i++) {			Hjava_lang_Class* etype;			etype = xmeth->exception_table->entry[i].catch_type;			if (etype == 0) {				willCatch(BADARRAYINDEX);			}			else {				if (instanceof(javaLangArrayIndexOutOfBoundsException, etype)) {					willCatch(BADARRAYINDEX);				}			}		}	}	/*	 * Initialise the translator.	 */	success = initInsnSequence(xmeth, codeperbytecode * METHOD_BYTECODE_LEN(xmeth), xmeth->localsz, xmeth->stacksz, einfo);	if (success == false) {		goto done;	}	/***************************************/	/* Next reduce bytecode to native code */	/***************************************/	pc = 0;	start_function();	check_stack_limit();	if (Kaffe_JavaVMArgs[0].enableVerboseCall != 0) {		softcall_trace(xmeth);	}	monitor_enter();	if (IS_STARTOFBASICBLOCK(0)) {		end_basic_block();		success = generateInsnSequence(einfo);		if (success == false) {			goto done;		}		start_basic_block();	}	for (; pc < len; pc = npc) {		assert(stackno <= maxStack+maxLocal);		assert(stackno >= 0);		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;                }		start_instruction();		/* Note start of exception handling blocks */		if (IS_STARTOFEXCEPTION(pc)) {			stackno = xmeth->localsz + xmeth->stacksz - 1;			start_exception_block();		}		switch (base[pc]) {		default:			printf("Unknown bytecode %d\n", base[pc]);			leaveTranslator();#if defined(KAFFE_FEEDBACK)			if( kaffe_feedback_file )				unlockMutex(kaffe_feedback_file);#endif			unlockMutex(xmeth->class->centry);			postException(einfo, JAVA_LANG(VerifyError));                        success = false;			break;#include "kaffe.def"		}		/* Note maximum number of temp slots used and reset it */		if (tmpslot > maxTemp) {			maxTemp = tmpslot;		}		tmpslot = 0;SCHK(		sanityCheck();					)		if (IS_STARTOFBASICBLOCK(npc)) {			end_basic_block();			success = generateInsnSequence(einfo);			if (success == false) {				goto done;			}			start_basic_block();			stackno = STACKPOINTER(npc);SCHK(			sanityCheck();				)		}	}	end_function();	makeFakeCalls();	assert(maxTemp < MAXTEMPS);	finishInsnSequence(0, &ncode, einfo);	installMethodCode(0, xmeth, &ncode);done:;	tidyVerifyMethod(&codeInfo);	reinvoke = false;#if defined(KAFFE_PROFILER)	if (profFlag) {		profiler_click_t end;		profiler_get_clicks(end);		xmeth->jitClicks = end - xmeth->jitClicks;		globalMethod = 0;	}#endifDBG(MOREJIT,    dprintf("Translating %s.%s%s (%s) %p\n",	    xmeth->class->name->data,	    xmeth->name->data,	    METHOD_SIGD(xmeth),	    isStatic ? "static" : "normal", METHOD_NATIVECODE(xmeth));    )	if (Kaffe_JavaVMArgs[0].enableVerboseJIT) {		tme = currentTime();		jitStats.time += (int)(tme - tms);		printf("<JIT: %s.%s%s time %dms (%dms) @ %p (%p)>\n",		       CLASS_CNAME(xmeth->class),		       xmeth->name->data, METHOD_SIGD(xmeth),		       (int)(tme - tms), jitStats.time,		       METHOD_NATIVECODE(xmeth), xmeth);	}	leaveTranslator();#if defined(KAFFE_FEEDBACK)	if( kaffe_feedback_file )		unlockMutex(kaffe_feedback_file);#endifdone3:;	unlockMutex(xmeth->class->centry);	return (success);}/* * Generate the code. */jbooleanfinishInsnSequence(void* dummy, nativeCodeInfo* code, errorInfo* einfo){	uint32 constlen;	nativecode* methblock;	nativecode* codebase;	jboolean success;	/* Emit pending instructions */	success = generateInsnSequence(einfo);	if (success == false) {		return (false);	}	/* Okay, put this into malloc'ed memory */	constlen = nConst * sizeof(union _constpoolval);	methblock = gc_malloc(constlen + CODEPC, GC_ALLOC_JITCODE);	if (methblock == 0) {		postOutOfMemory(einfo);		return (false);	}	codebase = methblock + constlen;	memcpy(codebase, codeblock, CODEPC);	gc_free(codeblock);	/* Establish any code constants */	establishConstants(methblock);	/* Link it */	linkLabels((uintp)codebase);	/* Note info on the compiled code for later installation */	code->mem = methblock;	code->memlen = constlen + CODEPC;	code->code = codebase;	code->codelen = CODEPC;	return (true);}/* * Get the instruction offset corresponding to the given PC. * If the PC doesn't point at the start of a valid instruction, * look forward until we find one. */staticintgetInsnPC(int pc){	int res;	for (;;) {		res = INSNPC(pc);		if (res != -1) {			return (res);		}		pc++;	}}/* * Install the compiled code in the method. * Returns true if successful */voidinstallMethodCode(void* ignore, Method* meth, nativeCodeInfo* code){	uint32 i;	bool res;	jexceptionEntry* e;#if defined(KAFFE_XPROFILER) || defined(KAFFE_XDEBUGGING)	struct mangled_method *mm = 0;#endif#if defined(KAFFE_FEEDBACK)	char *sym = 0;#endif	/* Work out new estimate of code per bytecode */	code_generated += code->memlen;	bytecode_processed += METHOD_BYTECODE_LEN(meth);	/* When using GCJ, the only use for the translator may be to output	 * JNI wrappers which have zero bytecode ;-); hence the test	 */	if (bytecode_processed > 0) {		codeperbytecode = code_generated / bytecode_processed;	}	GC_WRITE(meth, code->mem);	{		/* Workaround for KFREE() ? : bug on gcc 2.7.2 */		void *nc = METHOD_NATIVECODE(meth);		KFREE(nc);	}	SET_METHOD_JITCODE(meth, code->code);	if( meth->c.bcode.code )		gc_free(meth->c.bcode.code);	meth->c.ncode.ncode_start = code->mem;	meth->c.ncode.ncode_end = (void*)((uintp)code->code + code->codelen);#if defined(KAFFE_FEEDBACK)	if( kaffe_feedback_file && !meth->class->loader )	{		sym = KMALLOC(strlen(CLASS_CNAME(meth->class)) +			      1 + /* '/' */			      strlen(meth->name->data) +			      strlen(METHOD_SIGD(meth)) +			      1);		sprintf(sym,			"%s/%s%s",			CLASS_CNAME(meth->class),			meth->name->data,			METHOD_SIGD(meth));		feedbackJITMethod(sym, code->code, code->codelen, true);		KFREE(sym);	}#endif#if defined(KAFFE_XPROFILER) || defined(KAFFE_XDEBUGGING)	if( (#if defined(KAFFE_XPROFILER)	     xProfFlag ||#else	     0 ||#endif#if defined(KAFFE_XDEBUGGING)	     machine_debug_file) &&#else	     0) &&#endif		(mm = createMangledMethod()) )	{		mangleMethod(mm, meth);	}#endif#if defined(KAFFE_XPROFILER)	profileFunction(mm, code->code, code->codelen);#endif	/* Flush code out of cache */#if defined(FLUSH_DCACHE)	FLUSH_DCACHE(code->code, (void*)((uintp)code->code + code->codelen));#endif	/* Translate exception table and make it available */	if (meth->exception_table != 0) {		for (i = 0; i < meth->exception_table->length; i++) {			e = &meth->exception_table->entry[i];			e->start_pc = getInsnPC(e->start_pc) + (uintp)code->code;			e->end_pc = getInsnPC(e->end_pc) + (uintp)code->code;			e->handler_pc = getInsnPC(e->handler_pc) + (uintp)code->code;		}	}	/* Translate line numbers table */	if (meth->lines != 0) {#if defined(KAFFE_XDEBUGGING)		struct debug_file *df = machine_debug_file;		if( df )		{			/* Mark the start of this source file */			addDebugInfo(df,				     DIA_SourceFile,				     meth->class->sourcefile, code->code,				     DIA_Function,				     meth, mm, meth->lines->entry[0].line_nr,				     code->code, code->codelen,				     DIA_DONE);		}#endif		for (i = 0; i < meth->lines->length; i++) {			meth->lines->entry[i].start_pc = getInsnPC(meth->lines->entry[i].start_pc) + (uintp)code->code;#if defined(KAFFE_XDEBUGGING)			if( df )			{				/* Add line debugging */				addDebugInfo(df,					     DIA_SourceLine,					     meth->lines->entry[i].line_nr,					     meth->lines->entry[i].start_pc -					     (uintp)code->code,					     DIA_DONE);			}#endif		}#if defined(KAFFE_XDEBUGGING)		if( df )		{			/*			 * Mark the end of the function.  This needs to be here			 * so that gdb doesn't get confused about the range of			 * the function since that will be determined by the			 * next debugging information that is added.			 */			addDebugInfo(df,				     DIA_EndFunction,				     code->code + code->codelen,				     DIA_DONE);		}#endif	}	else	{#if defined(KAFFE_XDEBUGGING)		/*		 * No line debugging, but we'd like a symbol to show up anyways		 */		if( machine_debug_file )		{			addDebugInfo(machine_debug_file,				     DIA_SourceFile, meth->class->sourcefile,				     code->code,				     DIA_Function, meth, mm, 0,				     code->code, code->codelen,				     DIA_EndFunction,				     code->code + code->codelen,				     DIA_DONE);		}#endif	}#if defined(KAFFE_XPROFILER) || defined(KAFFE_XDEBUGGING)	deleteMangledMethod(mm);#endif	res = makeMethodActive(meth);	assert(res == true);	/* record framesize for gcj unwinding information */#if defined(LABEL_Lframe)	LABEL_Lframe(&meth->framesize, /* unused */ 0, /* unused */ 0);#endif}/* * Init instruction generation. */jbooleaninitInsnSequence(Method* meth, int codesize, int localsz, int stacksz, errorInfo* einfo){	/* Clear various counters */	tmpslot = 0;	maxTemp = 0;	maxPush = 0;	stackno = localsz + stacksz;	npc = 0;	/* Do any machine dependent JIT initialization */#if defined(INIT_JIT_MD)	INIT_JIT_MD(meth);#endif	initSeq();	initRegisters();	initSlots(stackno);	resetLabels();	/* Before generating code, try to guess how much space we'll need. */	codeblock_size = codesize;

⌨️ 快捷键说明

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