📄 machine.c
字号:
/* machine.c * Translate the Kaffe instruction set to the native one. * * Copyright (c) 1996-1999 * Transvirtual Technologies, Inc. All rights reserved. * * Copyright (c) 2003, 2004 * Kaffe.org contributors. See ChangeLog for details. All rights reserved. * * Cross-language profiling changes contributed by * the Flux Research Group, Department of Computer Science, * University of Utah, http://www.cs.utah.edu/flux/ * * See the file "license.terms" for information on usage and redistribution * of this file. */#define SCHK(s)#define SUSE(s)#include "config.h"#include "config-std.h"#include "config-mem.h"#include "gtypes.h"#include "md.h"#include "classMethod.h"#include "bytecode.h"#include "slots.h"#include "registers.h"#include "seq.h"#include "gc.h"#include "machine.h"#include "basecode.h"#include "icode.h"#include "labels.h"#include "constpool.h"#include "codeproto.h"#include "checks.h"#include "access.h"#include "object.h"#include "constants.h"#include "baseClasses.h"#include "code.h"#include "access.h"#include "lookup.h"#include "exception.h"#include "errors.h"#include "locks.h"#include "code-analyse.h"#include "external.h"#include "soft.h"#include "thread.h"#include "itypes.h"#include "support.h"#include "xprofiler.h"#if defined(KAFFE_FEEDBACK)#include "feedback.h"#endif#include "debugFile.h"#include "fileSections.h"#include "mangle.h"#include "jvmpi_kaffe.h"#include "kaffe_jni.h"#include "native-wrapper.h"#include "stats.h"const char* engine_name = "Just-in-time v3";/** * top of the operand stack. localsz <= stackno < localsz+stacksz */int stackno;int maxStack;int maxLocal;int maxTemp;int maxArgs;int maxPush;int isStatic;codeinfo* codeInfo;/** * index of first unused element of tempinfo (next available temp slot) */int tmpslot;int argcount = 0; /* Function call argument count */uint32 pc;uint32 npc;/* Various exception related things */jitflags willcatch;/* jit3 specific prototypes from icode.c */void explicit_check_null (int x, SlotInfo* obj, int y);void check_null (int x, SlotInfo* obj, int y);void check_div (int x, SlotInfo* obj, int y);void check_div_long (int x, SlotInfo* obj, int y);void softcall_fakecall (label* from,label* to, void* func);/* Unit in which code block is increased when overrun */#define ALLOCCODEBLOCKSZ 8192/* Codeblock redzone - allows for safe overrun when generating instructions */#define CODEBLOCKREDZONE 256static unsigned int codeblock_size;static int code_generated;static int bytecode_processed;static int codeperbytecode;iStaticLock translatorlock;struct { int time;} jitStats;static jboolean generateInsnSequence(errorInfo*);/** * Look for exception handlers that enclose the given PC in the given method. * If a match is found, it will set the appropriate willcatch flags. * * @param meth The method that may contain an exception handler. * @param pc The location within the method to look for a handler. */static void checkCaughtExceptions(Method* meth, uint32 _pc);void initFakeCalls(void);static void makeFakeCalls(void);static void relinkFakeCalls(void);/* Desktop edition */#include "debug.h"Method *globalMethod;#if defined(KAFFE_PROFILER)int profFlag;static void printProfilerStats(void);#endifJTHREAD_JMPBUF JIT3_jumpExitWithOOM;void KaffeJIT3_exitWithOOM(){ JTHREAD_LONGJMP(JIT3_jumpExitWithOOM, 1);}jboolean KaffeJIT3_setupExitWithOOM(struct _errorInfo* einfo){ if (!JTHREAD_SETJMP(JIT3_jumpExitWithOOM)) return false; postOutOfMemory(einfo); return true;}/* * Init instruction generation. */jbooleaninitInsnSequence(int localsz, int stacksz, errorInfo* einfo){ /* Clear various counters */ tmpslot = 0; maxTemp = 0; maxPush = 0; stackno = localsz + stacksz; npc = 0; initSeq(); initRegisters(); initSlots(stackno); /* Before generating code, try to guess how much space we'll need. */ codeblock_size = ALLOCCODEBLOCKSZ; codeblock = gc_malloc(codeblock_size + CODEBLOCKREDZONE, KGC_ALLOC_JIT_CODEBLOCK); if (codeblock == 0) { postOutOfMemory(einfo); return (false); } CODEPC = 0; return (true);}/* * Translate a method into native code. * * Registers are allocated per basic block, using an LRU algorithm. * Contents of registers are spilled at the end of basic block, * depending on the edges in the CFG leaving the basic block: * * - If there is an edge from the basic block to an exception handler, * local variables are spilled on the stack * * - If there is only one non-exception edge, and the target basic * block is following the current block immediately, no spills are done * * - Otherwise, the local variables and the operand stack are spilled * onto the stack */jbooleantranslate(Method* xmeth, errorInfo* einfo){#if defined(KAFFE_VMDEBUG) int i;#endif /* defined(KAFFE_VMDEBUG) */ jint low; jint high; jvalue tmpl; int idx; SlotInfo* tmp; SlotInfo* tmp2; SlotInfo* mtable; bytecode* base; uint32 len; callInfo cinfo; fieldInfo finfo; Hjava_lang_Class* crinfo; codeinfo* mycodeInfo; nativeCodeInfo ncode; int64 tms = 0; int64 tme; static bool reinvoke = false; jboolean success = true; lockClass(xmeth->class); if (METHOD_TRANSLATED(xmeth)) { goto done3; } /* If this code block is native, then just set it up and return */ if (methodIsNative(xmeth)) { void *func = native(xmeth, einfo); if (func != NULL) { engine_create_wrapper(xmeth, func); KAFFEJIT_TO_NATIVE(xmeth); } else { success = false; } goto done3; } /* Scan the code and determine the basic blocks */ success = analyzeMethod(xmeth, &mycodeInfo, einfo); if (success == false) { /* It may happen that we already have translated it * by implicit recursion in the verifier. */ if (METHOD_TRANSLATED(xmeth)) success = true; goto done3; }#if defined(KAFFE_FEEDBACK) if( kaffe_feedback_file ) lockMutex(kaffe_feedback_file);#endif /* Only one in the translator at once. Must check the translation * hasn't been done by someone else once we get it. */ enterTranslator(); startTiming(&fulljit, "JIT translation"); if (Kaffe_JavaVMArgs.enableVerboseJIT) { tms = currentTime(); }DBG(MOREJIT, dprintf("callinfo = %p\n", &cinfo); );#if defined(KAFFE_PROFILER) if (profFlag) { static int init = 0; if (!init) { atexit(printProfilerStats); init = 1; } profiler_get_clicks(xmeth->jitClicks); xmeth->callsCount = 0; xmeth->totalClicks = 0; xmeth->totalChildrenClicks = 0; }#endif globalMethod = xmeth; codeInfo = mycodeInfo; /* Handle null calls specially */ if (METHOD_BYTECODE_LEN(xmeth) == 1 && METHOD_BYTECODE_CODE(xmeth)[0] == RETURN) { SET_METHOD_NATIVECODE(xmeth, (nativecode*)soft_null_call); goto done; } assert(reinvoke == false); reinvoke = true; maxLocal = xmeth->localsz; maxStack = xmeth->stacksz; maxArgs = sizeofSigMethod(xmeth, false); if (maxArgs == -1) { goto done; } if (xmeth->accflags & ACC_STATIC) { isStatic = 1; } else { isStatic = 0; maxArgs += 1; } if (KaffeJIT3_setupExitWithOOM(einfo)) { success = false; goto oom_error; }DBG(MOREJIT, dprintf("Method: %s.%s%s\n", CLASS_CNAME(xmeth->class), xmeth->name->data, METHOD_SIGD(xmeth)); for (i = 0; i < maxLocal; i++) { dprintf(" L%d: %2d", i, codeInfo->localuse[i].use); } dprintf("\n");); base = (bytecode*)METHOD_BYTECODE_CODE(xmeth); len = METHOD_BYTECODE_LEN(xmeth); /* * Initialise the translator. */ initFakeCalls(); /* Do any machine dependent JIT initialization */#if defined(INIT_JIT_MD) INIT_JIT_MD(xmeth);#endif success = initInsnSequence(xmeth->localsz, xmeth->stacksz, einfo); if (success == false) { goto done; } /***************************************/ /* Next reduce bytecode to native code */ /***************************************/ pc = 0; start_function(); check_stack_limit(); if (Kaffe_JavaVMArgs.enableVerboseCall != 0) { softcall_trace(xmeth); } monitor_enter(); if (IS_STARTOFBASICBLOCK(0)) { end_basic_block(); success = generateInsnSequence(einfo); if (success == false) { goto done; } start_basic_block(); } for (; pc < len; pc = npc) { assert(stackno <= maxStack+maxLocal); assert(stackno >= 0); npc = pc + insnLen[base[pc]]; /* Skip over the generation of any unreachable basic blocks */ if (IS_UNREACHABLE(pc)) { while (npc < len && !IS_STARTOFBASICBLOCK(npc) && !IS_STARTOFEXCEPTION(npc)) { npc = npc + insnLen[base[npc]]; }DBG(JIT, dprintf("unreachable basic block pc [%d:%d]\n", pc, npc - 1); ); if (IS_STARTOFBASICBLOCK(npc)) { end_basic_block(); start_basic_block(); stackno = STACKPOINTER(npc); } continue; } /* Determine various exception conditions */ checkCaughtExceptions(xmeth, pc); start_instruction(); /* Note start of exception handling blocks */ if (IS_STARTOFEXCEPTION(pc)) { stackno = xmeth->localsz + xmeth->stacksz - 1; start_exception_block(); } switch (base[pc]) { default: printf("Unknown bytecode %d\n", base[pc]); leaveTranslator();#if defined(KAFFE_FEEDBACK) if( kaffe_feedback_file ) unlockMutex(kaffe_feedback_file);#endif unlockClass(xmeth->class); postException(einfo, JAVA_LANG(VerifyError)); success = false; break;#include "kaffe.def" } /* Note maximum number of temp slots used and reset it */ if (tmpslot > maxTemp) { maxTemp = tmpslot; } tmpslot = 0;SCHK( sanityCheck(); ) if (IS_STARTOFBASICBLOCK(npc)) { end_basic_block(); success = generateInsnSequence(einfo); if (success == false) { goto done; } start_basic_block(); stackno = STACKPOINTER(npc);SCHK( sanityCheck(); ) } } end_function(); makeFakeCalls(); assert(maxTemp < MAXTEMPS); if( finishInsnSequence(NULL, &ncode, einfo) ) { installMethodCode(NULL, xmeth, &ncode); } else { success = false; } goto done;oom_error:; KaffeJIT3_cleanupInsnSequence(); done:; KaffeJIT3_resetLabels(); KaffeJIT3_resetConstants(); tidyAnalyzeMethod(&codeInfo); reinvoke = false;#if defined(KAFFE_PROFILER) if (profFlag) { profiler_click_t end; profiler_get_clicks(end); xmeth->jitClicks = end - xmeth->jitClicks; }#endif globalMethod = NULL;DBG(MOREJIT, dprintf("Translating %s.%s%s (%s) %p\n", xmeth->class->name->data, xmeth->name->data, METHOD_SIGD(xmeth), isStatic ? "static" : "normal", METHOD_NATIVECODE(xmeth)); ); if (Kaffe_JavaVMArgs.enableVerboseJIT) { tme = currentTime(); jitStats.time += (int)(tme - tms); printf("<JIT: %s.%s%s time %dms (%dms) @ %p (%p)>\n", CLASS_CNAME(xmeth->class), xmeth->name->data, METHOD_SIGD(xmeth), (int)(tme - tms), jitStats.time, METHOD_NATIVECODE(xmeth), xmeth); } stopTiming(&fulljit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -