/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e l i n q u i s h M a g i c k M e m o r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory() % or AcquireQuantumMemory() for reuse. % % The format of the RelinquishMagickMemory method is: % % void *RelinquishMagickMemory(void *memory) % % A description of each parameter follows: % % o memory: A pointer to a block of memory to free for reuse. % */ MagickExport void *RelinquishMagickMemory(void *memory) { if (memory == (void *) NULL) return((void *) NULL); #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT) memory_methods.destroy_memory_handler(memory); #else LockSemaphoreInfo(memory_semaphore); assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0); assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0); if ((*BlockHeader(memory) & PreviousBlockBit) == 0) { void *previous; /* Coalesce with previous adjacent block. */ previous=PreviousBlock(memory); RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous))); *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) | (*BlockHeader(previous) & ~SizeMask); memory=previous; } if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0) { void *next; /* Coalesce with next adjacent block. */ next=NextBlock(memory); RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next))); *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) | (*BlockHeader(memory) & ~SizeMask); } *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory); *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit); InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory))); UnlockSemaphoreInfo(memory_semaphore); #endif return((void *) NULL); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e l i n q u i s h M a g i c k M e m o r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % RelinquishMagickMemory() zeros memory that has been allocated, frees it for % reuse. % % The format of the RelinquishMagickMemory method is: % % void *RelinquishMagickMemory(void *memory) % % A description of each parameter follows: % % o memory: A pointer to a block of memory to free for reuse. % */ MagickExport void *RelinquishMagickMemory(void *memory) { if (memory == (void *) NULL) return((void *) NULL); #if !defined(UseEmbeddableMagick) free(memory); #else assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0); assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0); AcquireSemaphoreInfo(&memory_semaphore); if ((*BlockHeader(memory) & PreviousBlockBit) == 0) { void *previous; /* Coalesce with previous adjacent block. */ previous=PreviousBlock(memory); RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous))); *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) | (*BlockHeader(previous) & ~SizeMask); memory=previous; } if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0) { void *next; /* Coalesce with next adjacent block. */ next=NextBlock(memory); RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next))); *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) | (*BlockHeader(memory) & ~SizeMask); } *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory); *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit); InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory))); RelinquishSemaphoreInfo(memory_semaphore); #endif return((void *) NULL); }
void SimpleDeadCodeElimination::Execute(Function* function) { StaticList<Instruction*, 512> worklist; Dictionary<Instruction*, bool> inWorklist; // If an instruction is in the worklist. // Try to remove 'store' instructions that have no effect. // The algorithm is really simple, but should catch cases like // arrays initialized with constants that were propagated already. RemoveDeadStores(function); // Try to remove copy/set operations that are unused, // because the aggregates they target are never referenced. RemoveDeadCopyOperations(function); // We process the blocks from last to first, and the instructions in the block // from last to first too; this allows removing more instructions on each // iteration that the usual first-last order. for(auto block = function->LastBlock(); block; block = block->PreviousBlock()) { // If the block is unreachable we remove all instructions from it, // but don't remove the block; this will be handled by the CFG Simplifier, // which knows how to repair the Dominator Tree. if(block->IsUnreachable() && (block->IsEmpty() == false)) { CleanUnreachableBlock(block); continue; } for(auto instr = block->LastInstruction(); instr; instr = instr->PreviousInstruction()) { if(GetSafetyInfo()->IsDefinitelyDead(instr)) { worklist.Add(instr); inWorklist.Add(instr, true); } } } // Process while we have instructions in the worklist. while(worklist.IsNotEmpty()) { auto instr = worklist.RemoveLast(); inWorklist.Remove(instr); // Remove the instruction if it's dead. if(GetSafetyInfo()->IsDefinitelyDead(instr)) { // All the instructions that where used by this one // may be dead now, add them to the worklist. for(int i = 0; i < instr->SourceOpCount(); i++) { auto sourceOp = instr->GetSourceOp(i); // Make sure we don't add an instruction in the worklist twice. if(auto definingInstr = sourceOp->DefiningInstruction()) { if(inWorklist.ContainsKey(definingInstr) == false) { worklist.Add(definingInstr); inWorklist.Add(definingInstr, true); } } } InstructionRemoved(instr); instr->RemoveFromBlock(true /* free */); } } // If there were removed stored we may now have variables // that are not used by any instruction. RemoveDeadVariables(function); }