VarCell* Context::_newStackCell(uint32_t size, uint32_t alignment) { VarCell* cell = static_cast<VarCell*>(_zoneAllocator.alloc(sizeof(VarCell))); if (cell == nullptr) goto _NoMemory; if (alignment == 0) alignment = BaseContext_getDefaultAlignment(size); if (alignment > 64) alignment = 64; ASMJIT_ASSERT(Utils::isPowerOf2(alignment)); size = Utils::alignTo<uint32_t>(size, alignment); // Insert it sorted according to the alignment and size. { VarCell** pPrev = &_memStackCells; VarCell* cur = *pPrev; while (cur != nullptr) { if ((cur->getAlignment() > alignment) || (cur->getAlignment() == alignment && cur->getSize() > size)) { pPrev = &cur->_next; cur = *pPrev; continue; } break; } cell->_next = cur; cell->_offset = 0; cell->_size = size; cell->_alignment = alignment; *pPrev = cell; _memStackCellsUsed++; _memMaxAlign = Utils::iMax<uint32_t>(_memMaxAlign, alignment); _memStackTotal += size; } return cell; _NoMemory: _compiler->setLastError(kErrorNoHeapMemory); return nullptr; }
Error Context::resolveCellOffsets() { VarCell* varCell = _memVarCells; VarCell* stackCell = _memStackCells; uint32_t stackAlignment = 0; if (stackCell != nullptr) stackAlignment = stackCell->getAlignment(); uint32_t pos64 = 0; uint32_t pos32 = pos64 + _mem64ByteVarsUsed * 64; uint32_t pos16 = pos32 + _mem32ByteVarsUsed * 32; uint32_t pos8 = pos16 + _mem16ByteVarsUsed * 16; uint32_t pos4 = pos8 + _mem8ByteVarsUsed * 8 ; uint32_t pos2 = pos4 + _mem4ByteVarsUsed * 4 ; uint32_t pos1 = pos2 + _mem2ByteVarsUsed * 2 ; uint32_t stackPos = pos1 + _mem1ByteVarsUsed; uint32_t gapAlignment = stackAlignment; uint32_t gapSize = 0; // TODO: Not used! if (gapAlignment) Utils::alignDiff(stackPos, gapAlignment); stackPos += gapSize; uint32_t gapPos = stackPos; uint32_t allTotal = stackPos; // Vars - Allocated according to alignment/width. while (varCell != nullptr) { uint32_t size = varCell->getSize(); uint32_t offset = 0; switch (size) { case 1: offset = pos1 ; pos1 += 1 ; break; case 2: offset = pos2 ; pos2 += 2 ; break; case 4: offset = pos4 ; pos4 += 4 ; break; case 8: offset = pos8 ; pos8 += 8 ; break; case 16: offset = pos16; pos16 += 16; break; case 32: offset = pos32; pos32 += 32; break; case 64: offset = pos64; pos64 += 64; break; default: ASMJIT_NOT_REACHED(); } varCell->setOffset(static_cast<int32_t>(offset)); varCell = varCell->_next; } // Stack - Allocated according to alignment/width. while (stackCell != nullptr) { uint32_t size = stackCell->getSize(); uint32_t alignment = stackCell->getAlignment(); uint32_t offset; // Try to fill the gap between variables/stack first. if (size <= gapSize && alignment <= gapAlignment) { offset = gapPos; gapSize -= size; gapPos -= size; if (alignment < gapAlignment) gapAlignment = alignment; } else { offset = stackPos; stackPos += size; allTotal += size; } stackCell->setOffset(offset); stackCell = stackCell->_next; } _memAllTotal = allTotal; return kErrorOk; }