1 //go:build (gc.conservative || gc.custom || gc.precise || gc.boehm) && moxie.wasm
2 3 package runtime
4 5 import (
6 "internal/task"
7 "runtime/volatile"
8 "unsafe"
9 )
10 11 func gcMarkReachable() {
12 markStack()
13 findGlobals(markRoots)
14 }
15 16 //go:extern runtime.stackChainStart
17 var stackChainStart *stackChainObject
18 19 type stackChainObject struct {
20 parent *stackChainObject
21 numSlots uintptr
22 }
23 24 // markStack marks all root pointers found on the stack.
25 //
26 // - Goroutine stacks are heap allocated and always reachable in some way
27 // (for example through internal/task.currentTask) so they will always be
28 // scanned.
29 // - The system stack (aka startup stack) is not heap allocated, so even
30 // though it may be referenced it will not be scanned by default.
31 //
32 // The compiler also inserts code to store all globals in a chain via
33 // stackChainStart. Luckily we don't need to scan these, as these globals are
34 // stored on the goroutine stack and are therefore already getting scanned.
35 func markStack() {
36 // Hack to force LLVM to consider stackChainStart to be live.
37 // Without this hack, loads and stores may be considered dead and objects on
38 // the stack might not be correctly tracked. With this volatile load, LLVM
39 // is forced to consider stackChainStart (and everything it points to) as
40 // live.
41 volatile.LoadUint32((*uint32)(unsafe.Pointer(&stackChainStart)))
42 43 // Scan the system stack.
44 var sysSP uintptr
45 if task.OnSystemStack() {
46 // We are on the system stack.
47 // Use the current stack pointer.
48 sysSP = getCurrentStackPointer()
49 } else {
50 // We are in a goroutine.
51 // Use the saved stack pointer.
52 sysSP = savedStackPointer
53 }
54 markRoots(sysSP, stackTop)
55 }
56 57 // trackPointer is a stub function call inserted by the compiler during IR
58 // construction. Calls to it are later replaced with regular stack bookkeeping
59 // code.
60 func trackPointer(ptr, alloca unsafe.Pointer)
61 62 // swapStackChain swaps the stack chain.
63 // This is called from internal/task when switching goroutines.
64 func swapStackChain(dst **stackChainObject) {
65 *dst, stackChainStart = stackChainStart, *dst
66 }
67 68 func gcResumeWorld() {
69 // Nothing to do here (single threaded).
70 }
71