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

📄 machine.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
getInsnPC(int pc, codeinfo* codeInfo, nativeCodeInfo *code){	int res;	int maxPc = codeInfo->codelen;	for (;pc<maxPc;pc++) {		res = INSNPC(pc);		if (res != -1) {			return (res);		}	}	return code->codelen;}/* * Install the compiled code in the method. * Returns true if successful */voidinstallMethodCode(void* ignore, Method* meth, nativeCodeInfo* code){	uint32 i;	jexceptionEntry* e;	void *tramp;#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);	tramp = METHOD_NATIVECODE(meth);	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 = gc_malloc(strlen(CLASS_CNAME(meth->class)) +				1 + /* '/' */				strlen(meth->name->data) +				strlen(METHOD_SIGD(meth)) +				1,				GC_ALLOC_JITTEMP);		sprintf(sym,			"%s/%s%s",			CLASS_CNAME(meth->class),			meth->name->data,			METHOD_SIGD(meth));		feedbackJITMethod(sym, code->code, code->codelen, true);		gc_free(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	gc_free(tramp);	/* 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, codeInfo, code) + (uintp)code->code;			e->end_pc = getInsnPC(e->end_pc, codeInfo, code) + (uintp)code->code;			e->handler_pc = getInsnPC(e->handler_pc, codeInfo, code) + (uintp)code->code;			if (e->start_pc >= e->end_pc)			  fprintf(stderr, 				 "WARNING Bad bytecode! Illegal exception table entry:"				 " start_pc=%d is not lower than end_pc=%d in method %s.%s(%s)\n"				 "See Java Virtual Machine Specification 2nd Edition $4.7.3 for details.\n"				 "Please report this bug to the developers of the application you're running on kaffe.\n"				 "A simple fix might be to use another java compiler to build the application.\n",				 e->start_pc, e->end_pc,				 CLASS_CNAME(meth->class),				 meth->name->data,				 METHOD_SIGD(meth));		}	}	/* 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, codeInfo, code) + (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		/* 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);	/* Before generating code, try to guess how much space we'll need. */	codeblock_size = ALLOCCODEBLOCKSZ;	codeblock = gc_malloc(codeblock_size + CODEBLOCKREDZONE,			      GC_ALLOC_JIT_CODEBLOCK);	if (codeblock == 0) {		postOutOfMemory(einfo);		return (false);	}	CODEPC = 0;	/*	 * add the method as the first entry to the constant pool to speed up	 * finding a method for a given pc.	 */	newConstant(CPref, meth);		return (true);}/* * Generate instructions from current set of sequences. */staticjbooleangenerateInsnSequence(errorInfo* einfo){	sequence* t;	int i;	int m;	for (t = firstSeq; t != currSeq; t = t->next) {		/* If we overrun the codeblock, reallocate and continue.  */		if (CODEPC >= codeblock_size) {			nativecode *new_codeblock;						codeblock_size += ALLOCCODEBLOCKSZ;			new_codeblock = gc_realloc(codeblock,						   codeblock_size +						   CODEBLOCKREDZONE,						   GC_ALLOC_JIT_CODEBLOCK);			if (new_codeblock == NULL) {				gc_free(codeblock);				codeblock = NULL;				postOutOfMemory(einfo);				return (false);			} else {				codeblock = new_codeblock;			}		}SCHK(		sanityCheck();					);		/* Generate sequences */		assert(t->func != 0);		if (t->refed != 0) {			(*(t->func))(t);		}		else {			/* printf("discard instruction\n"); */		}		/* Handle dead slots */		m = t->lastuse;		if (m != 0) {			for (i = 0; m != 0; m = m >> 1, i++) {				if ((m & 1) != 0) {					assert(!isGlobal(t->u[i].slot));					slot_kill_readonce(t->u[i].slot);					/*					 * If this sequence is in an exception					 * handler we need to spill the slot					 * in case its used in a subsequent					 * basic block.					 */					if( t->jflags.ANY )					{						spillAndUpdate(t->u[i].slot,							       true);					}					slot_invalidate(t->u[i].slot);				}			}		}	}	/* Reset */	initSeq();	return (true);}/* * check what synchronous exceptions are caught for a given instruction */staticvoid checkCaughtExceptions(Method* meth, uint32 pc){	unsigned int i;	willcatch.ANY = false;	willcatch.BADARRAYINDEX = false;	willcatch.NULLPOINTER = false;	if (meth->exception_table == 0) 		return;	/* Determine various exception conditions */	for (i = 0; i < meth->exception_table->length; i++) {		Hjava_lang_Class* etype;		/* include only if exception handler range matches pc */		if (meth->exception_table->entry[i].start_pc > pc ||		    meth->exception_table->entry[i].end_pc <= pc)			continue;		willCatch(ANY);		etype = meth->exception_table->entry[i].catch_type;		if (etype == 0) {			willCatch(BADARRAYINDEX);			willCatch(NULLPOINTER);		}		else {			if (instanceof(javaLangArrayIndexOutOfBoundsException, etype)) {				willCatch(BADARRAYINDEX);			}			if (instanceof(javaLangNullPointerException, etype)) {				willCatch(NULLPOINTER);			}		}	}}/* * Start a new instruction. */voidstartInsn(sequence* s){	SET_INSNPC(const_int(2), CODEPC);}voiddoSpill(sequence* s){	SlotData** mem;	SlotData* sd;	int type;	int old_ro;SCHK(	sanityCheck();						)	type = s->u[2].value.i;	old_ro = enable_readonce;	if (type == SR_SYNC) {		enable_readonce = 0;	}	/* Spill the registers */	for (mem = s->u[1].smask; *mem != 0; mem++) {		sd = *mem;		/* Determine if we need to spill this slot at all */		if ((sd->modified & rwrite) != 0 && sd->regno != NOREG) {			switch (type) {			case SR_BASIC:			case SR_SUBBASIC:				/* We only spill if it's not global */				if (!isGlobal(sd)) {					spillAndUpdate(sd, true);				}				break;			case SR_SYNC:				spillAndUpdate(sd, false);				break;			case SR_FUNCTION:				if (calleeSave(sd->regno) == 0 || s->jflags.ANY != 0) {					spillAndUpdate(sd, true);				}				break;			default:				ABORT();			}		}	}	/* If this isn't being done for a function call we can free the	 * spill mask now.  Otherwise it will be freed by the function	 * reloader.	 */	if (type != SR_FUNCTION) {		gc_free(s->u[1].smask);	}	enable_readonce = old_ro;SCHK(	sanityCheck();						)}voiddoReload(sequence* s){	SlotData* sd;	SlotData** mem;	int type;SCHK(	sanityCheck();						)	type = s->u[2].value.i;	for (mem = s->u[1].smask; *mem != 0; mem++) {		sd = *mem;		if (sd->regno != NOREG && !isGlobal(sd)) {			switch (type) {			case SR_BASIC:			case SR_SUBBASIC:				slot_invalidate(sd);				break;			case SR_FUNCTION:				if (calleeSave(sd->regno) == 0) {					slot_invalidate(sd);				}				break;			case SR_START:			case SR_EXCEPTION:				break;			default:				ABORT();			}		}	}	/* Deal with global reloading */	for (mem = s->u[1].smask; *mem != 0; mem++) {		sd = *mem;		if (isGlobal(sd)) {			switch (type) {			case SR_BASIC:			case SR_SUBBASIC:				if (!isGlobalReadonly(sd)) {					sd->modified = rwrite;				}				break;			case SR_FUNCTION:				break;			case SR_START:				if (isGlobalPreload(sd)) {					reload(sd);				}				break;			case SR_EXCEPTION:				reload(sd);				break;			default:				ABORT();			}		}	}	gc_free(s->u[1].smask);SCHK(	sanityCheck();						)}/* * Create the spill/reload mask. * This contains a list of slot/global pairs indicating which slots are * active and should be spilled or reloaded now.  The global flag indicates * that at this point the slot is global (ie. carried between basic blocks) * so should be handled with care. */SlotData**createSpillMask(void)

⌨️ 快捷键说明

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