executejava_aligned.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,990 行 · 第 1/5 页
C
1,990 行
/* * @(#)executejava_aligned.c 1.404 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/* * 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_ALIGNMENT_BASED_DISPATCHING - use alignment-based dispatching. * CVM_OPCODE_ALIGN_SIZE - opcode size for alignment-based dispatching. * CVM_ALIGN_OPCODE - macro used to actually do the opcode alignment. * CVM_CHECK_OPCODE_SIZES - debugging support for alignment-based dispatching. * CVM_ADD_4K_PAD - Add a 4K pad for better caching behaviour. * CVM_ALIGN_4K - Macro used to assist in doing the 4K pad. *//* * 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. * * NOTE: will be defined automatically if CVM_ALIGNMENT_BASED_DISPATCHING * is defined. *//* * 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. *//* * CVM_ALIGNMENT_BASED_DISPATCHING - Use dispatching technique that assumes * all opcodes are aligned to a certain sized boundary. * * Some compilers support the ability to align opcodes on a certain * sized boundary. If you do this and also make the implementation of * all opcodes no bigger than the alignment size, then you can do what * is known as alignment-based dispatching. The address you need to * jump to for an opocode's implementation is always the address of * the first opcode (opc_nop) + the opcode left shifted a certain * number of bits. On some platforms this saves you an instruction and * in all cases is saves you having to do a memory fetch from the goto * table. * * The following must hold true for alignment-based dispatching to work: * 1. The alignment size (CVM_OPCODE_ALIGN_SIZE) must be a power of 2. * 2. All opcode implementations must be no bigger than CVM_OPCODE_ALIGN_SIZE. * 3. The opcodes must be implemented in order of their opcode number. * * (2) has already been taken care of for you on sparc and sarm when the * CVM_OPCODE_ALIGN_SIZE is 64 bytes. Other platform may require more work * in the interpreter loop to get the size down to 64 bytes. No attempt * was made to keep opcodes small enough to fit in 64 bytes on x86 because * there didn't seem to be a performance gain. Note that all types of * debugging must be turned off to keep the opcode size no bigger than 64. * * (3) has also already been taken care of for all platforms. *//* * CVM_OPCODE_ALIGN_SIZE - the size in bytes to align each opcode to if * CVM_ALIGNMENT_BASED_DISPATCHING is defined. *//* * CVM_ALIGN_OPCODE - macro used to actually do the opcode alignment. *//* * CVM_CHECK_OPCODE_SIZES - if defined, then debugging code is added * that will print out the size of each opcode implementations and * warn you if any are too big. * * WARNING: Only enable this for debugging purposes. Otherwise it may * slow down the interpreter loop very slightly. * * WARNING: turning on this option could possibly affect how the compiler * allocates registers for executeJava(), causing some opcodes to have * a different size than they would if this option was off. To date this * does not seem to have been a problem on sparc, arm, and x86. *//* * CVM_ADD_4K_PAD - if defined, then a 4k pad block is addd after the * implementation of the opcodes in order to improve caching behaviour * for the interpreter loop. * * The main loop is a bit less than 16k (~250 opcodes times 64 bytes * per opcode). It was noticed that 45% of the opcodes executed are in * the first 4k of the loop. By putting a 4k pad of after the loop, * this prevent any of the overflow (spill over) code located after * the opcodes from executing in the same cache lines as the first 4K * of the loop. This gives about a 4% performance boost on sparc. * * The following assumptions are made. Otherwise this code may not help * performance and will waste space. * 1. A 16K instructon cache is assumed. * 2. The cache address that any address maps to is simply its * address & 0x3FFF. * 3. The amount of code in excuteJava before the first opcode is less * than about 300 bytes * * NOTE: CVM_ADD_4K_PAD will be disabled in CVM_ALIGNMENT_BASED_DISPATCHING * is not defined. *//* * CVM_ALIGN_4K - macro used to do assist in adding the 4K padd if * CVM_ADD_4K_PAD 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. */#ifdef __GNUC__#define CVM_USELABELS#endif/* * Only do alignment-based dispatching when ussing gcc and * compiling for sparc or sarm. */#if defined(__GNUC__) && \ (defined(__sparc__) || defined(arm) || defined(__arm__) || defined(__arm))/*#define CVM_ALIGNMENT_BASED_DISPATCHING*/#endif/* * Setup various alignment-based dispatching info for various processors. * Note that these will only be used if CVM_ALIGNMENT_BASED_DISPATCHING * is defined. */#if defined(__sparc__) || defined(arm) || defined(__arm__) || defined(__arm)#define CVM_OPCODE_ALIGN_SIZE 64#else#define CVM_OPCODE_ALIGN_SIZE 128#endif#if defined(__sparc__)#define CVM_ADD_4K_PAD#endif#if defined(arm) || defined(__arm__) || defined(__arm)#define CVM_ALIGN_OPCODE __asm__ __volatile__ ( ".align 6" ::: "memory") #define CVM_ALIGN_4K __asm__ __volatile__ ( ".align 12" ::: "memory");#elif defined(__sparc__)#define CVM_ALIGN_OPCODE __asm__ __volatile__ ( ".align 64" ::: "memory") #define CVM_ALIGN_4K __asm__ __volatile__ ( ".align 4096" ::: "memory");#else#define CVM_ALIGN_OPCODE __asm__ __volatile__ ( ".align 128" ::: "memory") #define CVM_ALIGN_4K __asm__ __volatile__ ( ".align 8192" ::: "memory");#endif/* * If CVM_ALIGNMENT_BASED_DISPATCHING is defined and you want some * debugging output to tell you how big each opcode implementation is, * then define CVM_CHECK_OPCODE_SIZES. */#if 0 /* only turn on for debugging */#define CVM_CHECK_OPCODE_SIZES#endif/* * None of the following can be true if using alignment-based dispatching. */#if defined(CVM_JVMPI_TRACE_INSTRUCTION) || \ defined(CVM_JVMTI) || defined(CVM_DEBUG) || defined (CVM_DEBUG_ASSERTS) || \ defined(CVM_INSTRUCTION_COUNTING) || !defined(CVM_OPTIMIZED)#undef CVM_ALIGNMENT_BASED_DISPATCHING#endif/* * Alignment-based dispatching is required for CVM_CHECK_OPCODE_SIZES. */#ifndef CVM_ALIGNMENT_BASED_DISPATCHING#undef CVM_CHECK_OPCODE_SIZES#endif/* * If CVM_ALIGNMENT_BASED_DISPATCHING is not defined, the make sure that * CVM_ALIGN_OPCODE does nothing. */#ifndef CVM_ALIGNMENT_BASED_DISPATCHING#undef CVM_ALIGN_OPCODE#define CVM_ALIGN_OPCODE#endif/* * CVM_ALIGNMENT_BASED_DISPATCHING requires CVM_USELABELS */#ifdef CVM_ALIGNMENT_BASED_DISPATCHING#define CVM_USELABELS#endif/* * CVM_USELABELS requires CVM_PREFETCH_OPCODE */#ifdef CVM_USELABELS#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/* * Currently, because of the funny way sarm lays out references to * global data, we need to turn on CVM_GENERATE_ASM_LABELS in order to * get the references to fall in just the right place. Otherwise it will * end up making an opcode too big. */#if defined(CVM_ALIGNMENT_BASED_DISPATCHING) && \ (defined(arm) || defined(__arm__) || defined(__arm))#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); \ }#else#define TRACEIF(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];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?