-
Notifications
You must be signed in to change notification settings - Fork 45
[WIP] Embedded device GC #1286
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
base: main
Are you sure you want to change the base?
[WIP] Embedded device GC #1286
Conversation
PR Review Complete ✅I've conducted a comprehensive review of PR #1286 focusing on code quality, potential bugs, improvements, architecture decisions, and documentation consistency. Todo List:
SummaryThis PR introduces significant enhancements for ESP32 baremetal runtime support, including comprehensive libc integration and cross-compilation improvements. The changes are well-structured and follow good software engineering practices. Architecture Assessment ⭐⭐⭐⭐⭐Excellent architectural decisions:
Code Quality Review✅ Strengths
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Sweep goes through all memory and frees unmarked memory. | ||
// It returns how many bytes are free in the heap after the sweep. | ||
func sweep() (freeBytes uintptr) { | ||
freeCurrentObject := false | ||
var freed uint64 | ||
for block := gcBlock(0); block < endBlock; block++ { | ||
switch block.state() { | ||
case blockStateHead: | ||
// Unmarked head. Free it, including all tail blocks following it. | ||
block.markFree() | ||
freeCurrentObject = true | ||
gcFrees++ | ||
freed++ | ||
case blockStateTail: | ||
if freeCurrentObject { | ||
// This is a tail object following an unmarked head. | ||
// Free it now. | ||
block.markFree() | ||
freed++ | ||
} | ||
case blockStateMark: | ||
// This is a marked object. The next tail blocks must not be freed, | ||
// but the mark bit must be removed so the next GC cycle will | ||
// collect this object if it is unreferenced then. | ||
block.unmark() | ||
freeCurrentObject = false | ||
case blockStateFree: | ||
freeBytes += bytesPerBlock | ||
} | ||
} | ||
gcFreedBlocks += freed | ||
freeBytes += uintptr(freed) * bytesPerBlock | ||
return | ||
} | ||
|
||
// dumpHeap can be used for debugging purposes. It dumps the state of each heap | ||
// block to standard output. | ||
func dumpHeap() { | ||
println("heap:") | ||
for block := gcBlock(0); block < endBlock; block++ { | ||
switch block.state() { | ||
case blockStateHead: | ||
print("*") | ||
case blockStateTail: | ||
print("-") | ||
case blockStateMark: | ||
print("#") | ||
default: // free | ||
print("·") | ||
} | ||
if block%64 == 63 || block+1 == endBlock { | ||
println() | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//go:linkname _heapStart _heapStart | ||
var _heapStart [0]byte | ||
|
||
//go:linkname _heapEnd _heapEnd | ||
var _heapEnd [0]byte | ||
|
||
//go:linkname _globals_start _globals_start | ||
var _globals_start [0]byte | ||
|
||
//go:linkname _globals_end _globals_end | ||
var _globals_end [0]byte |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE: current _heapStart
_heapEnd
_globals_start
_globals_end
is define at targets/esp32.app.elf.ld
// Mark phase: mark all reachable objects, recursively. | ||
gcMarkReachable() | ||
|
||
finishMark() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE: when baremetal && hasScheduler
will have another logic around finishMark()
52df58c
to
dba50fb
Compare
No description provided.