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

📄 machine.c

📁 kaffe是一个java虚拟机的源代码。里面包含了一些java例程和标准的java包。
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (codeblock_size < ALLOCCODEBLOCKSZ) {		codeblock_size = ALLOCCODEBLOCKSZ;	}	codeblock = gc_malloc(codeblock_size + CODEBLOCKREDZONE, GC_ALLOC_JITTEMP);	if (codeblock == 0) {		postOutOfMemory(einfo);		return (false);	}	CODEPC = 0;	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) {			codeblock_size += ALLOCCODEBLOCKSZ;			codeblock = gc_realloc(codeblock, codeblock_size + CODEBLOCKREDZONE, GC_ALLOC_JITTEMP);			if (codeblock == 0) {				postOutOfMemory(einfo);				return (false);			}		}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);					slot_invalidate(t->u[i].slot);				}			}		}	}	/* Reset */	initSeq();	return (true);}/* * 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 || canCatch(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){	SlotData** mem;	SlotData* d;	int i;	int c;	/* Count the number of slots we need to remember.  Note: we	 * include the number of potentially active temps.	 */	i = maxLocal + maxStack + tmpslot;	c = 0;	for (i--; i >= 0; i--) {		d = slotinfo[i].slot;		if (d->rseq != 0 || d->wseq != 0 || isGlobal(d)) {			c++;		}	}#if defined(STACK_LIMIT)	d = stack_limit->slot;	if (d->rseq != 0 || d->wseq != 0) {		c++;	}#endif	c++; /* Add null slot on the end */	mem = gc_malloc(c * sizeof(SlotData*), GC_ALLOC_JITCODE);	i = maxLocal + maxStack + tmpslot;	c = 0;	for (i--; i >= 0; i--) {		d = slotinfo[i].slot;		if (d->rseq != 0 || d->wseq != 0 || isGlobal(d)) {			mem[c++] = d;		}	}#if defined(STACK_LIMIT)	d = stack_limit->slot;	if (d->rseq != 0 || d->wseq != 0) {		mem[c++] = d;	}#endif	return (mem);}/* * Alias one slot's register to reference another. */voidslotAlias(sequence* s){	int reg;	SlotData* to;	SlotData* from;	int type;SCHK(	sanityCheck();						)	to = s->u[0].slot;	type = s->u[1].value.i;	from = s->u[2].slot;	/* If this slot has a register we must invalidate it before we	 * overwrite it.	 */	if (to->regno != NOREG) {		/* If it has the register already then don't do anything */		if (from->regno == to->regno) {			return;		}		assert(isGlobal(to) == 0);		slot_invalidate(to);	}	/* Get the register we're aliasing and attach the 'to' slot	 * to it.	 */	reg = slotRegister(from, type, rread, NOREG);	reginfo[reg].refs++;	to->regno = reg;	to->modified = rwrite;	/* Prepend slot onto register use lists */	to->rnext = reginfo[reg].slot;	reginfo[reg].slot = to;SCHK(	sanityCheck();						)}staticintsortSlots(const void* s1, const void* s2){	localUse* lcluse1;	localUse* lcluse2;	lcluse1 = &codeInfo->localuse[*((SlotInfo**)s1) - localinfo];	lcluse2 = &codeInfo->localuse[*((SlotInfo**)s2) - localinfo];	if (lcluse1->use == lcluse2->use) {		return (0);	}	else if (lcluse1->use > lcluse2->use) {		return (-1);	}	else {		return (1);	}}staticvoidbindSlotToGlobal(int lcl, int r, int type){	kregs* reg;	SlotData* dslot;	int gtype;	reg = &reginfo[r];	dslot = localinfo[lcl].slot;	reg->ctype = type;	reg->type |= Rglobal;	reg->refs++;	reg->slot = dslot;	dslot->regno = r;	gtype = GL_ISGLOBAL;	/* If this is an argument then pre-load */	if (lcl < maxArgs) {		gtype |= GL_PRELOAD;	}	/* If this slot is never written note that the global is	 * read only.	 */	if (codeInfo->localuse[lcl].write == -1) {		gtype |= GL_RONLY;	}	setGlobal(dslot, gtype);}/* * Setup global registers */voidsetupGlobalRegisters(void){#if defined(NR_GLOBALS)	SlotInfo** slots;	int j;	int max;	/* If we don't have any code info we can't do any global	 * optimization	 */	if (codeInfo == 0) {		return;	}	/* Allocate an array for the slot pointers and copy them in */	slots = gc_malloc((1+maxLocal) * sizeof(SlotInfo*), GC_ALLOC_JITCODE);	for (j = 0; j < maxLocal; j++) {		slots[j] = &localinfo[j];	}	/* Sort the slots to the most used is first */	qsort(slots, maxLocal, sizeof(SlotInfo*), sortSlots);	/* Allocate the slots to globals */	max = NR_GLOBALS;	for (j = 0; j < maxLocal && max > 0; j++) {		int k;		int i;		localUse* lcl;		i = slots[j] - localinfo;		lcl = &codeInfo->localuse[i];		for (k = 0; k < MAXREG; k++) {			kregs* reg;			reg = &reginfo[k];			if ((reg->flags & Rglobal) == 0) {				/* Not a global */			}			else if ((reg->type & Rglobal) != 0) {				/* Already used */			}			else if (lcl->type == TINT && (reg->type & Rint) != 0) {				bindSlotToGlobal(i, k, Rint);				max--;				break;			}			else if (lcl->type == TOBJ && (reg->type & Rref) != 0) {				bindSlotToGlobal(i, k, Rref);				max--;				break;			}		}	}	gc_free(slots);#endif}voidsetupArgumentRegisters(void){#if defined(NR_ARGUMENTS)	int args;	int i;	static sequence argseq[1];	args = maxArgs;	if (args > NR_ARGUMENTS) {		args = NR_ARGUMENTS;	}	for (i = 0; i < args; i++) {		writeslot(argseq, i, &localinfo[i], 1);		localinfo[i].slot->modified = rwrite;	}#if defined(STACK_LIMIT)	if (args < NR_ARGUMENTS) {		writeslot(argseq, i, stack_limit, 1);		stack_limit->slot->modified = rwrite;	}#endif#endif}/* * Build multi-dimensional array. *  This is sufficiently different from the standard *  to require our own routine. */void*jit_soft_multianewarray(Hjava_lang_Class* class, jint dims, ...){	errorInfo einfo;	int array[16];	Hjava_lang_Object* obj;	jint arg;	int i;	int* arraydims;	va_list ap;        if (dims < 16-1) {		arraydims = array;	}	else {		arraydims = checkPtr(gc_calloc(dims+1, sizeof(int), GC_ALLOC_JITCODE));	}	/* Extract the dimensions into an array */	va_start(ap, dims);	for (i = 0; i < dims; i++) {		arg = va_arg(ap, jint);		if (arg < 0) {			if (arraydims != array) {				gc_free (arraydims);			}                        throwException(NegativeArraySizeException);		}		arraydims[i] = arg;	}	arraydims[i] = -1;	va_end(ap);	/* Mmm, okay now build the array using the wonders of recursion */        obj = newMultiArrayChecked(class, arraydims, &einfo);	if (arraydims != array) {		gc_free(arraydims);	}	if (!obj) {		throwError(&einfo);	}	/* Return the base object */	return (obj);}/* * Include the machine specific trampoline functions. */#include "trampolines.c"staticvoidnullCall(void){}typedef struct _fakeCall {	struct _fakeCall*	next;	label*			from;	label*			to;	void*			func;} fakeCall;static fakeCall* firstFake;static fakeCall* lastFake;static fakeCall* currFake;/* * Build a fake call to a function. *  A fake call has a return address which is different from where it's *  actually called from. */label*newFakeCall(void* func, uintp currpc){	label* from;	label* to;	/* This is used to mark where I'm calling from */	from = reference_code_label(currpc);	/* This is where I'm calling to */	to = newLabel();	to->type = Linternal;	to->at = 0;	to->to = 0;	to->from = 0;	if (currFake == 0) {		currFake = gc_malloc(sizeof(fakeCall), GC_ALLOC_JITCODE);		if (lastFake == 0) {			firstFake = currFake;		}		else {			lastFake->next = currFake;		}		lastFake = currFake;	}	currFake->from = from;	currFake->to = to;	currFake->func = func;	currFake = currFake->next;	return (to);}staticvoidmakeFakeCalls(void){	fakeCall* c;	for (c = firstFake; c != currFake; c = c->next) {		softcall_fakecall(c->from, c->to, c->func);	}	currFake = firstFake;}/* * return what engine we're using */char*getEngine(void){	return "kaffe.jit";}#if defined(KAFFE_PROFILER)static jlong click_multiplier;static profiler_click_t click_divisor;static FILE *prof_output;static intprofilerClassStat(Hjava_lang_Class *clazz, void *param){	Method *meth;	int mindex;	for (mindex = clazz->nmethods, meth = clazz->methods; mindex-- > 0; meth++) {		if (meth->callsCount == 0)			continue;		fprintf(prof_output,			"%10d %10.6g %10.6g %10.6g %10.6g %s.%s%s\n",			meth->callsCount,			(click_multiplier * ((double)meth->totalClicks)) / click_divisor,			(click_multiplier * ((double)(meth->totalClicks						      - meth->totalChildrenClicks)))			/ click_divisor,			(click_multiplier * ((double)meth->totalChildrenClicks)) / click_divisor,			(click_multiplier * ((double)meth->jitClicks)) / click_divisor,			meth->class->name->data,			meth->name->data,			METHOD_SIGD(meth)		       );	}	return 0;}static voidprintProfilerStats(void){	profiler_click_t start, end;	jlong m_start, m_end;	/* If the profFlag == 0, don't bother printing anything */	if (profFlag == 0)		return; 	/* open file */ 	prof_output = fopen("prof.out", "w");	if (prof_output == NULL) {		return;	}	/* Need to figure out what profiler_click  _really_ is.	 * Use currentTime() to guest how long is a second.  Call it before	 * to don't count dynamic linker resolve time.  */	m_start = currentTime();	profiler_get_clicks(start);	sleep (1);	m_end = currentTime();	profiler_get_clicks(end);	click_multiplier = m_end - m_start;	click_divisor = end - start;	fprintf(prof_output,		"# clockTick: %lld per 1/%lld seconds aka %lld per milliseconds\n",		click_divisor,		click_multiplier,		click_divisor / click_multiplier); 	fprintf(prof_output, "%10s %10s %10s %10s %10s %s\n", 		"#    count", "total", "self", "children", "jit", 		"method-name");	/* Traverse through class hash table */	walkClassPool(profilerClassStat, NULL);	fclose(prof_output);}#endif

⌨️ 快捷键说明

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