📄 machine.c
字号:
KaffeJIT_linkLabels(codeInfo, (uintp)jch->code_start); /* Note info on the compiled code for later installation */ code->mem = methblock; code->memlen = exc_len + constlen + CODEPC; code->code = jch->code_start; code->codelen = CODEPC; return (true);}static intgetInsnPC(int pc, codeinfo* codeInfo, nativeCodeInfo* code) { int maxPC = codeInfo->codelen; while (pc < maxPC) { if (IS_STARTOFINSTRUCTION(pc)) { int insn = INSNPC(pc); if (insn!=-1) { return insn; } } pc++; } return code->codelen;} /* * Install the compiled code in the method. */voidinstallMethodCode(codeinfo* codeInfo, Method* meth, nativeCodeInfo* code){ unsigned int i; jexceptionEntry* e; jitCodeHeader *jch; void *tramp; /* Work out new estimate of code per bytecode */ code_generated += code->memlen; bytecode_processed += meth->c.bcode.codelen; codeperbytecode = code_generated / bytecode_processed; tramp = METHOD_NATIVECODE(meth); /* install the jitted code */ SET_METHOD_JITCODE(meth, code->code); setMethodCodeStart(meth, code->mem); meth->c.ncode.ncode_end = (nativecode *)code->code + code->codelen; jch = (jitCodeHeader *)code->mem; jch->method = meth; /* Flush code out of cache */ FLUSH_DCACHE(METHOD_NATIVECODE(meth), meth->c.ncode.ncode_end);#if defined(MD_REGISTER_JIT_EXCEPTION_INFO) MD_REGISTER_JIT_EXCEPTION_INFO (getMethodCodeStart(meth), METHOD_NATIVECODE(meth), meth->c.ncode.ncode_end);#endif /* Translate exception table and make it available */ if (meth->exception_table != 0) { for (i = 0; i < meth->exception_table->length; i++) { /* Note that we cannot assume that the bytecode * instructions that are at the start/end/handler * pc index have a corresponding native pc. * They only have one if they already emitted * native instructions during translation. * Jikes, for instance, likes to put a `nop' at * the end_pc index of an exception handler range. * * If this happens, we simply find the next bytecode * instruction that has a native pc and use it instead. */ 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; assert(e->start_pc <= e->end_pc); } } /* Translate line numbers table */ if (meth->lines != 0) { 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; } }}/* * Init instruction generation. */boolinitInsnSequence(Method* meth, int codesize, int localsz, int stacksz, struct _errorInfo *einfo){ /* Clear various counters */ tmpslot = 0; maxTemp = 0; maxPush = 0; stackno = localsz + stacksz; maxTemp = MAXTEMPS - 1; /* XXX */ npc = 0; initSeq(); initRegisters(); initSlots(stackno); KaffeJIT_resetLabels(); KaffeJIT_resetConstants(); localinfo = &slotinfo[0]; tempinfo = &localinfo[stackno]; /* Before generating code, try to guess how much space we'll need. */ codeblock_size = codesize; if (codeblock_size < ALLOCCODEBLOCKSZ) { codeblock_size = ALLOCCODEBLOCKSZ; } codeblock = KMALLOC(codeblock_size + CODEBLOCKREDZONE); if (!codeblock) { postOutOfMemory(einfo); return false; } addToCounter(&jitcodeblock, "jitmem-codeblock", 1, (jlong) GCSIZEOF(codeblock)); CODEPC = 0; /* * add the method we're translating as the first entry to the constant pool, * so that we can look it up pretty easily when creating stack traces. */ KaffeJIT_newConstant(CPref, meth); return true;}/* */void KaffeJIT_cleanupInsnSequence(){ initSeq();}/* * Generate instructions from current set of sequences. */staticvoidgenerateInsnSequence(codeinfo* codeInfo){ sequence* t; for (t = firstSeq; t != currSeq; t = t->next) { /* If we overrun the codeblock, reallocate and continue. */ if (CODEPC >= codeblock_size) { codeblock_size += ALLOCCODEBLOCKSZ; addToCounter(&jitcodeblock, "jitmem-codeblock", 0, -(jlong)GCSIZEOF(codeblock)); codeblock = KREALLOC(codeblock, codeblock_size + CODEBLOCKREDZONE); addToCounter(&jitcodeblock, "jitmem-codeblock", 0, (jlong)GCSIZEOF(codeblock)); } /* Generate sequences */ (*(void (*)(sequence*, codeinfo*))(t->func))(t, codeInfo); } /* Reset */ initSeq();}/* * Start a new instruction. */voidstartInsn(sequence* s, codeinfo* codeInfo){ SET_INSNPC(const_int(2), CODEPC);}/* * Mark slot not to be written back. */voidnowritebackSlot(sequence* s){ seq_slot(s, 0)->modified |= rnowriteback;}/* * Start a new basic block. */voidstartBlock(sequence* s){ startSubBlock(s);}/* * Start a new basic sub-block. */voidstartSubBlock(sequence* s UNUSED){ int i; /* Invalidate all slots - don't use clobberRegister which will * flush them - we do not want to do that even if they are dirty. */ for (i = maxslot - 1; i >= 0; i--) { if (slotinfo[i].regno != NOREG) { register_invalidate(slotinfo[i].regno); slot_invalidate(&slotinfo[i]); } }}/* * Fixup after a function call. */voidfixupFunctionCall(sequence* s UNUSED){ int i; /* Invalidate all slots - don't use clobberRegister which will * flush them - we do not want to do that even if they are dirty. */ for (i = maxslot - 1; i >= 0; i--) { if (slotinfo[i].regno != NOREG && (KaffeVM_jitGetRegInfo()[slotinfo[i].regno].flags & Rnosaveoncall) == 0) { register_invalidate(slotinfo[i].regno); slot_invalidate(&slotinfo[i]); } }}/* * End a basic block. */voidendBlock(sequence* s){ endSubBlock(s);}/* * End a basic sub-block. */voidendSubBlock(sequence* s){ int stkno; int tmpslot; int i; /* Spill locals */ for (i = 0; i < maxLocal; i++) { if ((localinfo[i].modified & rwrite) != 0 && localinfo[i].regno != NOREG) { if ((localinfo[i].modified & rnowriteback) == 0) { spill(&localinfo[i]); localinfo[i].modified = 0; } else { localinfo[i].modified &= ~rnowriteback; } } } /* Spill stack */ stkno = const_int(1); for (i = stkno; i < maxStack+maxLocal; i++) { if ((localinfo[i].modified & rwrite) != 0 && localinfo[i].regno != NOREG) { if ((localinfo[i].modified & rnowriteback) == 0) { spill(&localinfo[i]); localinfo[i].modified = 0; } else { localinfo[i].modified &= ~rnowriteback; } } } /* Spill temps currently in use */ tmpslot = const_int(2); for (i = 0; i < tmpslot; i++) { if ((tempinfo[i].modified & rwrite) != 0 && tempinfo[i].regno != NOREG) { if ((tempinfo[i].modified & rnowriteback) == 0) { spill(&tempinfo[i]); tempinfo[i].modified = 0; } else { tempinfo[i].modified &= ~rnowriteback; } } }}/* * Prepare register state for function call. */voidprepareFunctionCall(sequence* s){ int stkno; int tmpslot; int i; /* Spill locals */ for (i = 0; i < maxLocal; i++) { if ((localinfo[i].modified & rwrite) != 0 && localinfo[i].regno != NOREG && (KaffeVM_jitGetRegInfo()[localinfo[i].regno].flags & Rnosaveoncall) == 0) { spill(&localinfo[i]); localinfo[i].modified = 0; } } /* Spill stack */ stkno = const_int(1); for (i = stkno; i < maxStack+maxLocal; i++) { if ((localinfo[i].modified & rwrite) != 0 && localinfo[i].regno != NOREG && (KaffeVM_jitGetRegInfo()[localinfo[i].regno].flags & Rnosaveoncall) == 0) { spill(&localinfo[i]); localinfo[i].modified = 0; } } /* Spill temps currently in use */ tmpslot = const_int(2); for (i = 0; i < tmpslot; i++) { if ((tempinfo[i].modified & rwrite) != 0 && tempinfo[i].regno != NOREG && (KaffeVM_jitGetRegInfo()[tempinfo[i].regno].flags & Rnosaveoncall) == 0) { spill(&tempinfo[i]); tempinfo[i].modified = 0; } }}/* * Sync register state back to memory (but don't clean anything). */voidsyncRegisters(sequence* s){ int stkno; int tmpslot; int i; int old_ro; old_ro = KaffeVM_jitGetEnableReadonce(); KaffeVM_jitSetEnableReadonce(0); /* Spill locals */ for (i = 0; i < maxLocal; i++) { if ((localinfo[i].modified & rwrite) != 0 && localinfo[i].regno != NOREG && (KaffeVM_jitGetRegInfo()[localinfo[i].regno].flags & Rnosaveoncall) == 0) { spill(&localinfo[i]); } } /* Spill stack */ stkno = const_int(1); for (i = stkno; i < maxLocal+maxStack; i++) { if ((localinfo[i].modified & rwrite) != 0 && localinfo[i].regno != NOREG && (KaffeVM_jitGetRegInfo()[localinfo[i].regno].flags & Rnosaveoncall) == 0) { spill(&localinfo[i]); } } /* Spill temps currently in use */ tmpslot = const_int(2); for (i = 0; i < tmpslot; i++) { if ((tempinfo[i].modified & rwrite) != 0 && tempinfo[i].regno != NOREG && (KaffeVM_jitGetRegInfo()[tempinfo[i].regno].flags & Rnosaveoncall) == 0) { spill(&tempinfo[i]); } } KaffeVM_jitSetEnableReadonce(old_ro);}/* * Cancel any pending nowriteback flags. */voidcancelNoWriteback(void){ int i; for (i = stackno; i < maxLocal+maxStack; i++) { localinfo[i].modified &= ~rnowriteback; }}/* * check what synchronous exceptions are caught for a given instruction */staticvoid checkCaughtExceptions(Method* meth, unsigned int pc){ unsigned int i; 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; 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); } } }}/* * 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 + -