📄 inlinejsr.c
字号:
#if MYDEBUG printf("Creating code of length %d\n", pc);#endif for (codeRef = context->codeRef; codeRef < codeRefEnd; codeRef++) { if (codeRef->flags != CRF_SKIP) { instruction_data_type *this_idata = &idata[codeRef->inumber]; opcode_type opcode = this_idata->opcode; int pc = codeRef->offset; unsigned char *source = &oldCode[this_idata->offset]; unsigned char *target = &newCode[pc]; #if MYDEBUG printf("\t%d:\t%d\tpc=%d\t%s (%d) \n", (codeRef - context->codeRef), (this_idata - vcontext->instruction_data), pc, (this_idata->opcode == 256 ? "invokeinit" : opnames[this_idata->opcode]), this_idata->offset );#endif switch(opcode) { case opc_ifeq: case opc_ifne: case opc_iflt: case opc_ifge: case opc_ifgt: case opc_ifle: case opc_ifnull: case opc_ifnonnull: case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmplt: case opc_if_icmpge: case opc_if_icmpgt: case opc_if_icmple: case opc_if_acmpeq: case opc_if_acmpne: case opc_goto: case opc_goto_w: target[0] = source[0]; updateTarget(context, this_idata->operand.i, codeRef->subroutine, target + 1, pc, this_idata->length - 1); break; case opc_jsr: case opc_jsr_w: target[0] = opc_goto; if (codeRef->flags == CRF_JSR_SIMPLE_GOTO) { updateTarget(context, this_idata->operand.i, codeRef->subroutine, target + 1, pc, this_idata->length - 1); } else if (codeRef->flags == CRF_JSR_TARGETED_GOTO) { updateTarget(context, this_idata->operand.i, codeRef[1].subroutine, target + 1, pc, this_idata->length - 1); } else { panic("Shouldn't have anything referring to jsr"); } break; case opc_ret: if (codeRef->flags & CRF_RET_SIMPLE_GOTO) { int gotoTarget = codeRef->subroutine->nextInstruction->offset; target[0] = opc_goto; target[1] = (gotoTarget - pc) >> 8; target[2] = (gotoTarget - pc); } else { panic("Shouldn't have anything referring to ret"); } break; default: memcpy(target, source, this_idata->length); break; case opc_tableswitch: case opc_lookupswitch: { int *successors = this_idata->operand.ip; int keys = successors[0] - 1; /* don't include default */ SubrContext *subroutine = codeRef->subroutine; int i; long *targetPtr, *sourcePtr; target[0] = source[0]; target[1] = target[2] = target[3] = 0; /* clear alignment */ targetPtr = (long *)UCALIGN(target + 1); sourcePtr = (long *)UCALIGN(source + 1); /* Update the default target */ updateTarget(context, successors[1], subroutine, targetPtr, pc, 4); if (opcode == opc_tableswitch) { targetPtr[1] = sourcePtr[1]; /* low */ targetPtr[2] = sourcePtr[2]; /* high */ for (i = 0; i < keys; i++) { updateTarget(context, successors[2 + i], subroutine, &targetPtr[3 + i], pc, 4); } } else { targetPtr[1] = sourcePtr[1]; /* pairs */ for (i = 0; i < keys; i++) { targetPtr[2 + (i << 1)] = sourcePtr[2 + (i << 1)]; updateTarget(context, successors[2 + i], subroutine, &targetPtr[3 + (i << 1)], pc, 4); } } break; } } } } mb->code = newCode; mb->code_length = newCodeLength;}static void fixupExceptionHandlers(JsrContext *context) { const int catchFrameSize = sizeof(struct CatchFrame); context_type *vcontext = context->vcontext; struct methodblock *mb = vcontext->mb; short *code_data = vcontext->code_data; /* maps offset to inumber */ CodeRef *codeRefEnd = context->codeRefEnd; /* Structure to hold new catch frames */ struct CatchFrame *catchFrames = malloc(catchFrameSize * MAX_CODE_SIZE); struct CatchFrame *currentCatchFrame = catchFrames; CodeRef *hRef, *instRef; unsigned long i; /* Look at each exception handler */ for (i = 0; i < mb->exception_table_length; i++) { struct CatchFrame *this_handler = &mb->exception_table[i]; int start_inumber = code_data[this_handler->start_pc]; int end_inumber = code_data[this_handler->end_pc]; int handler_inumber = code_data[this_handler->handler_pc]; /* First instruction that maps to the specified handler */ for (hRef = context->mapping[handler_inumber] ; hRef != NULL; hRef = hRef->next) { /* Find all instructions that go to this handler. */ bool_t wasMatch = FALSE; for (instRef = context->codeRef; instRef < codeRefEnd; instRef++) { if (instRef->flags != CRF_SKIP) { bool_t thisMatch = instRef->inumber >= start_inumber && instRef->inumber < end_inumber && subroutineGoto(context, instRef->subroutine, hRef->subroutine); if (thisMatch && !wasMatch) { /* Start a new catch frame */ memcpy(currentCatchFrame, this_handler, catchFrameSize); currentCatchFrame->handler_pc = hRef->offset; currentCatchFrame->start_pc = instRef->offset; wasMatch = TRUE; } else if (wasMatch && !thisMatch) { currentCatchFrame->end_pc = instRef->offset; currentCatchFrame++; wasMatch = FALSE; } } } if (wasMatch) { /* We end the code still in the catch frame */ currentCatchFrame->end_pc = mb->code_length; currentCatchFrame++; } } } /* free(mb->exception_table); */ mb->exception_table_length = currentCatchFrame - catchFrames; mb->exception_table = realloc(catchFrames, (char *)currentCatchFrame - (char *)catchFrames);}static void fixupLineNumberTable(JsrContext *context) { context_type *vcontext = context->vcontext; struct methodblock *mb = vcontext->mb; int tableLength = mb->line_number_table_length; instruction_data_type *idata = vcontext->instruction_data; instruction_data_type *last_idata = &idata[vcontext->instruction_count - 1]; int oldCodeLength = last_idata->offset + last_idata->length; struct lineno *lineTable = malloc(sizeof(struct lineno) * MAX_CODE_SIZE); struct lineno *currentLineTableEntry = lineTable; unsigned long *mapTable = calloc(sizeof(short *), oldCodeLength); CodeRef *codeRefEnd = context->codeRefEnd; CodeRef *codeRef; int i, currentLineNumber; { unsigned long startPC, endPC, line, pc; for (i = 0; i < tableLength - 1; i++) { startPC = mb->line_number_table[i].pc; endPC = mb->line_number_table[i + 1].pc; line = mb->line_number_table[i].line_number; for (pc = startPC; pc < endPC; pc++) { mapTable[pc] = line; } } startPC = mb->line_number_table[tableLength - 1].pc; endPC = oldCodeLength; line = mb->line_number_table[tableLength - 1].line_number; for (pc = startPC; pc < endPC; pc++) { mapTable[pc] = line; } } currentLineNumber = -1; for (codeRef = context->codeRef; codeRef < codeRefEnd; codeRef++) { if (codeRef->flags != CRF_SKIP) { instruction_data_type *this_idata = &idata[codeRef->inumber]; int thisLineNumber = mapTable[this_idata->offset]; if (thisLineNumber != currentLineNumber) { currentLineTableEntry->line_number = thisLineNumber; currentLineTableEntry->pc = codeRef->offset; currentLineTableEntry++; currentLineNumber = thisLineNumber; } } } free(mapTable); mb->line_number_table = realloc(lineTable, (char *)currentLineTableEntry - (char *)lineTable); mb->line_number_table_length = currentLineTableEntry - lineTable;}static void fixupVariableTable(JsrContext *context) { context_type *vcontext = context->vcontext; struct methodblock *mb = context->vcontext->mb; instruction_data_type *idata = vcontext->instruction_data; CodeRef *codeRefEnd = context->codeRefEnd; CodeRef *codeRef; unsigned long i; struct localvar *localVars = malloc(sizeof(struct localvar) * MAX_CODE_SIZE); struct localvar *currentLocalVar = localVars; for (i = 0; i < mb->localvar_table_length; i++) { struct localvar *oldEntry = &mb->localvar_table[i]; int startPC = oldEntry->pc0; int endPC = startPC + oldEntry->length; /* inclusive! */ bool_t was_matching = FALSE; for (codeRef = context->codeRef; codeRef < codeRefEnd; codeRef++) { if (codeRef->flags != CRF_SKIP) { instruction_data_type *this_idata = &idata[codeRef->inumber]; bool_t is_matching = this_idata->offset >= startPC && this_idata->offset <= endPC; if (!was_matching && is_matching) { memcpy(currentLocalVar, oldEntry, sizeof(struct localvar)); currentLocalVar->pc0 = codeRef->offset; was_matching = TRUE; } else if (was_matching && !is_matching) { currentLocalVar->length = codeRef[-1].offset - currentLocalVar->pc0; currentLocalVar++; was_matching = FALSE; } } } if (was_matching) { currentLocalVar->length = codeRefEnd[-1].offset - currentLocalVar->pc0; currentLocalVar++; } } /* free(mb->localvar_table); */ mb->localvar_table_length = currentLocalVar - localVars; mb->localvar_table = realloc(localVars, (char *)currentLocalVar - (char *)localVars);}static voidupdateTarget(JsrContext *context, int inumber, SubrContext* subroutine, void* target, int offset, int size){ CodeRef *codeRef; for (codeRef = context->mapping[inumber]; codeRef != NULL; codeRef = codeRef->next) { if (subroutineGoto(context, subroutine, codeRef->subroutine)) { int value = codeRef->offset - offset; unsigned char *t = target; if (size == 2) { t[0] = value >> 8; t[1] = value; } else if (size == 4) { t[0] = value >> 24; t[1] = value >> 16; t[2] = value >> 8; t[3] = value; } else { panic("Bad value passed for size"); } return; } } panic("Cannot find value for updateTarget");}static bool_t subroutineGoto(JsrContext *context, SubrContext *from, SubrContext *to){ if (to == NULL || to == from) { return TRUE; } else if (from == NULL || to->depth >= from->depth) { return FALSE; } else { do { from = from->parent; } while (from->depth > to->depth); return from == to; }}static bool_t matchSubroutine(JsrContext *context, instruction_data_type *this_idata, SubrContext *subroutine){ int depth = subroutine->depth; int i; for (i = depth - 1; i >= 0; --i) { if (this_idata->register_info.masks[i].entry != subroutine->target) { return FALSE; } subroutine = subroutine->parent; } return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -