📄 machine.c
字号:
leaveTranslator();#if defined(KAFFE_FEEDBACK) if( kaffe_feedback_file ) unlockMutex(kaffe_feedback_file);#endifdone3:; unlockClass(xmeth->class);#if defined(ENABLE_JVMPI) if (success && JVMPI_EVENT_ISENABLED(JVMPI_EVENT_COMPILED_METHOD_LOAD) ) { JVMPI_Event ev; jvmpiFillMethodLoad(&ev, xmeth); jvmpiPostEvent(&ev); }#endif return (success);}voidKaffeJIT3_cleanupInsnSequence(){ sequence *s; for (s = firstSeq; s != currSeq; s = s->next) { if (s->func != doSpill) continue; /* According to doSpill */ gc_free(s->u[1].smask); } initSeq();}/* * Generate the code. */jbooleanfinishInsnSequence(void* dummy UNUSED, nativeCodeInfo* code, errorInfo* einfo){ uint32 constlen; jitCodeHeader *jch; nativecode* methblock; jboolean success; uintp const_align = sizeof(union _constpoolval) - 1; /* Emit pending instructions */ success = generateInsnSequence(einfo); if (success == false) { return (false); } relinkFakeCalls(); /* Okay, put this into malloc'ed memory. We allocate some more * memory for alignment purpose. */ constlen = KaffeJIT3_getNumberOfConstants() * sizeof(union _constpoolval); methblock = gc_malloc(sizeof(jitCodeHeader) + constlen + const_align + CODEPC, KGC_ALLOC_JITCODE); if (methblock == 0) { postOutOfMemory(einfo); return (false); } jch = (jitCodeHeader *)methblock; jch->pool = (void *)(jch + 1); jch->pool = (void *) ( ((unsigned long)(jch->pool) + const_align) & ~const_align); jch->code_start = ((nativecode *)jch->pool) + constlen; jch->code_len = CODEPC; memcpy(jch->code_start, codeblock, jch->code_len); gc_free(codeblock); /* Establish any code constants */ KaffeJIT3_establishConstants(jch->pool); /* Link it */ KaffeJIT3_linkLabels((uintp)jch->code_start); /* Note info on the compiled code for later installation */ code->mem = methblock; code->memlen = constlen + CODEPC; code->code = jch->code_start; code->codelen = CODEPC; return (true);}/* * Get the instruction offset corresponding to the given PC. * If the PC doesn't point at the start of a valid instruction, * look forward until we find one. If we reach the end of the * method, we return code->codelen */staticintgetInsnPC(int _pc, codeinfo* _codeInfo, nativeCodeInfo *code){ int maxPc = _codeInfo->codelen; while (_pc < maxPc) { if (IS_STARTOFINSTRUCTION(_pc)) { int res = INSNPC(_pc); if (res != -1) { return (res); } } _pc ++; } return code->codelen;}/* * Install the compiled code in the method. * Returns true if successful */voidinstallMethodCode(void* ignore UNUSED, Method* meth, nativeCodeInfo* code){ uint32 i; jexceptionEntry* e; jitCodeHeader *jch; 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; } //KGC_WRITE(meth, code->mem); jch = (jitCodeHeader *)code->mem; jch->method = meth; tramp = METHOD_NATIVECODE(meth); SET_METHOD_JITCODE(meth, code->code); setMethodCodeStart(meth, 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, KGC_ALLOC_JITTEMP); assert(sym != NULL); 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 /* 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; assert (e->start_pc <= e->end_pc); } } /* Translate line numbers table */ if (meth->lines != 0) {#if defined(KAFFE_XDEBUGGING) struct debug_file *df = machine_debug_file; /* Mark the start of this source file */ char *sourcefile = meth->class->sourcefile; if (! sourcefile) sourcefile = "Unknown source file"; addDebugInfo(df, DIA_IncludeFile, meth->class->name->data, meth->class->packageLength, 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) /* 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( meth->lvars != NULL ) { localVariableEntry *lve; for (i = 0; i < meth->lvars->length; i++) { lve = &meth->lvars->entry[i]; lve->start_pc = (uintp)code->code + getInsnPC(lve->start_pc, codeInfo, code);#if defined(KAFFE_XDEBUGGING) && defined(SLOT2LOCALOFFSET) if( df != NULL ) { struct Hjava_lang_Class *cl; const char *vname, *vsig; errorInfo einfo; vname = CONST_UTF2CHAR( lve->name_index, CLASS_CONSTANTS(meth->class)); vsig = CONST_UTF2CHAR( lve->descriptor_index, CLASS_CONSTANTS(meth->class)); cl = getClassFromSignature( vsig, meth->class->loader, &einfo); if( cl == NULL ) { discardErrorInfo(&einfo); } /* Add line debugging */ addDebugInfo(df, lve->index < maxArgs ? DIA_Parameter : DIA_LocalVariable, vname, cl, local(lve->index)->slot->offset, DIA_DONE); }#endif } }#if defined(KAFFE_XDEBUGGING) /* * 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 */ char *sourcefile = meth->class->sourcefile; if (! sourcefile) sourcefile = "Unknown source file"; addDebugInfo( machine_debug_file, DIA_IncludeFile, meth->class->name->data, meth->class->packageLength, 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}/* * 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, KGC_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); 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: KAFFEVM_ABORT(); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -