void CMyByteArray::ReallocateDataSpace( size_t szAddition ) { //只有此条件才会分配空间,也即调用此函数前必须检测空间剩余 //assert(GetSpaceLeft()<szAddition); //计算除去剩余空间后还应增加的空间大小 size_t left = szAddition - GetSpaceLeft(); //按分配粒度计算块数及剩余 size_t nBlocks = left / GetGranularity(); size_t cbRemain = left - nBlocks*GetGranularity(); if(cbRemain) ++nBlocks; //计算新空间并重新分配 size_t newDataSize = m_iDataSize + nBlocks*GetGranularity(); void* pData = (void*)new char[newDataSize]; //复制原来的数据到新空间 //memcpy支持第3个参数传0吗? if(GetSpaceUsed()) memcpy(pData,m_pData,GetSpaceUsed()); if(m_pData) delete[] m_pData; m_pData = pData; m_iDataSize = newDataSize; }
size_t CMyByteArray::Write( const void* data,size_t sz ) { if(sz > GetSpaceLeft()) ReallocateDataSpace(sz); memcpy((char*)m_pData+GetSpaceUsed(),data,sz); GetSpaceUsed() += sz; return sz; }
void MipsJit::Compile(u32 em_address) { PROFILE_THIS_SCOPE("jitc"); if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) { ClearCache(); } int block_num = blocks.AllocateBlock(em_address); JitBlock *b = blocks.GetBlock(block_num); DoJit(em_address, b); blocks.FinalizeBlock(block_num, jo.enableBlocklink); bool cleanSlate = false; if (js.hasSetRounding && !js.lastSetRounding) { WARN_LOG(JIT, "Detected rounding mode usage, rebuilding jit with checks"); // Won't loop, since hasSetRounding is only ever set to 1. js.lastSetRounding = js.hasSetRounding; cleanSlate = true; } if (cleanSlate) { // Our assumptions are all wrong so it's clean-slate time. ClearCache(); Compile(em_address); } }
void Jit::Compile(u32 em_address) { if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) { ClearCache(); } int block_num = blocks.AllocateBlock(em_address); JitBlock *b = blocks.GetBlock(block_num); blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, b)); }
/* =============== idMsgQueue::Add =============== */ bool idMsgQueue::Add( const byte *data, const int size ) { if( GetSpaceLeft() < size + 8 ) { return false; } int sequence = last; WriteShort( size ); WriteLong( sequence ); WriteData( data, size ); last++; return true; }
const u8 *MipsJit::DoJit(u32 em_address, JitBlock *b) { js.cancel = false; js.blockStart = js.compilerPC = mips_->pc; js.lastContinuedPC = 0; js.initialBlockSize = 0; js.nextExit = 0; js.downcountAmount = 0; js.curBlock = b; js.compiling = true; js.inDelaySlot = false; js.PrefixStart(); b->normalEntry = GetCodePtr(); js.numInstructions = 0; while (js.compiling) { MIPSOpcode inst = Memory::Read_Opcode_JIT(js.compilerPC); js.downcountAmount += MIPSGetInstructionCycleEstimate(inst); MIPSCompileOp(inst); js.compilerPC += 4; js.numInstructions++; // Safety check, in case we get a bunch of really large jit ops without a lot of branching. if (GetSpaceLeft() < 0x800 || js.numInstructions >= JitBlockCache::MAX_BLOCK_INSTRUCTIONS) { FlushAll(); WriteExit(js.compilerPC, js.nextExit++); js.compiling = false; } } b->codeSize = GetCodePtr() - b->normalEntry; // Don't forget to zap the newly written instructions in the instruction cache! FlushIcache(); if (js.lastContinuedPC == 0) b->originalSize = js.numInstructions; else { // We continued at least once. Add the last proxy and set the originalSize correctly. blocks.ProxyBlock(js.blockStart, js.lastContinuedPC, (js.compilerPC - js.lastContinuedPC) / sizeof(u32), GetCodePtr()); b->originalSize = js.initialBlockSize; } return b->normalEntry; }
void Jit::Compile(u32 em_address) { if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) { ClearCache(); } int block_num = blocks.AllocateBlock(em_address); JitBlock *b = blocks.GetBlock(block_num); DoJit(em_address, b); blocks.FinalizeBlock(block_num, jo.enableBlocklink); // Drat. The VFPU hit an uneaten prefix at the end of a block. if (js.startDefaultPrefix && js.MayHavePrefix()) { WARN_LOG(JIT, "Uneaten prefix at end of block: %08x", js.compilerPC - 4); js.startDefaultPrefix = false; // Our assumptions are all wrong so it's clean-slate time. ClearCache(); // Let's try that one more time. We won't get back here because we toggled the value. Compile(em_address); } }
const u8 *Jit::DoJit(u32 em_address, JitBlock *b) { js.cancel = false; js.blockStart = js.compilerPC = mips_->pc; js.nextExit = 0; js.downcountAmount = 0; js.curBlock = b; js.compiling = true; js.inDelaySlot = false; js.afterOp = JitState::AFTER_NONE; js.PrefixStart(); // We add a check before the block, used when entering from a linked block. b->checkedEntry = GetCodePtr(); // Downcount flag check. The last block decremented downcounter, and the flag should still be available. FixupBranch skip = J_CC(CC_NBE); MOV(32, M(&mips_->pc), Imm32(js.blockStart)); JMP(asm_.outerLoop, true); // downcount hit zero - go advance. SetJumpTarget(skip); b->normalEntry = GetCodePtr(); MIPSAnalyst::AnalysisResults analysis = MIPSAnalyst::Analyze(em_address); gpr.Start(mips_, analysis); fpr.Start(mips_, analysis); js.numInstructions = 0; while (js.compiling) { // Jit breakpoints are quite fast, so let's do them in release too. CheckJitBreakpoint(js.compilerPC, 0); MIPSOpcode inst = Memory::Read_Opcode_JIT(js.compilerPC); js.downcountAmount += MIPSGetInstructionCycleEstimate(inst); MIPSCompileOp(inst); if (js.afterOp & JitState::AFTER_CORE_STATE) { // TODO: Save/restore? FlushAll(); // If we're rewinding, CORE_NEXTFRAME should not cause a rewind. // It doesn't really matter either way if we're not rewinding. // CORE_RUNNING is <= CORE_NEXTFRAME. CMP(32, M(&coreState), Imm32(CORE_NEXTFRAME)); FixupBranch skipCheck = J_CC(CC_LE); if (js.afterOp & JitState::AFTER_REWIND_PC_BAD_STATE) MOV(32, M(&mips_->pc), Imm32(js.compilerPC)); else MOV(32, M(&mips_->pc), Imm32(js.compilerPC + 4)); WriteSyscallExit(); SetJumpTarget(skipCheck); js.afterOp = JitState::AFTER_NONE; } if (js.afterOp & JitState::AFTER_MEMCHECK_CLEANUP) { js.afterOp &= ~JitState::AFTER_MEMCHECK_CLEANUP; } js.compilerPC += 4; js.numInstructions++; // Safety check, in case we get a bunch of really large jit ops without a lot of branching. if (GetSpaceLeft() < 0x800) { FlushAll(); WriteExit(js.compilerPC, js.nextExit++); js.compiling = false; } } b->codeSize = (u32)(GetCodePtr() - b->normalEntry); NOP(); AlignCode4(); b->originalSize = js.numInstructions; return b->normalEntry; }