Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: user defined heap size #27

Merged
merged 5 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@
"autocomplete": "node ./scripts/updateAutocompleteDocs.js",
"build_sicp_package": "./scripts/build_sicp_package.sh",
"publish_sicp_package": "./scripts/publish_sicp_package.sh",
"benchmark": "jest --runInBand --testPathPattern='.*benchmark.*' --testPathIgnorePatterns='/dist/'",
"prepare": "husky install"
"benchmark": "jest --runInBand --testPathPattern='.*benchmark.*' --testPathIgnorePatterns='/dist/'"
},
"devDependencies": {
"@types/jest": "^29.0.0",
Expand Down
4 changes: 2 additions & 2 deletions src/go-slang/ece.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { PREDECLARED_FUNCTIONS, PREDECLARED_IDENTIFIERS } from './lib/predeclare
import { Scheduler } from './scheduler'
import { BuiltinOp, CallExpression, Instruction, NodeType, SourceFile } from './types'

export function evaluate(program: SourceFile, slangContext: SlangContext): Value {
export function evaluate(program: SourceFile, heapSize: number, slangContext: SlangContext): Value {
const scheduler = new Scheduler(slangContext)

const C = new Stack<Instruction | HeapAddress>()
Expand All @@ -18,7 +18,7 @@ export function evaluate(program: SourceFile, slangContext: SlangContext): Value
// `SourceFile` is the root node of the AST which has latest (monotonically increasing) uid of all AST nodes
// Therefore, the next uid to be used to track AST nodes is the uid of SourceFile + 1
const A = new AstMap((program.uid as number) + 1)
const H = new Heap(A, scheduler)
const H = new Heap(A, scheduler, heapSize)

// inject predeclared functions into the global environment
const B = new Map<number, (...args: any[]) => any>()
Expand Down
4 changes: 2 additions & 2 deletions src/go-slang/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { resolvedErrorPromise } from '../runner'
import { evaluate } from './ece'
import { SourceFile } from './types'

export async function goRunner(program: any, context: Context): Promise<Result> {
const value = evaluate(program as SourceFile, context)
export async function goRunner(program: any, heapSize: number, context: Context): Promise<Result> {
const value = evaluate(program as SourceFile, heapSize, context)
if (context.errors.length > 0) {
return resolvedErrorPromise
}
Expand Down
8 changes: 4 additions & 4 deletions src/go-slang/lib/heap/config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/* Set of default configurations for the heap used in the Go ECE */

// The default size of the heap in words
// Total heap size (in bytes) = DEFAULT_HEAP_SIZE * WORD_SIZE
export const DEFAULT_HEAP_SIZE = 4096 // in words

// The smallest addressable unit in the heap
// We can think of it as the heap containing N number of words, each of size WORD_SIZE
export const WORD_SIZE = 8 // in bytes

// The default size of the heap in words
// Total heap size (in bytes)
export const DEFAULT_HEAP_SIZE = 4096 * WORD_SIZE

// The byte offset to the size of a heap object within a tagged pointer
export const SIZE_OFFSET = 5 // in bytes
11 changes: 7 additions & 4 deletions src/go-slang/lib/heap/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ export class Heap {
// NOTE: this is hacky and should be refactored
private scheduler: Scheduler

constructor(astMap: AstMap, scheduler: Scheduler, n_words?: number) {
constructor(astMap: AstMap, scheduler: Scheduler, heapSize: number = DEFAULT_HEAP_SIZE) {
this.astMap = astMap
this.scheduler = scheduler

const totalBytes = (n_words ?? DEFAULT_HEAP_SIZE) * WORD_SIZE
this.memory = new DataView(new ArrayBuffer(totalBytes))
console.log(`[Heap]: Initializing heap with size ${heapSize} bytes.`) // DEBUG
this.memory = new DataView(new ArrayBuffer(heapSize))

const buddyAllocSize = Math.ceil(Math.log2(totalBytes))
const buddyAllocSize = Math.ceil(Math.log2(heapSize))

this.buddyBlocks = Array.from({ length: buddyAllocSize + 1 }, () => new Set())
// initialize the block with the maximum size (= size of the entire heap)
Expand Down Expand Up @@ -382,11 +382,14 @@ export class Heap {
}
}

let _totalFreedWords = 0 // DEBUG
this.buddyBlockMap.forEach((_, addr) => {
if (!activeHeapAddresses.has(addr) && this.tag(addr) !== PointerTag.AstNode) {
_totalFreedWords += this.size(addr) + 1
this.buddyFree(addr)
}
})
console.log(`[Heap]: GC freed ${_totalFreedWords * WORD_SIZE} bytes of memory.`) // DEBUG

// retry allocation
alloc_heap_addr = this.buddyAlloc((size + 1) * WORD_SIZE)
Expand Down
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface IOptions {
executionMethod: ExecutionMethod
variant: Variant
originalMaxExecTime: number
heapSize: number
useSubst: boolean
isPrelude: boolean
throwInfiniteLoops: boolean
Expand Down Expand Up @@ -234,7 +235,8 @@ export async function runFilesInContext(
if (program === null) {
return resolvedErrorPromise
}
return goRunner(program, context)
const { heapSize } = options
return goRunner(program, heapSize!, context)
}

if (
Expand Down
1 change: 1 addition & 0 deletions src/runner/sourceRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const DEFAULT_SOURCE_OPTIONS: Readonly<IOptions> = {
executionMethod: 'auto',
variant: Variant.DEFAULT,
originalMaxExecTime: 1000,
heapSize: 32768,
useSubst: false,
isPrelude: false,
throwInfiniteLoops: true,
Expand Down
Loading