⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inlinejsr.c

📁 已经移植好的java虚拟机
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * @(#)inlinejsr.c	1.22 02/09/27 * * Copyright 1995-2001 by Sun Microsystems, Inc., * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. * All rights reserved. *  * This software is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information").  You * shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with Sun. * Use is subject to license terms. *//*========================================================================= * SYSTEM:    Verifier * SUBSYSTEM: JSR inlining * FILE:      inlinejsr.c * OVERVIEW:  Routines for inlining of JSR and RET bytecodes.   * * AUTHOR:    Frank Yellin, Sun Microsystems, Inc. *            Edited by Tasneem Sayeed, Sun Microsystems *=======================================================================*//*========================================================================= * Include files *=======================================================================*/#include <check_code.h>/*========================================================================= * Globals and extern declarations *=======================================================================*//* Maximum byte code size is 64K. */#define MAX_CODE_SIZE 65535typedef struct SubrContext {    int id;                         /* id, for debugging */    int depth;                      /* depth of subroutine */    struct SubrContext *parent;     /* subroutine of caller */    struct CodeRef *caller;         /* jsr that got us there */    struct CodeRef *nextInstruction; /* first instruction following inlining */    int target;    struct SubrContext *next;   /* linked list of all subr contexts */} SubrContext;/* global context, keep track of info when a method is rewritten */typedef struct JsrContext {    context_type *vcontext;     /* The verifier's context */    struct CodeRef *codeRef;    /* big array of codeRef's */    struct CodeRef *codeRefEnd; /* pointer to next codeRef to fill in */    int scontext_id;            /* ID assigned to last SubrContext */    struct SubrContext *allSubrContexts; /* pointer to linked list */    struct CodeRef **mapping;   /* maps inumbers CodeRef's */} JsrContext;/* A single instruction in the resulting stream */typedef struct CodeRef {     long inumber;               /* instruction number in original code */    SubrContext *subroutine;    /* subroutine call that this is part of */    enum { CRF_NORMAL,          /* normal instruction */           CRF_SKIP,            /* skip this instruction */           CRF_JSR_SIMPLE_GOTO, /* jsr to subroutine that doesn't return */           CRF_JSR_TARGETED_GOTO, /* jsr to subroutine that does return */           CRF_RET_SIMPLE_GOTO  /* ret that's not at the end of subroutine */    } flags;    /* My offset in the new code */    int offset;    struct CodeRef *next;       /* next codeRef with same "inumber" */} CodeRef;static bool_t matchSubroutine(JsrContext *, instruction_data_type*,                             SubrContext *);static bool_t subroutineGoto(JsrContext *, SubrContext *, SubrContext *);static voidrewriteOneSubroutine(JsrContext *context, SubrContext *subroutine);static void fixupCode(JsrContext*);static void fixupExceptionHandlers(JsrContext*);static void fixupLineNumberTable(JsrContext*);static void fixupVariableTable(JsrContext*);static voidupdateTarget(JsrContext *,              int inumber,              SubrContext* subroutine,              void* target, int offset, int size);voidrewriteCode(context_type *vcontext, struct methodblock *mb){    JsrContext context_buf;    JsrContext *context = &context_buf;#if MYDEBUG    printf("Starting %s.%s%s\n", cbName(mb->fb.clazz), mb->fb.name, mb->fb.signature);#endif    /* Initialize the context */    memset(context, 0, sizeof(context));    context->vcontext = vcontext; /* The verifier context */    /* Allow up to MAX_CODE_SIZE instructions.  */    context->codeRef = (CodeRef *)malloc(MAX_CODE_SIZE * sizeof(CodeRef));    context->codeRefEnd = context->codeRef;    /* Id (for debugging) of last subroutine structure created */    context->scontext_id = 0;       /* Keep a list of all subroutines, so that we can easily free() them */    context->allSubrContexts = NULL;    /* Make it easy to go from inumber to all CodeRef's that have that inumber*/    context->mapping = (CodeRef **)calloc(vcontext->instruction_count,                                           sizeof(CodeRef **));    /* Fill in context->codeRef with this routine.  In line all subroutine     * calls, and delete all unreachable code */    rewriteOneSubroutine(context, NULL);    /* Modify mb->code and mb->code_length for the new code */    fixupCode(context);    /* Update the exception table */    if (mb->exception_table_length != 0) {         fixupExceptionHandlers(context);    }    /* Update the line number table */    if (mb->line_number_table_length != 0) {         fixupLineNumberTable(context);    }    /* Update the local variable table */    if (mb->localvar_table_length != 0) {         fixupVariableTable(context);    }    /* Clean up */    free(context->codeRef);    free(context->mapping);    /* Free all the subroutine contexts that we created */    while (context->allSubrContexts != NULL) {         SubrContext *this = context->allSubrContexts;        SubrContext *next = this->next;        free(this);        context->allSubrContexts = next;    }}static voidrewriteOneSubroutine(JsrContext *context, SubrContext *subroutine){     context_type *vcontext = context->vcontext;    int depth = subroutine ? subroutine->depth : 0;    instruction_data_type *idata = vcontext->instruction_data;    int instruction_count = vcontext->instruction_count;    CodeRef **mapping = context->mapping;    instruction_data_type *this_idata;    int inumber;    int count = 0;    CodeRef *retOpcode = NULL;        for (    inumber = 0, this_idata = idata;             inumber < instruction_count;             inumber++, this_idata++) {         if (    (this_idata->or_flags & FLAG_REACHED)             &&  (this_idata->register_info.mask_count == depth)            &&  ((depth == 0)                      || matchSubroutine(context, this_idata, subroutine))) {                         /* We have an instruction that is part of this subroutine */            CodeRef *codeRef = context->codeRefEnd++;#if MYDEBUG            printf("\t%d:\t%d (%d)\t%s (%d)\n",                    (codeRef - context->codeRef), /* new instruction index */                   inumber, (subroutine ? subroutine->id : 0),                   (this_idata->opcode == 256                          ? "invokeinit" : opnames[this_idata->opcode]),                   this_idata->offset);#endif            codeRef->inumber = inumber;            codeRef->subroutine = subroutine;            codeRef->flags = CRF_NORMAL;            codeRef->next = mapping[inumber]; /* Add to inumber mapping */            mapping[inumber] = codeRef;            count++;            if (count == 1 && depth > 0) {                 /* This is the first instruction included as part of the                 * subroutine call.  If it's the target of the jsr that got                 * us here, then we can just "ignore" the jsr.                   * Otherwise, we have to convert the 'jsr' into a 'goto'                 */                CodeRef *caller = subroutine->caller;                if (inumber != idata[caller->inumber].operand.i) {                     caller->flags = CRF_JSR_TARGETED_GOTO;                }            }            switch(this_idata->opcode) {                 case opc_jsr: case opc_jsr_w:                     if (this_idata->operand2.i == UNKNOWN_RET_INSTRUCTION) {                         /* We're calling a subroutine that doesn't return.                         * The verifier has already made sure that the                         * subroutine doesn't have a deeper depth.                         * We turn the JSR into a goto */                        codeRef->flags = CRF_JSR_SIMPLE_GOTO;                    } else {                         SubrContext *newSubr = malloc(sizeof(SubrContext));                        /* In rare cases, we'll have to change this in the                         * subroutine code */                        codeRef->flags = CRF_SKIP;                        /* Create a new subroutine, and inline it */                        newSubr->id = ++context->scontext_id;                        newSubr->caller = codeRef;                        newSubr->target = this_idata->operand.i;                        newSubr->depth = depth + 1;                        newSubr->nextInstruction = NULL; /* unknown for now */                        newSubr->parent = subroutine;                        /* Add this to the list of all subroutine contexts */                        newSubr->next = context->allSubrContexts;                        context->allSubrContexts = newSubr;                        /* Generate the code for this subroutine */                        rewriteOneSubroutine(context, newSubr);                    }                    break;                case opc_ret:                    if (retOpcode != NULL) {                         /* There should only be one per subroutine */                        panic("Multiple return opcodes??");                    } else if (depth == 0) {                         /* We're not in a subroutine */                        panic("Ret at depth = 0");                    }                    retOpcode = codeRef;                    /* Flags are set at the end of the loop, below */                    break;                case opc_astore:                     /* We discard any astore's that move a return address                     * from the stack to a register.                      */                    if (GET_ITEM_TYPE(this_idata->stack_info.stack->item)                                         == ITEM_ReturnAddress) {                        codeRef->flags = CRF_SKIP;                     }                     break;                default:                     /* Nothing to do */                    break;            }        }    }    if (depth > 0) {         subroutine->nextInstruction = context->codeRefEnd;        if (retOpcode != NULL) {             /* If the last instruction wasn't a 'ret', then we need to             * convert the 'ret' into a 'goto'.             */            if (context->codeRefEnd == retOpcode + 1) {                 retOpcode->flags = CRF_SKIP;            } else {                 retOpcode->flags = CRF_RET_SIMPLE_GOTO;            }        }    }}static voidfixupCode(JsrContext *context) {    context_type *vcontext = context->vcontext;    instruction_data_type *idata = vcontext->instruction_data;    struct methodblock *mb = vcontext->mb;    unsigned char *oldCode = mb->code;    CodeRef *codeRefEnd = context->codeRefEnd;    unsigned char *newCode;    CodeRef *codeRef;    int pc;    long newCodeLength;    /* Assign offsets to each instruction. */#if MYDEBUG    printf("Assigning offsets\n");#endif    for (pc = 0, codeRef = context->codeRef; codeRef < codeRefEnd; codeRef++) {        instruction_data_type *this_idata = &idata[codeRef->inumber];        opcode_type opcode = this_idata->opcode;                codeRef->offset = pc;#if MYDEBUG        printf("\t%d:\t%d\tpc=%d\t%s (%d) %s\n",                (codeRef - context->codeRef),                (this_idata - vcontext->instruction_data),                pc,                (this_idata->opcode == 256                     ? "invokeinit" : opnames[this_idata->opcode]),               this_idata->offset,               ((codeRef->flags == CRF_SKIP) ? " XX" : "")               );#endif                /* Now increment the pc, depending on the instruction */        if (codeRef->flags == CRF_SKIP) {             /* do nothing */        } else if (opcode == opc_tableswitch || opcode == opc_lookupswitch) {            /* This mysterious calculation works.              * The first term increments pc and then rounds it up to a             * multiple of 4.   The second term is the size of the word-aligned             * values.             */            pc = ((pc + 1 + 3) & ~3) + ((this_idata->length - 1) & ~3);        } else if (opcode == opc_ret) {             /* We must be turning it into an opc_goto */            pc += 3;        } else {             pc += this_idata->length;        }    }    /* Create a new code object */    newCode = (unsigned char *)malloc(pc);    newCodeLength = pc;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -