1 | /* Copyright JS Foundation and other contributors, http://js.foundation |
2 | * |
3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
4 | * you may not use this file except in compliance with the License. |
5 | * You may obtain a copy of the License at |
6 | * |
7 | * http://www.apache.org/licenses/LICENSE-2.0 |
8 | * |
9 | * Unless required by applicable law or agreed to in writing, software |
10 | * distributed under the License is distributed on an "AS IS" BASIS |
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | * See the License for the specific language governing permissions and |
13 | * limitations under the License. |
14 | */ |
15 | |
16 | #include <stdlib.h> |
17 | #include "handle-scope-internal.h" |
18 | #include "jext-common.h" |
19 | |
20 | static jerryx_handle_scope_t jerryx_handle_scope_root = |
21 | { |
22 | .prelist_handle_count = 0, |
23 | .handle_ptr = NULL, |
24 | }; |
25 | static jerryx_handle_scope_t *jerryx_handle_scope_current = &jerryx_handle_scope_root; |
26 | static jerryx_handle_scope_pool_t jerryx_handle_scope_pool = |
27 | { |
28 | .count = 0, |
29 | .start = NULL, |
30 | }; |
31 | |
32 | #define JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST \ |
33 | jerryx_handle_scope_pool.prelist + JERRYX_SCOPE_PRELIST_SIZE - 1 |
34 | |
35 | #define JERRYX_HANDLE_SCOPE_PRELIST_IDX(scope) (scope - jerryx_handle_scope_pool.prelist) |
36 | |
37 | /** |
38 | * Get current handle scope top of stack. |
39 | */ |
40 | jerryx_handle_scope_t * |
41 | jerryx_handle_scope_get_current (void) |
42 | { |
43 | return jerryx_handle_scope_current; |
44 | } /* jerryx_handle_scope_get_current */ |
45 | |
46 | /** |
47 | * Get root handle scope. |
48 | */ |
49 | jerryx_handle_scope_t * |
50 | jerryx_handle_scope_get_root (void) |
51 | { |
52 | return &jerryx_handle_scope_root; |
53 | } /* jerryx_handle_scope_get_root */ |
54 | |
55 | /** |
56 | * Determines if given handle scope is located in pre-allocated list. |
57 | * |
58 | * @param scope - the one to be determined. |
59 | */ |
60 | static bool |
61 | jerryx_handle_scope_is_in_prelist (jerryx_handle_scope_t *scope) |
62 | { |
63 | return (jerryx_handle_scope_pool.prelist <= scope) |
64 | && (scope <= (jerryx_handle_scope_pool.prelist + JERRYX_SCOPE_PRELIST_SIZE - 1)); |
65 | } /** jerryx_handle_scope_is_in_prelist */ |
66 | |
67 | /** |
68 | * Get the parent of given handle scope. |
69 | * If given handle scope is in prelist, the parent must be in prelist too; |
70 | * if given is the first item of heap chain list, the parent must be the last one of prelist; |
71 | * the parent must be in chain list otherwise. |
72 | * |
73 | * @param scope - the one to be permformed on. |
74 | * @returns - the parent of the given scope. |
75 | */ |
76 | jerryx_handle_scope_t * |
77 | jerryx_handle_scope_get_parent (jerryx_handle_scope_t *scope) |
78 | { |
79 | if (scope == &jerryx_handle_scope_root) |
80 | { |
81 | return NULL; |
82 | } |
83 | if (!jerryx_handle_scope_is_in_prelist (scope)) |
84 | { |
85 | jerryx_handle_scope_dynamic_t *dy_scope = (jerryx_handle_scope_dynamic_t *) scope; |
86 | if (dy_scope == jerryx_handle_scope_pool.start) |
87 | { |
88 | return JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST; |
89 | } |
90 | jerryx_handle_scope_dynamic_t *parent = dy_scope->parent; |
91 | return (jerryx_handle_scope_t *) parent; |
92 | } |
93 | if (scope == jerryx_handle_scope_pool.prelist) |
94 | { |
95 | return &jerryx_handle_scope_root; |
96 | } |
97 | return jerryx_handle_scope_pool.prelist + JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope) - 1; |
98 | } /** jerryx_handle_scope_get_parent */ |
99 | |
100 | /** |
101 | * Get the child of given handle scope. |
102 | * If the given handle scope is in heap chain list, its child must be in heap chain list too; |
103 | * if the given handle scope is the last one of prelist, its child must be the first item of chain list; |
104 | * the children are in prelist otherwise. |
105 | * |
106 | * @param scope - the one to be permformed on. |
107 | * @returns the child of the given scope. |
108 | */ |
109 | jerryx_handle_scope_t * |
110 | jerryx_handle_scope_get_child (jerryx_handle_scope_t *scope) |
111 | { |
112 | if (scope == &jerryx_handle_scope_root) |
113 | { |
114 | if (jerryx_handle_scope_pool.count > 0) |
115 | { |
116 | return jerryx_handle_scope_pool.prelist; |
117 | } |
118 | return NULL; |
119 | } |
120 | if (!jerryx_handle_scope_is_in_prelist (scope)) |
121 | { |
122 | jerryx_handle_scope_dynamic_t *child = ((jerryx_handle_scope_dynamic_t *) scope)->child; |
123 | return (jerryx_handle_scope_t *) child; |
124 | } |
125 | if (scope == JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST) |
126 | { |
127 | return (jerryx_handle_scope_t *) jerryx_handle_scope_pool.start; |
128 | } |
129 | ptrdiff_t idx = JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope); |
130 | if (idx < 0) |
131 | { |
132 | return NULL; |
133 | } |
134 | if ((unsigned long) idx >= jerryx_handle_scope_pool.count - 1) |
135 | { |
136 | return NULL; |
137 | } |
138 | return jerryx_handle_scope_pool.prelist + idx + 1; |
139 | } /** jerryx_handle_scope_get_child */ |
140 | |
141 | /** |
142 | * Claims a handle scope either from prelist or allocating a new memory block, |
143 | * and increment pool's scope count by 1, and set current scope to the newly claimed one. |
144 | * If there are still available spaces in prelist, claims a block in prelist; |
145 | * otherwise allocates a new memory block from heap and sets its fields to default values, |
146 | * and link it to previously dynamically allocated scope, or link it to pool's start pointer. |
147 | * |
148 | * @returns the newly claimed handle scope pointer. |
149 | */ |
150 | jerryx_handle_scope_t * |
151 | jerryx_handle_scope_alloc (void) |
152 | { |
153 | jerryx_handle_scope_t *scope; |
154 | if (jerryx_handle_scope_pool.count < JERRYX_SCOPE_PRELIST_SIZE) |
155 | { |
156 | scope = jerryx_handle_scope_pool.prelist + jerryx_handle_scope_pool.count; |
157 | } |
158 | else |
159 | { |
160 | jerryx_handle_scope_dynamic_t *dy_scope; |
161 | dy_scope = (jerryx_handle_scope_dynamic_t *) jerry_heap_alloc (sizeof (jerryx_handle_scope_dynamic_t)); |
162 | JERRYX_ASSERT (dy_scope != NULL); |
163 | dy_scope->child = NULL; |
164 | |
165 | if (jerryx_handle_scope_pool.count != JERRYX_SCOPE_PRELIST_SIZE) |
166 | { |
167 | jerryx_handle_scope_dynamic_t *dy_current = (jerryx_handle_scope_dynamic_t *) jerryx_handle_scope_current; |
168 | dy_scope->parent = dy_current; |
169 | dy_current->child = dy_scope; |
170 | } |
171 | else |
172 | { |
173 | jerryx_handle_scope_pool.start = dy_scope; |
174 | dy_scope->parent = NULL; |
175 | } |
176 | |
177 | scope = (jerryx_handle_scope_t *) dy_scope; |
178 | } |
179 | |
180 | scope->prelist_handle_count = 0; |
181 | scope->escaped = false; |
182 | scope->handle_ptr = NULL; |
183 | |
184 | jerryx_handle_scope_current = scope; |
185 | ++jerryx_handle_scope_pool.count; |
186 | return (jerryx_handle_scope_t *) scope; |
187 | } /** jerryx_handle_scope_alloc */ |
188 | |
189 | /** |
190 | * Deannounce a previously claimed handle scope, return it to pool |
191 | * or free the allocated memory block. |
192 | * |
193 | * @param scope - the one to be freed. |
194 | */ |
195 | void |
196 | jerryx_handle_scope_free (jerryx_handle_scope_t *scope) |
197 | { |
198 | if (scope == &jerryx_handle_scope_root) |
199 | { |
200 | return; |
201 | } |
202 | |
203 | --jerryx_handle_scope_pool.count; |
204 | if (scope == jerryx_handle_scope_current) |
205 | { |
206 | jerryx_handle_scope_current = jerryx_handle_scope_get_parent (scope); |
207 | } |
208 | |
209 | if (!jerryx_handle_scope_is_in_prelist (scope)) |
210 | { |
211 | jerryx_handle_scope_dynamic_t *dy_scope = (jerryx_handle_scope_dynamic_t *) scope; |
212 | if (dy_scope == jerryx_handle_scope_pool.start) |
213 | { |
214 | jerryx_handle_scope_pool.start = dy_scope->child; |
215 | } |
216 | else if (dy_scope->parent != NULL) |
217 | { |
218 | dy_scope->parent->child = dy_scope->child; |
219 | } |
220 | jerry_heap_free (dy_scope, sizeof (jerryx_handle_scope_dynamic_t)); |
221 | return; |
222 | } |
223 | /** |
224 | * Nothing to do with scopes in prelist |
225 | */ |
226 | } /** jerryx_handle_scope_free */ |
227 | |