executejava_standard.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,078 行 · 第 1/5 页
C
2,078 行
/* * @(#)executejava_standard.c 1.45 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_ENABLED#include "javavm/include/jvmtiExport.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#ifdef CVM_HW#include "include/hw.h"#endif/* * The following macros are used to define how opcode dispatching is * done. The are all described immediately below and defined a bit later * based on the compiler be used and the target processor. * * CVM_USELABELS - use gcc style first class label. * CVM_PREFETCH_OPCODE - force prefetching of next opcode. *//* * CVM_USELABELS - If defined, then gcc-style first class labels are * used for the opcode dispatching rather than a switch statement. * * Using this feataure improves performance because it allows the compiler * to schedule the opcode dispatching code in with the opcode's * implementation. *//* * CVM_PREFETCH_OPCODE - if defined, then forces the next opcode to be * fetched within the implementation of each 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. * * NOTE: will be defined automatically if CVM_USELABELS is defined. *//* * Always prefetch opcodes unless we are using the sun cc compiler * for sparc, in which case doing the prefetch seems to cause slower * code to be generated. */#if defined(__GNUC__) || !defined(__sparc__)#define CVM_PREFETCH_OPCODE#endif/* * Only do label dispatching when using gcc. * The latest ARM tool chain (RVCT 2.2) supports GNU extensions, * but doesn't seem to understand pointer to label. */#if defined(__GNUC__) && !defined(__RVCT__)#define CVM_USELABELS#endif/* * CVM_USELABELS requires CVM_PREFETCH_OPCODE */#ifdef CVM_USELABELS#define CVM_PREFETCH_OPCODE#endif/* * For hardware execution we can't prefetch since we don't know where the * hardware will leave the pc. And for now, we use a loop instead of labels. */#ifdef CVM_HW#undef CVM_PREFETCH_OPCODE#undef CVM_USELABELS#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() \ CVMtraceStatus(("stack=0x%x frame=0x%x locals=0x%x tos=0x%x pc=0x%x\n", \ stack, frame, locals, topOfStack, pc));#ifdef CVM_TRACE#define TRACEIF(o, a) \ if (pc[0] == o) { \ TRACE(a); \ }#define TRACEIFW(o, a) \ if (pc[1] == o) { \ TRACE(a); \ }#else#define TRACEIF(o, a)#define TRACEIFW(o, a)#endif/* * 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)) { \ initCb = cb; \ goto init_class; \ } \ JVMPI_TRACE_INSTRUCTION();#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#if defined(CVM_JVMTI_ENABLED) || defined(CVM_JVMPI_TRACE_INSTRUCTION)#define CVM_LOSSLESS_OPCODES#endif#ifdef CVM_JVMTI_ENABLED#define CVM_EXECUTE_JAVA_METHOD CVMgcUnsafeExecuteJavaMethodJVMTI/* Note: JVMTI_PROCESS_POP_FRAME_AND_EARLY_RETURN() checks for the need to pop a frame or force an early return. ForceEarlyReturn can come about via requests from the agent during a event notification from the interpreter e.g. single stepping. So, after a JVMTI event is posted, we should check for the request. Alternately, it is possible for a request to come asynchronously from another thread. Unlike ForceEarlyReturn which can be requested both ways, PopFrame can only be requested from another thread. However, with asynchronous requests, the synchronous point is as good as any a point to check for the request. Hence, we always check immediately after a JVMTI event is posted reqardless of whether we're antcipating a synchronous or asynchronous request. *//* FIXME: Consolidate the FramePop and NeedEarlyReturn into a single field so that we only need to do one comparison in the normal case where neither were requested. */#define JVMTI_PROCESS_POP_FRAME_AND_EARLY_RETURN() \ if (CVMjvmtiNeedFramePop(ee)) { \ goto handle_pop_frame; \ } else if (CVMjvmtiNeedEarlyReturn(ee)) { \ goto handle_early_return; \ }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?