/* * find all the leaders (instruction) in the InstrList given, * leaders returned as an ArrayList(set) of Instruction* */ ArrayList *findLeaders(InstrList *iList){ Instruction *temp_ins; ArrayList *leaders = al_newGeneric(AL_LIST_SET, addressCompare, refPrint, NULL); int i=0; //add first instr into leader list Instruction *instr = getInstruction(iList, i); al_add(leaders, (void *)(instr->addr)); for(i=0;i<iList->numInstrs;i++){ Instruction *instr = getInstruction(iList, i); //ignore non-jump instructions and native invocations if(!isBranch(iList, instr) && !isRetInstruction(iList, instr) && !(isInvokeInstruction(iList, instr) && INSTR_HAS_FLAG(instr, INSTR_IS_SCRIPT_INVOKE)) ) continue; /* add: * instr as target of jump * instr immediately after jump */ if(isBranch(iList, instr)){ if(!instr->jmpOffset){ printInstruction(instr); } assert(instr->jmpOffset); al_add(leaders, (void *)(instr->addr + instr->jmpOffset)); assert(instr->length>0); al_add(leaders, (void *)(instr->addr + instr->length)); } else if(isRetInstruction(iList, instr)){ if(i < iList->numInstrs-1){ temp_ins = getInstruction(iList, i+1); al_add(leaders, (void *)(temp_ins->addr)); } } else{ //non-native invoke and document.write() which generate code if(i < iList->numInstrs-1){ assert(isInvokeInstruction(iList, instr) && INSTR_HAS_FLAG(instr, INSTR_IS_SCRIPT_INVOKE)); temp_ins = getInstruction(iList, i+1); al_add(leaders, (void *)(temp_ins->addr)); } } } return leaders; }
void ForestCell::_updateBounds() { mIsDirty = false; mBounds = Box3F::Invalid; mLargestItem = ForestItem::Invalid; F32 radius; if ( isBranch() ) { for ( U32 i=0; i < 4; i++ ) { mBounds.intersect( mSubCells[i]->getBounds() ); radius = mSubCells[i]->mLargestItem.getRadius(); if ( radius > mLargestItem.getRadius() ) mLargestItem = mSubCells[i]->mLargestItem; } return; } // Loop thru all the items in this cell. Vector<ForestItem>::const_iterator item = mItems.begin(); for ( ; item != mItems.end(); item++ ) { mBounds.intersect( (*item).getWorldBox() ); radius = (*item).getRadius(); if ( radius > mLargestItem.getRadius() ) mLargestItem = (*item); } }
list listWritedReg(instruction ins, int dico_entry) { list L=NULL; if(ins.value==-1) { return L; //Si l'instruction est invalide } switch(dico_data[dico_entry].type) { case 0: //R type if(ins.r.rd!=0) { L=insert(ins.r.rd,L); } break; case 1: //I type (il faut separer les branchs, qui n'ont pas le meme comportement) if(isBranch(dico_entry)!=0) { //Si ce n'est pas une branch, on write rt if(ins.i.rt!=0) { L=insert(ins.i.rt,L); } } break; default: //J type no register break; } //printList(L); return L; }
static PTXInstruction* getBranch(block_iterator block) { if(block->instructions.empty()) return nullptr; auto ptxBranch = static_cast<ir::PTXInstruction*>( block->instructions.back()); if(!ptxBranch->isBranch()) return nullptr; return ptxBranch; }
int NCodeHook<ArchT>::getMinOffset(const unsigned char* codePtr, unsigned int jumpPatchSize) { _DecodeResult result; _DecodedInst instructions[MaxInstructions]; unsigned int instructionCount = 0; result = distorm_decode(0, codePtr, 20, ArchT::DisasmType, instructions, MaxInstructions, &instructionCount); if (result != DECRES_SUCCESS) return -1; unsigned int offset = 0; for (unsigned int i = 0; offset < jumpPatchSize && i < instructionCount; ++i) { if (isBranch((const char*)instructions[i].mnemonic.p)) return -1; offset += instructions[i].size; } // If we were unable to disassemble enough instructions we fail. if (offset < jumpPatchSize) return -1; return offset; }
// Can this statement forego codegen? bool isTrivial() const {return !isBranch() && !isEffect();}
const ForestItem& ForestCell::insertItem( ForestItemKey key, ForestItemData *data, const MatrixF &xfm, F32 scale ) { AssertFatal( key != 0, "ForestCell::insertItem() - Got null key!" ); AssertFatal( data != NULL, "ForestCell::insertItem() - Got null datablock!" ); // Make sure we update the bounds later. mIsDirty = true; // PhysicsBody is now invalid and must be rebuilt later. SAFE_DELETE( mPhysicsRep[0] ); SAFE_DELETE( mPhysicsRep[1] ); // Destroy batches so we recreate it on // the next next render. freeBatches(); // Ok... do we need to split this cell? if ( isLeaf() && mItems.size() > MaxItems ) { // Add the children. for ( U32 i=0; i < 4; i++ ) mSubCells[i] = new ForestCell( _makeChildRect( i ) ); // Now push all our current children down. Vector<ForestItem>::iterator item = mItems.begin(); for ( ; item != mItems.end(); item++ ) { U32 index = _getSubCell( item->getPosition().x, item->getPosition().y ); mSubCells[index]->insertItem( item->getKey(), item->getData(), item->getTransform(), item->getScale() ); } // Clean up. mItems.clear(); mItems.compact(); } // Do we have children? if ( isBranch() ) { // Ok... kick this item down then. U32 index = _getSubCell( xfm.getPosition().x, xfm.getPosition().y ); const ForestItem &result = mSubCells[index]->insertItem( key, data, xfm, scale ); AssertFatal( index == _getSubCell( result.getPosition().x, result.getPosition().y ), "ForestCell::insertItem() - binning is hosed." ); return result; } // Do the datablock preload here to insure it happens // before an item is used in the scene. data->preload(); // First see if we can find it. This is nifty so // I'll explain it a bit more. // // The find function does a binary search thru the // sorted item list. // // If found the index is the position of the item. // // If not found the index is the correct insertion // position for adding the new item. // // So not only do we have a fast find which is worst // case O(log n)... but we also have the proper insert // position to maintain a sorted item list. // U32 index; bool found = findIndexByKey( key, &index ); // If we didn't find one then insert it. if ( !found ) mItems.insert( index ); // Update the item settings. ForestItem &item = mItems[ index ]; item.setData( data ); item.setTransform( xfm, scale ); if ( !found ) item.setKey( key ); return item; }
void computeBytecodeBasicBlocks(CodeBlock* codeBlock, Vector<RefPtr<BytecodeBasicBlock> >& basicBlocks) { Vector<unsigned, 32> jumpTargets; computePreciseJumpTargets(codeBlock, jumpTargets); // Create the entry and exit basic blocks. BytecodeBasicBlock* entry = new BytecodeBasicBlock(BytecodeBasicBlock::EntryBlock); basicBlocks.append(adoptRef(entry)); BytecodeBasicBlock* exit = new BytecodeBasicBlock(BytecodeBasicBlock::ExitBlock); // Find basic block boundaries. BytecodeBasicBlock* current = new BytecodeBasicBlock(0, 0); linkBlocks(entry, current); basicBlocks.append(adoptRef(current)); bool nextInstructionIsLeader = false; Interpreter* interpreter = codeBlock->vm()->interpreter; Instruction* instructionsBegin = codeBlock->instructions().begin(); unsigned instructionCount = codeBlock->instructions().size(); for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount;) { OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode); unsigned opcodeLength = opcodeLengths[opcodeID]; bool createdBlock = false; // If the current bytecode is a jump target, then it's the leader of its own basic block. if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) { BytecodeBasicBlock* block = new BytecodeBasicBlock(bytecodeOffset, opcodeLength); basicBlocks.append(adoptRef(block)); current = block; createdBlock = true; nextInstructionIsLeader = false; bytecodeOffset += opcodeLength; } // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block. if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID)) nextInstructionIsLeader = true; if (createdBlock) continue; // Otherwise, just add to the length of the current block. current->addBytecodeLength(opcodeLength); bytecodeOffset += opcodeLength; } // Link basic blocks together. for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* block = basicBlocks[i].get(); if (block->isEntryBlock() || block->isExitBlock()) continue; bool fallsThrough = true; for (unsigned bytecodeOffset = block->leaderBytecodeOffset(); bytecodeOffset < block->leaderBytecodeOffset() + block->totalBytecodeLength();) { const Instruction& currentInstruction = instructionsBegin[bytecodeOffset]; OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction.u.opcode); unsigned opcodeLength = opcodeLengths[opcodeID]; // If we found a terminal bytecode, link to the exit block. if (isTerminal(opcodeID)) { ASSERT(bytecodeOffset + opcodeLength == block->leaderBytecodeOffset() + block->totalBytecodeLength()); linkBlocks(block, exit); fallsThrough = false; break; } // If we found a throw, get the HandlerInfo for this instruction to see where we will jump. // If there isn't one, treat this throw as a terminal. This is true even if we have a finally // block because the finally block will create its own catch, which will generate a HandlerInfo. if (isThrow(opcodeID)) { ASSERT(bytecodeOffset + opcodeLength == block->leaderBytecodeOffset() + block->totalBytecodeLength()); HandlerInfo* handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset); fallsThrough = false; if (!handler) { linkBlocks(block, exit); break; } for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* otherBlock = basicBlocks[i].get(); if (handler->target == otherBlock->leaderBytecodeOffset()) { linkBlocks(block, otherBlock); break; } } break; } // If we found a branch, link to the block(s) that we jump to. if (isBranch(opcodeID)) { ASSERT(bytecodeOffset + opcodeLength == block->leaderBytecodeOffset() + block->totalBytecodeLength()); Vector<unsigned, 1> bytecodeOffsetsJumpedTo; findJumpTargetsForBytecodeOffset(codeBlock, bytecodeOffset, bytecodeOffsetsJumpedTo); for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* otherBlock = basicBlocks[i].get(); if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderBytecodeOffset())) linkBlocks(block, otherBlock); } if (isUnconditionalBranch(opcodeID)) fallsThrough = false; break; } bytecodeOffset += opcodeLength; } // If we fall through then link to the next block in program order. if (fallsThrough) { ASSERT(i + 1 < basicBlocks.size()); BytecodeBasicBlock* nextBlock = basicBlocks[i + 1].get(); linkBlocks(block, nextBlock); } } basicBlocks.append(adoptRef(exit)); }
bool DecodedInstruction::isJmp() const { // if it's conditional branch, it's not a jmp return isBranch(false); }
void BytecodeBasicBlock::computeImpl(Block* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks) { Vector<unsigned, 32> jumpTargets; computePreciseJumpTargets(codeBlock, instructionsBegin, instructionCount, jumpTargets); auto appendBlock = [&] (std::unique_ptr<BytecodeBasicBlock>&& block) { block->m_index = basicBlocks.size(); basicBlocks.append(WTFMove(block)); }; auto linkBlocks = [&] (BytecodeBasicBlock* from, BytecodeBasicBlock* to) { from->addSuccessor(to); }; // Create the entry and exit basic blocks. basicBlocks.reserveCapacity(jumpTargets.size() + 2); auto entry = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock); auto firstBlock = std::make_unique<BytecodeBasicBlock>(0, 0); linkBlocks(entry.get(), firstBlock.get()); appendBlock(WTFMove(entry)); BytecodeBasicBlock* current = firstBlock.get(); appendBlock(WTFMove(firstBlock)); auto exit = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::ExitBlock); bool nextInstructionIsLeader = false; Interpreter* interpreter = codeBlock->vm()->interpreter; for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount;) { OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset]); unsigned opcodeLength = opcodeLengths[opcodeID]; bool createdBlock = false; // If the current bytecode is a jump target, then it's the leader of its own basic block. if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) { auto newBlock = std::make_unique<BytecodeBasicBlock>(bytecodeOffset, opcodeLength); current = newBlock.get(); appendBlock(WTFMove(newBlock)); createdBlock = true; nextInstructionIsLeader = false; bytecodeOffset += opcodeLength; } // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block. if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID)) nextInstructionIsLeader = true; if (createdBlock) continue; // Otherwise, just add to the length of the current block. current->addLength(opcodeLength); bytecodeOffset += opcodeLength; } // Link basic blocks together. for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* block = basicBlocks[i].get(); if (block->isEntryBlock() || block->isExitBlock()) continue; bool fallsThrough = true; for (unsigned bytecodeOffset = block->leaderOffset(); bytecodeOffset < block->leaderOffset() + block->totalLength();) { OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset]); unsigned opcodeLength = opcodeLengths[opcodeID]; // If we found a terminal bytecode, link to the exit block. if (isTerminal(opcodeID)) { ASSERT(bytecodeOffset + opcodeLength == block->leaderOffset() + block->totalLength()); linkBlocks(block, exit.get()); fallsThrough = false; break; } // If we found a throw, get the HandlerInfo for this instruction to see where we will jump. // If there isn't one, treat this throw as a terminal. This is true even if we have a finally // block because the finally block will create its own catch, which will generate a HandlerInfo. if (isThrow(opcodeID)) { ASSERT(bytecodeOffset + opcodeLength == block->leaderOffset() + block->totalLength()); auto* handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset); fallsThrough = false; if (!handler) { linkBlocks(block, exit.get()); break; } for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* otherBlock = basicBlocks[i].get(); if (handler->target == otherBlock->leaderOffset()) { linkBlocks(block, otherBlock); break; } } break; } // If we found a branch, link to the block(s) that we jump to. if (isBranch(opcodeID)) { ASSERT(bytecodeOffset + opcodeLength == block->leaderOffset() + block->totalLength()); Vector<unsigned, 1> bytecodeOffsetsJumpedTo; findJumpTargetsForBytecodeOffset(codeBlock, instructionsBegin, bytecodeOffset, bytecodeOffsetsJumpedTo); for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* otherBlock = basicBlocks[i].get(); if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderOffset())) linkBlocks(block, otherBlock); } if (isUnconditionalBranch(opcodeID)) fallsThrough = false; break; } bytecodeOffset += opcodeLength; } // If we fall through then link to the next block in program order. if (fallsThrough) { ASSERT(i + 1 < basicBlocks.size()); BytecodeBasicBlock* nextBlock = basicBlocks[i + 1].get(); linkBlocks(block, nextBlock); } } appendBlock(WTFMove(exit)); for (auto& basicBlock : basicBlocks) basicBlock->shrinkToFit(); }
void BytecodeBasicBlock::computeImpl(Block* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks) { Vector<InstructionStream::Offset, 32> jumpTargets; computePreciseJumpTargets(codeBlock, instructions, jumpTargets); auto appendBlock = [&] (std::unique_ptr<BytecodeBasicBlock>&& block) { block->m_index = basicBlocks.size(); basicBlocks.append(WTFMove(block)); }; auto linkBlocks = [&] (BytecodeBasicBlock* from, BytecodeBasicBlock* to) { from->addSuccessor(to); }; // Create the entry and exit basic blocks. basicBlocks.reserveCapacity(jumpTargets.size() + 2); auto entry = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock); auto firstBlock = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock); linkBlocks(entry.get(), firstBlock.get()); appendBlock(WTFMove(entry)); BytecodeBasicBlock* current = firstBlock.get(); appendBlock(WTFMove(firstBlock)); auto exit = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::ExitBlock); bool nextInstructionIsLeader = false; for (const auto& instruction : instructions) { auto bytecodeOffset = instruction.offset(); OpcodeID opcodeID = instruction->opcodeID(); bool createdBlock = false; // If the current bytecode is a jump target, then it's the leader of its own basic block. if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) { auto newBlock = std::make_unique<BytecodeBasicBlock>(instruction); current = newBlock.get(); appendBlock(WTFMove(newBlock)); createdBlock = true; nextInstructionIsLeader = false; } // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block. if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID)) nextInstructionIsLeader = true; if (createdBlock) continue; // Otherwise, just add to the length of the current block. current->addLength(instruction->size()); } // Link basic blocks together. for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* block = basicBlocks[i].get(); if (block->isEntryBlock() || block->isExitBlock()) continue; bool fallsThrough = true; for (auto bytecodeOffset : block->offsets()) { auto instruction = instructions.at(bytecodeOffset); OpcodeID opcodeID = instruction->opcodeID(); // If we found a terminal bytecode, link to the exit block. if (isTerminal(opcodeID)) { ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength()); linkBlocks(block, exit.get()); fallsThrough = false; break; } // If we found a throw, get the HandlerInfo for this instruction to see where we will jump. // If there isn't one, treat this throw as a terminal. This is true even if we have a finally // block because the finally block will create its own catch, which will generate a HandlerInfo. if (isThrow(opcodeID)) { ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength()); auto* handler = codeBlock->handlerForBytecodeOffset(instruction.offset()); fallsThrough = false; if (!handler) { linkBlocks(block, exit.get()); break; } for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* otherBlock = basicBlocks[i].get(); if (handler->target == otherBlock->leaderOffset()) { linkBlocks(block, otherBlock); break; } } break; } // If we found a branch, link to the block(s) that we jump to. if (isBranch(opcodeID)) { ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength()); Vector<InstructionStream::Offset, 1> bytecodeOffsetsJumpedTo; findJumpTargetsForInstruction(codeBlock, instruction, bytecodeOffsetsJumpedTo); size_t numberOfJumpTargets = bytecodeOffsetsJumpedTo.size(); ASSERT(numberOfJumpTargets); for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* otherBlock = basicBlocks[i].get(); if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderOffset())) { linkBlocks(block, otherBlock); --numberOfJumpTargets; if (!numberOfJumpTargets) break; } } // numberOfJumpTargets may not be 0 here if there are multiple jumps targeting the same // basic blocks (e.g. in a switch type opcode). Since we only decrement numberOfJumpTargets // once per basic block, the duplicates are not accounted for. For our purpose here, // that doesn't matter because we only need to link to the target block once regardless // of how many ways this block can jump there. if (isUnconditionalBranch(opcodeID)) fallsThrough = false; break; } } // If we fall through then link to the next block in program order. if (fallsThrough) { ASSERT(i + 1 < basicBlocks.size()); BytecodeBasicBlock* nextBlock = basicBlocks[i + 1].get(); linkBlocks(block, nextBlock); } } appendBlock(WTFMove(exit)); for (auto& basicBlock : basicBlocks) basicBlock->shrinkToFit(); }
bool XmlNode::isLeaf() { return !isBranch(); }
void x86RevDis::RevDisasm(uint32 uStartAddr, uint32 uCurAddr) { CPU_ADDR curAddr; curAddr.addr32.offset = uCurAddr; for (unsigned i=uCurAddr-uStartAddr;i<m_uSize;) { x86dis_insn* insn = (x86dis_insn*)m_decoder.decode(m_pCode+i,m_uSize-i,curAddr); m_mapResult.insert(std::map<uint32,x86dis_insn>::value_type(curAddr.addr32.offset,*insn)); const char* pcsIns = m_decoder.str(insn,DIS_STYLE_HEX_ASMSTYLE | DIS_STYLE_HEX_UPPERCASE | DIS_STYLE_HEX_NOZEROPAD); //printf("%08X\t%s\n",curAddr.addr32.offset, pcsIns); i += insn->size; curAddr.addr32.offset += insn->size; switch (isBranch(insn)) { case br_return: return; case br_jump: { CPU_ADDR branch = branchAddr(insn); if (branch.addr32.offset<uStartAddr || branch.addr32.offset>uStartAddr+m_uSize) { //跳转到的地址不在本段代码内 break; } std::map<uint32,x86dis_insn>::iterator it = m_mapResult.find(branch.addr32.offset); if (it!=m_mapResult.end()) { //已经反过了 break; } return RevDisasm(uStartAddr,branch.addr32.offset); } case br_jXX: case br_call: { CPU_ADDR branch = branchAddr(insn); if (branch.addr32.offset<uStartAddr || branch.addr32.offset>uStartAddr+m_uSize) { //跳转到的地址不在本段代码内 break; } std::map<uint32,x86dis_insn>::iterator it = m_mapResult.find(branch.addr32.offset); if (it!=m_mapResult.end()) { //已经反过了 break; } RevDisasm(uStartAddr,branch.addr32.offset); } break; } } }