Пример #1
0
QTextFrame *QTextDocumentPrivate::insertFrame(int start, int end, const QTextFrameFormat &format)
{
    Q_ASSERT(start >= 0 && start < length());
    Q_ASSERT(end >= 0 && end < length());
    Q_ASSERT(start <= end || end == -1);

    if (start != end && frameAt(start) != frameAt(end))
        return 0;

    beginEditBlock();

    QTextFrame *frame = qobject_cast<QTextFrame *>(createObject(format));
    Q_ASSERT(frame);

    // #### using the default block and char format below might be wrong
    int idx = formats.indexForFormat(QTextBlockFormat());
    QTextCharFormat cfmt;
    cfmt.setObjectIndex(frame->objectIndex());
    int charIdx = formats.indexForFormat(cfmt);

    insertBlock(QTextBeginningOfFrame, start, idx, charIdx, QTextUndoCommand::MoveCursor);
    insertBlock(QTextEndOfFrame, ++end, idx, charIdx, QTextUndoCommand::KeepCursor);

    frame->d_func()->fragment_start = find(start).n;
    frame->d_func()->fragment_end = find(end).n;

    insert_frame(frame);

    endEditBlock();

    return frame;
}
Пример #2
0
void QTextDocumentPrivate::init()
{
    rtFrame = 0;
    framesDirty = false;

    bool undoState = undoEnabled;
    undoEnabled = false;
    initialBlockCharFormatIndex = formats.indexForFormat(QTextCharFormat());
    insertBlock(0, formats.indexForFormat(QTextBlockFormat()), formats.indexForFormat(QTextCharFormat()));
    undoEnabled = undoState;
    modified = false;
    modifiedState = 0;
}
Пример #3
0
/**
 * Free a memory block in an expanded heap
 */
void
MEMFreeToExpHeap(ExpandedHeap *heap, void *block)
{
   ScopedSpinLock lock(&heap->lock);
   auto base = mem::untranslate(block);

   if (!base) {
      return;
   }

   if (base < heap->bottom || base >= heap->top) {
      gLog->warn("FreeToExpHeap outside heap region; {:08x} not within {:08x}-{:08x}", base, heap->bottom, heap->top);
      return;
   }

   // Get the block header
   base = base - static_cast<uint32_t>(sizeof(ExpandedHeapBlock));

   // Remove used blocked
   auto usedBlock = make_virtual_ptr<ExpandedHeapBlock>(base);
   auto addr = usedBlock->addr;
   auto size = usedBlock->size;
   eraseBlock(heap->usedBlockList, usedBlock);

   // Create free block
   auto freeBlock = make_virtual_ptr<ExpandedHeapBlock>(addr);
   freeBlock->addr = addr;
   freeBlock->size = size;
   insertBlock(heap->freeBlockList, freeBlock);

   // Merge with next free if contiguous
   auto nextFree = freeBlock->next;

   if (nextFree && nextFree->addr == freeBlock->addr + freeBlock->size) {
      freeBlock->size += nextFree->size;
      eraseBlock(heap->freeBlockList, nextFree);
   }

   // Merge with previous free if contiguous
   auto prevFree = freeBlock->prev;

   if (prevFree && freeBlock->addr == prevFree->addr + prevFree->size) {
      prevFree->size += freeBlock->size;
      eraseBlock(heap->freeBlockList, freeBlock);
   }
}
Пример #4
0
void StorageSetOrJoinBase::restoreFromFile(const String & file_path)
{
    ReadBufferFromFile backup_buf(file_path);
    CompressedReadBuffer compressed_backup_buf(backup_buf);
    NativeBlockInputStream backup_stream(compressed_backup_buf, 0);

    backup_stream.readPrefix();
    while (Block block = backup_stream.read())
        insertBlock(block);
    backup_stream.readSuffix();

    /// TODO Add speed, compressed bytes, data volume in memory, compression ratio ... Generalize all statistics logging in project.
    LOG_INFO(&Logger::get("StorageSetOrJoinBase"), std::fixed << std::setprecision(2)
        << "Loaded from backup file " << file_path << ". "
        << backup_stream.getProfileInfo().rows << " rows, "
        << backup_stream.getProfileInfo().bytes / 1048576.0 << " MiB. "
        << "State has " << getSize() << " unique rows.");
}
Пример #5
0
void StorageSetOrJoinBase::restoreFromFile(const String & file_path)
{
	ReadBufferFromFile backup_buf(file_path);
	CompressedReadBuffer compressed_backup_buf(backup_buf);
	NativeBlockInputStream backup_stream(compressed_backup_buf);

	backup_stream.readPrefix();
	while (Block block = backup_stream.read())
		insertBlock(block);
	backup_stream.readSuffix();

	/// TODO Добавить скорость, сжатые байты, объём данных в памяти, коэффициент сжатия... Обобщить всё логгирование статистики в проекте.
	LOG_INFO(&Logger::get("StorageSetOrJoinBase"), std::fixed << std::setprecision(2)
		<< "Loaded from backup file " << file_path << ". "
		<< backup_stream.getInfo().rows << " rows, "
		<< backup_stream.getInfo().bytes / 1048576.0 << " MiB. "
		<< "State has " << getSize() << " unique rows.");
}
Пример #6
0
static void
replaceBlock(virtual_ptr<ExpandedHeapBlock> &head, virtual_ptr<ExpandedHeapBlock> old, virtual_ptr<ExpandedHeapBlock> block)
{
   if (!old) {
      insertBlock(head, block);
   } else {
      if (head == old) {
         head = block;
      } else {
         old->prev->next = block;
      }

      if (old->next) {
         old->next->prev = block;
      }

      block->next = old->next;
      block->prev = old->prev;
   }
}
Пример #7
0
void
MEMFreeToExpHeap(ExpandedHeap *heap, void *address)
{
   ScopedSpinLock lock(&heap->lock);
   auto base = gMemory.untranslate(address);

   if (!base) {
      return;
   }

   // Get the block header
   base = base - static_cast<uint32_t>(sizeof(ExpandedHeapBlock));

   // Remove used blocked
   auto usedBlock = make_p32<ExpandedHeapBlock>(base);
   auto addr = usedBlock->addr;
   auto size = usedBlock->size;
   eraseBlock(heap->usedBlockList, usedBlock);

   // Create free block
   auto freeBlock = make_p32<ExpandedHeapBlock>(addr);
   freeBlock->addr = addr;
   freeBlock->size = size;
   insertBlock(heap->freeBlockList, freeBlock);

   // Merge with next free if contiguous
   auto nextFree = freeBlock->next;

   if (nextFree && nextFree->addr == freeBlock->addr + freeBlock->size) {
      freeBlock->size += nextFree->size;
      eraseBlock(heap->freeBlockList, nextFree);
   }

   // Merge with previous free if contiguous
   auto prevFree = freeBlock->prev;

   if (prevFree && freeBlock->addr == prevFree->addr + prevFree->size) {
      prevFree->size += freeBlock->size;
      eraseBlock(heap->freeBlockList, freeBlock);
   }
}
Пример #8
0
static void
releaseMemory(virt_ptr<MEMExpHeap> heap,
              virt_ptr<uint8_t> memStart,
              virt_ptr<uint8_t> memEnd)
{
   decaf_check(memEnd - memStart >= sizeof(MEMExpHeapBlock) + 4);

   // Fill the released memory with debug data if needed
   if (heap->header.flags & MEMHeapFlags::DebugMode) {
      auto fillVal = MEMGetFillValForHeap(MEMHeapFillType::Freed);
      std::memset(memStart.get(), fillVal, memEnd - memStart);
   }

   // Find the preceeding block to the memory we are releasing
   virt_ptr<MEMExpHeapBlock> prevBlock = nullptr;
   virt_ptr<MEMExpHeapBlock> nextBlock = heap->freeList.head;

   for (auto block = heap->freeList.head; block; block = block->next) {
      if (getBlockMemStart(block) < memStart) {
         prevBlock = block;
         nextBlock = block->next;
      } else if (block >= prevBlock) {
         break;
      }
   }

   virt_ptr<MEMExpHeapBlock> freeBlock = nullptr;
   if (prevBlock) {
      // If there is a previous block, we need to check if we
      //  should just steal that block rather than making one.
      auto prevMemEnd = getBlockMemEnd(prevBlock);

      if (memStart == prevMemEnd) {
         // Previous block absorbs the new memory
         prevBlock->blockSize += static_cast<uint32_t>(memEnd - memStart);

         // Our free block becomes the previous one
         freeBlock = prevBlock;
      }
   }

   if (!freeBlock) {
      // We did not steal the previous block to free into,
      //  we need to allocate our own here.
      freeBlock = virt_cast<MEMExpHeapBlock *>(memStart);
      freeBlock->attribs = MEMExpHeapBlockAttribs::get(0);
      freeBlock->blockSize = static_cast<uint32_t>((memEnd - memStart) - sizeof(MEMExpHeapBlock));
      freeBlock->next = nullptr;
      freeBlock->prev = nullptr;
      freeBlock->tag = FreeTag;

      insertBlock(virt_addrof(heap->freeList), prevBlock, freeBlock);
   }

   if (nextBlock) {
      // If there is a next block, we need to possibly merge it down
      //  into this one.
      auto nextBlockStart = getBlockMemStart(nextBlock);

      if (nextBlockStart == memEnd) {
         // The next block needs to be merged into the freeBlock, as they
         //  are directly adjacent to each other in memory.
         auto nextBlockEnd = getBlockMemEnd(nextBlock);
         freeBlock->blockSize += static_cast<uint32_t>(nextBlockEnd - nextBlockStart);

         removeBlock(virt_addrof(heap->freeList), nextBlock);
      }
   }
}
Пример #9
0
static virt_ptr<MEMExpHeapBlock>
createUsedBlockFromFreeBlock(virt_ptr<MEMExpHeap> heap,
                             virt_ptr<MEMExpHeapBlock> freeBlock,
                             uint32_t size,
                             uint32_t alignment,
                             MEMExpHeapDirection dir)
{
   auto expHeapAttribs = heap->attribs.value();
   auto freeBlockAttribs = freeBlock->attribs.value();

   auto freeBlockPrev = freeBlock->prev;
   auto freeMemStart = getBlockMemStart(freeBlock);
   auto freeMemEnd = getBlockMemEnd(freeBlock);

   // Free blocks should never have alignment...
   decaf_check(!freeBlockAttribs.alignment());
   removeBlock(virt_addrof(heap->freeList), freeBlock);

   // Find where we are going to start
   auto alignedDataStart = virt_ptr<uint8_t> { };

   if (dir == MEMExpHeapDirection::FromStart) {
      alignedDataStart = align_up(freeMemStart + sizeof(MEMExpHeapBlock), alignment);
   } else if (dir == MEMExpHeapDirection::FromEnd) {
      alignedDataStart = align_down(freeMemEnd - size, alignment);
   } else {
      decaf_abort("Unexpected ExpHeap direction");
   }

   // Grab the block header pointer and validate everything is sane
   auto alignedBlock = virt_cast<MEMExpHeapBlock *>(alignedDataStart) - 1;
   decaf_check(alignedDataStart - sizeof(MEMExpHeapBlock) >= freeMemStart);
   decaf_check(alignedDataStart + size <= freeMemEnd);

   // Calculate the alignment waste
   auto topSpaceRemain = (alignedDataStart - freeMemStart) - sizeof(MEMExpHeapBlock);
   auto bottomSpaceRemain = static_cast<uint32_t>((freeMemEnd - alignedDataStart) - size);

   if (expHeapAttribs.reuseAlignSpace() || dir == MEMExpHeapDirection::FromEnd) {
      // If the user wants to reuse the alignment space, or we allocated from the bottom,
      //  we should try to release the top space back to the heap free list.
      if (topSpaceRemain > sizeof(MEMExpHeapBlock) + 4) {
         // We have enough room to put some of the memory back to the free list
         freeBlock = virt_cast<MEMExpHeapBlock *>(freeMemStart);
         freeBlock->attribs = MEMExpHeapBlockAttribs::get(0);
         freeBlock->blockSize = static_cast<uint32_t>(topSpaceRemain - sizeof(MEMExpHeapBlock));
         freeBlock->next = nullptr;
         freeBlock->prev = nullptr;
         freeBlock->tag = FreeTag;

         insertBlock(virt_addrof(heap->freeList), freeBlockPrev, freeBlock);
         topSpaceRemain = 0;
      }
   }

   if (expHeapAttribs.reuseAlignSpace() || dir == MEMExpHeapDirection::FromStart) {
      // If the user wants to reuse the alignment space, or we allocated from the top,
      //  we should try to release the bottom space back to the heap free list.
      if (bottomSpaceRemain > sizeof(MEMExpHeapBlock) + 4) {
         // We have enough room to put some of the memory back to the free list
         freeBlock = virt_cast<MEMExpHeapBlock *>(freeMemEnd - bottomSpaceRemain);
         freeBlock->attribs = MEMExpHeapBlockAttribs::get(0);
         freeBlock->blockSize = static_cast<uint32_t>(bottomSpaceRemain - sizeof(MEMExpHeapBlock));
         freeBlock->next = nullptr;
         freeBlock->prev = nullptr;
         freeBlock->tag = FreeTag;

         insertBlock(virt_addrof(heap->freeList), freeBlockPrev, freeBlock);
         bottomSpaceRemain = 0;
      }
   }

   // Update the structure with the new allocation
   alignedBlock->attribs = MEMExpHeapBlockAttribs::get(0)
      .alignment(static_cast<uint32_t>(topSpaceRemain))
      .allocDir(dir);
   alignedBlock->blockSize = size + bottomSpaceRemain;
   alignedBlock->prev = nullptr;
   alignedBlock->next = nullptr;
   alignedBlock->tag = UsedTag;

   insertBlock(virt_addrof(heap->usedList), nullptr, alignedBlock);

   if (heap->header.flags & MEMHeapFlags::ZeroAllocated) {
      memset(alignedDataStart, 0, size);
   } else if (heap->header.flags & MEMHeapFlags::DebugMode) {
      auto fillVal = MEMGetFillValForHeap(MEMHeapFillType::Allocated);
      memset(alignedDataStart, fillVal, size);
   }

   return alignedBlock;
}
Пример #10
0
/* dfs:
 *
 * Current scheme adds articulation point to first non-trivial child
 * block. If none exists, it will be added to its parent's block, if
 * non-trivial, or else given its own block.
 *
 * FIX:
 * This should be modified to:
 *  - allow user to specify which block gets a node, perhaps on per-node basis.
 *  - if an articulation point is not used in one of its non-trivial blocks,
 *    dummy edges should be added to preserve biconnectivity
 *  - turn on user-supplied blocks.
 *
 */
static void dfs(Agraph_t * g, Agnode_t * n, circ_state * state, int isRoot)
{
    Agedge_t *e;
    Agnode_t *curtop;

    LOWVAL(n) = VAL(n) = state->orderCount++;

    stackPush(state->bcstack, n);

    for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
	Agnode_t *neighbor = e->head;
	if (neighbor == n)
	    neighbor = e->tail;

	if (neighbor == PARENT(n))
	    continue;

	if (VAL(neighbor)) {
	    LOWVAL(n) = min_value(LOWVAL(n), VAL(neighbor));
	    continue;
	}
	if (!stackCheck(state->bcstack, n)) {
	    stackPush(state->bcstack, n);
	}

	PARENT(neighbor) = n;
	curtop = top(state->bcstack);
	dfs(g, neighbor, state, 0);

	LOWVAL(n) = min_value(LOWVAL(n), LOWVAL(neighbor));
	if (LOWVAL(neighbor) >= VAL(n)) {
	    block_t *block = NULL;
	    Agnode_t *np;
	    if (top(state->bcstack) != curtop)
		do {
		    np = stackPop(state->bcstack);
		    if (!BCDONE(np)) {
			if (!block)
			    block = makeBlock(g, state);
			addNode(block, np);
		    }
		} while (np != n);
	    if (block) {	/* If block != NULL, it's not empty */
		if (isRoot && (BLOCK(n) == block))
		    insertBlock(&state->bl, block);
		else
		    appendBlock(&state->bl, block);
	    }
	    if ((LOWVAL(n) < VAL(n)) && (!stackCheck(state->bcstack, n))) {
		stackPush(state->bcstack, n);
	    }
	}
    }
    if ((LOWVAL(n) == VAL(n)) && !BCDONE(n)) {
	block_t *block = makeBlock(g, state);
	stackPop(state->bcstack);
	addNode(block, n);
	if (isRoot)
	    insertBlock(&state->bl, block);
	else
	    appendBlock(&state->bl, block);
    }
}
Пример #11
0
/* find_blocks:
 */
static void find_blocks(Agraph_t * g, circ_state * state)
{
    Agnode_t *n;
    Agnode_t *root = NULL;
    block_t *rootBlock = NULL;
    blocklist_t ublks;
#ifdef USER_BLOCKS
    graph_t *clust_subg;
    graph_t *mg;
    edge_t *me;
    node_t *mm;
    int isRoot;
#endif

    initBlocklist(&ublks);

    /*      check to see if there is a node which is set to be the root
     */
    if (state->rootname) {
	root = agfindnode(g, state->rootname);
    }
    if (!root && state->N_root) {
	for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	    if (late_bool(ORIGN(n), state->N_root, 0)) {
		root = n;
		break;
	    }
	}
    }
#ifdef USER_BLOCKS
    /* process clusters first */
    /* by construction, all subgraphs are blocks and are non-empty */
    mm = g->meta_node;
    mg = mm->graph;
    for (me = agfstout(mg, mm); me; me = agnxtout(mg, me)) {
	block_t *block;

	clust_subg = agusergraph(me->head);

	isRoot = 0;
	block = mkBlock(clust_subg);
	/* block = makeBlock(g, state); */
	for (n = agfstnode(clust_subg); n; n = agnxtnode(clust_subg, n)) {
	    if (!BCDONE(n)) {	/* test not necessary if blocks disjoint */
		SET_BCDONE(n);
		BLOCK(n) = block;
		if (n == root)
		    isRoot = 1;
	    }
	}
	if (isRoot) {
	    /* Assume blocks are disjoint, so don't check if rootBlock is
	     * already assigned.
	     */
	    rootBlock = block;
	    insertBlock(&state->bl, block);
	} else {
	    appendBlock(&state->bl, block);
	}
    }
    ublks.first = state->bl.first;
    ublks.last = state->bl.last;
#endif

    if (!root)
	root = agfstnode(g);
    dfs(g, root, state, !rootBlock);

#ifdef USER_BLOCKS
    /* If g has user-supplied blocks, it may be disconnected.
     * We then fall into the following ugly loop.
     * We are guaranteed !VISITED(n) and PARENT(n) has been
     * set to a visited node.
     */
    if (ublks.first) {
	while (n = findUnvisited(&ublks)) {
	    dfs(g, n, state, 0);
	}
    }
#endif
}
Пример #12
0
t_cflow_Graph * createFlowGraph(t_list *instructions)
{
   t_cflow_Graph *result;
   t_basic_block *bblock;
   t_list *current_element;
   t_cflow_Node *current_node;
   t_axe_instruction *current_instr;
   int startingNode;
   int endingNode;

   /* initialize the global variable `cflow_errorcode' */
   cflow_errorcode = CFLOW_OK;
   
   /* preconditions */
   if (instructions == NULL){
      cflow_errorcode = CFLOW_INVALID_PROGRAM_INFO;
      return NULL;
   }
   
   /* alloc memory for a new control flow graph */
   result = allocGraph();
   if (result == NULL)
      return NULL;

   /* set the starting basic block */
   bblock = NULL;

   /* initialize the current element */
   current_element = instructions;
   while(current_element != NULL)
   {
      /* retrieve the current instruction */
      current_instr = (t_axe_instruction *) LDATA(current_element);
      assert(current_instr != NULL);

      if (isLoadInstruction(current_instr))
      {
         current_element = LNEXT(current_element);
         continue;
      }
         
      /* create a new node for the current basic block */
      current_node = allocNode(result, current_instr);
      if (current_node == NULL){
         finalizeGraph(result);
         return NULL;
      }

      /* test if the current instruction will start or end a block */
      startingNode = isStartingNode(current_instr);
      endingNode = isEndingNode(current_instr);

      if (startingNode || bblock == NULL)
      {
         /* alloc a new basic block */
         bblock = allocBasicBlock();
         if (bblock == NULL) {
            finalizeGraph(result);
            finalizeNode(current_node);
            return NULL;
         }

         /* add the current instruction to the newly created
          * basic block */
         insertNode(bblock, current_node);
         if (cflow_errorcode != CFLOW_OK) {
            finalizeGraph(result);
            finalizeNode(current_node);
            finalizeBasicBlock(bblock);
            return NULL;
         }

         /* add the new basic block to the control flow graph */
         insertBlock(result, bblock);
         if (cflow_errorcode != CFLOW_OK) {
            finalizeGraph(result);
            finalizeNode(current_node);
            finalizeBasicBlock(bblock);
            return NULL;
         }
      }
      else
      {
         /* add the current instruction to the current
          * basic block */
         insertNode(bblock, current_node);
         if (cflow_errorcode != CFLOW_OK) {
            finalizeGraph(result);
            finalizeNode(current_node);
            return NULL;
         }
      }

      if (endingNode)
         bblock = NULL;

      /* retrieve the next element */
      current_element = LNEXT(current_element);
   }

   /* update the basic blocks chain */
   updateFlowGraph(result);
   if (cflow_errorcode != CFLOW_OK) {
      finalizeGraph(result);
      return NULL;
   }

   /*return the graph */
   return result;
}
Пример #13
0
void ControlFlowAnalysis::BasicBlocks()
{
    for(auto i = _blockStarts.begin(); i != _blockStarts.end(); ++i)
    {
        uint start = *i;
        if(!IsValidAddress(start))
            continue;
        uint nextStart = _base + _size;
        auto next = std::next(i);
        if(next != _blockStarts.end())
            nextStart = *next;
        for(uint addr = start, prevaddr = 0; addr < _base + _size;)
        {
            prevaddr = addr;
            if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER))
            {
                if(_cp.InGroup(CS_GRP_RET) || _cp.GetId() == X86_INS_INT3)
                {
                    insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
                    break;
                }
                else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop())
                {
                    uint dest1 = GetReferenceOperand();
                    uint dest2 = _cp.GetId() != X86_INS_JMP ? addr + _cp.Size() : 0;
                    insertBlock(BasicBlock(start, addr, dest1, dest2));
                    insertParent(dest1, start);
                    insertParent(dest2, start);
                    break;
                }
                addr += _cp.Size();
            }
            else
                addr++;
            if(addr == nextStart)   //special case handling overlapping blocks
            {
                insertBlock(BasicBlock(start, prevaddr, 0, nextStart));
                insertParent(nextStart, start);
                break;
            }
        }
    }
    _blockStarts.clear();

#ifdef _WIN64
    int count = 0;
    EnumerateFunctionRuntimeEntries64([&](PRUNTIME_FUNCTION Function)
    {
        const uint funcAddr = _moduleBase + Function->BeginAddress;
        const uint funcEnd = _moduleBase + Function->EndAddress;

        // If within limits...
        if(funcAddr >= _base && funcAddr < _base + _size)
            _functionStarts.insert(funcAddr);
        count++;
        return true;
    });
    dprintf("%u functions from the exception directory...\n", count);
#endif // _WIN64

    dprintf("%u basic blocks, %u function starts detected...\n", _blocks.size(), _functionStarts.size());
}
Пример #14
0
/**
 * Allocate aligned memory from an expanded heap
 *
 * Sets the memory block group ID to the current active group ID.
 * If alignment is negative the memory is allocated from the top of the heap.
 * If alignment is positive the memory is allocated from the bottom of the heap.
 */
void *
MEMAllocFromExpHeapEx(ExpandedHeap *heap, uint32_t size, int alignment)
{
   ScopedSpinLock lock(&heap->lock);
   virtual_ptr<ExpandedHeapBlock> freeBlock, usedBlock;
   auto direction = MEMExpHeapDirection::FromBottom;
   uint32_t base;

   if (alignment < 0) {
      alignment = -alignment;
      direction = MEMExpHeapDirection::FromTop;
   }

   // Add size for block header and alignment
   uint32_t originalSize = size;
   size += sizeof(ExpandedHeapBlock);
   size += alignment;

   if (heap->mode == MEMExpHeapMode::FirstFree) {
      if (direction == MEMExpHeapDirection::FromBottom) {
         // Find first block large enough from bottom of heap
         for (auto block = heap->freeBlockList; block; block = block->next) {
            if (block->size < size) {
               continue;
            }

            freeBlock = block;
            break;
         }
      } else {  // direction == MEMExpHeapDirection::FromTop
         // Find first block large enough from top of heap
         for (auto block = getTail(heap->freeBlockList); block; block = block->prev) {
            if (block->size < size) {
               continue;
            }

            freeBlock = block;
            break;
         }
      }
   } else if (heap->mode == MEMExpHeapMode::NearestSize) {
      uint32_t nearestSize = -1;

      if (direction == MEMExpHeapDirection::FromBottom) {
         // Find block nearest in size from bottom of heap
         for (auto block = heap->freeBlockList; block; block = block->next) {
            if (block->size < size) {
               continue;
            }

            if (block->size - size < nearestSize) {
               nearestSize = block->size - size;
               freeBlock = block;
            }
         }
      } else {  // direction == MEMExpHeapDirection::FromTop
         // Find block nearest in size from top of heap
         for (auto block = getTail(heap->freeBlockList); block; block = block->prev) {
            if (block->size < size) {
               continue;
            }

            if (block->size - size < nearestSize) {
               nearestSize = block->size - size;
               freeBlock = block;
            }
         }
      }
   }

   if (!freeBlock) {
      gLog->error("MEMAllocFromExpHeapEx failed, no free block found for size {:08x} ({:08x}+{:x}+{:x})", size, originalSize, sizeof(ExpandedHeapBlock), alignment);
      MEMiDumpExpHeap(heap);
      return nullptr;
   }

   if (direction == MEMExpHeapDirection::FromBottom) {
      // Reduce freeblock size
      base = freeBlock->addr;
      freeBlock->size -= size;

      if (freeBlock->size < sMinimumBlockSize) {
         // Absorb free block as it is too small
         size += freeBlock->size;
         eraseBlock(heap->freeBlockList, freeBlock);
      } else {
         auto freeSize = freeBlock->size;

         // Replace free block
         auto old = freeBlock;
         freeBlock = make_virtual_ptr<ExpandedHeapBlock>(base + size);
         freeBlock->addr = base + size;
         freeBlock->size = freeSize;
         replaceBlock(heap->freeBlockList, old, freeBlock);
      }
   } else {  // direction == MEMExpHeapDirection::FromTop
      // Reduce freeblock size
      freeBlock->size -= size;
      base = freeBlock->addr + freeBlock->size;

      if (freeBlock->size < sMinimumBlockSize) {
         // Absorb free block as it is too small
         size += freeBlock->size;
         eraseBlock(heap->freeBlockList, freeBlock);
      }
   }

   // Create a new used block
   auto aligned = align_up(base + static_cast<uint32_t>(sizeof(ExpandedHeapBlock)), alignment);
   usedBlock = make_virtual_ptr<ExpandedHeapBlock>(aligned - static_cast<uint32_t>(sizeof(ExpandedHeapBlock)));
   usedBlock->addr = base;
   usedBlock->size = size;
   usedBlock->group = heap->group;
   usedBlock->direction = direction;
   insertBlock(heap->usedBlockList, usedBlock);
   return make_virtual_ptr<void>(aligned);
}
Пример #15
0
int QTextDocumentPrivate::insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation op)
{
    return insertBlock(QChar::ParagraphSeparator, pos, blockFormat, charFormat, op);
}