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 19static jerryx_handle_scope_t jerryx_handle_scope_root = 20{ 21 .prelist_handle_count = 0, 22 .handle_ptr = NULL, 23}; 24static jerryx_handle_scope_t *jerryx_handle_scope_current = &jerryx_handle_scope_root; 25static 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 */ 39jerryx_handle_scope_t * 40jerryx_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 */ 48jerryx_handle_scope_t * 49jerryx_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 */ 59static bool 60jerryx_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 */ 75jerryx_handle_scope_t * 76jerryx_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 */ 108jerryx_handle_scope_t * 109jerryx_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 */ 149jerryx_handle_scope_t * 150jerryx_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 */ 193void 194jerryx_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