You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
5.8 KiB

  1. #include "Python.h"
  2. /* A simple arena block structure.
  3. Measurements with standard library modules suggest the average
  4. allocation is about 20 bytes and that most compiles use a single
  5. block.
  6. TODO(jhylton): Think about a realloc API, maybe just for the last
  7. allocation?
  8. */
  9. #define DEFAULT_BLOCK_SIZE 8192
  10. #define ALIGNMENT 8
  11. #define ALIGNMENT_MASK (ALIGNMENT - 1)
  12. #define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)
  13. typedef struct _block {
  14. /* Total number of bytes owned by this block available to pass out.
  15. * Read-only after initialization. The first such byte starts at
  16. * ab_mem.
  17. */
  18. size_t ab_size;
  19. /* Total number of bytes already passed out. The next byte available
  20. * to pass out starts at ab_mem + ab_offset.
  21. */
  22. size_t ab_offset;
  23. /* An arena maintains a singly-linked, NULL-terminated list of
  24. * all blocks owned by the arena. These are linked via the
  25. * ab_next member.
  26. */
  27. struct _block *ab_next;
  28. /* Pointer to the first allocatable byte owned by this block. Read-
  29. * only after initialization.
  30. */
  31. void *ab_mem;
  32. } block;
  33. /* The arena manages two kinds of memory, blocks of raw memory
  34. and a list of PyObject* pointers. PyObjects are decrefed
  35. when the arena is freed.
  36. */
  37. struct _arena {
  38. /* Pointer to the first block allocated for the arena, never NULL.
  39. It is used only to find the first block when the arena is
  40. being freed.
  41. */
  42. block *a_head;
  43. /* Pointer to the block currently used for allocation. It's
  44. ab_next field should be NULL. If it is not-null after a
  45. call to block_alloc(), it means a new block has been allocated
  46. and a_cur should be reset to point it.
  47. */
  48. block *a_cur;
  49. /* A Python list object containing references to all the PyObject
  50. pointers associated with this area. They will be DECREFed
  51. when the arena is freed.
  52. */
  53. PyObject *a_objects;
  54. #if defined(Py_DEBUG)
  55. /* Debug output */
  56. size_t total_allocs;
  57. size_t total_size;
  58. size_t total_blocks;
  59. size_t total_block_size;
  60. size_t total_big_blocks;
  61. #endif
  62. };
  63. static block *
  64. block_new(size_t size)
  65. {
  66. /* Allocate header and block as one unit.
  67. ab_mem points just past header. */
  68. block *b = (block *)malloc(sizeof(block) + size);
  69. if (!b)
  70. return NULL;
  71. b->ab_size = size;
  72. b->ab_mem = (void *)(b + 1);
  73. b->ab_next = NULL;
  74. b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) -
  75. (Py_uintptr_t)(b->ab_mem);
  76. return b;
  77. }
  78. static void
  79. block_free(block *b) {
  80. while (b) {
  81. block *next = b->ab_next;
  82. free(b);
  83. b = next;
  84. }
  85. }
  86. static void *
  87. block_alloc(block *b, size_t size)
  88. {
  89. void *p;
  90. assert(b);
  91. size = ROUNDUP(size);
  92. if (b->ab_offset + size > b->ab_size) {
  93. /* If we need to allocate more memory than will fit in
  94. the default block, allocate a one-off block that is
  95. exactly the right size. */
  96. /* TODO(jhylton): Think about space waste at end of block */
  97. block *newbl = block_new(
  98. size < DEFAULT_BLOCK_SIZE ?
  99. DEFAULT_BLOCK_SIZE : size);
  100. if (!newbl)
  101. return NULL;
  102. assert(!b->ab_next);
  103. b->ab_next = newbl;
  104. b = newbl;
  105. }
  106. assert(b->ab_offset + size <= b->ab_size);
  107. p = (void *)(((char *)b->ab_mem) + b->ab_offset);
  108. b->ab_offset += size;
  109. return p;
  110. }
  111. PyArena *
  112. PyArena_New()
  113. {
  114. PyArena* arena = (PyArena *)malloc(sizeof(PyArena));
  115. if (!arena)
  116. return (PyArena*)PyErr_NoMemory();
  117. arena->a_head = block_new(DEFAULT_BLOCK_SIZE);
  118. arena->a_cur = arena->a_head;
  119. if (!arena->a_head) {
  120. free((void *)arena);
  121. return (PyArena*)PyErr_NoMemory();
  122. }
  123. arena->a_objects = PyList_New(0);
  124. if (!arena->a_objects) {
  125. block_free(arena->a_head);
  126. free((void *)arena);
  127. return (PyArena*)PyErr_NoMemory();
  128. }
  129. #if defined(Py_DEBUG)
  130. arena->total_allocs = 0;
  131. arena->total_size = 0;
  132. arena->total_blocks = 1;
  133. arena->total_block_size = DEFAULT_BLOCK_SIZE;
  134. arena->total_big_blocks = 0;
  135. #endif
  136. return arena;
  137. }
  138. void
  139. PyArena_Free(PyArena *arena)
  140. {
  141. int r;
  142. assert(arena);
  143. #if defined(Py_DEBUG)
  144. /*
  145. fprintf(stderr,
  146. "alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n",
  147. arena->total_allocs, arena->total_size, arena->total_blocks,
  148. arena->total_block_size, arena->total_big_blocks,
  149. PyList_Size(arena->a_objects));
  150. */
  151. #endif
  152. block_free(arena->a_head);
  153. /* This property normally holds, except when the code being compiled
  154. is sys.getobjects(0), in which case there will be two references.
  155. assert(arena->a_objects->ob_refcnt == 1);
  156. */
  157. /* Clear all the elements from the list. This is necessary
  158. to guarantee that they will be DECREFed. */
  159. r = PyList_SetSlice(arena->a_objects,
  160. 0, PyList_GET_SIZE(arena->a_objects), NULL);
  161. assert(r == 0);
  162. assert(PyList_GET_SIZE(arena->a_objects) == 0);
  163. Py_DECREF(arena->a_objects);
  164. free(arena);
  165. }
  166. void *
  167. PyArena_Malloc(PyArena *arena, size_t size)
  168. {
  169. void *p = block_alloc(arena->a_cur, size);
  170. if (!p)
  171. return PyErr_NoMemory();
  172. #if defined(Py_DEBUG)
  173. arena->total_allocs++;
  174. arena->total_size += size;
  175. #endif
  176. /* Reset cur if we allocated a new block. */
  177. if (arena->a_cur->ab_next) {
  178. arena->a_cur = arena->a_cur->ab_next;
  179. #if defined(Py_DEBUG)
  180. arena->total_blocks++;
  181. arena->total_block_size += arena->a_cur->ab_size;
  182. if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE)
  183. ++arena->total_big_blocks;
  184. #endif
  185. }
  186. return p;
  187. }
  188. int
  189. PyArena_AddPyObject(PyArena *arena, PyObject *obj)
  190. {
  191. int r = PyList_Append(arena->a_objects, obj);
  192. if (r >= 0) {
  193. Py_DECREF(obj);
  194. }
  195. return r;
  196. }