static void ensure_room_for(struct json_builder *json, int count) { int offset, size, new_size; if (has_room_for(json, count)) return; offset = json->write-json->buffer; size = json->end-json->buffer; new_size = next_size_that_fits(size, count + offset); json->buffer = realloc(json->buffer, new_size); json->write = json->buffer + offset; json->end = json->buffer + new_size; }
static bool block_is_full (StgCompactNFDataBlock *block) { bdescr *bd; // We consider a block full if we could not fit // an entire closure with 7 payload items // (this leaves a slop of 64 bytes at most, but // it avoids leaving a block almost empty to fit // a large byte array, while at the same time // it avoids trying to allocate a large closure // in a chain of almost empty blocks) bd = Bdescr((StgPtr)block); return (!has_room_for(bd,7)); }
void * allocateForCompact (Capability *cap, StgCompactNFData *str, StgWord sizeW) { StgPtr to; StgWord next_size; StgCompactNFDataBlock *block; bdescr *bd; ASSERT(str->nursery != NULL); ASSERT(str->hp > Bdescr((P_)str->nursery)->start); ASSERT(str->hp <= Bdescr((P_)str->nursery)->start + Bdescr((P_)str->nursery)->blocks * BLOCK_SIZE_W); retry: if (str->hp + sizeW < str->hpLim) { to = str->hp; str->hp += sizeW; return to; } bd = Bdescr((P_)str->nursery); bd->free = str->hp; // We know it doesn't fit in the nursery // if it is a large object, allocate a new block if (sizeW > LARGE_OBJECT_THRESHOLD/sizeof(W_)) { next_size = BLOCK_ROUND_UP(sizeW*sizeof(W_) + sizeof(StgCompactNFData)); block = compactAppendBlock(cap, str, next_size); bd = Bdescr((P_)block); to = bd->free; bd->free += sizeW; return to; } // move the nursery past full blocks if (block_is_full (str->nursery)) { do { str->nursery = str->nursery->next; } while (str->nursery && block_is_full(str->nursery)); if (str->nursery == NULL) { str->nursery = compactAppendBlock(cap, str, str->autoBlockW * sizeof(W_)); } bd = Bdescr((P_)str->nursery); str->hp = bd->free; str->hpLim = bd->start + bd->blocks * BLOCK_SIZE_W; goto retry; } // try subsequent blocks for (block = str->nursery->next; block != NULL; block = block->next) { bd = Bdescr((P_)block); if (has_room_for(bd,sizeW)) { to = bd->free; bd->free += sizeW; return to; } } // If all else fails, allocate a new block of the right size. next_size = stg_max(str->autoBlockW * sizeof(StgWord), BLOCK_ROUND_UP(sizeW * sizeof(StgWord) + sizeof(StgCompactNFDataBlock))); block = compactAppendBlock(cap, str, next_size); bd = Bdescr((P_)block); to = bd->free; bd->free += sizeW; return to; }