// This file is part of www.nand2tetris.org // and the book "The Elements of Computing Systems" // by Nisan and Schocken, MIT Press. // File name: projects/12/Memory.jack /** * This library provides two services: direct access to the computer's main * memory (RAM), and allocation and recycling of memory blocks. The Hack RAM * consists of 32,768 words, each holding a 16-bit binary number. */ class Memory { static Array ram; static Array heap; static int freeList; static int heapBottom; /** Initializes the class. */ function void init() { let ram = 0; let heap = 2048; // heapBase let heapBottom = 16384; let freeList = heap; let heap[0] = heapBottom - heap; // length of first block let heap[1] = 0; // next pointer return; } /** Returns the RAM value at the given address. */ function int peek(int address) { return ram[address]; } /** Sets the RAM value at the given address to the given value. */ function void poke(int address, int value) { let ram[address] = value; return; } /** Finds an available RAM block of the given size and returns * a reference to its base address. */ function int alloc(int size) { var int curr, next, len; var int block; let curr = freeList; // Search for a block with enough space (size + 1 for header) while (~(curr = 0)) { let len = ram[curr]; // Check if block is large enough (size + 1 for header) // Ideally we also want to leave at least 2 words for the free block itself to remain valid if (len > (size + 2)) { // Carve from the end of the block let ram[curr] = len - (size + 1); // Reduce free block size let block = curr + ram[curr]; // Base of new block (including header) let ram[block] = size + 1; // Set allocated block size (including header) return block + 1; // Return user pointer } let curr = ram[curr + 1]; // Next block } return 0; // Out of memory } /** De-allocates the given object (cast as an array) by making * it available for future allocations. */ function void deAlloc(Array o) { var int block; let block = o - 1; // Get header // Append to head of freeList let ram[block + 1] = freeList; let freeList = block; return; } }