• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 static jerryx_handle_scope_t jerryx_handle_scope_root =
20 {
21   .prelist_handle_count = 0,
22   .handle_ptr = NULL,
23 };
24 static jerryx_handle_scope_t *jerryx_handle_scope_current = &jerryx_handle_scope_root;
25 static jerryx_handle_scope_pool_t jerryx_handle_scope_pool =
26 {
27   .count = 0,
28   .start = NULL,
29 };
30 
31 #define JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST \
32   jerryx_handle_scope_pool.prelist + JERRYX_SCOPE_PRELIST_SIZE - 1
33 
34 #define JERRYX_HANDLE_SCOPE_PRELIST_IDX(scope) (scope - jerryx_handle_scope_pool.prelist)
35 
36 /**
37  * Get current handle scope top of stack.
38  */
39 jerryx_handle_scope_t *
jerryx_handle_scope_get_current(void)40 jerryx_handle_scope_get_current (void)
41 {
42   return jerryx_handle_scope_current;
43 } /* jerryx_handle_scope_get_current */
44 
45 /**
46  * Get root handle scope.
47  */
48 jerryx_handle_scope_t *
jerryx_handle_scope_get_root(void)49 jerryx_handle_scope_get_root (void)
50 {
51   return &jerryx_handle_scope_root;
52 } /* jerryx_handle_scope_get_root */
53 
54 /**
55  * Determines if given handle scope is located in pre-allocated list.
56  *
57  * @param scope - the one to be determined.
58  */
59 static bool
jerryx_handle_scope_is_in_prelist(jerryx_handle_scope_t * scope)60 jerryx_handle_scope_is_in_prelist (jerryx_handle_scope_t *scope)
61 {
62   return (jerryx_handle_scope_pool.prelist <= scope)
63   && (scope <= (jerryx_handle_scope_pool.prelist + JERRYX_SCOPE_PRELIST_SIZE - 1));
64 } /** jerryx_handle_scope_is_in_prelist */
65 
66 /**
67  * Get the parent of given handle scope.
68  * If given handle scope is in prelist, the parent must be in prelist too;
69  * if given is the first item of heap chain list, the parent must be the last one of prelist;
70  * the parent must be in chain list otherwise.
71  *
72  * @param scope - the one to be permformed on.
73  * @returns - the parent of the given scope.
74  */
75 jerryx_handle_scope_t *
jerryx_handle_scope_get_parent(jerryx_handle_scope_t * scope)76 jerryx_handle_scope_get_parent (jerryx_handle_scope_t *scope)
77 {
78   if (scope == &jerryx_handle_scope_root)
79   {
80     return NULL;
81   }
82   if (!jerryx_handle_scope_is_in_prelist (scope))
83   {
84     jerryx_handle_scope_dynamic_t *dy_scope = (jerryx_handle_scope_dynamic_t *) scope;
85     if (dy_scope == jerryx_handle_scope_pool.start)
86     {
87       return JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST;
88     }
89     jerryx_handle_scope_dynamic_t *parent = dy_scope->parent;
90     return (jerryx_handle_scope_t *) parent;
91   }
92   if (scope == jerryx_handle_scope_pool.prelist)
93   {
94     return &jerryx_handle_scope_root;
95   }
96   return jerryx_handle_scope_pool.prelist + JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope) - 1;
97 } /** jerryx_handle_scope_get_parent */
98 
99 /**
100  * Get the child of given handle scope.
101  * If the given handle scope is in heap chain list, its child must be in heap chain list too;
102  * if the given handle scope is the last one of prelist, its child must be the first item of chain list;
103  * the children are in prelist otherwise.
104  *
105  * @param scope - the one to be permformed on.
106  * @returns the child of the given scope.
107  */
108 jerryx_handle_scope_t *
jerryx_handle_scope_get_child(jerryx_handle_scope_t * scope)109 jerryx_handle_scope_get_child (jerryx_handle_scope_t *scope)
110 {
111   if (scope == &jerryx_handle_scope_root)
112   {
113     if (jerryx_handle_scope_pool.count > 0)
114     {
115       return jerryx_handle_scope_pool.prelist;
116     }
117     return NULL;
118   }
119   if (!jerryx_handle_scope_is_in_prelist (scope))
120   {
121     jerryx_handle_scope_dynamic_t *child = ((jerryx_handle_scope_dynamic_t *) scope)->child;
122     return (jerryx_handle_scope_t *) child;
123   }
124   if (scope == JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST)
125   {
126     return (jerryx_handle_scope_t *) jerryx_handle_scope_pool.start;
127   }
128   long idx = (long)(JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope));
129   if (idx < 0)
130   {
131     return NULL;
132   }
133   if ((unsigned long) idx >= jerryx_handle_scope_pool.count - 1)
134   {
135     return NULL;
136   }
137   return jerryx_handle_scope_pool.prelist + idx + 1;
138 } /** jerryx_handle_scope_get_child */
139 
140 /**
141  * Claims a handle scope either from prelist or allocating a new memory block,
142  * and increment pool's scope count by 1, and set current scope to the newly claimed one.
143  * If there are still available spaces in prelist, claims a block in prelist;
144  * otherwise allocates a new memory block from heap and sets its fields to default values,
145  * and link it to previously dynamically allocated scope, or link it to pool's start pointer.
146  *
147  * @returns the newly claimed handle scope pointer.
148  */
149 jerryx_handle_scope_t *
jerryx_handle_scope_alloc(void)150 jerryx_handle_scope_alloc (void)
151 {
152   jerryx_handle_scope_t *scope;
153   if (jerryx_handle_scope_pool.count < JERRYX_SCOPE_PRELIST_SIZE)
154   {
155     scope = jerryx_handle_scope_pool.prelist + jerryx_handle_scope_pool.count;
156   }
157   else
158   {
159     jerryx_handle_scope_dynamic_t *dy_scope = malloc (sizeof (jerryx_handle_scope_dynamic_t));
160     JERRYX_HANDLE_SCOPE_ASSERT (dy_scope != NULL);
161     dy_scope->child = NULL;
162 
163     if (jerryx_handle_scope_pool.count != JERRYX_SCOPE_PRELIST_SIZE)
164     {
165       jerryx_handle_scope_dynamic_t *dy_current = (jerryx_handle_scope_dynamic_t *) jerryx_handle_scope_current;
166       dy_scope->parent = dy_current;
167       dy_current->child = dy_scope;
168     }
169     else
170     {
171       jerryx_handle_scope_pool.start = dy_scope;
172       dy_scope->parent = NULL;
173     }
174 
175     scope = (jerryx_handle_scope_t *) dy_scope;
176   }
177 
178   scope->prelist_handle_count = 0;
179   scope->escaped = false;
180   scope->handle_ptr = NULL;
181 
182   jerryx_handle_scope_current = scope;
183   ++jerryx_handle_scope_pool.count;
184   return (jerryx_handle_scope_t *) scope;
185 } /** jerryx_handle_scope_alloc */
186 
187 /**
188  * Deannounce a previously claimed handle scope, return it to pool
189  * or free the allocated memory block.
190  *
191  * @param scope - the one to be freed.
192  */
193 void
jerryx_handle_scope_free(jerryx_handle_scope_t * scope)194 jerryx_handle_scope_free (jerryx_handle_scope_t *scope)
195 {
196   if (scope == &jerryx_handle_scope_root)
197   {
198     return;
199   }
200 
201   --jerryx_handle_scope_pool.count;
202   if (scope == jerryx_handle_scope_current)
203   {
204     jerryx_handle_scope_current = jerryx_handle_scope_get_parent (scope);
205   }
206 
207   if (!jerryx_handle_scope_is_in_prelist (scope))
208   {
209     jerryx_handle_scope_dynamic_t *dy_scope = (jerryx_handle_scope_dynamic_t *) scope;
210     if (dy_scope == jerryx_handle_scope_pool.start)
211     {
212       jerryx_handle_scope_pool.start = dy_scope->child;
213     }
214     else if (dy_scope->parent != NULL)
215     {
216       dy_scope->parent->child = dy_scope->child;
217     }
218     free (dy_scope);
219     return;
220   }
221   /**
222    * Nothing to do with scopes in prelist
223    */
224 } /** jerryx_handle_scope_free */
225