📄 executejava_split2.c
字号:
/* * @(#)executejava_split2.c 1.77 06/10/25 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "javavm/include/defs.h"#include "javavm/include/objects.h"#include "javavm/include/directmem.h"#include "javavm/include/indirectmem.h"#include "javavm/include/opcodes.h"#include "javavm/include/interpreter.h"#include "javavm/include/classes.h"#include "javavm/include/stacks.h"#include "javavm/include/globalroots.h"#include "javavm/include/gc_common.h"#include "javavm/include/globals.h"#include "javavm/include/preloader.h"#include "javavm/include/utils.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/clib.h"#include "javavm/include/porting/doubleword.h"#include "javavm/include/porting/float.h"#include "javavm/include/porting/int.h"#include "javavm/include/porting/jni.h"#ifdef CVM_JVMTI#include "javavm/include/jvmti_impl.h"#include "generated/offsets/java_lang_Thread.h"#endif#ifdef CVM_JVMPI#include "javavm/include/jvmpi_impl.h"#endif#ifdef CVM_JIT#include "javavm/include/jit_common.h"#endif/* * CVM_USELABELS - If using GCC, then use labels for the opcode dispatching * rather than a switch statement. This improves performance because it * gives us the oportunity to have the instructions that calculate the * next opcode to jump to be intermixed with the rest of the instructions * that implement the opcode (see UPDATE_PC_AND_TOS_AND_CONTINUE macro). */#ifdef __GNUC__#define CVM_USELABELS#endif/* * CVM_PREFETCH_OPCODE - Some compilers do better if you prefetch the next * opcode before going back to the top of the while loop, rather then having * the top of the while loop handle it. This provides a better opportunity * for instruction scheduling. Some compilers just do this prefetch * automatically. Some actually end up with worse performance if you * force the prefetch. Solaris gcc seems to do better, but cc does worse. */#ifdef __GNUC__#define CVM_PREFETCH_OPCODE#endif/* * CVM_GENERATE_ASM_LABELS - Define this if you want an asm label generated * at the start of each opcode and goto label. This makes it much easier * to read the generated assembler. However, this seems to slightly change * the generated code in some very minor ways on some processors. x86 does * not seem to be affected, but sparc does. This option only works with gcc. */#if 0 /* off by default */#define CVM_GENERATE_ASM_LABELS#endif /* * GET_INDEX - Macro used for getting an unaligned unsigned short from * the byte codes. */#undef GET_INDEX#define GET_INDEX(ptr) (CVMgetUint16(ptr))/* %comment c001 */#define CVMisROMPureCode(cb) (CVMcbIsInROM(cb))/* * Tracing macros */#undef TRACE#undef TRACEIF#undef TRACESTATUS#define TRACE(a) CVMtraceOpcode(a)#define TRACESTATUS(frame) { \ CVMtraceStatus(("stack=0x%x frame=0x%x locals=0x%x tos=0x%x pc=0x%x\n", \ &ee->interpreterStack, frame, locals, topOfStack, pc)); \ }#ifdef CVM_TRACE#define TRACEIF(o, a) \ if (*pc == o) { \ TRACE(a); \ }#else#define TRACEIF(o, a)#endif/* * CVM_JAVA_ERROR - Macro for throwing a java exception from * the interpreter loop. It makes sure that the PC is flushed * and the topOfStack is reset before CVMsignalError is called. */#define CVM_JAVA_ERROR(exception_, error_) \{ \ DECACHE_PC(frame); /* required for CVMsignalError */ \ CVM_RESET_JAVA_TOS(frame->topOfStack, frame); \ CVMthrow##exception_(ee, error_); \ goto handle_exception; \}/* * INIT_CLASS_IF_NEEDED - Makes sure that static initializers are * run for a class. Used in opc_*_checkinit_quick opcodes. */#undef INIT_CLASS_IF_NEEDED#define INIT_CLASS_IF_NEEDED(ee, cb) \ if (CVMcbInitializationNeeded(cb, ee)) { \ DECACHE_PC(frame); \ DECACHE_TOS(frame); \ *retCb = cb; \ /* pc == NULL means init_class must be performed */ \ return NULL; \ } \ JVMPI_TRACE_INSTRUCTION();/* * Check that the returned PC and TOS from the second level are in line * with the current frame */#ifdef CVM_DEBUG_ASSERTSstatic CVMBoolframeSanity(CVMFrame* frame){ return CVMframePrev(frame) != frame;}#endif#ifdef CVM_INSTRUCTION_COUNTING#include "generated/javavm/include/opcodeSimplification.h"/* * Instruction counting. CVMbigCount is incremented every 1M * insns. CVMsmallCount keeps track of the small change. */static CVMUint32 CVMsmallCount = 0;static CVMUint32 CVMbigCount = 0;/* * Maximum length of sequences tracked */#define CVM_SEQ_DEPTH 3/* * An information node. Incidence of byte-codes at this depth, and pointers * to information nodes at the next depth. */struct CVMRunInfo { int incidence[256]; struct CVMRunInfo* followers[256];};typedef struct CVMRunInfo CVMRunInfo;/* * The sliding window of byte-codes most recently executed. */static CVMOpcode CVMopcodeWindow[CVM_SEQ_DEPTH];static int CVMopcodeWindowIdx;/* * The root of all sequence information nodes. */static CVMRunInfo* CVMseqInfo;/* * Record window of last executed opcodes, starting from index idx. * Lazily create information nodes. */ static voidCVMrecordWindow(int idx){ int i; CVMRunInfo* record = CVMseqInfo; CVMOpcode currOpcode = CVMopcodeWindow[idx]; /* * Traverse information node tree, creating nodes as needed. */ for (i = 1; i < CVM_SEQ_DEPTH; i++) { CVMUint32 theIdx; CVMRunInfo* nextRecord; record->incidence[currOpcode]++; nextRecord = record->followers[currOpcode]; if (nextRecord == 0) { nextRecord = calloc(1, sizeof(CVMRunInfo)); record->followers[currOpcode] = nextRecord; } record = nextRecord; theIdx = (idx + i) % CVM_SEQ_DEPTH; currOpcode = CVMopcodeWindow[theIdx]; } /* * We are now at the right level. Record this opcode. */ record->incidence[currOpcode]++;}static voidCVMupdateStats(CVMOpcode opcode){ CVMopcodeWindow[CVMopcodeWindowIdx] = CVMopcodeSimplification[opcode]; CVMopcodeWindowIdx++; CVMopcodeWindowIdx %= CVM_SEQ_DEPTH; CVMrecordWindow(CVMopcodeWindowIdx);}void CVMinitStats(){ CVMopcodeWindowIdx = 0; CVMseqInfo = calloc(1, sizeof(CVMRunInfo));}static voidCVMdumpStats2(){ CVMOpcode opcode1, opcode2; CVMconsolePrintf("Instruction count=%dM[,%d]\n", CVMbigCount, CVMsmallCount); printf("\n\n\n\nSequences:\n"); for (opcode1 = 0; opcode1 < 255; opcode1++) { for (opcode2 = 0; opcode2 < 255; opcode2++) { CVMRunInfo* info = CVMseqInfo->followers[opcode1]; if (info != 0) { if (info->incidence[opcode2] != 0) { printf("%d Seq: <%s>,<%s>\n", info->incidence[opcode2], CVMopnames[opcode1], CVMopnames[opcode2]); } } } }}static voidCVMdumpStats3(){ CVMOpcode opcode1, opcode2, opcode3; CVMconsolePrintf("Instruction count=%dM[,%d]\n", CVMbigCount, CVMsmallCount); printf("\n\n\n\nSequences:\n"); for (opcode1 = 0; opcode1 < 255; opcode1++) { for (opcode2 = 0; opcode2 < 255; opcode2++) { for (opcode3 = 0; opcode3 < 255; opcode3++) { CVMRunInfo* info = CVMseqInfo->followers[opcode1]; if (info != 0) { info = info->followers[opcode2]; if (info != 0) { if (info->incidence[opcode3] != 0) { printf("%d Seq: <%s>,<%s>,<%s>\n", info->incidence[opcode3], CVMopnames[opcode1], CVMopnames[opcode2], CVMopnames[opcode3]); } } } } } }}static voidCVMdumpStats4(){ CVMOpcode opcode1, opcode2, opcode3, opcode4; CVMconsolePrintf("Instruction count=%dM[,%d]\n", CVMbigCount, CVMsmallCount); printf("\n\n\n\nSequences:\n"); for (opcode1 = 0; opcode1 < 255; opcode1++) { for (opcode2 = 0; opcode2 < 255; opcode2++) { for (opcode3 = 0; opcode3 < 255; opcode3++) { for (opcode4 = 0; opcode4 < 255; opcode4++) { CVMRunInfo* info = CVMseqInfo->followers[opcode1]; if (info != 0) { info = info->followers[opcode2]; if (info != 0) { info = info->followers[opcode3]; if (info != 0) { if (info->incidence[opcode4] != 0) { printf("%d Seq: <%s>,<%s>,<%s>,<%s>\n", info->incidence[opcode4], CVMopnames[opcode1], CVMopnames[opcode2], CVMopnames[opcode3], CVMopnames[opcode4]); } } } } } } } }}voidCVMdumpStats(){ CVMdumpStats2(); CVMdumpStats3();/* CVMdumpStats4(); */}#define UPDATE_INSTRUCTION_COUNT(opcode) \{ \ CVMsmallCount++; \ if (CVMsmallCount % 1000000 == 0) { \ CVMbigCount++; \ CVMsmallCount = 0; \ } \ CVMupdateStats(opcode); \}#else#define UPDATE_INSTRUCTION_COUNT(opcode)#endif#ifdef CVM_JVMTI/* NOTE: This macro must be called AFTER the PC has been incremented. CVMjvmtiNotifyDebuggerOfSingleStep may cause a breakpoint opcode to get inserted at the current PC to allow the debugger to coalesce single-step events. Therefore, we need to refetch the opcode after calling out to JVMTI. */#define JVMTI_SINGLE_STEPPING(opcodeVar) \{ \ if (ee->jvmtiSingleStepping && CVMjvmtiThreadEventsEnabled(ee)) { \ DECACHE_PC(frame); \ DECACHE_TOS(frame); \ CVMD_gcSafeExec(ee, { \ CVMjvmtiPostSingleStepEvent(ee, pc); \ }); \ /* Refetch opcode. See above. */ \ opcodeVar = *pc; \ OPCODE_UPDATE_NEXT(opcodeVar); \ } \}#define JVMTI_WATCHING_FIELD_ACCESS(location) \ if (CVMglobals.jvmtiWatchingFieldAccess) { \ DECACHE_PC(frame); \ DECACHE_TOS(frame); \ CVMD_gcSafeExec(ee, { \ CVMjvmtiPostFieldAccessEvent(ee, location, fb); \ }); \ }#define JVMTI_WATCHING_FIELD_MODIFICATION(location, isDoubleWord, isRef) \ if (CVMglobals.jvmtiWatchingFieldModification) { \ jvalue val; \ DECACHE_PC(frame); \ DECACHE_TOS(frame); \ if (isDoubleWord) { \ CVMassert(CVMfbIsDoubleWord(fb)); \ if (CVMtypeidGetType(CVMfbNameAndTypeID(fb)) == CVM_TYPEID_LONG) { \ val.j = CVMjvm2Long(&STACK_INFO(-2).raw); \ } else /* CVM_TYPEID_DOUBLE */ { \ val.d = CVMjvm2Double(&STACK_INFO(-2).raw); \ } \ } else if (isRef) { \ val.l = &STACK_ICELL(-1); \ } else { \ val.i = STACK_INT(-1); \ } \ CVMD_gcSafeExec(ee, { \ CVMjvmtiPostFieldModificationEvent(ee, location, fb, val); \ }); \ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -