1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Dmitry Stogov <dmitry@zend.com> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id:$ */
20
21 #ifndef _ZEND_ARENA_H_
22 #define _ZEND_ARENA_H_
23
24 #include "zend.h"
25
26 typedef struct _zend_arena zend_arena;
27
28 struct _zend_arena {
29 char *ptr;
30 char *end;
31 zend_arena *prev;
32 };
33
zend_arena_create(size_t size)34 static zend_always_inline zend_arena* zend_arena_create(size_t size)
35 {
36 zend_arena *arena = (zend_arena*)emalloc(size);
37
38 arena->ptr = (char*) arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena));
39 arena->end = (char*) arena + size;
40 arena->prev = NULL;
41 return arena;
42 }
43
zend_arena_destroy(zend_arena * arena)44 static zend_always_inline void zend_arena_destroy(zend_arena *arena)
45 {
46 do {
47 zend_arena *prev = arena->prev;
48 efree(arena);
49 arena = prev;
50 } while (arena);
51 }
52
53 #define ZEND_ARENA_ALIGNMENT 8U
54
zend_arena_alloc(zend_arena ** arena_ptr,size_t size)55 static zend_always_inline void* zend_arena_alloc(zend_arena **arena_ptr, size_t size)
56 {
57 zend_arena *arena = *arena_ptr;
58 char *ptr = arena->ptr;
59
60 size = ZEND_MM_ALIGNED_SIZE(size);
61
62 if (EXPECTED(size <= (size_t)(arena->end - ptr))) {
63 arena->ptr = ptr + size;
64 } else {
65 size_t arena_size =
66 UNEXPECTED((size + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena))) > (size_t)(arena->end - (char*) arena)) ?
67 (size + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena))) :
68 (size_t)(arena->end - (char*) arena);
69 zend_arena *new_arena = (zend_arena*)emalloc(arena_size);
70
71 ptr = (char*) new_arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena));
72 new_arena->ptr = (char*) new_arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena)) + size;
73 new_arena->end = (char*) new_arena + arena_size;
74 new_arena->prev = arena;
75 *arena_ptr = new_arena;
76 }
77
78 return (void*) ptr;
79 }
80
zend_arena_calloc(zend_arena ** arena_ptr,size_t count,size_t unit_size)81 static zend_always_inline void* zend_arena_calloc(zend_arena **arena_ptr, size_t count, size_t unit_size)
82 {
83 int overflow;
84 size_t size;
85 void *ret;
86
87 size = zend_safe_address(unit_size, count, 0, &overflow);
88 if (UNEXPECTED(overflow)) {
89 zend_error(E_ERROR, "Possible integer overflow in zend_arena_calloc() (%zu * %zu)", unit_size, count);
90 }
91 ret = zend_arena_alloc(arena_ptr, size);
92 memset(ret, 0, size);
93 return ret;
94 }
95
zend_arena_checkpoint(zend_arena * arena)96 static zend_always_inline void* zend_arena_checkpoint(zend_arena *arena)
97 {
98 return arena->ptr;
99 }
100
zend_arena_release(zend_arena ** arena_ptr,void * checkpoint)101 static zend_always_inline void zend_arena_release(zend_arena **arena_ptr, void *checkpoint)
102 {
103 zend_arena *arena = *arena_ptr;
104
105 while (UNEXPECTED((char*)checkpoint > arena->end) ||
106 UNEXPECTED((char*)checkpoint <= (char*)arena)) {
107 zend_arena *prev = arena->prev;
108 efree(arena);
109 *arena_ptr = arena = prev;
110 }
111 ZEND_ASSERT((char*)checkpoint > (char*)arena && (char*)checkpoint <= arena->end);
112 arena->ptr = (char*)checkpoint;
113 }
114
115 #endif /* _ZEND_ARENA_H_ */
116
117 /*
118 * Local variables:
119 * tab-width: 4
120 * c-basic-offset: 4
121 * indent-tabs-mode: t
122 * End:
123 * vim600: sw=4 ts=4 fdm=marker
124 * vim<600: sw=4 ts=4
125 */
126