github.com/moontrade/nogc@v0.1.7/tinygc_tinygowasm.go (about) 1 //go:build gc.provided && tinygo.wasm 2 3 package nogc 4 5 import ( 6 "unsafe" 7 ) 8 9 func getCollector() *gc { 10 if collector != nil { 11 return collector 12 } 13 p := AllocZeroed(unsafe.Sizeof(gc{})) 14 collector = (*gc)(p.Unsafe()) 15 initGC(collector, 64) 16 return collector 17 } 18 19 //////////////////////////////////////////////////////////////////////////////////// 20 // GC Instance 21 //////////////////////////////////////////////////////////////////////////////////// 22 23 //go:linkname gcInitHeap runtime.gcInitHeap 24 func gcInitHeap(heapStart, heapEnd uintptr) { 25 if allocator == nil { 26 if gc_TRACE { 27 println("gcInitHeap initAllocator", uint(heapStart), uint(heapEnd)) 28 } 29 initAllocator(heapStart, heapEnd) 30 } else { 31 println("allocator is already initialized") 32 } 33 if gc_TRACE { 34 println("gcInitHeap", uint(heapStart), uint(heapEnd)) 35 } 36 //p := AllocZeroed(unsafe.Sizeof(gc{})) 37 //collector = (*gc)(p.Unsafe()) 38 getCollector() 39 //initGC(&collector, 64) 40 //collector = newGC(64, doMarkGlobals, doMarkStack) 41 } 42 43 //////////////////////////////////////////////////////////////////////////////////// 44 // gcAlloc hook 45 //////////////////////////////////////////////////////////////////////////////////// 46 47 //go:linkname gcAlloc runtime.gcAlloc 48 func gcAlloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer { 49 if gc_TRACE { 50 println("gcAlloc", uint(size), uint(uintptr(layout))) 51 } 52 println("gcAlloc", uint(size), uint(uintptr(layout))) 53 54 //ptr := AllocZeroed(size) 55 ptr := collector.New(size) 56 return unsafe.Pointer(ptr) 57 } 58 59 //go:linkname gcRealloc runtime.gcRealloc 60 func gcRealloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer { 61 if gc_TRACE { 62 println("gcRealloc", uint(uintptr(ptr)), "size", uint(size)) 63 } 64 p := collector.Realloc(uintptr(ptr), size) 65 return unsafe.Pointer(p) 66 } 67 68 //////////////////////////////////////////////////////////////////////////////////// 69 // gcFree hook 70 //////////////////////////////////////////////////////////////////////////////////// 71 72 //go:linkname gcFree runtime.gcFree 73 func gcFree(ptr unsafe.Pointer) { 74 if gc_TRACE { 75 println("gcFree", uint(uintptr(ptr))) 76 } 77 if !collector.Free(uintptr(ptr)) { 78 Free(Pointer(ptr)) 79 } 80 } 81 82 //go:linkname gcRegisterGlobal runtime.gcRegisterGlobal 83 func gcRegisterGlobal(ptr uintptr, tag int) { 84 if gc_TRACE { 85 println("gcRegisterGlobal", uint(ptr), "tag", tag) 86 } 87 switch tag { 88 case 1: 89 getCollector().runqueue = ptr 90 case 2: 91 getCollector().sleepQueue = ptr 92 case 3: 93 //println("gcRegisterGlobal", uint(ptr), "tag", tag) 94 getCollector().currentTask = ptr 95 case 4: 96 getCollector().heapStart = ptr 97 case 5: 98 getCollector().heapEnd = ptr 99 case 6: 100 getCollector().globalsStart = ptr 101 case 7: 102 getCollector().globalsEnd = ptr 103 case 8: 104 getCollector().envArgs = ptr 105 case 9: 106 getCollector().envArgsPointer = ptr 107 } 108 } 109 110 //////////////////////////////////////////////////////////////////////////////////// 111 // gcRun hook 112 //////////////////////////////////////////////////////////////////////////////////// 113 114 //go:linkname gcRun runtime.gcRun 115 func gcRun() { 116 if gc_TRACE { 117 println("gcRun") 118 } 119 //start := time.Now().UnixNano() 120 121 collector.Collect() 122 123 //println("full GC", time.Now().UnixNano()-start) 124 //collector.Print() 125 } 126 127 //go:linkname gcKeepAlive runtime.gcKeepAlive 128 func gcKeepAlive(x interface{}) { 129 if gc_TRACE { 130 println("gcKeepAlive") 131 } 132 } 133 134 //go:linkname gcSetFinalizer runtime.gcSetFinalizer 135 func gcSetFinalizer(obj interface{}, finalizer interface{}) { 136 if gc_TRACE { 137 println("gcSetFinalizer") 138 } 139 } 140 141 //////////////////////////////////////////////////////////////////////////////////// 142 // gcSetHeapEnd hook 143 //////////////////////////////////////////////////////////////////////////////////// 144 145 //go:linkname gcSetHeapEnd runtime.gcSetHeapEnd 146 func gcSetHeapEnd(newHeapEnd uintptr) { 147 if gc_TRACE { 148 println("gcSetHeapEnd", uint(newHeapEnd)) 149 } 150 } 151 152 //////////////////////////////////////////////////////////////////////////////////// 153 // markGlobals hook 154 //////////////////////////////////////////////////////////////////////////////////// 155 156 func doMarkGlobals() { 157 if gc_TRACE { 158 println("doMarkGlobals") 159 } 160 markScheduler() 161 markGlobals() 162 } 163 164 //go:linkname markGlobals runtime.markGlobals 165 func markGlobals() 166 167 //go:linkname gcMarkGlobals runtime.gcMarkGlobals 168 func gcMarkGlobals(start, end uintptr) { 169 if gc_TRACE { 170 println("gcMarkGlobals", uint(start), uint(end)) 171 } 172 //println("gcMarkGlobals", uint(start), uint(end)) 173 collector.markRoots(start, end) 174 } 175 176 //////////////////////////////////////////////////////////////////////////////////// 177 // markStack hook 178 //////////////////////////////////////////////////////////////////////////////////// 179 180 func doMarkStack() { 181 if gc_TRACE { 182 println("doMarkStack") 183 } 184 markStack() 185 } 186 187 //go:linkname gcMarkStackObject runtime.gcMarkStackObject 188 func gcMarkStackObject(start, end uintptr) { 189 if gc_TRACE { 190 println("gcMarkStackObject", uint(start), uint(end)) 191 } 192 193 //println("gcMarkStackObject", uint(start), uint(end)) 194 //for ptr := start; ptr < end; ptr += unsafe.Alignof(ptr) { 195 // p := *(*uintptr)(unsafe.Pointer(ptr)) - gc_ObjectOverhead 196 // println("stack slot", uint(ptr), "value", uint(p)) 197 //} 198 collector.markRoots(start, end) 199 } 200 201 //go:linkname markStack runtime.markStack 202 func markStack() 203 204 //////////////////////////////////////////////////////////////////////////////////// 205 // gcMarkRoots hook 206 //////////////////////////////////////////////////////////////////////////////////// 207 208 //go:linkname gcMarkRoots runtime.gcMarkRoots 209 func gcMarkRoots(start, end uintptr) { 210 if gc_TRACE { 211 println("gcMarkRoots", uint(start), uint(end)) 212 } 213 collector.markRoots(start, end) 214 } 215 216 //////////////////////////////////////////////////////////////////////////////////// 217 // gcMarkRoot hook 218 //////////////////////////////////////////////////////////////////////////////////// 219 220 //go:linkname gcMarkRoot runtime.gcMarkRoot 221 func gcMarkRoot(addr, root uintptr) { 222 if gc_TRACE { 223 println("gcMarkRoot", uint(addr), uint(root)) 224 } 225 if root == 0 { 226 return 227 } 228 collector.markRoot(root) 229 } 230 231 //////////////////////////////////////////////////////////////////////////////////// 232 // markScheduler hook 233 //////////////////////////////////////////////////////////////////////////////////// 234 235 //go:linkname markScheduler runtime.markScheduler 236 func markScheduler() 237 238 //////////////////////////////////////////////////////////////////////////////////// 239 // gcMarkTask hook 240 //////////////////////////////////////////////////////////////////////////////////// 241 242 //go:linkname gcMarkTask runtime.gcMarkTask 243 func gcMarkTask(runQueuePtr, taskPtr uintptr) { 244 if gc_TRACE { 245 println("gcMarkTask", uint(allocator.HeapStart), uint(runQueuePtr), uint(taskPtr)) 246 } 247 println("gcMarkTask", uint(allocator.HeapStart), uint(runQueuePtr), uint(taskPtr)) 248 if taskPtr == 0 { 249 return 250 } 251 collector.markRoot(taskPtr) 252 }