Changeset 391 for python/trunk/Python/pyarena.c
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Python/pyarena.c
r2 r391 13 13 14 14 #define DEFAULT_BLOCK_SIZE 8192 15 #define ALIGNMENT 16 #define ALIGNMENT_MASK 17 #define ROUNDUP(x) 15 #define ALIGNMENT 8 16 #define ALIGNMENT_MASK (ALIGNMENT - 1) 17 #define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK) 18 18 19 19 typedef struct _block { 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 20 /* Total number of bytes owned by this block available to pass out. 21 * Read-only after initialization. The first such byte starts at 22 * ab_mem. 23 */ 24 size_t ab_size; 25 26 /* Total number of bytes already passed out. The next byte available 27 * to pass out starts at ab_mem + ab_offset. 28 */ 29 size_t ab_offset; 30 31 /* An arena maintains a singly-linked, NULL-terminated list of 32 * all blocks owned by the arena. These are linked via the 33 * ab_next member. 34 */ 35 struct _block *ab_next; 36 37 /* Pointer to the first allocatable byte owned by this block. Read- 38 * only after initialization. 39 */ 40 void *ab_mem; 41 41 } block; 42 42 … … 47 47 48 48 struct _arena { 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #if defined(Py_DEBUG) 69 70 71 72 73 74 49 /* Pointer to the first block allocated for the arena, never NULL. 50 It is used only to find the first block when the arena is 51 being freed. 52 */ 53 block *a_head; 54 55 /* Pointer to the block currently used for allocation. It's 56 ab_next field should be NULL. If it is not-null after a 57 call to block_alloc(), it means a new block has been allocated 58 and a_cur should be reset to point it. 59 */ 60 block *a_cur; 61 62 /* A Python list object containing references to all the PyObject 63 pointers associated with this area. They will be DECREFed 64 when the arena is freed. 65 */ 66 PyObject *a_objects; 67 68 #if defined(Py_DEBUG) 69 /* Debug output */ 70 size_t total_allocs; 71 size_t total_size; 72 size_t total_blocks; 73 size_t total_block_size; 74 size_t total_big_blocks; 75 75 #endif 76 76 }; … … 79 79 block_new(size_t size) 80 80 { 81 82 83 84 85 86 87 88 89 b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) - 90 91 81 /* Allocate header and block as one unit. 82 ab_mem points just past header. */ 83 block *b = (block *)malloc(sizeof(block) + size); 84 if (!b) 85 return NULL; 86 b->ab_size = size; 87 b->ab_mem = (void *)(b + 1); 88 b->ab_next = NULL; 89 b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) - 90 (Py_uintptr_t)(b->ab_mem); 91 return b; 92 92 } 93 93 94 94 static void 95 95 block_free(block *b) { 96 97 98 99 100 96 while (b) { 97 block *next = b->ab_next; 98 free(b); 99 b = next; 100 } 101 101 } 102 102 … … 104 104 block_alloc(block *b, size_t size) 105 105 { 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 106 void *p; 107 assert(b); 108 size = ROUNDUP(size); 109 if (b->ab_offset + size > b->ab_size) { 110 /* If we need to allocate more memory than will fit in 111 the default block, allocate a one-off block that is 112 exactly the right size. */ 113 /* TODO(jhylton): Think about space waste at end of block */ 114 block *newbl = block_new( 115 size < DEFAULT_BLOCK_SIZE ? 116 DEFAULT_BLOCK_SIZE : size); 117 if (!newbl) 118 return NULL; 119 assert(!b->ab_next); 120 b->ab_next = newbl; 121 b = newbl; 122 } 123 124 assert(b->ab_offset + size <= b->ab_size); 125 p = (void *)(((char *)b->ab_mem) + b->ab_offset); 126 b->ab_offset += size; 127 return p; 128 128 } 129 129 … … 131 131 PyArena_New() 132 132 { 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 #if defined(Py_DEBUG) 150 151 152 153 154 155 #endif 156 133 PyArena* arena = (PyArena *)malloc(sizeof(PyArena)); 134 if (!arena) 135 return (PyArena*)PyErr_NoMemory(); 136 137 arena->a_head = block_new(DEFAULT_BLOCK_SIZE); 138 arena->a_cur = arena->a_head; 139 if (!arena->a_head) { 140 free((void *)arena); 141 return (PyArena*)PyErr_NoMemory(); 142 } 143 arena->a_objects = PyList_New(0); 144 if (!arena->a_objects) { 145 block_free(arena->a_head); 146 free((void *)arena); 147 return (PyArena*)PyErr_NoMemory(); 148 } 149 #if defined(Py_DEBUG) 150 arena->total_allocs = 0; 151 arena->total_size = 0; 152 arena->total_blocks = 1; 153 arena->total_block_size = DEFAULT_BLOCK_SIZE; 154 arena->total_big_blocks = 0; 155 #endif 156 return arena; 157 157 } 158 158 … … 160 160 PyArena_Free(PyArena *arena) 161 161 { 162 int r; 163 assert(arena); 164 #if defined(Py_DEBUG) 165 /* 166 fprintf(stderr, 167 "alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n", 168 arena->total_allocs, arena->total_size, arena->total_blocks, 169 arena->total_block_size, arena->total_big_blocks, 170 PyList_Size(arena->a_objects)); 171 */ 172 #endif 173 block_free(arena->a_head); 174 /* This property normally holds, except when the code being compiled 175 is sys.getobjects(0), in which case there will be two references. 176 assert(arena->a_objects->ob_refcnt == 1); 177 */ 178 179 /* Clear all the elements from the list. This is necessary 180 to guarantee that they will be DECREFed. */ 181 r = PyList_SetSlice(arena->a_objects, 182 0, PyList_GET_SIZE(arena->a_objects), NULL); 183 assert(r == 0); 184 assert(PyList_GET_SIZE(arena->a_objects) == 0); 185 Py_DECREF(arena->a_objects); 186 free(arena); 162 assert(arena); 163 #if defined(Py_DEBUG) 164 /* 165 fprintf(stderr, 166 "alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n", 167 arena->total_allocs, arena->total_size, arena->total_blocks, 168 arena->total_block_size, arena->total_big_blocks, 169 PyList_Size(arena->a_objects)); 170 */ 171 #endif 172 block_free(arena->a_head); 173 /* This property normally holds, except when the code being compiled 174 is sys.getobjects(0), in which case there will be two references. 175 assert(arena->a_objects->ob_refcnt == 1); 176 */ 177 178 Py_DECREF(arena->a_objects); 179 free(arena); 187 180 } 188 181 … … 190 183 PyArena_Malloc(PyArena *arena, size_t size) 191 184 { 192 193 194 195 #if defined(Py_DEBUG) 196 197 198 #endif 199 200 201 202 #if defined(Py_DEBUG) 203 204 205 206 207 #endif 208 209 185 void *p = block_alloc(arena->a_cur, size); 186 if (!p) 187 return PyErr_NoMemory(); 188 #if defined(Py_DEBUG) 189 arena->total_allocs++; 190 arena->total_size += size; 191 #endif 192 /* Reset cur if we allocated a new block. */ 193 if (arena->a_cur->ab_next) { 194 arena->a_cur = arena->a_cur->ab_next; 195 #if defined(Py_DEBUG) 196 arena->total_blocks++; 197 arena->total_block_size += arena->a_cur->ab_size; 198 if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE) 199 ++arena->total_big_blocks; 200 #endif 201 } 202 return p; 210 203 } 211 204 … … 213 206 PyArena_AddPyObject(PyArena *arena, PyObject *obj) 214 207 { 215 216 217 218 219 220 } 208 int r = PyList_Append(arena->a_objects, obj); 209 if (r >= 0) { 210 Py_DECREF(obj); 211 } 212 return r; 213 }
Note:
See TracChangeset
for help on using the changeset viewer.