//Coalesce free blocks if possible static void *coalesce(void *bp) { size_t prev_alloc = block_free(block_prev(get_header(bp))); size_t next_alloc = block_free(block_next(get_header(bp))); size_t size = block_size(get_header(bp)); if(prev_alloc && next_alloc) return bp; else if(prev_alloc && !next_alloc) { size += block_size(block_next(get_header(bp))); PUT(get_header(bp), PACK(size, 0)); PUT(get_footer(bp), PACK(size, 0)); } else if(!prev_alloc && next_alloc) { size += block_size(block_prev(get_header(bp))); PUT(get_header(prev_bp(bp)), PACK(size, 0)); PUT(get_footer(bp), PACK(size, 0)); bp = prev_bp(bp); } else if(!prev_alloc && !next_alloc) { size += block_size(block_next(get_header(bp))) + block_size(block_prev(get_header(bp))); PUT(get_header(prev_bp(bp)), PACK(size, 0)); PUT(get_footer(next_bp(bp)), PACK(size, 0)); bp = prev_bp(bp); } checkheap(1); return bp; }
void WhileStatement::toIR(IRState *irs) { assert(0); // was "lowered" #if 0 Blockx *blx = irs->blx; /* Create a new state, because we need a new continue and break target */ IRState mystate(irs,this); mystate.breakBlock = block_calloc(blx); mystate.contBlock = block_calloc(blx); list_append(&blx->curblock->Bsucc, mystate.contBlock); block_next(blx, BCgoto, mystate.contBlock); incUsage(irs, loc); block_appendexp(mystate.contBlock, condition->toElem(&mystate)); block_next(blx, BCiftrue, NULL); /* curblock is the start of the while loop body */ list_append(&mystate.contBlock->Bsucc, blx->curblock); if (body) body->toIR(&mystate); list_append(&blx->curblock->Bsucc, mystate.contBlock); block_next(blx, BCgoto, mystate.breakBlock); list_append(&mystate.contBlock->Bsucc, mystate.breakBlock); #endif }
void DoStatement::toIR(IRState *irs) { Blockx *blx = irs->blx; IRState mystate(irs,this); mystate.breakBlock = block_calloc(blx); mystate.contBlock = block_calloc(blx); block *bpre = blx->curblock; block_next(blx, BCgoto, NULL); list_append(&bpre->Bsucc, blx->curblock); list_append(&mystate.contBlock->Bsucc, blx->curblock); list_append(&mystate.contBlock->Bsucc, mystate.breakBlock); if (body) body->toIR(&mystate); list_append(&blx->curblock->Bsucc, mystate.contBlock); block_next(blx, BCgoto, mystate.contBlock); incUsage(irs, condition->loc); block_appendexp(mystate.contBlock, condition->toElemDtor(&mystate)); block_next(blx, BCiftrue, mystate.breakBlock); }
void UnrolledLoopStatement::toIR(IRState *irs) { Blockx *blx = irs->blx; IRState mystate(irs, this); mystate.breakBlock = block_calloc(blx); block *bpre = blx->curblock; block_next(blx, BCgoto, NULL); block *bdo = blx->curblock; list_append(&bpre->Bsucc, bdo); block *bdox; size_t dim = statements->dim; for (size_t i = 0 ; i < dim ; i++) { Statement *s = statements->tdata()[i]; if (s != NULL) { mystate.contBlock = block_calloc(blx); s->toIR(&mystate); bdox = blx->curblock; block_next(blx, BCgoto, mystate.contBlock); list_append(&bdox->Bsucc, mystate.contBlock); } } bdox = blx->curblock; block_next(blx, BCgoto, mystate.breakBlock); list_append(&bdox->Bsucc, mystate.breakBlock); }
void visit(UnrolledLoopStatement *s) { Blockx *blx = irs->blx; IRState mystate(irs, s); mystate.breakBlock = block_calloc(blx); block *bpre = blx->curblock; block_next(blx, BCgoto, NULL); block *bdo = blx->curblock; bpre->appendSucc(bdo); block *bdox; size_t dim = s->statements->dim; for (size_t i = 0 ; i < dim ; i++) { Statement *s2 = (*s->statements)[i]; if (s2 != NULL) { mystate.contBlock = block_calloc(blx); Statement_toIR(s2, &mystate); bdox = blx->curblock; block_next(blx, BCgoto, mystate.contBlock); bdox->appendSucc(mystate.contBlock); } } bdox = blx->curblock; block_next(blx, BCgoto, mystate.breakBlock); bdox->appendSucc(mystate.breakBlock); }
void visit(DoStatement *s) { Blockx *blx = irs->blx; IRState mystate(irs,s); mystate.breakBlock = block_calloc(blx); mystate.contBlock = block_calloc(blx); block *bpre = blx->curblock; block_next(blx, BCgoto, NULL); bpre->appendSucc(blx->curblock); mystate.contBlock->appendSucc(blx->curblock); mystate.contBlock->appendSucc(mystate.breakBlock); if (s->_body) Statement_toIR(s->_body, &mystate); blx->curblock->appendSucc(mystate.contBlock); block_next(blx, BCgoto, mystate.contBlock); incUsage(irs, s->condition->loc); block_appendexp(mystate.contBlock, toElemDtor(s->condition, &mystate)); block_next(blx, BCiftrue, mystate.breakBlock); }
void IfStatement::toIR(IRState *irs) { elem *e; Blockx *blx = irs->blx; //printf("IfStatement::toIR('%s')\n", condition->toChars()); IRState mystate(irs, this); // bexit is the block that gets control after this IfStatement is done block *bexit = mystate.breakBlock ? mystate.breakBlock : block_calloc(); incUsage(irs, loc); #if 0 if (match) { /* Generate: * if (match = RTLSYM_IFMATCH(string, pattern)) ... */ assert(condition->op == TOKmatch); e = matchexp_toelem((MatchExp *)condition, &mystate, RTLSYM_IFMATCH); Symbol *s = match->toSymbol(); symbol_add(s); e = el_bin(OPeq, TYnptr, el_var(s), e); } else #endif e = condition->toElemDtor(&mystate); block_appendexp(blx->curblock, e); block *bcond = blx->curblock; block_next(blx, BCiftrue, NULL); list_append(&bcond->Bsucc, blx->curblock); if (ifbody) ifbody->toIR(&mystate); list_append(&blx->curblock->Bsucc, bexit); if (elsebody) { block_next(blx, BCgoto, NULL); list_append(&bcond->Bsucc, blx->curblock); elsebody->toIR(&mystate); list_append(&blx->curblock->Bsucc, bexit); } else list_append(&bcond->Bsucc, bexit); block_next(blx, BCgoto, bexit); }
void visit(ForStatement *s) { //printf("visit(ForStatement)) %u..%u\n", s->loc.linnum, s->endloc.linnum); Blockx *blx = irs->blx; IRState mystate(irs,s); mystate.breakBlock = block_calloc(blx); mystate.contBlock = block_calloc(blx); if (s->_init) Statement_toIR(s->_init, &mystate); block *bpre = blx->curblock; block_next(blx,BCgoto,NULL); block *bcond = blx->curblock; bpre->appendSucc(bcond); mystate.contBlock->appendSucc(bcond); if (s->condition) { incUsage(irs, s->condition->loc); block_appendexp(bcond, toElemDtor(s->condition, &mystate)); block_next(blx,BCiftrue,NULL); bcond->appendSucc(blx->curblock); bcond->appendSucc(mystate.breakBlock); } else { /* No conditional, it's a straight goto */ block_next(blx,BCgoto,NULL); bcond->appendSucc(blx->curblock); } if (s->_body) Statement_toIR(s->_body, &mystate); /* End of the body goes to the continue block */ blx->curblock->appendSucc(mystate.contBlock); block_setLoc(blx->curblock, s->endloc); block_next(blx, BCgoto, mystate.contBlock); if (s->increment) { incUsage(irs, s->increment->loc); block_appendexp(mystate.contBlock, toElemDtor(s->increment, &mystate)); } /* The 'break' block follows the for statement. */ block_next(blx,BCgoto, mystate.breakBlock); }
// Returns a pointer if block of sufficient size is available // will allocate a new block if none are free static void* find_free_block(int index, size_t size){ REQUIRES(0 <= index && index < NUM_FREE_LISTS); void* block; void* current; int new_index = index; while(new_index < NUM_FREE_LISTS){ current = free_lists[new_index]; while(current != NULL){ if(block_size(current) >= size){ // if(new_index > index){ // block = split_block(new_index); // block_mark(block, 0); // return block; // } block = current; block_mark(block, 0); remove_block_from_list(new_index, block); } current = block_next(current); } new_index++; } assert(aligned(block)); block = allocate_block(size); ENSURES(block != NULL); return block; }
/** @fn RBUF_BLOCK *ringbuffer_alloc(RINGBUFFER * rb, int size) * @brief 在ringbuffer中开辟size大小的数据块 * @param rb 环形缓冲区指针. * @param size 需要开辟的数据块的大小 * @return 指向该数据块的指针 */ RBUF_BLOCK *ringbuffer_alloc(RINGBUFFER * rb, int size) { /*调整数据块大小4字节对齐*/ int align_length = ALIGN(sizeof(RBUF_BLOCK) + size); int i; /*循环2次实现一个环形的功能*/ for (i = 0;i < 2;i++) { int free_size = 0; RBUF_BLOCK * blk = block_ptr(rb, rb->head); do { // printf("blk->length:%d\n",blk->length); // printf("blk->offset:%d\n",blk->offset); /*如果当前blk还在使用则返回NULL表示没有剩余的空间可以分配*/ if ((blk->length >= sizeof(RBUF_BLOCK)) && (blk->id >= 0)) { return NULL; } /*回收碎片*/ free_size += ALIGN(blk->length); if (free_size >= align_length) { return _alloc(rb, free_size , size); } blk = block_next(rb, blk); } while(blk); /*如果后面没有足够的空间分配则从头分配*/ rb->head = 0; } return NULL; }
void GotoStatement::toIR(IRState *irs) { Blockx *blx = irs->blx; if (!label->statement) { error("label %s is undefined", label->toChars()); return; } if (tf != label->statement->tf) error("cannot goto forward out of or into finally block"); block *bdest = labelToBlock(loc, blx, label, 1); if (!bdest) return; block *b = blx->curblock; incUsage(irs, loc); if (b->Btry != bdest->Btry) { // Check that bdest is in an enclosing try block for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry) { if (!bt) { //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry); error("cannot goto into try block"); break; } } } list_append(&b->Bsucc,bdest); block_next(blx,BCgoto,NULL); }
void visit(GotoStatement *s) { Blockx *blx = irs->blx; assert(s->label->statement); assert(s->tf == s->label->statement->tf); block *bdest = labelToBlock(irs, s->loc, blx, s->label, 1); if (!bdest) return; block *b = blx->curblock; incUsage(irs, s->loc); b->appendSucc(bdest); block_setLoc(b, s->loc); // Check that bdest is in an enclosing try block for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry) { if (!bt) { //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry); s->error("cannot goto into try block"); break; } } block_next(blx,BCgoto,NULL); }
void GotoDefaultStatement::toIR(IRState *irs) { block *b; Blockx *blx = irs->blx; block *bdest = irs->getDefaultBlock(); b = blx->curblock; // The rest is equivalent to GotoStatement // Adjust exception handler scope index if in different try blocks if (b->Btry != bdest->Btry) { // Check that bdest is in an enclosing try block for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry) { if (!bt) { //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry); error("cannot goto into try block"); break; } } //setScopeIndex(blx, b, bdest->Btry ? bdest->Btry->Bscope_index : -1); } list_append(&b->Bsucc,bdest); incUsage(irs, loc); block_next(blx,BCgoto,NULL); }
/* * Place the block and potentially split the block * Return: Nothing */ static void place(void *block, unsigned int awords) { REQUIRES(awords >= 2 && awords % 2 == 0); REQUIRES(block != NULL); REQUIRES(in_heap(block)); REQUIRES(in_list(block)); unsigned int cwords = block_size(block); //the size of the given freeblock block_delete(block); // delete block from the seg list ENSURES(!in_list(block)); if ((cwords - awords) >= 4) { set_size(block, awords); block_mark(block, ALLOCATED); block = block_next(block); set_size(block, cwords - awords - 2); block_mark(block, FREE); block_insert(block); ENSURES(in_list(block)); } else { set_size(block, cwords); block_mark(block, ALLOCATED); } }
/* * Extends the heap with a new free block * Return: the pointer to the new free block * NULL on error. */ static void *extend_heap(unsigned int words) { REQUIRES(words > 4); uint32_t *block; uint32_t *next; /* Ask for 2 more words for header and footer */ words = (words % 2) ? (words + 1) : words; if (VERBOSE) printf("Extend Words = %d bytes\n", words * 4); if ((long)(block = mem_sbrk(words * WSIZE)) == -1) return NULL; block--; // back step 1 since the last one is the epi block set_size(block, words - 2); block_mark(block, FREE); ENSURES(block != NULL); // New eqilogue block next = block_next(block); set_size(next, 0); *next |= 0x40000000; //block_mark(block_next(block), ALLOCATED); ENSURES(!block_free(next)); ENSURES(block_size(next) == 0); block = coalesce(block); // Coalesce if necessary ENSURES(in_list(block)); return block; }
static struct ringbuffer_block * _alloc(struct ringbuffer * rb, int total_size , int size) { //get start point ,from rb->head on struct ringbuffer_block * blk = block_ptr(rb, rb->head); //get align length int align_length = ALIGN(sizeof(struct ringbuffer_block) + size); //set real length blk->length = sizeof(struct ringbuffer_block) + size; //blk real size ,no align blk->offset = 0; //set length with no align ,cause padding space no need to read blk->next = -1; blk->id = -1; //get next blk struct ringbuffer_block * next = block_next(rb, blk); if (next) { rb->head = block_offset(rb, next); //set head to offset(start) of next blk if (align_length < total_size) { next->length = total_size - align_length; //next blk is the remain space, set length of rest space if (next->length >= sizeof(struct ringbuffer_block)) { next->id = -1; //-1 means blk available } } } else { rb->head = 0; //if no next , means roll back ,head set to 0 } return blk; }
//ring buffer alloc struct ringbuffer_block * ringbuffer_alloc(struct ringbuffer * rb, int size) { //get align size needed int align_length = ALIGN(sizeof(struct ringbuffer_block) + size); int i; for (i=0;i<2;i++) { int free_size = 0; //find start pointer, from rb->head on struct ringbuffer_block * blk = block_ptr(rb, rb->head); //blk is next point of last blk //so blk is next space to use do { //轮转之前不会执行,只有轮转后后可能执行,轮转后遇到不可分配的,应该强行回收 if (blk->length >= sizeof(struct ringbuffer_block) && blk->id >= 0) //id >= 0 means mem in use return NULL; free_size += ALIGN(blk->length); if (free_size >= align_length) { return _alloc(rb, free_size , size); } blk = block_next(rb, blk); //find space available } while(blk); rb->head = 0; //roll back ,do again } return NULL; }
void visit(GotoCaseStatement *s) { Blockx *blx = irs->blx; Label *clabel = getLabel(irs, blx, s->cs); block *bdest = clabel->lblock; block *b = blx->curblock; // The rest is equivalent to GotoStatement // Adjust exception handler scope index if in different try blocks if (b->Btry != bdest->Btry) { // Check that bdest is in an enclosing try block for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry) { if (!bt) { //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry); s->error("cannot goto into try block"); break; } } //setScopeIndex(blx, b, bdest->Btry ? bdest->Btry->Bscope_index : -1); } b->appendSucc(bdest); incUsage(irs, s->loc); block_next(blx,BCgoto,NULL); }
void ForStatement::toIR(IRState *irs) { Blockx *blx = irs->blx; IRState mystate(irs,this); mystate.breakBlock = block_calloc(blx); mystate.contBlock = block_calloc(blx); if (init) init->toIR(&mystate); block *bpre = blx->curblock; block_next(blx,BCgoto,NULL); block *bcond = blx->curblock; list_append(&bpre->Bsucc, bcond); list_append(&mystate.contBlock->Bsucc, bcond); if (condition) { incUsage(irs, condition->loc); block_appendexp(bcond, condition->toElemDtor(&mystate)); block_next(blx,BCiftrue,NULL); list_append(&bcond->Bsucc, blx->curblock); list_append(&bcond->Bsucc, mystate.breakBlock); } else { /* No conditional, it's a straight goto */ block_next(blx,BCgoto,NULL); list_append(&bcond->Bsucc, blx->curblock); } if (body) body->toIR(&mystate); /* End of the body goes to the continue block */ list_append(&blx->curblock->Bsucc, mystate.contBlock); block_next(blx, BCgoto, mystate.contBlock); if (increment) { incUsage(irs, increment->loc); block_appendexp(mystate.contBlock, increment->toElemDtor(&mystate)); } /* The 'break' block follows the for statement. */ block_next(blx,BCgoto, mystate.breakBlock); }
void TryFinallyStatement::toIR(IRState *irs) { //printf("TryFinallyStatement::toIR()\n"); Blockx *blx = irs->blx; #if SEH if (!global.params.is64bit) nteh_declarvars(blx); #endif block *tryblock = block_goto(blx, BCgoto, NULL); int previndex = blx->scope_index; tryblock->Blast_index = previndex; tryblock->Bscope_index = blx->next_index++; blx->scope_index = tryblock->Bscope_index; // Current scope index setScopeIndex(blx,tryblock,tryblock->Bscope_index); blx->tryblock = tryblock; block_goto(blx,BC_try,NULL); IRState bodyirs(irs, this); block *breakblock = block_calloc(blx); block *contblock = block_calloc(blx); tryblock->appendSucc(contblock); contblock->BC = BC_finally; if (body) body->toIR(&bodyirs); blx->tryblock = tryblock->Btry; // back to previous tryblock setScopeIndex(blx,blx->curblock,previndex); blx->scope_index = previndex; block_goto(blx,BCgoto, breakblock); block *finallyblock = block_goto(blx,BCgoto,contblock); assert(finallyblock == contblock); block_goto(blx,BC_finally,NULL); IRState finallyState(irs, this); breakblock = block_calloc(blx); contblock = block_calloc(blx); setScopeIndex(blx, blx->curblock, previndex); if (finalbody) finalbody->toIR(&finallyState); block_goto(blx, BCgoto, contblock); block_goto(blx, BCgoto, breakblock); block *retblock = blx->curblock; block_next(blx,BC_ret,NULL); finallyblock->appendSucc(blx->curblock); retblock->appendSucc(blx->curblock); }
/* * Merge block with adjacent free blocks * Return: the pointer to the new free block */ static void *coalesce(void *block) { REQUIRES(block != NULL); REQUIRES(in_heap(block)); uint32_t *prev_block = block_prev(block); uint32_t *next_block = block_next(block); int prev_free = block_free(prev_block); int next_free = block_free(next_block); unsigned int words = block_size(block); if (prev_free && next_free) { // Case 4, both free block_delete(prev_block); block_delete(next_block); words += block_size(prev_block) + block_size(next_block) + 4; set_size(prev_block, words); block_mark(prev_block, FREE); block = (void *)prev_block; block_insert(block); ENSURES(in_list(block)); } else if (!prev_free && next_free) { // Case 2, next if free block_delete(next_block); words += block_size(next_block) + 2; set_size(block, words); block_mark(block, FREE); block_insert(block); ENSURES(in_list(block)); } else if (prev_free && !next_free) { // Case 3, prev is free block_delete(prev_block); words += block_size(prev_block) + 2; set_size(prev_block, words); block_mark(prev_block, FREE); block = (void *)prev_block; block_insert(block); ENSURES(in_list(block)); } else { // Case 1, both unfree block_insert(block); ENSURES(in_list(block)); return block; } return block; }
//Find the first fit static void *find_first_fit(size_t size) { uint32_t *ptr = (uint32_t *)heap_ptr + 2; unsigned int bsize = block_size(ptr); while(bsize > 0) { if((size <= bsize) && !block_free(ptr)) return (void *)block_mem(ptr); ptr = block_next(ptr); bsize = block_size(ptr); } return NULL; }
int ringbuffer_collect(struct ringbuffer * rb) { int id = _last_id(rb); struct ringbuffer_block *blk = block_ptr(rb, 0); do { if (blk->length >= sizeof(struct ringbuffer_block) && blk->id == id) { blk->id = -1; } blk = block_next(rb, blk); } while(blk); return id; }
void DefaultStatement::toIR(IRState *irs) { Blockx *blx = irs->blx; block *bcase = blx->curblock; block *bdefault = irs->getDefaultBlock(); block_next(blx,BCgoto,bdefault); list_append(&bcase->Bsucc,blx->curblock); if (blx->tryblock != irs->getSwitchBlock()->Btry) error("default cannot be in different try block level from switch"); incUsage(irs, loc); if (statement) statement->toIR(irs); }
void visit(DefaultStatement *s) { Blockx *blx = irs->blx; block *bcase = blx->curblock; block *bdefault = irs->getDefaultBlock(); block_next(blx,BCgoto,bdefault); bcase->appendSucc(blx->curblock); if (blx->tryblock != irs->getSwitchBlock()->Btry) s->error("default cannot be in different try block level from switch"); incUsage(irs, s->loc); if (s->statement) Statement_toIR(s->statement, irs); }
/** @fn int ringbuffer_collect(RINGBUFFER * rb) * @brief 收集最早分配的还在使用的同一id的数据块以便覆盖 * @param rb 环形缓冲区指针 * @return 返回该数据块id */ int ringbuffer_collect(RINGBUFFER * rb) { int id = _last_id(rb); RBUF_BLOCK *blk = block_ptr(rb, 0); do { if (blk->length >= sizeof(RBUF_BLOCK) && blk->id == id) { blk->id = -1; } blk = block_next(rb, blk); } while(blk); return id; }
static int _last_id(struct ringbuffer * rb) { int i; for (i=0;i<2;i++) { struct ringbuffer_block * blk = block_ptr(rb, rb->head); do { if (blk->length >= sizeof(struct ringbuffer_block) && blk->id >= 0) return blk->id; blk = block_next(rb, blk); } while(blk); rb->head = 0; } return -1; }
//Extend the heap static void *extend_heap(size_t words) { //Even number of words to maintain alignment size_t size = (words % 2) ? ((words + 1) * WSIZE) : (words * WSIZE); uint32_t *bp = mem_sbrk(size); if((long)bp == -1) return NULL; PUT(get_header(bp), PACK(size, 0)); PUT(get_footer(bp), PACK(size, 0)); PUT(block_next(get_header(bp)), PACK(0,1)); return coalesce(bp); }
static void remove_block_from_list(int index, void* block){ REQUIRES(0 <= index && index < NUM_FREE_LISTS); void* next = block_next(block); void* prev = block_prev(block); if(free_lists[index] == block) free_lists[index] = next; if(prev != NULL) set_next_pointer(prev, next); if(next != NULL) set_prev_pointer(next, prev); set_next_pointer(block, NULL); set_prev_pointer(block, NULL); }
/** * A block has been placed, it is time for a new block. * Oh... and the timer needs to be reset, I guess.. * params: * game */ void game_next(game_t *game) { assert(game); game_block_reset(game); block_next(game->player); // next block in queue ++game->player; if(game->player >= (game->queue + BLOCK_QUEUE_SIZE)) { game->player = game->queue; } game->timer = 6 * TICKS_PER_SEC; }