📄 jitregman.c
字号:
CVMassert(!con->compilationContext->inConditionalCode);#ifdef CVMCPU_HAS_ZERO_REG if (constant == 0 && con->preallocatedResourceForConstantZero != NULL) { rp = con->preallocatedResourceForConstantZero; } else #endif { rp = CVMRMfindResourceConstant32(con, constant); } if (rp != NULL) { CVMassert(CVMRMisConstant(rp)); CVMRMincRefCount(con, rp); } else { rp = CVMRMallocateAndPutOnList(con); rp->size = 1; rp->nregs= 1; rp->spillLoc = -1; rp->localNo = CVMRM_INVALID_LOCAL_NUMBER; rp->expr = NULL; rp->regno = -1; rp->flags |= CVMRMConstant32; rp->constant = constant;#ifdef CVM_TRACE_JIT rp->name = CVMJITgetSymbolName(con->compilationContext); CVMJITresetSymbolName(con->compilationContext);#endif /* Add this to our constant-resource mapping */ associateResourceWithConstant32(con, rp, constant); } return rp;}#ifdef CVM_JIT_USE_FP_HARDWARECVMRMResource*CVMRMfindResourceConstant32InRegister(CVMJITRMContext* con, CVMInt32 constant){ CVMRMResource* rp = CVMRMfindResourceConstant32(con, constant); if (rp != NULL && rp->regno == -1) { rp = NULL; } return rp;}static CVMBool isNonNaN(const CVMInt32 imm32) { enum { NaNmask = 0x7F800000 }; return imm32 && (imm32 & NaNmask) != NaNmask;}CVMRMResource *CVMRMfindResourceForNonNaNConstant(CVMJITRMContext* con){ CVMRMResource* rp; for (rp = con->resourceList; rp != NULL; rp = rp->next) { if (CVMRMisConstant(rp) && rp->regno != -1 && isNonNaN(rp->constant)) { break; } } return rp;}#endif/* * Create a resource for a 32-bit constant and load the constant * into a register. */CVMRMResource*CVMRMgetResourceForConstant32( CVMJITRMContext* con, CVMRMregset target, CVMRMregset avoid, CVMInt32 constant){ CVMRMResource* rp; rp = CVMRMbindResourceForConstant32(con, constant); CVMassert(CVMRMisConstant(rp)); /* Make sure it is in a register */ ensureInRegister(con, target, avoid, getRegisterPreference(con, target, avoid), CVM_FALSE, rp); return rp;}/* * Create a resource for a local, but don't load the local into the registers. */CVMRMResource*CVMRMbindResourceForLocal( CVMJITRMContext* rc, int size, CVMBool isRef, CVMInt32 localNumber){ CVMRMResource* rp = rc->local2res[localNumber];#ifdef CVM_DEBUG_ASSERTS CVMJITCompilationContext* con = rc->compilationContext;#endif CVMassert(!con->inConditionalCode); if (rp != NULL) { /* local already has a resource */ CVMassert(size == rp->size); CVMRMincRefCount(rc, rp); } else { /* allocate a new resource for this local */ rp = CVMRMallocateAndPutOnList(rc); rp->size = size; rp->nregs = RM_NREGISTERS(rc, size); rp->spillLoc = -1; rp->constant = -1; rp->expr = NULL; rp->regno = -1; rp->flags = CVMRMLocalVar; rp->localNo = localNumber; CVMassert(rc->local2res[localNumber] == NULL); rc->local2res[localNumber] = rp; if (size == 2) { rc->local2res[localNumber + 1] = rp; } if (isRef) { rp->flags |= CVMRMref; } }#ifdef CVMJIT_STRICT_REFLOCAL_ASSERTS CVMassert(isRef == CVMRMisRef(rp)); /* Make sure we agree */ { CVMBool localIsRef; CVMJITsetContains(&con->localRefSet, localNumber, localIsRef); CVMassert(localIsRef == isRef); }#endif return rp;}CVMRMResource*CVMRMgetResourceForLocal( CVMJITRMContext* rc, CVMRMregset target, CVMRMregset avoid, int size, CVMBool isRef, CVMBool strict, CVMInt32 localNumber){ /* get resource for local */ CVMRMResource* rp = CVMRMbindResourceForLocal(rc, size, isRef, localNumber); /* load local into register */ ensureInRegister(rc, target, avoid, getRegisterPreference(rc, target, avoid), strict, rp); return rp;}static voidflushLocal(CVMJITRMContext* con, CVMInt32 localNumber){ CVMRMResource *rp = con->local2res[localNumber]; CVMJITCompilationContext* cc = con->compilationContext; if (rp != NULL) { /* Make sure we got a resource representing a local */ CVMassert(CVMRMisLocal(rp)); /* not good any more. */ /* if it was lingering just for that sake, get rid of it */ if (CVMRMgetRefCount(con, rp) == 0) { if (rp->size == 2) { CVMassert(rp->localNo == localNumber || rp->localNo + 1 == localNumber); localNumber = rp->localNo; CVMassert(con->local2res[localNumber + 1] == rp); con->local2res[localNumber + 1] = NULL; } con->local2res[localNumber] = NULL; deleteResource(con, rp); } else { if (rp->regno == -1) { /* * This is a hideous special case. * we have a value in a resource shadowing the local, * BUT it's been spilled, presumably to its java local, * AND we need this value in the future (refCount >0). * This means that we must RE-LOAD the value into a register * so that it is preserved. If necessary, it can be spilled * to the spill area, but not back to the register. * We are pretty desparate here, so are not going to be * picky about register selection. We'll just re-spill if * we need to. */ int regNo = findAvailableRegister(con, RM_ANY_SET, CVMRM_EMPTY_SET, CVM_FALSE, CVM_FALSE, rp->nregs); pinToRegister(con, rp, regNo); reloadRegister(cc, con, rp); CVMRMunpinResource(con, rp); /* * It is now safe to do the store. */ } CVMassert(con->local2res[localNumber] == rp); if (rp->size == 2) { CVMassert(rp->localNo == localNumber || rp->localNo + 1 == localNumber); localNumber = rp->localNo; CVMassert(con->local2res[localNumber + 1] == rp); con->local2res[localNumber + 1] = NULL; } con->local2res[localNumber] = NULL; CVMassert(rp->localNo == localNumber); rp->flags &= ~CVMRMLocalVar; /* disassociate from the local: */ rp->localNo = CVMRM_INVALID_LOCAL_NUMBER; /* and in any case, it is now out-of-sync with * its (new) spill location. */ rp->flags |= CVMRMdirty; } }}/* * Like CVMRMstoreJavaLocal, but * does not do as much work. */extern voidCVMRMstoreReturnValue(CVMJITRMContext* con, CVMRMResource* valueToStore){ CVMJITCompilationContext* cc = con->compilationContext; CVMassert(!(valueToStore->flags & CVMRMtrash)); CVMRMassertContextMatch(con, valueToStore); CVMCPUemitFrameReference(cc, RM_STORE_OPCODE(con, valueToStore->size), CVMRMgetRegisterNumber(valueToStore), CVMCPU_FRAME_LOCAL, 0);}/* * get the opcode appropriate for storing this resource to memory */extern CVMInt32CVMRMgetStoreOpcode(CVMJITRMContext* con, CVMRMResource* valueToStore){ CVMassert(!(valueToStore->flags & CVMRMtrash)); CVMRMassertContextMatch(con, valueToStore); return RM_STORE_OPCODE(con, valueToStore->size);}/* * get the opcode appropriate for loading this resource from memory */extern CVMInt32CVMRMgetLoadOpcode(CVMJITRMContext* con, CVMRMResource* valueToStore){ CVMassert(!(valueToStore->flags & CVMRMtrash)); CVMRMassertContextMatch(con, valueToStore); return RM_LOAD_OPCODE(con, valueToStore->size);}voidCVMRMstoreJavaLocal( CVMJITRMContext* con, CVMRMResource* valueToStore, int size, CVMBool isRef, CVMInt32 localNumber){ CVMJITCompilationContext* cc = con->compilationContext; int nregs; CVMassert(!con->compilationContext->inConditionalCode); CVMassert( !(valueToStore->flags & CVMRMtrash) ); CVMRMassertContextMatch(con, valueToStore); nregs = RM_NREGISTERS(con, size); #ifdef CVM_JIT_USE_FP_HARDWARE { /* If there are two register banks, make sure to * invalidate entries in the other one!! */ int contextIndex; CVMJITRMContext* otherContext; contextIndex = con - &(cc->RMcontext[0]); /* * C pointer arithmetic gives the index of the element: 0 or 1. * now find the other one: * map 0=>1 or 1=>0 */ contextIndex ^= 1; otherContext = &(cc->RMcontext[contextIndex]); flushLocal(otherContext, localNumber); if (nregs == 2) { flushLocal(otherContext, localNumber + 1); } }#endif flushLocal(con, localNumber); if (nregs == 2) { flushLocal(con, localNumber + 1); } CVMCPUemitFrameReference(cc, RM_STORE_OPCODE(con, size), CVMRMgetRegisterNumber(valueToStore), CVMCPU_FRAME_LOCAL, localNumber); valueToStore->flags &= ~CVMRMdirty; /* did store, so no longer dirty */ if (!CVMRMisLocal(valueToStore)) { /* now associate it with this local */ valueToStore->localNo = localNumber; valueToStore->flags |= CVMRMLocalVar; CVMassert(con->local2res[localNumber] == NULL); con->local2res[localNumber] = valueToStore; if (size == 2) { con->local2res[localNumber + 1] = valueToStore; }#ifdef CVMJIT_STRICT_REFLOCAL_ASSERTS if (isRef != CVMRMisRef(valueToStore)) { if (CVMRMisConstant(valueToStore)) { CVMassert(valueToStore->constant == 0); } else { CVMassert(CVM_FALSE); } }#endif } if (isRef) { CVMJITlocalrefsSetRef(cc, &cc->localRefSet, localNumber); } else { CVMJITlocalrefsSetValue(cc, &cc->localRefSet, localNumber, size == 2); }#if 0 /* DEBUGGING ONLY CVMconsolePrintf("DIGESTED LOCALREFS NODE: "); CVMJITsetDumpElements(con, &refsNode->refLocals); CVMconsolePrintf("\n"); */#endif}static voidCVMRMpinResource0( CVMJITRMContext* con, CVMRMResource* rp, CVMRMregset target, CVMRMregset avoid, CVMRMRegisterPreference pref, CVMBool strict){ CVMCodegenComment *comment; CVMJITCompilationContext* cc = con->compilationContext; int regNo; CVMassert(!con->compilationContext->inConditionalCode); CVMassert( !(rp->flags & CVMRMtrash) ); if (rp->flags & CVMRMpinned) { return; /* already pinned */ } else if (rp->regno != -1) { /* * already in a register. * If we're lucky, it's in the target set and we * can just pin it in. * Otherwise, we have to move it. Grumble. */ CVMRMregset rmask = 1U << rp->regno; /* * When strict is set, we choose not to shuffle if * the register is in the target set, even if it is * also in the avoid set. * * Note the use of rmask with target and rp->rmask * with avoid. This is because double word resources * interpret the target set as a "start set". So * Rn,Rn+1 is allowed if Rn is in the target set, even * if Rn+1 is not. */#ifdef SHUFFLE_FOR_AVOID if (strict ? !(rmask & target) : (rp->rmask & avoid))#else if (strict && !(rmask & target))#endif { /* Currently in a register we want to avoid. * Needed to shuffle it into an acceptable one. */ CVMJITpopCodegenComment(cc, comment); shuffleRegisters(con, rp, target, avoid, pref, strict); CVMJITpushCodegenComment(cc, comment); } else { /* resource is not in a register we need to avoid */ con->pinnedRegisters |= rp->rmask; rp->flags |= CVMRMpinned; } return; } CVMJITpopCodegenComment(cc, comment); regNo = findAvailableRegister(con, target, avoid, pref, strict, rp->nregs); CVMassert(regNo != -1); pinToRegister(con, rp, regNo); reloadRegister(cc, con, rp); CVMJITpushCodegenComment(cc, comment);}/* * For now, ask for any register. * Eventually, we should probably pass in * the expression so we can make a better decision based * on reference counts or other usage information. */voidCVMRMpinResource( CVMJITRMContext* con, CVMRMResource* rp, CVMRMregset target, CVMRMregset avoid){ CVMRMassertContextMatch(con, rp); CVMRMpinResource0(con, rp, target, avoid, getRegisterPreference(con, target, avoid), CVM_FALSE);}/* * Be sure to respect the target and avoid sets strictly. */voidCVMRMpinResourceStrict( CVMJITRMContext* con, CVMRMResource* rp, CVMRMregset target, CVMRMregset avoid){ CVMRMassertContextMatch(con, rp); CVMRMpinResource0(con, rp, target, avoid, CVMRM_REGPREF_TARGET, CVM_TRUE);}CVMRMResource *CVMRMpinResourceSpecific( CVMJITRMContext* con,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -