diff --git a/src/runtime/gc_boehm.go b/src/runtime/gc_boehm.go index 66a78697f..02ee0aaa9 100644 --- a/src/runtime/gc_boehm.go +++ b/src/runtime/gc_boehm.go @@ -165,6 +165,9 @@ func libgc_size(ptr uintptr) uintptr //export GC_push_all func libgc_push_all(bottom, top uintptr) +//export GC_push_all_eager +func libgc_push_all_eager(bottom, top uintptr) + //export GC_push_all_stack func libgc_push_all_stack(bottom, top uintptr) diff --git a/src/runtime/gc_globals_range.go b/src/runtime/gc_globals_range.go index 5702e2b1c..2f7d0ac73 100644 --- a/src/runtime/gc_globals_range.go +++ b/src/runtime/gc_globals_range.go @@ -5,31 +5,12 @@ package runtime import "unsafe" func markGlobals() { - rangeCount := gcGlobalRootCount() - if rangeCount == 0 { - return + for i := uintptr(0); i < gcGlobalRootCount(); i++ { + addr := gcGlobalRoot(uintptr(i)) + // GC_push_all queues one range per call and overflows Boehm's mark + // stack for programs with thousands of roots. Scan each range now. + libgc_push_all_eager(uintptr(addr), uintptr(addr)+gcGlobalRootSize(i)) } - - var rootCount uintptr - for i := uintptr(0); i < rangeCount; i++ { - rootCount += gcGlobalRootSize(i) / unsafe.Sizeof(uintptr(0)) - } - - // markRoots only accepts a range, so copy all global pointers into - // contiguous scratch space for marking. - roots := unsafe.Slice((*uintptr)(gcGlobalRootValues()), rootCount) - var rootIndex uintptr - for i := uintptr(0); i < rangeCount; i++ { - addr := gcGlobalRoot(i) - size := gcGlobalRootSize(i) - for offset := uintptr(0); offset < size; offset += unsafe.Sizeof(uintptr(0)) { - roots[rootIndex] = *(*uintptr)(unsafe.Add(addr, offset)) - rootIndex++ - } - } - - start := uintptr(unsafe.Pointer(&roots[0])) - markRoots(start, start+rootCount*unsafe.Sizeof(roots[0])) } // These functions are generated by the compiler from the pointer layouts of @@ -37,4 +18,3 @@ func markGlobals() { func gcGlobalRootCount() uintptr func gcGlobalRoot(index uintptr) unsafe.Pointer func gcGlobalRootSize(index uintptr) uintptr -func gcGlobalRootValues() unsafe.Pointer diff --git a/transform/testdata/gc-stackslots.ll b/transform/testdata/gc-stackslots.ll index 912051901..2ec36367f 100644 --- a/transform/testdata/gc-stackslots.ll +++ b/transform/testdata/gc-stackslots.ll @@ -19,8 +19,6 @@ declare ptr @runtime.gcGlobalRoot(i32) declare i32 @runtime.gcGlobalRootSize(i32) -declare ptr @runtime.gcGlobalRootValues() - ; Generic function that returns a pointer (that must be tracked). define ptr @getPointer() { ret ptr @someGlobal diff --git a/transform/testdata/gc-stackslots.out.ll b/transform/testdata/gc-stackslots.out.ll index 5fdad3f6a..b3fc586e5 100644 --- a/transform/testdata/gc-stackslots.out.ll +++ b/transform/testdata/gc-stackslots.out.ll @@ -9,7 +9,6 @@ target triple = "wasm32-unknown-unknown-wasm" @ptrArrayGlobal = global [8 x ptr] zeroinitializer @constantPtrGlobal = constant ptr @someGlobal @runtime.gcGlobalRoots = internal constant [4 x { ptr, i32 }] [{ ptr, i32 } { ptr @ptrGlobal, i32 4 }, { ptr, i32 } { ptr @structGlobal, i32 4 }, { ptr, i32 } { ptr getelementptr (i8, ptr @structGlobal, i32 8), i32 8 }, { ptr, i32 } { ptr @ptrArrayGlobal, i32 32 }] -@runtime.gcGlobalRootValueArray = internal global [12 x i32] zeroinitializer declare void @runtime.trackPointer(ptr nocapture readonly) @@ -36,11 +35,6 @@ entry: ret i32 %3 } -define ptr @runtime.gcGlobalRootValues() { -entry: - ret ptr @runtime.gcGlobalRootValueArray -} - define ptr @getPointer() { ret ptr @someGlobal }