Skip to content

Commit 0ec095e

Browse files
anuraagadeadprogram
authored andcommitted
Add -gc=custom option (#3302)
* Add -gc=custom option
1 parent a9b8191 commit 0ec095e

File tree

7 files changed

+67
-6
lines changed

7 files changed

+67
-6
lines changed

compileopts/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func (c *Config) GC() string {
105105
// that can be traced by the garbage collector.
106106
func (c *Config) NeedsStackObjects() bool {
107107
switch c.GC() {
108-
case "conservative", "precise":
108+
case "conservative", "custom", "precise":
109109
for _, tag := range c.BuildTags() {
110110
if tag == "tinygo.wasm" {
111111
return true

compileopts/options.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
)
99

1010
var (
11-
validGCOptions = []string{"none", "leaking", "conservative", "precise"}
11+
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
1212
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
1313
validSerialOptions = []string{"none", "uart", "usb"}
1414
validPrintSizeOptions = []string{"none", "short", "full"}

compileopts/options_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
func TestVerifyOptions(t *testing.T) {
1111

12-
expectedGCError := errors.New(`invalid gc option 'incorrect': valid values are none, leaking, conservative, precise`)
12+
expectedGCError := errors.New(`invalid gc option 'incorrect': valid values are none, leaking, conservative, custom, precise`)
1313
expectedSchedulerError := errors.New(`invalid scheduler option 'incorrect': valid values are none, tasks, asyncify`)
1414
expectedPrintSizeError := errors.New(`invalid size option 'incorrect': valid values are none, short, full`)
1515
expectedPanicStrategyError := errors.New(`invalid panic option 'incorrect': valid values are print, trap`)
@@ -48,6 +48,12 @@ func TestVerifyOptions(t *testing.T) {
4848
GC: "conservative",
4949
},
5050
},
51+
{
52+
name: "GCOptionCustom",
53+
opts: compileopts.Options{
54+
GC: "custom",
55+
},
56+
},
5157
{
5258
name: "InvalidSchedulerOption",
5359
opts: compileopts.Options{

src/internal/task/gc_stack_chain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build (gc.conservative || gc.precise) && tinygo.wasm
1+
//go:build (gc.conservative || gc.custom || gc.precise) && tinygo.wasm
22

33
package task
44

src/internal/task/gc_stack_noop.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build !(gc.conservative || gc.precise) || !tinygo.wasm
1+
//go:build !(gc.conservative || gc.custom || gc.precise) || !tinygo.wasm
22

33
package task
44

src/runtime/gc_custom.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//go:build gc.custom
2+
// +build gc.custom
3+
4+
package runtime
5+
6+
// This GC strategy allows an external GC to be plugged in instead of the builtin
7+
// implementations.
8+
//
9+
// The interface defined in this file is not stable and can be broken at anytime, even
10+
// across minor versions.
11+
//
12+
// runtime.markStack() must be called at the beginning of any GC cycle. //go:linkname
13+
// on a function without a body can be used to access this internal function.
14+
//
15+
// The custom implementation must provide the following functions in the runtime package
16+
// using the go:linkname directive:
17+
//
18+
// - func initHeap()
19+
// - func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
20+
// - func free(ptr unsafe.Pointer)
21+
// - func markRoots(start, end uintptr)
22+
// - func GC()
23+
//
24+
//
25+
// In addition, if targeting wasi, the following functions should be exported for interoperability
26+
// with wasi libraries that use them. Note, this requires the export directive, not go:linkname.
27+
//
28+
// - func malloc(size uintptr) unsafe.Pointer
29+
// - func free(ptr unsafe.Pointer)
30+
// - func calloc(nmemb, size uintptr) unsafe.Pointer
31+
// - func realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer
32+
33+
import (
34+
"unsafe"
35+
)
36+
37+
// initHeap is called when the heap is first initialized at program start.
38+
func initHeap()
39+
40+
// alloc is called to allocate memory. layout is currently not used.
41+
func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
42+
43+
// free is called to explicitly free a previously allocated pointer.
44+
func free(ptr unsafe.Pointer)
45+
46+
// markRoots is called with the start and end addresses to scan for references.
47+
// It is currently only called with the top and bottom of the stack.
48+
func markRoots(start, end uintptr)
49+
50+
// GC is called to explicitly run garbage collection.
51+
func GC()
52+
53+
func setHeapEnd(newHeapEnd uintptr) {
54+
// Heap is in custom GC so ignore for when called from wasm initialization.
55+
}

src/runtime/gc_stack_portable.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build (gc.conservative || gc.precise) && tinygo.wasm
1+
//go:build (gc.conservative || gc.custom || gc.precise) && tinygo.wasm
22

33
package runtime
44

0 commit comments

Comments
 (0)