📄 machine.c
字号:
{ 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_JIT_SLOTS); 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 (reginfo[from->regno].flags & Rreadonce) { /* * XXX Aggressively spill the floating point register on x86. * Otherwise it might not get spilled out at all. */ spillAndUpdate(from, true); } /* 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 = ®info[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) || (codeInfo->localuse == 0)) { return; } /* Allocate an array for the slot pointers and copy them in */ slots = gc_malloc((1+maxLocal) * sizeof(SlotInfo*), GC_ALLOC_JIT_SLOTS); 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 = ®info[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_JITTEMP)); } /* 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"typedef struct _fakeCall { struct _fakeCall* next; struct _fakeCall* parent; label* from; label* to; void* func;} fakeCall;/* XXX These are globally shared */static fakeCall* firstFake;static fakeCall** lastFake = &firstFake;static fakeCall* fakePool;static fakeCall* redundantFake;staticvoidinitFakeCalls(void){ *lastFake = redundantFake; redundantFake = 0; fakePool = firstFake; firstFake = 0; lastFake = &firstFake;}fakeCall *findFakeCall(void *func){ fakeCall *fc, *retval = 0; for( fc = firstFake; fc && !retval; fc = fc->next ) { if( fc->func == func ) retval = fc; } return( retval );}/* * 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){ fakeCall *fc; 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; /* XXX This isn't safe, but noone checks the return value :( */ if( fakePool ) { fc = fakePool; fakePool = fakePool->next; fc->next = 0; } else { fc = GC_malloc(main_collector, sizeof(fakeCall), GC_ALLOC_JIT_FAKE_CALL); }#if defined(HAVE_branch_and_link) fc->parent = findFakeCall(func);#endif fc->from = from; fc->to = to; fc->func = func; if( fc->parent ) { fc->next = redundantFake; redundantFake = fc; } else { *lastFake = fc; lastFake = &fc->next; } return (to);}staticvoidmakeFakeCalls(void){ fakeCall* c; for (c = firstFake; c; c = c->next) { softcall_fakecall(c->from, c->to, c->func); }}staticvoid relinkFakeCalls(void){ fakeCall *fc; for( fc = redundantFake; fc; fc = fc->next ) { fc->to->to = fc->parent->to->to; fc->to->type = fc->parent->to->type; fc->from->at = fc->parent->from->at; fc->from->type = fc->parent->from->type; assert(fc->to->from != 0); }}/* * 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 + -