//------------ Begin of function HillRes::scan -----------// short HillRes::scan(char patternId, char searchPriority, char specialFlag, char findFirst) { err_when(patternId < 1 || patternId > max_pattern_id); // ------- find the range which patternId may exist ------// // find the start of this pattern and next pattern short startBlockIdx = first_block(patternId); short endBlockIdx = first_block(patternId+1); short foundBlockId = 0; short foundCount = 0; for(short j = startBlockIdx; j < endBlockIdx; ++j) { HillBlockInfo *hillBlockInfo = hill_block_info_array+j-1; if( hillBlockInfo->pattern_id == patternId && hillBlockInfo->priority == searchPriority && hillBlockInfo->special_flag == specialFlag) { if( findFirst) return j; if( misc.random(++foundCount) == 0) { foundBlockId = j; } } } return foundBlockId; // not found }
static void load_code_heap(FILE *file, image_header *h, vm_parameters *p) { cell good_size = h->code_size + (1 << 19); if(good_size > p->code_size) p->code_size = good_size; init_code_heap(p->code_size); if(h->code_size != 0) { size_t bytes_read = fread(first_block(&code),1,h->code_size,file); if(bytes_read != h->code_size) { print_string("truncated image: "); print_fixnum(bytes_read); print_string(" bytes read, "); print_cell(h->code_size); print_string(" bytes expected\n"); fatal_error("load_code_heap failed",0); } } code_relocation_base = h->code_relocation_base; build_free_list(&code,h->code_size); }
/* After code GC, all referenced code blocks have status set to B_MARKED, so any which are allocated and not marked can be reclaimed. */ void free_unmarked(F_HEAP *heap) { F_BLOCK *prev = NULL; F_BLOCK *scan = first_block(heap); while(scan) { switch(scan->status) { case B_ALLOCATED: if(prev && prev->status == B_FREE) prev->size += scan->size; else { scan->status = B_FREE; prev = scan; } break; case B_FREE: if(prev && prev->status == B_FREE) prev->size += scan->size; break; case B_MARKED: scan->status = B_ALLOCATED; prev = scan; break; default: critical_error("Invalid scan->status",(CELL)scan); } scan = next_block(heap,scan); } build_free_list(heap,heap->segment->size); }
/* Compute total sum of sizes of free blocks, and size of largest free block */ void heap_usage(F_HEAP *heap, CELL *used, CELL *total_free, CELL *max_free) { *used = 0; *total_free = 0; *max_free = 0; F_BLOCK *scan = first_block(heap); while(scan) { switch(scan->status) { case B_ALLOCATED: *used += scan->size; break; case B_FREE: *total_free += scan->size; if(scan->size > *max_free) *max_free = scan->size; break; default: critical_error("Invalid scan->status",(CELL)scan); } scan = next_block(heap,scan); } }
/* Compute total sum of sizes of free blocks, and size of largest free block */ void heap::heap_usage(cell *used, cell *total_free, cell *max_free) { *used = 0; *total_free = 0; *max_free = 0; heap_block *scan = first_block(); while(scan) { switch(scan->status) { case B_ALLOCATED: *used += scan->size; break; case B_FREE: *total_free += scan->size; if(scan->size > *max_free) *max_free = scan->size; break; default: myvm->critical_error("Invalid scan->status",(cell)scan); } scan = next_block(scan); } }
bool WavpackSource::parseWrapper() { int fd = fileno(m_fp.get()); util::FilePositionSaver saver__(fd); _lseeki64(fd, 0, SEEK_SET); WavpackHeader hdr; if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) return false; if (std::memcmp(hdr.ckID, "wvpk", 4) != 0) return false; if (hdr.ckSize < sizeof(hdr) || hdr.ckSize > 0x1000000) return false; std::vector<char> first_block(hdr.ckSize); _lseeki64(fd, 0, SEEK_SET); if (read(fd, &first_block[0], hdr.ckSize) != hdr.ckSize) return false; void *loc = m_module.GetWrapperLocation(&first_block[0], 0); if (!loc) return false; ptrdiff_t off = static_cast<char *>(loc) - &first_block[0]; _lseeki64(fd, off, SEEK_SET); try { WaveSource src(m_fp, false); memcpy(&m_asbd, &src.getSampleFormat(), sizeof(m_asbd)); return true; } catch (const std::runtime_error &) { return false; } }
/* Save the current image to disk */ bool save_image(const F_CHAR *filename) { FILE* file; F_HEADER h; FPRINTF(stderr,"*** Saving %s...\n",filename); file = OPEN_WRITE(filename); if(file == NULL) { fprintf(stderr,"Cannot open image file: %s\n",strerror(errno)); return false; } F_ZONE *tenured = &data_heap->generations[TENURED]; h.magic = IMAGE_MAGIC; h.version = IMAGE_VERSION; h.data_relocation_base = tenured->start; h.data_size = tenured->here - tenured->start; h.code_relocation_base = code_heap.segment->start; h.code_size = heap_size(&code_heap); h.t = T; h.bignum_zero = bignum_zero; h.bignum_pos_one = bignum_pos_one; h.bignum_neg_one = bignum_neg_one; CELL i; for(i = 0; i < USER_ENV; i++) { if(i < FIRST_SAVE_ENV) h.userenv[i] = F; else h.userenv[i] = userenv[i]; } fwrite(&h,sizeof(F_HEADER),1,file); if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) { fprintf(stderr,"Save data heap failed: %s\n",strerror(errno)); return false; } if(fwrite(first_block(&code_heap),h.code_size,1,file) != 1) { fprintf(stderr,"Save code heap failed: %s\n",strerror(errno)); return false; } if(fclose(file)) { fprintf(stderr,"Failed to close image file: %s\n",strerror(errno)); return false; } return true; }
/* Compute where each block is going to go, after compaction */ cell heap::compute_heap_forwarding() { heap_block *scan = first_block(); char *address = (char *)first_block(); while(scan) { if(scan->type() != FREE_BLOCK_TYPE) { forwarding[scan] = address; address += scan->size(); } scan = next_block(scan); } return (cell)address - seg->start; }
void heap::clear_mark_bits() { heap_block *scan = first_block(); while(scan) { scan->set_marked_p(false); scan = next_block(scan); } }
/* Compute where each block is going to go, after compaction */ cell heap::compute_heap_forwarding(unordered_map<heap_block *,char *> &forwarding) { heap_block *scan = first_block(); char *address = (char *)first_block(); while(scan) { if(scan->status == B_ALLOCATED) { forwarding[scan] = address; address += scan->size; } else if(scan->status == B_MARKED) myvm->critical_error("Why is the block marked?",0); scan = next_block(scan); } return (cell)address - seg->start; }
/* Apply a function to every code block */ void iterate_code_heap(CODE_HEAP_ITERATOR iter) { F_BLOCK *scan = first_block(&code_heap); while(scan) { if(scan->status != B_FREE) iterate_code_heap_step(block_to_compiled(scan),iter); scan = next_block(&code_heap,scan); } }
/* Compute where each block is going to go, after compaction */ CELL compute_heap_forwarding(F_HEAP *heap) { F_BLOCK *scan = first_block(heap); CELL address = (CELL)first_block(heap); while(scan) { if(scan->status == B_ALLOCATED) { scan->forwarding = (F_BLOCK *)address; address += scan->size; } else if(scan->status == B_MARKED) critical_error("Why is the block marked?",0); scan = next_block(heap,scan); } return address - heap->segment->start; }
/* If in the middle of code GC, we have to grow the heap, data GC restarts from scratch, so we have to unmark any marked blocks. */ void heap::unmark_marked() { heap_block *scan = first_block(); while(scan) { if(scan->status == B_MARKED) scan->status = B_ALLOCATED; scan = next_block(scan); } }
/* Called after reading the code heap from the image file, and after code GC. In the former case, we must add a large free block from compiling.base + size to compiling.limit. */ void build_free_list(F_HEAP *heap, CELL size) { F_BLOCK *prev = NULL; F_BLOCK *prev_free = NULL; F_BLOCK *scan = first_block(heap); F_BLOCK *end = (F_BLOCK *)(heap->segment->start + size); /* Add all free blocks to the free list */ while(scan && scan < end) { switch(scan->status) { case B_FREE: update_free_list(heap,prev_free,scan); prev_free = scan; break; case B_ALLOCATED: break; default: critical_error("Invalid scan->status",(CELL)scan); break; } prev = scan; scan = next_block(heap,scan); } /* If there is room at the end of the heap, add a free block. This branch is only taken after loading a new image, not after code GC */ if((CELL)(end + 1) <= heap->segment->end) { end->status = B_FREE; end->next_free = NULL; end->size = heap->segment->end - (CELL)end; /* add final free block */ update_free_list(heap,prev_free,end); } /* This branch is taken if the newly loaded image fits exactly, or after code GC */ else { /* even if there's no room at the end of the heap for a new free block, we might have to jigger it up by a few bytes in case prev + prev->size */ if(prev) prev->size = heap->segment->end - (CELL)prev; /* this is the last free block */ update_free_list(heap,prev_free,NULL); } }
/* If in the middle of code GC, we have to grow the heap, GC restarts from scratch, so we have to unmark any marked blocks. */ void unmark_marked(F_HEAP *heap) { F_BLOCK *scan = first_block(heap); while(scan) { if(scan->status == B_MARKED) scan->status = B_ALLOCATED; scan = next_block(heap,scan); } }
void heap::compact_heap(unordered_map<heap_block *,char *> &forwarding) { heap_block *scan = first_block(); while(scan) { heap_block *next = next_block(scan); if(scan->status == B_ALLOCATED) memmove(forwarding[scan],scan,scan->size); scan = next; } }
// ####### begin Gilbert 28/1 #######// //------------ Begin of function HillRes::locate -----------// short HillRes::locate(char patternId, char subPattern, char searchPriority, char specialFlag) { err_when(patternId < 1 || patternId > max_pattern_id); // ------- find the range which patternId may exist ------// // find the start of this pattern and next pattern short startBlockIdx = first_block(patternId); short endBlockIdx = first_block(patternId+1); for(short j = startBlockIdx; j < endBlockIdx; ++j) { HillBlockInfo *hillBlockInfo = hill_block_info_array+j-1; if( hillBlockInfo->pattern_id == patternId && hillBlockInfo->sub_pattern_id == subPattern && hillBlockInfo->priority == searchPriority && hillBlockInfo->special_flag == specialFlag) { return j; } } return 0; // not found }
void compact_heap(F_HEAP *heap) { F_BLOCK *scan = first_block(heap); while(scan) { F_BLOCK *next = next_block(heap,scan); if(scan->status == B_ALLOCATED && scan != scan->forwarding) memcpy(scan->forwarding,scan,scan->size); scan = next; } }
void heap::compact_heap() { heap_block *scan = first_block(); while(scan) { heap_block *next = next_block(scan); if(scan->type() != FREE_BLOCK_TYPE) memmove(forwarding[scan],scan,scan->size()); scan = next; } }
/* Called after reading the code heap from the image file, and after code GC. In the former case, we must add a large free block from compiling.base + size to compiling.limit. */ void heap::build_free_list(cell size) { heap_block *prev = NULL; clear_free_list(); size = (size + block_size_increment - 1) & ~(block_size_increment - 1); heap_block *scan = first_block(); free_heap_block *end = (free_heap_block *)(seg->start + size); /* Add all free blocks to the free list */ while(scan && scan < (heap_block *)end) { switch(scan->status) { case B_FREE: add_to_free_list((free_heap_block *)scan); break; case B_ALLOCATED: break; default: myvm->critical_error("Invalid scan->status",(cell)scan); break; } prev = scan; scan = next_block(scan); } /* If there is room at the end of the heap, add a free block. This branch is only taken after loading a new image, not after code GC */ if((cell)(end + 1) <= seg->end) { end->status = B_FREE; end->size = seg->end - (cell)end; /* add final free block */ add_to_free_list(end); } /* This branch is taken if the newly loaded image fits exactly, or after code GC */ else { /* even if there's no room at the end of the heap for a new free block, we might have to jigger it up by a few bytes in case prev + prev->size */ if(prev) prev->size = seg->end - (cell)prev; } }
/* The size of the heap, not including the last block if it's free */ cell heap::heap_size() { heap_block *scan = first_block(); while(next_block(scan) != NULL) scan = next_block(scan); /* this is the last block in the heap, and it is free */ if(scan->type() == FREE_BLOCK_TYPE) return (cell)scan - seg->start; /* otherwise the last block is allocated */ else return seg->size; }
/* The size of the heap, not including the last block if it's free */ CELL heap_size(F_HEAP *heap) { F_BLOCK *scan = first_block(heap); while(next_block(heap,scan) != NULL) scan = next_block(heap,scan); /* this is the last block in the heap, and it is free */ if(scan->status == B_FREE) return (CELL)scan - heap->segment->start; /* otherwise the last block is allocated */ else return heap->segment->size; }
INLINE void load_code_heap(FILE *file, F_HEADER *h, F_PARAMETERS *p) { CELL good_size = h->code_size + (1 << 19); if(good_size > p->code_size) p->code_size = good_size; init_code_heap(p->code_size); if(h->code_size != 0 && fread(first_block(&code_heap),h->code_size,1,file) != 1) fatal_error("load_code_heap failed",0); code_relocation_base = h->code_relocation_base; build_free_list(&code_heap,h->code_size); }
/* Save the current image to disk */ bool save_image(const vm_char *filename) { FILE* file; image_header h; file = OPEN_WRITE(filename); if(file == NULL) { print_string("Cannot open image file: "); print_native_string(filename); nl(); print_string(strerror(errno)); nl(); return false; } zone *tenured = &data->generations[data->tenured()]; h.magic = image_magic; h.version = image_version; h.data_relocation_base = tenured->start; h.data_size = tenured->here - tenured->start; h.code_relocation_base = code.seg->start; h.code_size = heap_size(&code); h.t = T; h.bignum_zero = bignum_zero; h.bignum_pos_one = bignum_pos_one; h.bignum_neg_one = bignum_neg_one; for(cell i = 0; i < USER_ENV; i++) h.userenv[i] = (save_env_p(i) ? userenv[i] : F); bool ok = true; if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false; if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) ok = false; if(fwrite(first_block(&code),h.code_size,1,file) != 1) ok = false; if(fclose(file)) ok = false; if(!ok) { print_string("save-image failed: "); print_string(strerror(errno)); nl(); } return ok; }
/* Called after reading the code heap from the image file, and after code GC. In the former case, we must add a large free block from compiling.base + size to compiling.limit. */ void heap::build_free_list(cell size) { heap_block *prev = NULL; clear_free_list(); size = (size + block_size_increment - 1) & ~(block_size_increment - 1); heap_block *scan = first_block(); free_heap_block *end = (free_heap_block *)(seg->start + size); /* Add all free blocks to the free list */ while(scan && scan < (heap_block *)end) { if(scan->type() == FREE_BLOCK_TYPE) add_to_free_list((free_heap_block *)scan); prev = scan; scan = next_block(scan); } /* If there is room at the end of the heap, add a free block. This branch is only taken after loading a new image, not after code GC */ if((cell)(end + 1) <= seg->end) { end->set_marked_p(false); end->set_type(FREE_BLOCK_TYPE); end->set_size(seg->end - (cell)end); /* add final free block */ add_to_free_list(end); } /* This branch is taken if the newly loaded image fits exactly, or after code GC */ else { /* even if there's no room at the end of the heap for a new free block, we might have to jigger it up by a few bytes in case prev + prev->size */ if(prev) prev->set_size(seg->end - (cell)prev); } }
INLINE void load_code_heap(FILE *file, F_HEADER *h, F_PARAMETERS *p) { CELL good_size = h->code_size + (1 << 19); if(good_size > p->code_size) p->code_size = good_size; init_code_heap(p->code_size); if(h->code_size != 0) { long int bytes_read = fread(first_block(&code_heap),1,h->code_size,file); if(bytes_read != h->code_size) { fprintf(stderr,"truncated image: %ld bytes read, %ld bytes expected\n", bytes_read,h->code_size); fatal_error("load_code_heap failed",0); } } code_relocation_base = h->code_relocation_base; build_free_list(&code_heap,h->code_size); }
/* * For any block B_i in the queue, we know that the bsize for * that block is at least (f->length - B_i->col). * * If (f->length - B_0->col > f->max_width) then we can set B_0's * bsize to infinity (PP_MAX_BSIZE), update the csize of the head * token, and remove B_0 from the queue. The head token is ready to be * printed at this point (since its csize, bsize and fsize fields are * known). */ static void flush_wide_blocks(formatter_t *f) { pp_block_t *b; pp_open_token_t *tk, *head; while (!block_queue_is_empty(&f->block_queue)) { b = first_block(&f->block_queue); assert(b->col <= f->length); if (f->length - b->col <= f->max_width) break; /* * b has bsize > max_width: set its bsize to MAX * then remove it from the block queue */ tk = b->token; tk->bsize = PP_MAX_BSIZE; head = f->head_token; if (head != NULL) { // update csize and fsize of the head token head->csize = PP_MAX_BSIZE; if (head->fsize == 0) { head->fsize = PP_MAX_BSIZE; } } // print all queued tokens, until tk flush_tokens(f, tag_open(tk)); // tk becomes the head token assert(ptr_queue_first(&f->token_queue) == tag_open(tk)); f->head_token = tk; if (f->nclosed == f->queue_size) { f->nclosed --; } pop_first_block(&f->block_queue); f->queue_size --; } }
/* Compute total sum of sizes of free blocks, and size of largest free block */ void heap::heap_usage(cell *used, cell *total_free, cell *max_free) { *used = 0; *total_free = 0; *max_free = 0; heap_block *scan = first_block(); while(scan) { cell size = scan->size(); if(scan->type() == FREE_BLOCK_TYPE) { *total_free += size; if(size > *max_free) *max_free = size; } else *used += size; scan = next_block(scan); } }
/* Dump all code blocks for debugging */ void dump_heap(F_HEAP *heap) { CELL size = 0; F_BLOCK *scan = first_block(heap); while(scan) { char *status; switch(scan->status) { case B_FREE: status = "free"; break; case B_ALLOCATED: size += object_size(block_to_compiled(scan)->relocation); status = "allocated"; break; case B_MARKED: size += object_size(block_to_compiled(scan)->relocation); status = "marked"; break; default: status = "invalid"; break; } print_cell_hex((CELL)scan); print_string(" "); print_cell_hex(scan->size); print_string(" "); print_string(status); print_string("\n"); scan = next_block(heap,scan); } print_cell(size); print_string(" bytes of relocation data\n"); }
bool Function::IsFirstBlock(uint32_t block_id) const { return !ordered_blocks_.empty() && *first_block() == block_id; }