Skip to content

Commit cb3c44b

Browse files
Edward PalmerDavidSouther
authored andcommitted
Make memory and string behave like the hack versions would.
TESTED=StringTest works without Output.hack being in dir (with a String that has the same var ordering) and Pong from Chatper 9 plays.
1 parent 5bdfa09 commit cb3c44b

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

simulator/src/vm/os/memory.ts

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,67 @@ import { ERRNO } from "./errors.js";
33
import { OS } from "./os.js";
44

55
const HEAP_BASE = 2048;
6-
const HEAP_SIZE = 14336;
7-
8-
interface Segment {
9-
address: number;
10-
length: number;
11-
}
6+
const HEAP_SIZE = 14334;
127

138
export class MemoryLib {
149
private memory: VmMemory;
1510
private os: OS;
16-
17-
private freeSegments: Segment[] = [{ address: HEAP_BASE, length: HEAP_SIZE }];
11+
private freeListPtr: number;
1812

1913
public constructor(memory: VmMemory, os: OS) {
2014
this.memory = memory;
2115
this.os = os;
16+
this.freeListPtr = HEAP_BASE;
17+
this.memory.set(HEAP_BASE, 0);
18+
this.memory.set(HEAP_BASE + 1, HEAP_SIZE);
2219
}
2320

2421
alloc(size: number): number {
2522
if (size <= 0) {
2623
this.os.sys.error(ERRNO.ARRAY_SIZE_NOT_POSITIVE);
2724
return 0;
2825
}
29-
for (let i = 0; i < this.freeSegments.length; i++) {
30-
const seg = this.freeSegments[i];
31-
if (seg.length >= size) {
32-
const address = seg.address;
33-
seg.address += size + 1;
34-
seg.length -= size + 1;
35-
if (seg.length === 0) {
36-
this.freeSegments.splice(i, 1);
26+
27+
let blockPtr = this.freeListPtr;
28+
do {
29+
const nextFreeList = this.memory.get(blockPtr);
30+
const blockSize = this.memory.get(blockPtr + 1);
31+
if (blockSize >= size + 2) {
32+
// We can fit this required size and overhead in this block.
33+
this.memory.set(blockPtr + 1, size);
34+
35+
const newBlockPtr = blockPtr + 2 + size;
36+
const newBlockSize = blockSize - size - 2;
37+
this.memory.set(newBlockPtr, nextFreeList);
38+
this.memory.set(newBlockPtr + 1, newBlockSize);
39+
if (this.freeListPtr === blockPtr) {
40+
// Move freelist pointer to the new block.
41+
this.freeListPtr = newBlockPtr;
3742
}
38-
this.memory.set(address, size); // save the segment size for deallocation
39-
return address + 1;
43+
return blockPtr + 2;
44+
} else {
45+
// We can't fit this required size and overhead in this block.
46+
blockPtr = nextFreeList;
4047
}
41-
}
48+
} while (blockPtr !== 0);
49+
4250
this.os.sys.error(ERRNO.HEAP_OVERFLOW);
4351
return 0;
4452
}
4553

4654
deAlloc(address: number) {
47-
const size = this.memory.get(address - 1);
48-
this.freeSegments.push({ address: address - 1, length: size + 1 });
55+
const deallocBlockPtr = address - 2;
56+
// This will be the last block in the free list.
57+
this.memory.set(deallocBlockPtr, 0);
58+
59+
let blockPtr = this.freeListPtr;
60+
do {
61+
const nextBlockPtr = this.memory.get(blockPtr);
62+
if (nextBlockPtr === 0) {
63+
this.memory.set(blockPtr, deallocBlockPtr);
64+
return;
65+
}
66+
blockPtr = nextBlockPtr;
67+
} while (blockPtr !== 0);
4968
}
5069
}

simulator/src/vm/os/string.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@ export class StringLib {
3434
if (size < 0) {
3535
this.os.sys.error(ERRNO.STRING_LENGTH_NEG);
3636
}
37-
const pointer = this.os.memory.alloc(size + 2); // +2 to save length, maxLength fields
37+
const pointer = this.os.memory.alloc(size + 3); // +3 to save length, maxLength, charArray Ptr
3838
if (this.os.sys.halted) {
3939
// alloc returned with an error
4040
return 0;
4141
}
4242

4343
this.memory.set(pointer, size); // set maxLength = size
4444
this.memory.set(pointer + 1, 0); // set length = 0
45+
this.memory.set(pointer + 2, this.os.memory.alloc(size)); // set charArrayPtr.
4546
return pointer;
4647
}
4748

@@ -61,20 +62,24 @@ export class StringLib {
6162
this.memory.set(pointer + 1, length);
6263
}
6364

65+
private charArrayPointer(pointer: number) {
66+
return this.memory.get(pointer + 2);
67+
}
68+
6469
charAt(pointer: number, index: number) {
6570
if (index < 0 || index >= this.length(pointer)) {
6671
this.os.sys.error(ERRNO.GET_CHAR_INDEX_OUT_OF_BOUNDS);
6772
return 0;
6873
}
69-
return this.memory.get(pointer + index + 2); // +2 to skip the length fields
74+
return this.memory.get(this.charArrayPointer(pointer) + index);
7075
}
7176

7277
setCharAt(pointer: number, index: number, value: number) {
7378
if (index < 0 || index >= this.length(pointer)) {
7479
this.os.sys.error(ERRNO.SET_CHAR_INDEX_OUT_OF_BOUNDS);
7580
return;
7681
}
77-
this.memory.set(pointer + index + 2, value);
82+
this.memory.set(this.charArrayPointer(pointer) + index, value);
7883
}
7984

8085
// This returns the string pointer to allow compilation of string literals as described in the book,

0 commit comments

Comments
 (0)