📄 stackmap.c
字号:
/*0001*//*
/*0002./ * Copyright (c) 2000-2001 Sun Microsystems, Inc. All Rights Reserved.
/*0003./ *
/*0004./ * This software is the confidential and proprietary information of Sun
/*0005./ * Microsystems, Inc. ("Confidential Information"). You shall not
/*0006./ * disclose such Confidential Information and shall use it only in
/*0007./ * accordance with the terms of the license agreement you entered into
/*0008./ * with Sun.
/*0009./ *
/*0010./ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
/*0011./ * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
/*0012./ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
/*0013./ * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
/*0014./ * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
/*0015./ * THIS SOFTWARE OR ITS DERIVATIVES.
/*0016./ */
/*0017*/
/*0018*//*=========================================================================
/*0019./ * SYSTEM: KVM
/*0020./ * SUBSYSTEM: Stackmap based pointer calculation
/*0021./ * FILE: stackmap.c
/*0022./ * OVERVIEW: This file defines stackmap calculation operations
/*0023./ * that are needed by the exact garbage collector.
/*0024./ * AUTHOR: Frank Yellin
/*0025./ *=======================================================================*/
/*0026*/
/*0027*//*=========================================================================
/*0028./ * Include files
/*0029./ *=======================================================================*/
/*0030*/
/*0031*/#include <global.h>
/*0032*/
/*0033*//*=========================================================================
/*0034./ * Definitions and declarations
/*0035./ *=======================================================================*/
/*0036*/
/*0037*/#define BIT_SET(bit) map[(bit) >> 3] |= (((unsigned)1) << ((bit) & 7))
/*0038*/#define BIT_CLR(bit) map[(bit) >> 3] &= ~(((unsigned)1) << ((bit) & 7))
/*0039*/
/*0040*//*=========================================================================
/*0041./ * Static variables and functions (private to this file)
/*0042./ *=======================================================================*/
/*0043*/
/*0044*/static unsigned int
/*0045*/getInitialRegisterMask(METHOD, unsigned int *offsetP, char *map);
/*0046*/
/*0047*/static void
/*0048*/setBits(char *map, unsigned int bit, unsigned int count, unsigned char *values);
/*0049*/
/*0050*/static void
/*0051*/getBits(char *map, unsigned int bit, unsigned int count, unsigned char *results);
/*0052*/
/*0061*//*=========================================================================
/*0062./ * Functions
/*0063./ *=======================================================================*/
/*0064*/
/*0065*//*=========================================================================
/*0066./ * FUNCTION: getGCRegisterMask
/*0067./ * TYPE: Important GC function
/*0068./ * OVERVIEW: Returns a bitmap indicating the live size of the stack
/*0069./ * INTERFACE:
/*0070./ * parameters: thisMethod: The current method
/*0071./ * targetIP: An IP somewhere in the code. We want to find
/*0072./ * the register state just before this instruction
/*0073./ * map: A bitmap to be filled in
/*0074./ * returns: The size of the stack before the indicated instruction
/*0075./ * is executed.
/*0076./ *
//\\//\\//\\//\\//\\//\\//\\//\\//\\
/*0077./ * NOTE: The important side effect of this function is that it fills in
/*0078./ * map with a bitmap indicating the locals and stack that contain pointers.
//\\//\\//\\//\\//\\//\\//\\//\\//\\
/*0079./ * The first thisMethod->frameSize bits are the locals. The <returnValue>
/*0080./ * bits following are the state of the stack.
/*0081./ *=======================================================================*/
/*0082*/
/*0083*/static unsigned int
/*0084*/getInitialRegisterMask(METHOD, unsigned int *targetOffset, char *map);
/*0085*/
/*0086*/unsigned int
/*0087*/getGCRegisterMask(METHOD thisMethod, unsigned char *targetIP, char *map)
/*0088*/{
/*0089*/ CONSTANTPOOL cp = NULL;
/*0090*/ unsigned char *code = NULL;
/*0091*/ unsigned int codeOffset = 0;
/*0092*/ unsigned int localsCount = 0;
/*0093*/ unsigned int stackSize = 0;
/*0094*/ unsigned char *thisIP = NULL;
/*0095*/ unsigned char dupValues[6];
/*0096*/
/*0097*/ ByteCode token;
/*0098*/ unsigned int index = 0;
/*0099*/ METHOD method;
/*0100*/ FIELD field;
/*0101*/
/*0110*/ cp = thisMethod->ofClass->constPool;
/*0111*/ code = thisMethod->u.java.code;
/*0112*/ codeOffset = targetIP - code;
/*0113*/ localsCount = thisMethod->frameSize;
/*0114*/
/*0115*/ stackSize =
/*0116*/ /* This modifies codeOffset to be a location less than or
/*0117./ * equal to its original value. */
/*0118*/ getInitialRegisterMask(thisMethod, &codeOffset, map);
/*0119*/
/*0120*/ thisIP = code + codeOffset;
/*0121*/
/*0122*/ /* Our calculations are much simplified if we let stackSize also
/*0123./ * include the localsCount bits at the beginning of the stack map.
/*0124./ */
/*0125*/ stackSize += localsCount;
/*0126*/
/*0134*/ while (thisIP < targetIP) {
/*0141*/ /* Get the next token, and dispatch on it. */
/*0142*/ token = *thisIP++;
/*0143*/
/*0148*/ switch(token) {
/*0149*/ /* Store a single non pointer from the stack to a register */
/*0150*/ case ISTORE: case FSTORE:
/*0151*/ index = *thisIP++;
/*0152*/ storeInt:
/*0153*/ BIT_CLR(index);
/*0154*/ stackSize--;
/*0155*/ break;
/*0156*/
/*0157*/ /* Store a single pointer from the stack to a register */
/*0158*/ case ASTORE:
/*0159*/ index = *thisIP++;
/*0160*/ storePointer:
/*0161*/ BIT_SET(index);
/*0162*/ stackSize--;
/*0163*/ break;
/*0164*/
/*0165*/ /* Store a double or long from the stack to a register */
/*0166*/ case LSTORE: case DSTORE:
/*0167*/ index = *thisIP++;
/*0168*/ storeDouble:
/*0169*/ BIT_CLR(index);
/*0170*/ BIT_CLR(index + 1);
/*0171*/ stackSize -= 2;
/*0172*/ break;
/*0173*/
/*0174*/ case ISTORE_0: case ISTORE_1: case ISTORE_2: case ISTORE_3:
/*0175*/ index = token - ISTORE_0;
/*0176*/ goto storeInt;
/*0177*/
/*0178*/ case LSTORE_0: case LSTORE_1: case LSTORE_2: case LSTORE_3:
/*0179*/ index = token - LSTORE_0;
/*0180*/ goto storeDouble;
/*0181*/
/*0182*/ case FSTORE_0: case FSTORE_1: case FSTORE_2: case FSTORE_3:
/*0183*/ index = (token - FSTORE_0);
/*0184*/ goto storeInt;
/*0185*/
/*0186*/ case DSTORE_0: case DSTORE_1: case DSTORE_2: case DSTORE_3:
/*0187*/ index = (token - DSTORE_0);
/*0188*/ goto storeDouble;
/*0189*/
/*0190*/ case ASTORE_0: case ASTORE_1: case ASTORE_2: case ASTORE_3:
/*0191*/ index = (token - ASTORE_0);
/*0192*/ goto storePointer;
/*0193*/
/*0194*/ /* These leave any pointers on the stack as pointers, and
/*0195./ * any nonpointers on the stack as nonpointers */
/*0196*/ case GETFIELDP_FAST: /* Ptr => Ptr */
/*0197*/ case IINC:
/*0198*/ case CHECKCAST: case CHECKCAST_FAST:
/*0199*/ thisIP += 2;
/*0200*/ case NOP:
/*0201*/ case INEG: case LNEG: case FNEG: case DNEG:
/*0202*/ case I2F: case L2D: case F2I: case D2L:
/*0203*/ case I2B: case I2C: case I2S:
/*0204*/ break;
/*0205*/
/*0206*/ /* These push a non-pointer onto the stack */
/*0207*/ case SIPUSH:
/*0208*/ case GETSTATIC_FAST:
/*0209*/ thisIP++;
/*0210*/ case ILOAD: case FLOAD: case BIPUSH:
/*0211*/ thisIP++;
/*0212*/ case ACONST_NULL:
/*0213*/ case ICONST_M1: case ICONST_0: case ICONST_1:
/*0214*/ case ICONST_2: case ICONST_3: case ICONST_4: case ICONST_5:
/*0215*/ case FCONST_0: case FCONST_1: case FCONST_2:
/*0216*/ case ILOAD_0: case ILOAD_1: case ILOAD_2: case ILOAD_3:
/*0217*/ case FLOAD_0: case FLOAD_1: case FLOAD_2: case FLOAD_3:
/*0218*/ case I2L: case I2D: case F2L: case F2D:
/*0219*/ pushInt:
/*0220*/ BIT_CLR(stackSize);
/*0221*/ stackSize++;
/*0222*/ break;
/*0223*/
/*0224*/ /* These push two non-pointers onto the stack */
/*0225*/ case GETSTATIC2_FAST: case LDC2_W:
/*0226*/ thisIP++;
/*0227*/ case LLOAD: case DLOAD:
/*0228*/ thisIP++;
/*0229*/ case LCONST_0: case LCONST_1: case DCONST_0: case DCONST_1:
/*0230*/ case LLOAD_0: case LLOAD_1: case LLOAD_2: case LLOAD_3:
/*0231*/ case DLOAD_0: case DLOAD_1: case DLOAD_2: case DLOAD_3:
/*0232*/ pushDouble:
/*0233*/ BIT_CLR(stackSize);
/*0234*/ stackSize++;
/*0235*/ BIT_CLR(stackSize);
/*0236*/ stackSize++;
/*0237*/ break;
/*0238*/
/*0239*/ /* These push a pointer onto the stack */
/*0240*/ case NEW: case NEW_FAST:
/*0241*/ case GETSTATICP_FAST:
/*0242*/ thisIP++;
/*0243*/ case ALOAD:
/*0244*/ thisIP++;
/*0245*/ case ALOAD_0: case ALOAD_1: case ALOAD_2: case ALOAD_3:
/*0246*/ pushPointer:
/*0247*/ BIT_SET(stackSize);
/*0248*/ stackSize++;
/*0249*/ break;
/*0250*/
/*0251*/ /* These pop an item off the stack */
/*0252*/ case IFEQ: case IFNE: case IFLT: case IFGE:
/*0253*/ case IFGT: case IFLE: case IFNULL: case IFNONNULL:
/*0254*/ case PUTSTATIC_FAST:
/*0255*/ thisIP += 2;
/*0256*/ case POP: case IADD: case FADD: case ISUB: case FSUB:
/*0257*/ case IMUL: case FMUL: case IDIV: case FDIV: case IREM:
/*0258*/ case FREM: case ISHL: case LSHL: case ISHR: case LSHR:
/*0259*/ case IUSHR: case LUSHR:
/*0260*/ case IAND: case IOR: case IXOR:
/*0261*/ case L2I: case L2F: case D2I: case D2F:
/*0262*/ case FCMPL: case FCMPG:
/*0263*/ case MONITORENTER: case MONITOREXIT:
/*0264*/ case AALOAD: /* Ptr Int => Ptr */
/*0265*/ stackSize--;
/*0266*/ break;
/*0267*/
/*0268*/ /* These pop an item off the stack, and then push a pointer */
/*0269*/ case ANEWARRAY:
/*0270*/ case ANEWARRAY_FAST:
/*0271*/ thisIP++;
/*0272*/ case NEWARRAY:
/*0273*/ thisIP++;
/*0274*/ stackSize--;
/*0275*/ goto pushPointer;
/*0276*/
/*0277*/ /* These pop an item off the stack, and then push an int */
/*0278*/ case INSTANCEOF:
/*0279*/ case INSTANCEOF_FAST:
/*0280*/ case GETFIELD_FAST:
/*0281*/ thisIP += 2;
/*0282*/ case ARRAYLENGTH:
/*0283*/ stackSize--;
/*0284*/ goto pushInt;
/*0285*/
/*0286*/ /* These pop an item off the stack, and then put two nonptrs */
/*0287*/ case GETFIELD2_FAST:
/*0288*/ thisIP += 2;
/*0289*/ BIT_SET(stackSize-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -