📄 machine.c
字号:
} /* 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: KAFFEVM_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: KAFFEVM_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*), KGC_ALLOC_JIT_SLOTS); if (mem == NULL) KaffeJIT3_exitWithOOM(); 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(); )}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), KGC_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. */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;voidinitFakeCalls(void){ *lastFake = redundantFake; redundantFake = NULL; fakePool = firstFake; firstFake = NULL; lastFake = &firstFake;}#if defined(HAVE_branch_and_link)staticfakeCall *findFakeCall(void *func){ fakeCall *fc, *retval = NULL; for( fc = firstFake; fc && !retval; fc = fc->next ) { if( fc->func == func ) retval = fc; } return( retval );}#endif /* defined(HAVE_branch_and_link) *//* * 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 = KaffeJIT3_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 = NULL; } else { fc = KGC_malloc(main_collector, sizeof(fakeCall), KGC_ALLOC_JIT_FAKE_CALL); if (fc == NULL) KaffeJIT3_exitWithOOM(); }#if defined(HAVE_branch_and_link) fc->parent = findFakeCall(func);#endif fc->from = from; fc->to = to; fc->func = func; if( fc->parent != NULL ) { 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 */const char*getEngine(void){ return "kaffe.jit";}void initEngine(void){ initStaticLock(&translatorlock);}#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 UNUSED){ Method *meth; int mindex; for (mindex = CLASS_NMETHODS(clazz), meth = Kaffe_get_class_methods(clazz); 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 + -