// Start solving the problem. bool Board::Unblock(Blocks bs) { count_setblock = 0; count_checkblock = 0; count_setcell = 0; count_checkcell = 0; // Sort Blocks by block weight sort(bs.begin(), bs.end(), [](Block *a, Block *b) { return (a->weight > b->weight); }); for (auto i = bs.cbegin(); i != bs.cend(); i++) { (*i)->Print("Block " + to_string(i - bs.cbegin())); } // Find solution bool result = RecursiveSetBlock(bs, 0); cout << "count_setblock = " << count_setblock << endl << "count_checkblock = " << count_checkblock << endl << "count_setcell = " << count_setcell << endl << "count_checkcell = " << count_checkcell << endl; return result; }
~CFGCalculator() { for(Blocks::iterator i = blocks_.begin(); i != blocks_.end(); i++) { delete i->second; } }
void PatchMgr::getBlockCandidates(Scope &scope, Point::Type types, Candidates &ret) { Blocks blocks; getBlocks(scope, blocks); for (Blocks::iterator iter = blocks.begin(); iter != blocks.end(); ++iter) { if (types & Point::BlockEntry) ret.push_back(Candidate(Location::Block(*iter), Point::BlockEntry)); if (types & Point::BlockDuring) ret.push_back(Candidate(Location::Block(*iter), Point::BlockDuring)); if (types & Point::BlockExit) ret.push_back(Candidate(Location::Block(*iter), Point::BlockExit)); } }
void PatchMgr::getInsns(Scope &scope, Insns &insns) { Blocks blocks; getBlocks(scope, blocks); for (Blocks::iterator iter = blocks.begin(); iter != blocks.end(); ++iter) { PatchBlock::Insns tmp; (*iter)->getInsns(tmp); for (PatchBlock::Insns::iterator t = tmp.begin(); t != tmp.end(); ++t) { insns.push_back(InsnLoc_t(*iter, t->first, t->second)); } } }
void findDeadBlockEdges(Blocks &blocks) { /* Run through all blocks and find edges that are logically dead and will * never be taken. * * Currently, this is limited to one special case that occurs in scripts * compiled by the original BioWare NWScript compiler (at least in NWN and * KotOR): short-circuiting in if (x || y) conditionals. The original BioWare * compiler has a bug where it generates a JZ instead of a JMP, creating a * true branch that will never be taken and effectively disabling short- * circuiting. I.e. both x and y will always be evaluated; when x is true, * y will still be evaluated afterwards. * * We use very simple pattern-matching here. This is enough to find most * occurances of this case, but not all. */ for (Blocks::iterator b = blocks.begin(); b != blocks.end(); ++b) { if (!isTopStackJumper(*b) || (b->instructions.size() != 2) || b->parents.empty()) continue; /* Look through all parents of this block and make sure they fit the * pattern as well. They also all need to jump to this block with the * same branch edge (true or false). */ size_t parentEdge = SIZE_MAX; for (std::vector<const Block *>::const_iterator p = b->parents.begin(); p != b->parents.end(); ++p) { if (!isTopStackJumper(**p, &*b, &parentEdge)) { parentEdge = SIZE_MAX; break; } } if (parentEdge == SIZE_MAX) continue; assert(parentEdge < 2); /* We have now established that * 1) This block checks whether the top of the stack is == 0 * 2) All parent blocks check whether the top of the stack is == 0 * 3) All parent blocks jump with the same branch edge into this block * * Therefore, this block must also always follow the exact same edge. * This means the other edge is logically dead. */ b->childrenTypes[1 - parentEdge] = kBlockEdgeTypeDead; } }
bool IsBlockFree( const SBlock& p_Block )const { unsigned int unRight = p_Block.m_unLeft + p_Block.m_unWidth; unsigned int unBottom = p_Block.m_unTop + p_Block.m_unHeight; if( unRight > m_unWidth || unBottom > m_unHeight ) { return false; } Blocks::const_iterator IteEnd = m_vecBlocks.end(); for( Blocks::const_iterator Ite = m_vecBlocks.begin(); Ite != IteEnd; ++Ite ) { if( Ite->m_unLeft < unRight && p_Block.m_unLeft < Ite->m_unLeft + Ite->m_unWidth && Ite->m_unTop < unBottom && p_Block.m_unTop < Ite->m_unTop + Ite->m_unHeight ) { return false; } } return true; }
void findDeadBlockEdges(Blocks &blocks) { /* Run through all blocks and find edges that are logically dead and will * never be taken. * * Currently, this is limited to one special case that occurs in scripts * compiled by the original BioWare NWScript compiler (at least in NWN and * KotOR): short-circuiting in if (x || y) conditionals. The original BioWare * compiler has a bug where it generates a JZ instead of a JMP, creating a * true branch that will never be taken and effectively disabling short- * circuiting. I.e. both x and y will always be evaluated; when x is true, * y will still be evaluated afterwards. * * We use very simple pattern-matching here. This is enough to find most * occurrences of this case, but not all. * * For example, this is the control flow diagram for the bytecode, as * compiled by the original BioWare compiler, for * * if ((global_variable == 1) || (global_variable == 3)) * * . * | * V * .-------------------. * | CPTOPBP -4 4 | * | CONSTI 1 | * | EQII | * | CPTOPSP -4 4 | * | JZ | * '-------------------' * (true)| |(false) * | V (1) * | .--------------------. * | | CPTOPSP -4 4 | * | | JZ | (4) * | '--------------------' * | (false)| |(true) * | (2) | | (3) * V V | * .-------------------. | * | CPTOPBP -4 4 | | * | CONSTI 3 | | * | EQII | | * '-------------------' | * | | * V | * .-------------------. | * | LOGORII -4 4 | | * | JZ |<-' * '-------------------' * (true) | |(false) * ' ' * * "CPTOPSP -4 4" takes the top element on the stack and, without * popping it, pushes it again onto the top, creating a duplicate. * * When taking the false branch at (1) (which means that the variable * *is* equal to 1), we have already established that the top element * on the stack (which is getting copied a few times, so it's not * vanishing) is of a certain value. This means that the false branch * at (2) has to be taken as well. The true branch at (3) can't ever * be taken, and is therefore logically dead. * * Moreover, if the true branch at (3) would have been taken, this * had resulted in a stack smash, because JZ consumes a stack element, * and the LOGORII would now be one element short. * * Essentially, the whole block at (4) evaluates to a NOP. * * How this *should* have been compiled is thusly: * * . * | * V * .-------------------. * | CPTOPBP -4 4 | * | CONSTI 1 | * | EQII | * | CPTOPSP -4 4 | * | JZ | * '-------------------' * (true)| |(false) * | V * | .--------------------. * | | CPTOPSP -4 4 | (5) * | | JMP | * | '--------------------' * | | * | | * V | * .-------------------. | * | CPTOPBP -4 4 | | * | CONSTI 3 | | * | EQII | | * '-------------------' | * | | * V (6) | * .-------------------. | * | LOGORII -4 4 | | * | JZ |<-' * '-------------------' * (true) | |(false) * ' ' * * In the block at (5), the top element is now copied, and the code * jumps unconditionally to the LOGORII block at (6). In contrast * to JZ, JMP does not pop an element from the stack. The LOGORII * has enough elements to do its comparison. * * This is exactly what the OpenKnights compiler does. And this has * been fixed by BioWare by the time of Neverwinter Nights 2 as well. * * The short-circuiting && construct does not seem to have this fault. */ for (Blocks::iterator b = blocks.begin(); b != blocks.end(); ++b) { if (!isTopStackJumper(*b) || (b->instructions.size() != 2) || b->parents.empty()) continue; /* Look through all parents of this block and make sure they fit the * pattern as well. They also all need to jump to this block with the * same branch edge (true or false). */ size_t parentEdge = SIZE_MAX; for (std::vector<const Block *>::const_iterator p = b->parents.begin(); p != b->parents.end(); ++p) { if (!isTopStackJumper(**p, &*b, &parentEdge)) { parentEdge = SIZE_MAX; break; } } if (parentEdge == SIZE_MAX) continue; assert(parentEdge < 2); /* We have now established that * 1) This block checks whether the top of the stack is == 0 * 2) All parent blocks check whether the top of the stack is == 0 * 3) All parent blocks jump with the same branch edge into this block * * Therefore, this block must also always follow the exact same edge. * This means the other edge is logically dead. */ b->childrenTypes[1 - parentEdge] = kBlockEdgeTypeDead; } }
BlkModel::BlkModel(const BlkModel& rhs) { Blocks blocks = const_cast<BlkModel&>(rhs).blocks(); for (Blocks::iterator it = blocks.begin(); it != blocks.end(); ++it) addBlock(it->first, it->second); }
CFGBlock* find_block(int ip) { Blocks::iterator i = blocks_.find(ip); if(i == blocks_.end()) return 0; return i->second; }
void AbstractAligner::change_blocks_impl(Blocks& blocks) const { std::sort(blocks.begin(), blocks.end(), BlockSquareLess()); }
/** * Unpause par2-files * returns true, if the files with required number of blocks were unpaused, * or false if there are no more files in queue for this collection or not enough blocks. * special case: returns true if there are any unpaused par2-files in the queue regardless * of the amount of blocks; this is to keep par-checker wait for download completion. */ bool ParCoordinator::RequestMorePars(NZBInfo* pNZBInfo, const char* szParFilename, int iBlockNeeded, int* pBlockFound) { DownloadQueue* pDownloadQueue = DownloadQueue::Lock(); Blocks blocks; blocks.clear(); int iBlockFound = 0; int iCurBlockFound = 0; FindPars(pDownloadQueue, pNZBInfo, szParFilename, &blocks, true, true, &iCurBlockFound); iBlockFound += iCurBlockFound; if (iBlockFound < iBlockNeeded) { FindPars(pDownloadQueue, pNZBInfo, szParFilename, &blocks, true, false, &iCurBlockFound); iBlockFound += iCurBlockFound; } if (iBlockFound < iBlockNeeded) { FindPars(pDownloadQueue, pNZBInfo, szParFilename, &blocks, false, false, &iCurBlockFound); iBlockFound += iCurBlockFound; } if (iBlockFound >= iBlockNeeded) { // 1. first unpause all files with par-blocks less or equal iBlockNeeded // starting from the file with max block count. // if par-collection was built exponentially and all par-files present, // this step selects par-files with exact number of blocks we need. while (iBlockNeeded > 0) { BlockInfo* pBestBlockInfo = NULL; for (Blocks::iterator it = blocks.begin(); it != blocks.end(); it++) { BlockInfo* pBlockInfo = *it; if (pBlockInfo->m_iBlockCount <= iBlockNeeded && (!pBestBlockInfo || pBestBlockInfo->m_iBlockCount < pBlockInfo->m_iBlockCount)) { pBestBlockInfo = pBlockInfo; } } if (pBestBlockInfo) { if (pBestBlockInfo->m_pFileInfo->GetPaused()) { m_ParChecker.PrintMessage(Message::mkInfo, "Unpausing %s%c%s for par-recovery", pNZBInfo->GetName(), (int)PATH_SEPARATOR, pBestBlockInfo->m_pFileInfo->GetFilename()); pBestBlockInfo->m_pFileInfo->SetPaused(false); pBestBlockInfo->m_pFileInfo->SetExtraPriority(true); } iBlockNeeded -= pBestBlockInfo->m_iBlockCount; blocks.remove(pBestBlockInfo); delete pBestBlockInfo; } else { break; } } // 2. then unpause other files // this step only needed if the par-collection was built not exponentially // or not all par-files present (or some of them were corrupted) // this step is not optimal, but we hope, that the first step will work good // in most cases and we will not need the second step often while (iBlockNeeded > 0) { BlockInfo* pBlockInfo = blocks.front(); if (pBlockInfo->m_pFileInfo->GetPaused()) { m_ParChecker.PrintMessage(Message::mkInfo, "Unpausing %s%c%s for par-recovery", pNZBInfo->GetName(), (int)PATH_SEPARATOR, pBlockInfo->m_pFileInfo->GetFilename()); pBlockInfo->m_pFileInfo->SetPaused(false); pBlockInfo->m_pFileInfo->SetExtraPriority(true); } iBlockNeeded -= pBlockInfo->m_iBlockCount; } } bool bHasUnpausedParFiles = false; for (FileList::iterator it = pNZBInfo->GetFileList()->begin(); it != pNZBInfo->GetFileList()->end(); it++) { FileInfo* pFileInfo = *it; if (pFileInfo->GetParFile() && !pFileInfo->GetPaused()) { bHasUnpausedParFiles = true; break; } } DownloadQueue::Unlock(); if (pBlockFound) { *pBlockFound = iBlockFound; } for (Blocks::iterator it = blocks.begin(); it != blocks.end(); it++) { delete *it; } blocks.clear(); bool bOK = iBlockNeeded <= 0 || bHasUnpausedParFiles; return bOK; }