func goGcMalloc(size uintptr) *C.PyObject { // first, lock memLock, and arrange for it to be unlocked on return memLock.Lock() defer memLock.Unlock() g := (*C.PyGC_Head)(unsafe.Pointer(_goMalloc(size + headSize))) C.setGcRefs(g, C._PyGC_REFS_UNTRACKED) p := fromGc(g) // We need to move the original tracked entry to be indexed by the offset // address from fromGc px := uintptr(unsafe.Pointer(p)) gx := uintptr(unsafe.Pointer(g)) allocated[px] = allocated[gx] delete(allocated, gx) // We can't access the internals of the GC Module to manipulate the // generation counts, so we have to use a proxy object instead. We just // create a bare minimum object, initialise it, and then store it away to be // cleaned up later. proxy := C._PyObject_GC_Malloc(C.size_t(baseSize)) if proxy == nil { delete(allocated, px) return nil } C._PyObject_INIT(proxy, c(BaseType)) gcProxies[px] = proxy return p }
//export goGenericAlloc func goGenericAlloc(t unsafe.Pointer, n C.Py_ssize_t) unsafe.Pointer { var obj *C.PyObject typ := newType((*C.PyObject)(t)) size := uintptr(C.__PyObject_VAR_SIZE(c(typ), n)) if typ.IsGc() { obj = goGcMalloc(size) } else { obj = goMalloc(size) } if obj == nil { raise(MemoryError.ErrV(None)) return nil } if typ.o.tp_flags&C.Py_TPFLAGS_HEAPTYPE != 0 { typ.Incref() } if typ.o.tp_itemsize == 0 { C._PyObject_INIT(obj, c(typ)) } else { C._PyObject_INIT_VAR(obj, c(typ), n) } if typ.IsGc() { C.__PyObject_GC_TRACK(obj) } return unsafe.Pointer(obj) }