memory.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. // Copyright 2017 The Memory Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package memory implements a memory allocator.
  5. //
  6. // Build status
  7. //
  8. // available at https://modern-c.appspot.com/-/builder/?importpath=modernc.org%2fmemory
  9. //
  10. // Changelog
  11. //
  12. // 2017-10-03 Added alternative, unsafe.Pointer-based API.
  13. //
  14. // Package memory implements a memory allocator.
  15. //
  16. // Changelog
  17. //
  18. // 2017-10-03 Added alternative, unsafe.Pointer-based API.
  19. //
  20. // Benchmarks
  21. //
  22. // AMD Ryzen 9 3900X 12-Core Processor × 24
  23. //
  24. // jnml@3900x:~/src/modernc.org/memory$ date ; go version ; go test -run @ -bench . -benchmem |& tee log
  25. // Fri Nov 20 17:23:04 CET 2020
  26. // go version go1.15.5 linux/amd64
  27. // goos: linux
  28. // goarch: amd64
  29. // pkg: modernc.org/memory
  30. // BenchmarkFree16-24 141188362 8.26 ns/op 0 B/op 0 allocs/op
  31. // BenchmarkFree32-24 100000000 11.4 ns/op 0 B/op 0 allocs/op
  32. // BenchmarkFree64-24 67160647 18.3 ns/op 0 B/op 0 allocs/op
  33. // BenchmarkCalloc16-24 60612698 19.8 ns/op 0 B/op 0 allocs/op
  34. // BenchmarkCalloc32-24 47968105 23.8 ns/op 0 B/op 0 allocs/op
  35. // BenchmarkCalloc64-24 40752181 28.6 ns/op 0 B/op 0 allocs/op
  36. // BenchmarkGoCalloc16-24 66487354 17.8 ns/op 16 B/op 1 allocs/op
  37. // BenchmarkGoCalloc32-24 56009206 21.2 ns/op 32 B/op 1 allocs/op
  38. // BenchmarkGoCalloc64-24 52086571 23.4 ns/op 64 B/op 1 allocs/op
  39. // BenchmarkMalloc16-24 113943390 10.2 ns/op 0 B/op 0 allocs/op
  40. // BenchmarkMalloc32-24 113520471 10.2 ns/op 0 B/op 0 allocs/op
  41. // BenchmarkMalloc64-24 108787056 10.7 ns/op 0 B/op 0 allocs/op
  42. // BenchmarkUintptrFree16-24 146110286 7.94 ns/op 0 B/op 0 allocs/op
  43. // BenchmarkUintptrFree32-24 93052707 12.0 ns/op 0 B/op 0 allocs/op
  44. // BenchmarkUintptrFree64-24 69805262 17.3 ns/op 0 B/op 0 allocs/op
  45. // BenchmarkUintptrCalloc16-24 85282725 13.7 ns/op 0 B/op 0 allocs/op
  46. // BenchmarkUintptrCalloc32-24 66489789 17.9 ns/op 0 B/op 0 allocs/op
  47. // BenchmarkUintptrCalloc64-24 53561092 22.7 ns/op 0 B/op 0 allocs/op
  48. // BenchmarkUintptrMalloc16-24 222978858 5.28 ns/op 0 B/op 0 allocs/op
  49. // BenchmarkUintptrMalloc32-24 210443384 5.30 ns/op 0 B/op 0 allocs/op
  50. // BenchmarkUintptrMalloc64-24 213706227 5.47 ns/op 0 B/op 0 allocs/op
  51. // PASS
  52. // ok modernc.org/memory 70.528s
  53. // jnml@3900x:~/src/modernc.org/memory$
  54. //
  55. // Intel® Core™ i5-4670 CPU @ 3.40GHz × 4
  56. //
  57. // ==== jnml@4670:~/src/modernc.org/memory> date ; go version ; go test -run @ -bench . -benchmem |& tee log
  58. // Sat Dec 8 12:56:53 CET 2018
  59. // go version go1.11.2 linux/amd64
  60. // goos: linux
  61. // goarch: amd64
  62. // pkg: modernc.org/memory
  63. // BenchmarkFree16-4 100000000 14.7 ns/op 0 B/op 0 allocs/op
  64. // BenchmarkFree32-4 100000000 20.5 ns/op 0 B/op 0 allocs/op
  65. // BenchmarkFree64-4 50000000 32.8 ns/op 0 B/op 0 allocs/op
  66. // BenchmarkCalloc16-4 50000000 24.4 ns/op 0 B/op 0 allocs/op
  67. // BenchmarkCalloc32-4 50000000 29.2 ns/op 0 B/op 0 allocs/op
  68. // BenchmarkCalloc64-4 50000000 35.7 ns/op 0 B/op 0 allocs/op
  69. // BenchmarkGoCalloc16-4 50000000 27.0 ns/op 16 B/op 1 allocs/op
  70. // BenchmarkGoCalloc32-4 50000000 27.3 ns/op 32 B/op 1 allocs/op
  71. // BenchmarkGoCalloc64-4 30000000 37.9 ns/op 64 B/op 1 allocs/op
  72. // BenchmarkMalloc16-4 100000000 12.9 ns/op 0 B/op 0 allocs/op
  73. // BenchmarkMalloc32-4 100000000 12.9 ns/op 0 B/op 0 allocs/op
  74. // BenchmarkMalloc64-4 100000000 13.2 ns/op 0 B/op 0 allocs/op
  75. // BenchmarkUintptrFree16-4 100000000 12.0 ns/op 0 B/op 0 allocs/op
  76. // BenchmarkUintptrFree32-4 100000000 17.5 ns/op 0 B/op 0 allocs/op
  77. // BenchmarkUintptrFree64-4 50000000 28.9 ns/op 0 B/op 0 allocs/op
  78. // BenchmarkUintptrCalloc16-4 100000000 17.8 ns/op 0 B/op 0 allocs/op
  79. // BenchmarkUintptrCalloc32-4 100000000 22.9 ns/op 0 B/op 0 allocs/op
  80. // BenchmarkUintptrCalloc64-4 50000000 29.6 ns/op 0 B/op 0 allocs/op
  81. // BenchmarkUintptrMalloc16-4 200000000 7.31 ns/op 0 B/op 0 allocs/op
  82. // BenchmarkUintptrMalloc32-4 200000000 7.47 ns/op 0 B/op 0 allocs/op
  83. // BenchmarkUintptrMalloc64-4 200000000 7.68 ns/op 0 B/op 0 allocs/op
  84. // PASS
  85. // ok modernc.org/memory 73.859s
  86. // //
  87. // Intel® Xeon(R) CPU E5-1650 v2 @ 3.50GHz × 12
  88. //
  89. // ==== jnml@e5-1650:~/src/modernc.org/memory> date ; go version ; go test -run @ -bench . -benchmem
  90. // Fri Dec 7 14:18:50 CET 2018
  91. // go version go1.11.2 linux/amd64
  92. // goos: linux
  93. // goarch: amd64
  94. // pkg: modernc.org/memory
  95. // BenchmarkFree16-12 100000000 16.7 ns/op 0 B/op 0 allocs/op
  96. // BenchmarkFree32-12 50000000 25.0 ns/op 0 B/op 0 allocs/op
  97. // BenchmarkFree64-12 30000000 39.7 ns/op 0 B/op 0 allocs/op
  98. // BenchmarkCalloc16-12 50000000 26.3 ns/op 0 B/op 0 allocs/op
  99. // BenchmarkCalloc32-12 50000000 33.4 ns/op 0 B/op 0 allocs/op
  100. // BenchmarkCalloc64-12 30000000 38.3 ns/op 0 B/op 0 allocs/op
  101. // BenchmarkGoCalloc16-12 50000000 26.6 ns/op 16 B/op 1 allocs/op
  102. // BenchmarkGoCalloc32-12 50000000 26.8 ns/op 32 B/op 1 allocs/op
  103. // BenchmarkGoCalloc64-12 30000000 35.1 ns/op 64 B/op 1 allocs/op
  104. // BenchmarkMalloc16-12 100000000 13.5 ns/op 0 B/op 0 allocs/op
  105. // BenchmarkMalloc32-12 100000000 13.4 ns/op 0 B/op 0 allocs/op
  106. // BenchmarkMalloc64-12 100000000 14.1 ns/op 0 B/op 0 allocs/op
  107. // BenchmarkUintptrFree16-12 100000000 14.4 ns/op 0 B/op 0 allocs/op
  108. // BenchmarkUintptrFree32-12 100000000 21.7 ns/op 0 B/op 0 allocs/op
  109. // BenchmarkUintptrFree64-12 50000000 36.7 ns/op 0 B/op 0 allocs/op
  110. // BenchmarkUintptrCalloc16-12 100000000 20.4 ns/op 0 B/op 0 allocs/op
  111. // BenchmarkUintptrCalloc32-12 50000000 27.1 ns/op 0 B/op 0 allocs/op
  112. // BenchmarkUintptrCalloc64-12 50000000 33.4 ns/op 0 B/op 0 allocs/op
  113. // BenchmarkUintptrMalloc16-12 200000000 8.02 ns/op 0 B/op 0 allocs/op
  114. // BenchmarkUintptrMalloc32-12 200000000 8.28 ns/op 0 B/op 0 allocs/op
  115. // BenchmarkUintptrMalloc64-12 200000000 8.29 ns/op 0 B/op 0 allocs/op
  116. // PASS
  117. // ok modernc.org/memory 80.896s
  118. package memory // import "modernc.org/memory"
  119. import (
  120. "fmt"
  121. "math/bits"
  122. "os"
  123. "reflect"
  124. "unsafe"
  125. )
  126. const (
  127. headerSize = unsafe.Sizeof(page{})
  128. mallocAllign = 2 * unsafe.Sizeof(uintptr(0))
  129. maxSlotSize = 1 << maxSlotSizeLog
  130. maxSlotSizeLog = pageSizeLog - 2
  131. pageAvail = pageSize - headerSize
  132. pageMask = pageSize - 1
  133. pageSize = 1 << pageSizeLog
  134. )
  135. func init() {
  136. if unsafe.Sizeof(page{})%mallocAllign != 0 {
  137. panic("internal error")
  138. }
  139. }
  140. // if n%m != 0 { n += m-n%m }. m must be a power of 2.
  141. func roundup(n, m int) int { return (n + m - 1) &^ (m - 1) }
  142. type node struct {
  143. prev, next uintptr // *node
  144. }
  145. type page struct {
  146. brk int
  147. log uint
  148. size int
  149. used int
  150. }
  151. // Allocator allocates and frees memory. Its zero value is ready for use. The
  152. // exported counters are updated only when build tag memory.counters is
  153. // present.
  154. type Allocator struct {
  155. Allocs int // # of allocs.
  156. Bytes int // Asked from OS.
  157. cap [64]int
  158. lists [64]uintptr // *node
  159. Mmaps int // Asked from OS.
  160. pages [64]uintptr // *page
  161. regs map[uintptr]struct{} // map[*page]struct{}
  162. }
  163. func (a *Allocator) mmap(size int) (uintptr /* *page */, error) {
  164. p, size, err := mmap(size)
  165. if err != nil {
  166. return 0, err
  167. }
  168. if counters {
  169. a.Mmaps++
  170. a.Bytes += size
  171. }
  172. if a.regs == nil {
  173. a.regs = map[uintptr]struct{}{}
  174. }
  175. (*page)(unsafe.Pointer(p)).size = size
  176. a.regs[p] = struct{}{}
  177. return p, nil
  178. }
  179. func (a *Allocator) newPage(size int) (uintptr /* *page */, error) {
  180. size += int(headerSize)
  181. p, err := a.mmap(size)
  182. if err != nil {
  183. return 0, err
  184. }
  185. (*page)(unsafe.Pointer(p)).log = 0
  186. return p, nil
  187. }
  188. func (a *Allocator) newSharedPage(log uint) (uintptr /* *page */, error) {
  189. if a.cap[log] == 0 {
  190. a.cap[log] = int(pageAvail) / (1 << log)
  191. }
  192. size := int(headerSize) + a.cap[log]<<log
  193. p, err := a.mmap(size)
  194. if err != nil {
  195. return 0, err
  196. }
  197. a.pages[log] = p
  198. (*page)(unsafe.Pointer(p)).log = log
  199. return p, nil
  200. }
  201. func (a *Allocator) unmap(p uintptr /* *page */) error {
  202. delete(a.regs, p)
  203. if counters {
  204. a.Mmaps--
  205. }
  206. return unmap(p, (*page)(unsafe.Pointer(p)).size)
  207. }
  208. // UintptrCalloc is like Calloc except it returns an uintptr.
  209. func (a *Allocator) UintptrCalloc(size int) (r uintptr, err error) {
  210. if trace {
  211. defer func() {
  212. fmt.Fprintf(os.Stderr, "Calloc(%#x) %#x, %v\n", size, r, err)
  213. }()
  214. }
  215. if r, err = a.UintptrMalloc(size); r == 0 || err != nil {
  216. return 0, err
  217. }
  218. b := ((*rawmem)(unsafe.Pointer(r)))[:size:size]
  219. for i := range b {
  220. b[i] = 0
  221. }
  222. return r, nil
  223. }
  224. // UintptrFree is like Free except its argument is an uintptr, which must have
  225. // been acquired from UintptrCalloc or UintptrMalloc or UintptrRealloc.
  226. func (a *Allocator) UintptrFree(p uintptr) (err error) {
  227. if trace {
  228. defer func() {
  229. fmt.Fprintf(os.Stderr, "Free(%#x) %v\n", p, err)
  230. }()
  231. }
  232. if p == 0 {
  233. return nil
  234. }
  235. if counters {
  236. a.Allocs--
  237. }
  238. pg := p &^ uintptr(pageMask)
  239. log := (*page)(unsafe.Pointer(pg)).log
  240. if log == 0 {
  241. if counters {
  242. a.Bytes -= (*page)(unsafe.Pointer(pg)).size
  243. }
  244. return a.unmap(pg)
  245. }
  246. (*node)(unsafe.Pointer(p)).prev = 0
  247. (*node)(unsafe.Pointer(p)).next = a.lists[log]
  248. if next := (*node)(unsafe.Pointer(p)).next; next != 0 {
  249. (*node)(unsafe.Pointer(next)).prev = p
  250. }
  251. a.lists[log] = p
  252. (*page)(unsafe.Pointer(pg)).used--
  253. if (*page)(unsafe.Pointer(pg)).used != 0 {
  254. return nil
  255. }
  256. for i := 0; i < (*page)(unsafe.Pointer(pg)).brk; i++ {
  257. n := pg + headerSize + uintptr(i)<<log
  258. next := (*node)(unsafe.Pointer(n)).next
  259. prev := (*node)(unsafe.Pointer(n)).prev
  260. switch {
  261. case prev == 0:
  262. a.lists[log] = next
  263. if next != 0 {
  264. (*node)(unsafe.Pointer(next)).prev = 0
  265. }
  266. case next == 0:
  267. (*node)(unsafe.Pointer(prev)).next = 0
  268. default:
  269. (*node)(unsafe.Pointer(prev)).next = next
  270. (*node)(unsafe.Pointer(next)).prev = prev
  271. }
  272. }
  273. if a.pages[log] == pg {
  274. a.pages[log] = 0
  275. }
  276. if counters {
  277. a.Bytes -= (*page)(unsafe.Pointer(pg)).size
  278. }
  279. return a.unmap(pg)
  280. }
  281. // UintptrMalloc is like Malloc except it returns an uinptr.
  282. func (a *Allocator) UintptrMalloc(size int) (r uintptr, err error) {
  283. if trace {
  284. defer func() {
  285. fmt.Fprintf(os.Stderr, "Malloc(%#x) %#x, %v\n", size, r, err)
  286. }()
  287. }
  288. if size < 0 {
  289. panic("invalid malloc size")
  290. }
  291. if size == 0 {
  292. return 0, nil
  293. }
  294. if counters {
  295. a.Allocs++
  296. }
  297. log := uint(bits.Len(uint((size+int(mallocAllign)-1)&^int(mallocAllign-1) - 1)))
  298. if log > maxSlotSizeLog {
  299. p, err := a.newPage(size)
  300. if err != nil {
  301. return 0, err
  302. }
  303. return p + headerSize, nil
  304. }
  305. if a.lists[log] == 0 && a.pages[log] == 0 {
  306. if _, err := a.newSharedPage(log); err != nil {
  307. return 0, err
  308. }
  309. }
  310. if p := a.pages[log]; p != 0 {
  311. (*page)(unsafe.Pointer(p)).used++
  312. (*page)(unsafe.Pointer(p)).brk++
  313. if (*page)(unsafe.Pointer(p)).brk == a.cap[log] {
  314. a.pages[log] = 0
  315. }
  316. return p + headerSize + uintptr((*page)(unsafe.Pointer(p)).brk-1)<<log, nil
  317. }
  318. n := a.lists[log]
  319. p := n &^ uintptr(pageMask)
  320. a.lists[log] = (*node)(unsafe.Pointer(n)).next
  321. if next := (*node)(unsafe.Pointer(n)).next; next != 0 {
  322. (*node)(unsafe.Pointer(next)).prev = 0
  323. }
  324. (*page)(unsafe.Pointer(p)).used++
  325. return n, nil
  326. }
  327. // UintptrRealloc is like Realloc except its first argument is an uintptr,
  328. // which must have been returned from UintptrCalloc, UintptrMalloc or
  329. // UintptrRealloc.
  330. func (a *Allocator) UintptrRealloc(p uintptr, size int) (r uintptr, err error) {
  331. if trace {
  332. defer func() {
  333. fmt.Fprintf(os.Stderr, "UnsafeRealloc(%#x, %#x) %#x, %v\n", p, size, r, err)
  334. }()
  335. }
  336. switch {
  337. case p == 0:
  338. return a.UintptrMalloc(size)
  339. case size == 0 && p != 0:
  340. return 0, a.UintptrFree(p)
  341. }
  342. us := UintptrUsableSize(p)
  343. if us > size {
  344. return p, nil
  345. }
  346. if r, err = a.UintptrMalloc(size); err != nil {
  347. return 0, err
  348. }
  349. if us < size {
  350. size = us
  351. }
  352. copy((*rawmem)(unsafe.Pointer(r))[:size:size], (*rawmem)(unsafe.Pointer(p))[:size:size])
  353. return r, a.UintptrFree(p)
  354. }
  355. // UintptrUsableSize is like UsableSize except its argument is an uintptr,
  356. // which must have been returned from UintptrCalloc, UintptrMalloc or
  357. // UintptrRealloc.
  358. func UintptrUsableSize(p uintptr) (r int) {
  359. if trace {
  360. defer func() {
  361. fmt.Fprintf(os.Stderr, "UsableSize(%#x) %#x\n", p, r)
  362. }()
  363. }
  364. if p == 0 {
  365. return 0
  366. }
  367. return usableSize(p)
  368. }
  369. func usableSize(p uintptr) (r int) {
  370. pg := p &^ uintptr(pageMask)
  371. if log := (*page)(unsafe.Pointer(pg)).log; log != 0 {
  372. return 1 << log
  373. }
  374. return (*page)(unsafe.Pointer(pg)).size - int(headerSize)
  375. }
  376. // Calloc is like Malloc except the allocated memory is zeroed.
  377. func (a *Allocator) Calloc(size int) (r []byte, err error) {
  378. p, err := a.UintptrCalloc(size)
  379. if err != nil {
  380. return nil, err
  381. }
  382. var b []byte
  383. sh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
  384. sh.Cap = usableSize(p)
  385. sh.Data = p
  386. sh.Len = size
  387. return b, nil
  388. }
  389. // Close releases all OS resources used by a and sets it to its zero value.
  390. //
  391. // It's not necessary to Close the Allocator when exiting a process.
  392. func (a *Allocator) Close() (err error) {
  393. for p := range a.regs {
  394. if e := a.unmap(p); e != nil && err == nil {
  395. err = e
  396. }
  397. }
  398. *a = Allocator{}
  399. return err
  400. }
  401. // Free deallocates memory (as in C.free). The argument of Free must have been
  402. // acquired from Calloc or Malloc or Realloc.
  403. func (a *Allocator) Free(b []byte) (err error) {
  404. if b = b[:cap(b)]; len(b) == 0 {
  405. return nil
  406. }
  407. return a.UintptrFree(uintptr(unsafe.Pointer(&b[0])))
  408. }
  409. // Malloc allocates size bytes and returns a byte slice of the allocated
  410. // memory. The memory is not initialized. Malloc panics for size < 0 and
  411. // returns (nil, nil) for zero size.
  412. //
  413. // It's ok to reslice the returned slice but the result of appending to it
  414. // cannot be passed to Free or Realloc as it may refer to a different backing
  415. // array afterwards.
  416. func (a *Allocator) Malloc(size int) (r []byte, err error) {
  417. p, err := a.UintptrMalloc(size)
  418. if p == 0 || err != nil {
  419. return nil, err
  420. }
  421. sh := (*reflect.SliceHeader)(unsafe.Pointer(&r))
  422. sh.Cap = usableSize(p)
  423. sh.Data = p
  424. sh.Len = size
  425. return r, nil
  426. }
  427. // Realloc changes the size of the backing array of b to size bytes or returns
  428. // an error, if any. The contents will be unchanged in the range from the
  429. // start of the region up to the minimum of the old and new sizes. If the
  430. // new size is larger than the old size, the added memory will not be
  431. // initialized. If b's backing array is of zero size, then the call is
  432. // equivalent to Malloc(size), for all values of size; if size is equal to
  433. // zero, and b's backing array is not of zero size, then the call is equivalent
  434. // to Free(b). Unless b's backing array is of zero size, it must have been
  435. // returned by an earlier call to Malloc, Calloc or Realloc. If the area
  436. // pointed to was moved, a Free(b) is done.
  437. func (a *Allocator) Realloc(b []byte, size int) (r []byte, err error) {
  438. var p uintptr
  439. if b = b[:cap(b)]; len(b) != 0 {
  440. p = uintptr(unsafe.Pointer(&b[0]))
  441. }
  442. if p, err = a.UintptrRealloc(p, size); p == 0 || err != nil {
  443. return nil, err
  444. }
  445. sh := (*reflect.SliceHeader)(unsafe.Pointer(&r))
  446. sh.Cap = usableSize(p)
  447. sh.Data = p
  448. sh.Len = size
  449. return r, nil
  450. }
  451. // UsableSize reports the size of the memory block allocated at p, which must
  452. // point to the first byte of a slice returned from Calloc, Malloc or Realloc.
  453. // The allocated memory block size can be larger than the size originally
  454. // requested from Calloc, Malloc or Realloc.
  455. func UsableSize(p *byte) (r int) { return UintptrUsableSize(uintptr(unsafe.Pointer(p))) }
  456. // UnsafeCalloc is like Calloc except it returns an unsafe.Pointer.
  457. func (a *Allocator) UnsafeCalloc(size int) (r unsafe.Pointer, err error) {
  458. p, err := a.UintptrCalloc(size)
  459. if err != nil {
  460. return nil, err
  461. }
  462. return unsafe.Pointer(p), nil
  463. }
  464. // UnsafeFree is like Free except its argument is an unsafe.Pointer, which must
  465. // have been acquired from UnsafeCalloc or UnsafeMalloc or UnsafeRealloc.
  466. func (a *Allocator) UnsafeFree(p unsafe.Pointer) (err error) { return a.UintptrFree(uintptr(p)) }
  467. // UnsafeMalloc is like Malloc except it returns an unsafe.Pointer.
  468. func (a *Allocator) UnsafeMalloc(size int) (r unsafe.Pointer, err error) {
  469. p, err := a.UintptrMalloc(size)
  470. if err != nil {
  471. return nil, err
  472. }
  473. return unsafe.Pointer(p), nil
  474. }
  475. // UnsafeRealloc is like Realloc except its first argument is an
  476. // unsafe.Pointer, which must have been returned from UnsafeCalloc,
  477. // UnsafeMalloc or UnsafeRealloc.
  478. func (a *Allocator) UnsafeRealloc(p unsafe.Pointer, size int) (r unsafe.Pointer, err error) {
  479. q, err := a.UintptrRealloc(uintptr(p), size)
  480. if err != nil {
  481. return nil, err
  482. }
  483. return unsafe.Pointer(q), nil
  484. }
  485. // UnsafeUsableSize is like UsableSize except its argument is an
  486. // unsafe.Pointer, which must have been returned from UnsafeCalloc,
  487. // UnsafeMalloc or UnsafeRealloc.
  488. func UnsafeUsableSize(p unsafe.Pointer) (r int) { return UintptrUsableSize(uintptr(p)) }