1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include <stdlib.h>
17425bb815Sopenharmony_ci#include "handle-scope-internal.h"
18425bb815Sopenharmony_ci
19425bb815Sopenharmony_cistatic jerryx_handle_scope_t jerryx_handle_scope_root =
20425bb815Sopenharmony_ci{
21425bb815Sopenharmony_ci  .prelist_handle_count = 0,
22425bb815Sopenharmony_ci  .handle_ptr = NULL,
23425bb815Sopenharmony_ci};
24425bb815Sopenharmony_cistatic jerryx_handle_scope_t *jerryx_handle_scope_current = &jerryx_handle_scope_root;
25425bb815Sopenharmony_cistatic jerryx_handle_scope_pool_t jerryx_handle_scope_pool =
26425bb815Sopenharmony_ci{
27425bb815Sopenharmony_ci  .count = 0,
28425bb815Sopenharmony_ci  .start = NULL,
29425bb815Sopenharmony_ci};
30425bb815Sopenharmony_ci
31425bb815Sopenharmony_ci#define JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST \
32425bb815Sopenharmony_ci  jerryx_handle_scope_pool.prelist + JERRYX_SCOPE_PRELIST_SIZE - 1
33425bb815Sopenharmony_ci
34425bb815Sopenharmony_ci#define JERRYX_HANDLE_SCOPE_PRELIST_IDX(scope) (scope - jerryx_handle_scope_pool.prelist)
35425bb815Sopenharmony_ci
36425bb815Sopenharmony_ci/**
37425bb815Sopenharmony_ci * Get current handle scope top of stack.
38425bb815Sopenharmony_ci */
39425bb815Sopenharmony_cijerryx_handle_scope_t *
40425bb815Sopenharmony_cijerryx_handle_scope_get_current (void)
41425bb815Sopenharmony_ci{
42425bb815Sopenharmony_ci  return jerryx_handle_scope_current;
43425bb815Sopenharmony_ci} /* jerryx_handle_scope_get_current */
44425bb815Sopenharmony_ci
45425bb815Sopenharmony_ci/**
46425bb815Sopenharmony_ci * Get root handle scope.
47425bb815Sopenharmony_ci */
48425bb815Sopenharmony_cijerryx_handle_scope_t *
49425bb815Sopenharmony_cijerryx_handle_scope_get_root (void)
50425bb815Sopenharmony_ci{
51425bb815Sopenharmony_ci  return &jerryx_handle_scope_root;
52425bb815Sopenharmony_ci} /* jerryx_handle_scope_get_root */
53425bb815Sopenharmony_ci
54425bb815Sopenharmony_ci/**
55425bb815Sopenharmony_ci * Determines if given handle scope is located in pre-allocated list.
56425bb815Sopenharmony_ci *
57425bb815Sopenharmony_ci * @param scope - the one to be determined.
58425bb815Sopenharmony_ci */
59425bb815Sopenharmony_cistatic bool
60425bb815Sopenharmony_cijerryx_handle_scope_is_in_prelist (jerryx_handle_scope_t *scope)
61425bb815Sopenharmony_ci{
62425bb815Sopenharmony_ci  return (jerryx_handle_scope_pool.prelist <= scope)
63425bb815Sopenharmony_ci  && (scope <= (jerryx_handle_scope_pool.prelist + JERRYX_SCOPE_PRELIST_SIZE - 1));
64425bb815Sopenharmony_ci} /** jerryx_handle_scope_is_in_prelist */
65425bb815Sopenharmony_ci
66425bb815Sopenharmony_ci/**
67425bb815Sopenharmony_ci * Get the parent of given handle scope.
68425bb815Sopenharmony_ci * If given handle scope is in prelist, the parent must be in prelist too;
69425bb815Sopenharmony_ci * if given is the first item of heap chain list, the parent must be the last one of prelist;
70425bb815Sopenharmony_ci * the parent must be in chain list otherwise.
71425bb815Sopenharmony_ci *
72425bb815Sopenharmony_ci * @param scope - the one to be permformed on.
73425bb815Sopenharmony_ci * @returns - the parent of the given scope.
74425bb815Sopenharmony_ci */
75425bb815Sopenharmony_cijerryx_handle_scope_t *
76425bb815Sopenharmony_cijerryx_handle_scope_get_parent (jerryx_handle_scope_t *scope)
77425bb815Sopenharmony_ci{
78425bb815Sopenharmony_ci  if (scope == &jerryx_handle_scope_root)
79425bb815Sopenharmony_ci  {
80425bb815Sopenharmony_ci    return NULL;
81425bb815Sopenharmony_ci  }
82425bb815Sopenharmony_ci  if (!jerryx_handle_scope_is_in_prelist (scope))
83425bb815Sopenharmony_ci  {
84425bb815Sopenharmony_ci    jerryx_handle_scope_dynamic_t *dy_scope = (jerryx_handle_scope_dynamic_t *) scope;
85425bb815Sopenharmony_ci    if (dy_scope == jerryx_handle_scope_pool.start)
86425bb815Sopenharmony_ci    {
87425bb815Sopenharmony_ci      return JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST;
88425bb815Sopenharmony_ci    }
89425bb815Sopenharmony_ci    jerryx_handle_scope_dynamic_t *parent = dy_scope->parent;
90425bb815Sopenharmony_ci    return (jerryx_handle_scope_t *) parent;
91425bb815Sopenharmony_ci  }
92425bb815Sopenharmony_ci  if (scope == jerryx_handle_scope_pool.prelist)
93425bb815Sopenharmony_ci  {
94425bb815Sopenharmony_ci    return &jerryx_handle_scope_root;
95425bb815Sopenharmony_ci  }
96425bb815Sopenharmony_ci  return jerryx_handle_scope_pool.prelist + JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope) - 1;
97425bb815Sopenharmony_ci} /** jerryx_handle_scope_get_parent */
98425bb815Sopenharmony_ci
99425bb815Sopenharmony_ci/**
100425bb815Sopenharmony_ci * Get the child of given handle scope.
101425bb815Sopenharmony_ci * If the given handle scope is in heap chain list, its child must be in heap chain list too;
102425bb815Sopenharmony_ci * if the given handle scope is the last one of prelist, its child must be the first item of chain list;
103425bb815Sopenharmony_ci * the children are in prelist otherwise.
104425bb815Sopenharmony_ci *
105425bb815Sopenharmony_ci * @param scope - the one to be permformed on.
106425bb815Sopenharmony_ci * @returns the child of the given scope.
107425bb815Sopenharmony_ci */
108425bb815Sopenharmony_cijerryx_handle_scope_t *
109425bb815Sopenharmony_cijerryx_handle_scope_get_child (jerryx_handle_scope_t *scope)
110425bb815Sopenharmony_ci{
111425bb815Sopenharmony_ci  if (scope == &jerryx_handle_scope_root)
112425bb815Sopenharmony_ci  {
113425bb815Sopenharmony_ci    if (jerryx_handle_scope_pool.count > 0)
114425bb815Sopenharmony_ci    {
115425bb815Sopenharmony_ci      return jerryx_handle_scope_pool.prelist;
116425bb815Sopenharmony_ci    }
117425bb815Sopenharmony_ci    return NULL;
118425bb815Sopenharmony_ci  }
119425bb815Sopenharmony_ci  if (!jerryx_handle_scope_is_in_prelist (scope))
120425bb815Sopenharmony_ci  {
121425bb815Sopenharmony_ci    jerryx_handle_scope_dynamic_t *child = ((jerryx_handle_scope_dynamic_t *) scope)->child;
122425bb815Sopenharmony_ci    return (jerryx_handle_scope_t *) child;
123425bb815Sopenharmony_ci  }
124425bb815Sopenharmony_ci  if (scope == JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST)
125425bb815Sopenharmony_ci  {
126425bb815Sopenharmony_ci    return (jerryx_handle_scope_t *) jerryx_handle_scope_pool.start;
127425bb815Sopenharmony_ci  }
128425bb815Sopenharmony_ci  long idx = (long)(JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope));
129425bb815Sopenharmony_ci  if (idx < 0)
130425bb815Sopenharmony_ci  {
131425bb815Sopenharmony_ci    return NULL;
132425bb815Sopenharmony_ci  }
133425bb815Sopenharmony_ci  if ((unsigned long) idx >= jerryx_handle_scope_pool.count - 1)
134425bb815Sopenharmony_ci  {
135425bb815Sopenharmony_ci    return NULL;
136425bb815Sopenharmony_ci  }
137425bb815Sopenharmony_ci  return jerryx_handle_scope_pool.prelist + idx + 1;
138425bb815Sopenharmony_ci} /** jerryx_handle_scope_get_child */
139425bb815Sopenharmony_ci
140425bb815Sopenharmony_ci/**
141425bb815Sopenharmony_ci * Claims a handle scope either from prelist or allocating a new memory block,
142425bb815Sopenharmony_ci * and increment pool's scope count by 1, and set current scope to the newly claimed one.
143425bb815Sopenharmony_ci * If there are still available spaces in prelist, claims a block in prelist;
144425bb815Sopenharmony_ci * otherwise allocates a new memory block from heap and sets its fields to default values,
145425bb815Sopenharmony_ci * and link it to previously dynamically allocated scope, or link it to pool's start pointer.
146425bb815Sopenharmony_ci *
147425bb815Sopenharmony_ci * @returns the newly claimed handle scope pointer.
148425bb815Sopenharmony_ci */
149425bb815Sopenharmony_cijerryx_handle_scope_t *
150425bb815Sopenharmony_cijerryx_handle_scope_alloc (void)
151425bb815Sopenharmony_ci{
152425bb815Sopenharmony_ci  jerryx_handle_scope_t *scope;
153425bb815Sopenharmony_ci  if (jerryx_handle_scope_pool.count < JERRYX_SCOPE_PRELIST_SIZE)
154425bb815Sopenharmony_ci  {
155425bb815Sopenharmony_ci    scope = jerryx_handle_scope_pool.prelist + jerryx_handle_scope_pool.count;
156425bb815Sopenharmony_ci  }
157425bb815Sopenharmony_ci  else
158425bb815Sopenharmony_ci  {
159425bb815Sopenharmony_ci    jerryx_handle_scope_dynamic_t *dy_scope = malloc (sizeof (jerryx_handle_scope_dynamic_t));
160425bb815Sopenharmony_ci    JERRYX_HANDLE_SCOPE_ASSERT (dy_scope != NULL);
161425bb815Sopenharmony_ci    dy_scope->child = NULL;
162425bb815Sopenharmony_ci
163425bb815Sopenharmony_ci    if (jerryx_handle_scope_pool.count != JERRYX_SCOPE_PRELIST_SIZE)
164425bb815Sopenharmony_ci    {
165425bb815Sopenharmony_ci      jerryx_handle_scope_dynamic_t *dy_current = (jerryx_handle_scope_dynamic_t *) jerryx_handle_scope_current;
166425bb815Sopenharmony_ci      dy_scope->parent = dy_current;
167425bb815Sopenharmony_ci      dy_current->child = dy_scope;
168425bb815Sopenharmony_ci    }
169425bb815Sopenharmony_ci    else
170425bb815Sopenharmony_ci    {
171425bb815Sopenharmony_ci      jerryx_handle_scope_pool.start = dy_scope;
172425bb815Sopenharmony_ci      dy_scope->parent = NULL;
173425bb815Sopenharmony_ci    }
174425bb815Sopenharmony_ci
175425bb815Sopenharmony_ci    scope = (jerryx_handle_scope_t *) dy_scope;
176425bb815Sopenharmony_ci  }
177425bb815Sopenharmony_ci
178425bb815Sopenharmony_ci  scope->prelist_handle_count = 0;
179425bb815Sopenharmony_ci  scope->escaped = false;
180425bb815Sopenharmony_ci  scope->handle_ptr = NULL;
181425bb815Sopenharmony_ci
182425bb815Sopenharmony_ci  jerryx_handle_scope_current = scope;
183425bb815Sopenharmony_ci  ++jerryx_handle_scope_pool.count;
184425bb815Sopenharmony_ci  return (jerryx_handle_scope_t *) scope;
185425bb815Sopenharmony_ci} /** jerryx_handle_scope_alloc */
186425bb815Sopenharmony_ci
187425bb815Sopenharmony_ci/**
188425bb815Sopenharmony_ci * Deannounce a previously claimed handle scope, return it to pool
189425bb815Sopenharmony_ci * or free the allocated memory block.
190425bb815Sopenharmony_ci *
191425bb815Sopenharmony_ci * @param scope - the one to be freed.
192425bb815Sopenharmony_ci */
193425bb815Sopenharmony_civoid
194425bb815Sopenharmony_cijerryx_handle_scope_free (jerryx_handle_scope_t *scope)
195425bb815Sopenharmony_ci{
196425bb815Sopenharmony_ci  if (scope == &jerryx_handle_scope_root)
197425bb815Sopenharmony_ci  {
198425bb815Sopenharmony_ci    return;
199425bb815Sopenharmony_ci  }
200425bb815Sopenharmony_ci
201425bb815Sopenharmony_ci  --jerryx_handle_scope_pool.count;
202425bb815Sopenharmony_ci  if (scope == jerryx_handle_scope_current)
203425bb815Sopenharmony_ci  {
204425bb815Sopenharmony_ci    jerryx_handle_scope_current = jerryx_handle_scope_get_parent (scope);
205425bb815Sopenharmony_ci  }
206425bb815Sopenharmony_ci
207425bb815Sopenharmony_ci  if (!jerryx_handle_scope_is_in_prelist (scope))
208425bb815Sopenharmony_ci  {
209425bb815Sopenharmony_ci    jerryx_handle_scope_dynamic_t *dy_scope = (jerryx_handle_scope_dynamic_t *) scope;
210425bb815Sopenharmony_ci    if (dy_scope == jerryx_handle_scope_pool.start)
211425bb815Sopenharmony_ci    {
212425bb815Sopenharmony_ci      jerryx_handle_scope_pool.start = dy_scope->child;
213425bb815Sopenharmony_ci    }
214425bb815Sopenharmony_ci    else if (dy_scope->parent != NULL)
215425bb815Sopenharmony_ci    {
216425bb815Sopenharmony_ci      dy_scope->parent->child = dy_scope->child;
217425bb815Sopenharmony_ci    }
218425bb815Sopenharmony_ci    free (dy_scope);
219425bb815Sopenharmony_ci    return;
220425bb815Sopenharmony_ci  }
221425bb815Sopenharmony_ci  /**
222425bb815Sopenharmony_ci   * Nothing to do with scopes in prelist
223425bb815Sopenharmony_ci   */
224425bb815Sopenharmony_ci} /** jerryx_handle_scope_free */
225