@@ -3,48 +3,67 @@ import { ERRNO } from "./errors.js";
3
3
import { OS } from "./os.js" ;
4
4
5
5
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 ;
12
7
13
8
export class MemoryLib {
14
9
private memory : VmMemory ;
15
10
private os : OS ;
16
-
17
- private freeSegments : Segment [ ] = [ { address : HEAP_BASE , length : HEAP_SIZE } ] ;
11
+ private freeListPtr : number ;
18
12
19
13
public constructor ( memory : VmMemory , os : OS ) {
20
14
this . memory = memory ;
21
15
this . os = os ;
16
+ this . freeListPtr = HEAP_BASE ;
17
+ this . memory . set ( HEAP_BASE , 0 ) ;
18
+ this . memory . set ( HEAP_BASE + 1 , HEAP_SIZE ) ;
22
19
}
23
20
24
21
alloc ( size : number ) : number {
25
22
if ( size <= 0 ) {
26
23
this . os . sys . error ( ERRNO . ARRAY_SIZE_NOT_POSITIVE ) ;
27
24
return 0 ;
28
25
}
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 ;
37
42
}
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 ;
40
47
}
41
- }
48
+ } while ( blockPtr !== 0 ) ;
49
+
42
50
this . os . sys . error ( ERRNO . HEAP_OVERFLOW ) ;
43
51
return 0 ;
44
52
}
45
53
46
54
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 ) ;
49
68
}
50
69
}
0 commit comments