📄 machine.c
字号:
/* machine.c * Translate the Kaffe instruction set to the native one. * * Copyright (c) 1996-1999, 2003 * Transvirtual Technologies, Inc. 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 "methodCache.h"#include "support.h"#include "xprofiler.h"#include "feedback.h"#include "debugFile.h"#include "fileSections.h"#include "mangle.h"#include "jvmpi_kaffe.h"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 uint 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);static 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);#endif/* * Translate a method into native code. */jbooleantranslate(Method* xmeth, errorInfo* einfo){ int i; 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; int iLockRoot; lockClass(xmeth->class); if (METHOD_TRANSLATED(xmeth)) { goto done3; } /* If this code block is native, then just set it up and return */ if ((xmeth->accflags & ACC_NATIVE) != 0) { success = native(xmeth, einfo); if (success == true) { KAFFEJIT_TO_NATIVE(xmeth); } goto done3; } /* Scan the code and determine the basic blocks */ success = analyzeMethod(xmeth, &mycodeInfo, einfo); if (success == false) { 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(); if (Kaffe_JavaVMArgs[0].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; }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(); success = initInsnSequence(xmeth, codeperbytecode * METHOD_BYTECODE_LEN(xmeth), 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[0].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(0, &ncode, einfo) ) { installMethodCode(0, xmeth, &ncode); } else { success = false; }done:; resetLabels(); 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 = 0;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[0].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); } leaveTranslator();#if defined(KAFFE_FEEDBACK) if( kaffe_feedback_file ) unlockMutex(kaffe_feedback_file);#endifdone3:; unlockClass(xmeth->class);#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_COMPILED_METHOD_LOAD) && success ) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_COMPILED_METHOD_LOAD; ev.u.compiled_method_load.method_id = xmeth; ev.u.compiled_method_load.code_addr = METHOD_NATIVECODE(xmeth); ev.u.compiled_method_load.code_size = xmeth->c.ncode.ncode_end - xmeth->c.ncode.ncode_start; if( xmeth->lines ) { JVMPI_Lineno *jvmpi_lineno = NULL; int lpc; jvmpi_lineno = alloca(sizeof(JVMPI_Lineno) * xmeth->lines->length); for( lpc = 0; lpc < xmeth->lines->length; lpc++ ) { jvmpiConvertLineno(&jvmpi_lineno[lpc], &xmeth->lines->entry[lpc], METHOD_NATIVECODE(xmeth)); } ev.u.compiled_method_load.lineno_table_size = xmeth->lines->length; ev.u.compiled_method_load.lineno_table = jvmpi_lineno; } else { ev.u.compiled_method_load.lineno_table_size = 0; ev.u.compiled_method_load.lineno_table = NULL; } jvmpiPostEvent(&ev); }#endif return (success);}/* * Generate the code. */jbooleanfinishInsnSequence(void* dummy, nativeCodeInfo* code, errorInfo* einfo){ uint32 constlen; nativecode* methblock; nativecode* codebase; jboolean success; /* Emit pending instructions */ success = generateInsnSequence(einfo); if (success == false) { return (false); } relinkFakeCalls(); /* Okay, put this into malloc'ed memory */ constlen = nConst * sizeof(union _constpoolval); methblock = gc_malloc(constlen + CODEPC, GC_ALLOC_JITCODE); if (methblock == 0) { postOutOfMemory(einfo); return (false); } codebase = methblock + constlen; memcpy(codebase, codeblock, CODEPC); gc_free(codeblock); /* Establish any code constants */ establishConstants(methblock); /* Link it */ linkLabels((uintp)codebase); /* Note info on the compiled code for later installation */ code->mem = methblock; code->memlen = constlen + CODEPC; code->code = codebase; 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 */staticint
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -