// Expand or shrink a chunk returned by allocate_chunk(). // The chunk is never moved. // // Returns 0 if fail to expand (shrink will always succeed). Returns old // size if successful. size_t OsMemory_adjust_chunk(address chunk_ptr, size_t new_committed_size) { ChunkInfo* ci = get_chunk_info(chunk_ptr); size_t old_size = ci->size; size_t new_size = page_align_up(new_committed_size); if (new_size <= ci->mmaped_size) { int rv; if (new_size < old_size) { rv = protect_area(chunk_ptr + new_size, old_size - new_size); } else { rv = unprotect_area(chunk_ptr, new_size); } GUARANTEE(rv == 0, "mprotect must succeed"); ci->size = new_size; return old_size; } new_size = page_align_up(new_size - ci->mmaped_size); if (anon_mmap(chunk_ptr + ci->mmaped_size, new_size) == NULL) { return 0; } ci->mmaped_size += new_size; ci->size = ci->mmaped_size; unprotect_area(chunk_ptr, ci->size); return old_size; }
/** Records code chunk, corresponding to longest prefix of instruction sequence, * into buffer [current, end). Changes _instr_ to instruction immediately * following prefix. Returns next position in the buffer, or NULL if there is * not enough space. */ void* record_chunk(void* ctx, instr_t** instr, void* current, void* end) { struct code_chunk_t* chunk; ssize_t max; struct chunk_info_t chunk_info; chunk = current; max = end - current - sizeof(struct code_chunk_t); if(max <= 0) { return NULL; } if(max > UINT8_MAX) { max = UINT8_MAX; } chunk_info = get_chunk_info(ctx, instr, max); if(chunk_info.size == 0) { return NULL; } chunk->pc = (uintptr_t)chunk_info.pc; chunk->size = (uint8_t)chunk_info.size; memcpy(chunk->code, chunk_info.pc, chunk_info.size); return &chunk->code[chunk_info.size]; }
void OsMemory_free_chunk(address chunk_ptr) { ChunkInfo* ci = get_chunk_info(chunk_ptr); jvm_munmap(ci->addr, ci->mmaped_size); release_chunk(chunk_ptr); }