stackmaps.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,928 行 · 第 1/5 页
C
1,928 行
/* * @(#)stackmaps.c 1.111 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/classes.h"#include "javavm/include/interpreter.h"#include "javavm/include/stacks.h"#include "javavm/include/bcattr.h"#include "javavm/include/utils.h"#include "javavm/include/typeid.h"#include "javavm/include/opcodes.h"#include "javavm/include/globals.h"#include "javavm/include/stackmaps.h"#include "javavm/include/indirectmem.h"#ifdef CVM_JIT#include "javavm/include/jit/jit.h"#endif#include "javavm/include/clib.h"#include "javavm/include/porting/ansi/setjmp.h"#include "javavm/include/porting/int.h"#include "javavm/include/porting/system.h"#ifdef CVM_JVMTI#include "javavm/include/jvmtiExport.h"#endif#ifdef CVM_HW#include "include/hw.h"#endif#ifdef CVM_DEBUGstatic int CVMstackmapVerboseDebug = 0;#endif/* The Layout of the Stackmap Buffer ================================= The stackmaps for a method is made up of a list of entries: one for each GC point in the method. Each entry has a bytecode PC as a unique key. Most stack frames tend to be relatively small. Hence, the typical stackmap entry would fit within 32-bits: a 16-bit PC, and a 15-bit map. The remaining bit is used to indicate whether the map actually has more than 15 locals and/or stack words thereby requiring more than 15 bits in the map i.e. does it have an extended or super extended entry that holds the real information. How to find the real entry? ========================== The stackmap entry can be found by using the PC as the unique key. Given the PC, CVMstackmapGetEntryForPC() will acquire a basic stack map entry. A basic stackmap entry is one that fits within 32-bits. If bit 0 of entry->state[0] is set, then entry->state[0] actually contains an offset to a larger (more than 32bits) stackmap entry either in the extended region or the super extended region of stackmaps buffer. The offset value is computed as entry->state[0] >> 1, and is in units of CVMUint16 i.e. each offset represents a 16 bit increment. If the offset is less than CVM_STACKMAP_RESERVED_OFFSET, then the actual stackmap entry will reside in the extended region. It's address can be computed using the offset to index into the extended region which resides at the end of the basic region. If the offset is equal to CVM_STACKMAP_RESERVED_OFFSET, then the actual stackmap entry will reside in the super extended region. The start of the extended region will contain a pointer to the CVMStackMapSuperExtendedMaps struct (abbreviated as seMaps). The seMaps will contain a sorted list of pointers to every stackmap entry in the super extended region. To find the address of the actual stackmap entry that reside in the super extended region, we do a binary search on the entries in the seMaps keying off the PC. The memory layout ================= Stackmaps buffer: |----------------------------| CVMStackMaps | header info | |----------------------------| basic region | entry[0] | | entry[1] | | entry[2] | | ... | | entry[N] | |----------------------------| extended region | &seMaps | | extendedEntries[0] | | extendedEntries[1] | | ... | | extendedEntries[nE] | |----------------------------| seMaps | numOfSuperExtendedEntries | | &superExtendedEntries[0] | | &superExtendedEntries[0] | | ... | | &superExtendedEntries[nSE] | |----------------------------| super extended | superExtendedEntries[0] | region | superExtendedEntries[1] | | ... | | superExtendedEntries[nSE] | |----------------------------| where N is the total number of GC points. For each GC point there is one basic entry. nE is the total number of entries in the extended region which can be reached using an offset stored in the basic entry. nSE is the total number of entries in the super extended region. Entries in this region must be looked up via the seMaps table. Note: A given GC point can have only one of the following: 1. a basic entry 2. a basic entry + an extended entry 3. a basic entry + a super extended entry It cannot have both an extended entry and a super extended entry. Hence, nE + nSE <= N. Note: the sizes of the entries in the extended region and super extended region are of variable size. They aren't guaranteed to be uniform. Stackmap Context pointers ========================= stackMapAreaBegin points pass the end of the basic region to the start of the extended region. stackMapAreaEnd points to the end of the entire stackmaps buffer. If a super extended region is present, it will point just pass the end of the super extended region. Otherwise, it will point pass the end of the extended region or the basic region depending on whether the extended region is present or not. stackMapAreaPtr is used to determine the next location in the stackmaps buffer to emit data into. If the extended region is present, initially, it is pointed just pass the seMaps pointer in preparation for emitting the first entry in the extended region. If the extended region is not present, it will set equal to stackMapAreaBegin and will never be incremented. Optional Regions ================ The extended region, seMaps, and super extended region are all optional. They are included only when needed. In most cases, these regions will not be present in the stackmaps. What does this mean to the GC? ============================= The GC is not aware of the internal layout of the stackmap entries. The GC calls CVMstackmapGetEntryForPC(), and the appropriate stackmap entry will be returned to it. The returned entry may be a basic entry, an extended entry, or a super extended entry. They all look the same to the GC. The GC expects the entry to be of variable size. The boundary of the map is not attained from the entry but rather computed from the runtime topOfStack pointer of the stack frame. *//* CVM_STACKMAP_ENTRY_MIN_NUMBER_OF_CHUNKS is the number of CVMUint16 chunks that is available to store map bits in a basic stackmap entry. In the current implementation, this is always 1 and is determined by the definition of the CVMStackMapEntry struct in classes.h.*/#define CVM_STACKMAP_ENTRY_MIN_NUMBER_OF_CHUNKS 1/* CVM_STACKMAP_ENTRY_NUMBER_OF_BASIC_BITS is the number of map bits available in a basic stackmap entry. For a CVM_STACKMAP_ENTRY_MIN_NUMBER_OF_CHUNKS value of 1, the number of bits will be 15 (i.e. 16 - 1 bit reserved to indicate the presence/absence of an extended entry.*/#define CVM_STACKMAP_ENTRY_NUMBER_OF_BASIC_BITS \ ((CVM_STACKMAP_ENTRY_MIN_NUMBER_OF_CHUNKS * sizeof(CVMUint16) * 8) - 1)/* CVM_STACKMAP_RESERVED_OFFSET is the reserved offset to indicate that the stackmap entry is located in the super extended region of the stackmaps buffer. See comment above for more details. */#define CVM_STACKMAP_RESERVED_OFFSET (0x7fff)/* CVMStackMapSuperExtendedMaps is used to store a table of pointers to CVMStackMapEntry structs that reside in the super extended region of the stackmaps buffer. See comment above on the layout of the stackmaps buffer for more details. */typedef struct CVMStackMapSuperExtendedMaps CVMStackMapSuperExtendedMaps;struct CVMStackMapSuperExtendedMaps{ CVMUint32 numberOfEntries; CVMStackMapEntry *entries[1];};#define WRITE_INT16( pc, val ) { \ (pc)[0] = (val) >> 8; \ (pc)[1] = val & 0xff; \ }#define WRITE_INT32( pc, val ) { \ (pc)[0] = (val) >> 24; \ (pc)[1] = (val >>16)&0xff; \ (pc)[2] = (val >>8)&0xff; \ (pc)[3] = val & 0xff; \ }#define CVMalign4( n ) (( (n)+3)&~3)/* * This file contains routines to generate stackmaps for GC points. * * ASSUMPTION: The code for the method we are analyzing has already * been verified. */typedef CVMUint32 CVMCellTypeState;/* * Each cell (a local variable or a stack slot) can hold one of the * following values. * * (The program counter is used to track a JSR block, * and holds the *target* of a JSR, and not the return value). */#define CVM_MAP_BIT(n) ((CVMCellTypeState)1 << (n))#define CVMctsBottom ((CVMCellTypeState)0)#define CVMctsUninit CVM_MAP_BIT(31) /* The initial state of all locals (except the args) */#define CVMctsRef CVM_MAP_BIT(30) /* A reference type */#define CVMctsVal CVM_MAP_BIT(29) /* A value type */#define CVMctsPC CVM_MAP_BIT(28) /* A JSR PC type. The rest of the bits of the state contain the target PC of the JSR */#define CVMctsAll (CVMctsUninit | CVMctsRef | CVMctsVal | CVMctsPC)#define CVMctsIsUninit(cts) (((cts) & CVM_MAP_BIT(31)) != 0)#define CVMctsIsRef(cts) (((cts) & CVM_MAP_BIT(30)) != 0)#define CVMctsIsVal(cts) (((cts) & CVM_MAP_BIT(29)) != 0)#define CVMctsIsPC(cts) (((cts) & CVM_MAP_BIT(28)) != 0)#define CVMctsGetPC(cts) ((cts) & ~CVMctsAll)/* * In a 'CVMCellTypeState' the (relative) PC is only 28 bits wide anyway. * So there's no need to worry about losing bits and we can safely cast * our (on 64 bit platforms 64 bit wide) expression to 'CVMCellTypeState'. */#define CVMctsMakePC(pc) ((CVMCellTypeState)(CVMctsPC | (pc)))#define CVMctsGetFlags(cts) ((cts) & CVMctsAll)typedef struct CVMBasicBlock CVMBasicBlock;typedef struct CVMJsrTableEntry CVMJsrTableEntry;/* * The representation of a basic block. */struct CVMBasicBlock { CVMUint8* startPC; /* The absolute (ptr) start PC */ CVMCellTypeState* varState; /* The vars state on entry */ CVMCellTypeState* stackState; /* The stack state on entry */ CVMBool changed; /* Has the entry state changed? */ CVMInt32 topOfStack; /* The topOfStack for interpreting */ CVMBool isLive; /* Is this block reachable? */ CVMBool endsWithJsr; /* The bb ends with a JSR opcode? */ struct CVMBasicBlock* liveNext; /* Next on liveness analysis list */#ifdef CVM_JIT CVMBool endsWithRet; /* The bb ends with a ret opcode? */ CVMInt32 endTopOfStack;/* The topOfStack at the end of bb. */#endif struct CVMBasicBlock** successors; /* Successor BB's (0-terminated) */};/* * The representation of a JSR table. Keeps track of all JSR targets, * and for each, its callers. That way, we know who the possible callers * of a jsr block are when we encounter a 'ret' instruction during * abstract interpretation */struct CVMJsrTableEntry { CVMUint32 jsrPC; /* The start of the jsr block (relative) */ CVMUint32 jsrNoCalls; /* No of callers for this jsr target */ CVMBasicBlock** jsrCallers; /* Caller BB's of this jsr */};/* * When code is rewritten due to conflicts, it can change sizes. * The remapping of relative addresses is tracked using this. * It must be kept sorted by address. */typedef struct CVMstackmapPCMapEntry{ int addr; int adjustment;}CVMstackmapPCMapEntry;typedef struct CVMstackmapPCMap { int nAdjustments; int mapSize; struct CVMstackmapPCMapEntry map[1];} CVMstackmapPCMap;/* * The context for the current stackmap generation */typedef struct { CVMExecEnv* ee; /* Error handler context to longjmp to */ jmp_buf errorHandlerContext; /* Method information */ CVMMethodBlock* mb; CVMJavaMethodDescriptor* jmd; CVMClassBlock* cb; CVMConstantPool* cp; CVMUint8* code; CVMUint16 codeLen; CVMUint32 stateSize; /* Total 'state' size */ CVMUint16 nVars; /* No of locals */ CVMUint16 maxStack; /* Maximum number of stack slots */ /* Created data structures */ /* The first three are the heads of all allocated memory. We free them when done, or on error. */ CVMBasicBlock* basicBlocks; void* mapsArea; CVMStackMaps* stackMaps; CVMUint32 nBasicBlocks; CVMUint32 nGCPoints; CVMUint32* gcPointsBitmap; CVMBasicBlock** successorsArea; CVMBasicBlock* liveStack; /* liveness analysis stack */ /* Mapping from exception handler to basic block */ CVMUint32 nExceptionHandlers; CVMBasicBlock** exceptionsArea; /* Jsr table */ CVMJsrTableEntry* jsrTable; CVMUint32 jsrTableSize; /* The state of the interpretation of the current basic block. We need this because we don't want to destroy the entry state of a basic block. */ CVMCellTypeState* varState; CVMCellTypeState* stackState; /* * The memory area that holds the stackmaps. */ CVMUint16* stackMapAreaEnd; CVMUint16* stackMapAreaBegin; /* The allocation pointer */ CVMUint16* stackMapAreaPtr; /* The allocation pointer */ CVMUint32 stackMapLongFormatNumBytes; /* # of long format bytes */ /* Tracking info for the super extended region: */ CVMUint32 numberOfSuperExtendedEntries; CVMStackMapSuperExtendedMaps *seMaps; CVMUint32 currentNumberOfSEEntries; /* * Ref-uninit conflict uses of local variables */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?