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 "ecma-globals.h" 17425bb815Sopenharmony_ci#include "ecma-helpers.h" 18425bb815Sopenharmony_ci#include "ecma-property-hashmap.h" 19425bb815Sopenharmony_ci#include "jrt-libc-includes.h" 20425bb815Sopenharmony_ci#include "jcontext.h" 21425bb815Sopenharmony_ci 22425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 23425bb815Sopenharmony_ci * @{ 24425bb815Sopenharmony_ci * 25425bb815Sopenharmony_ci * \addtogroup ecmapropertyhashmap Property hashmap 26425bb815Sopenharmony_ci * @{ 27425bb815Sopenharmony_ci */ 28425bb815Sopenharmony_ci 29425bb815Sopenharmony_ci#if ENABLED (JERRY_PROPRETY_HASHMAP) 30425bb815Sopenharmony_ci 31425bb815Sopenharmony_ci/** 32425bb815Sopenharmony_ci * Compute the total size of the property hashmap. 33425bb815Sopenharmony_ci */ 34425bb815Sopenharmony_ci#define ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE(max_property_count) \ 35425bb815Sopenharmony_ci (sizeof (ecma_property_hashmap_t) + (max_property_count * sizeof (jmem_cpointer_t)) + (max_property_count >> 3)) 36425bb815Sopenharmony_ci 37425bb815Sopenharmony_ci/** 38425bb815Sopenharmony_ci * Number of items in the stepping table. 39425bb815Sopenharmony_ci */ 40425bb815Sopenharmony_ci#define ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS 8 41425bb815Sopenharmony_ci 42425bb815Sopenharmony_ci/** 43425bb815Sopenharmony_ci * Stepping values for searching items in the hashmap. 44425bb815Sopenharmony_ci */ 45425bb815Sopenharmony_cistatic const uint8_t ecma_property_hashmap_steps[ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS] JERRY_ATTR_CONST_DATA = 46425bb815Sopenharmony_ci{ 47425bb815Sopenharmony_ci 3, 5, 7, 11, 13, 17, 19, 23 48425bb815Sopenharmony_ci}; 49425bb815Sopenharmony_ci 50425bb815Sopenharmony_ci/** 51425bb815Sopenharmony_ci * Get the value of a bit in a bitmap. 52425bb815Sopenharmony_ci */ 53425bb815Sopenharmony_ci#define ECMA_PROPERTY_HASHMAP_GET_BIT(byte_p, index) \ 54425bb815Sopenharmony_ci ((byte_p)[(index) >> 3] & (1 << ((index) & 0x7))) 55425bb815Sopenharmony_ci 56425bb815Sopenharmony_ci/** 57425bb815Sopenharmony_ci * Clear the value of a bit in a bitmap. 58425bb815Sopenharmony_ci */ 59425bb815Sopenharmony_ci#define ECMA_PROPERTY_HASHMAP_CLEAR_BIT(byte_p, index) \ 60425bb815Sopenharmony_ci ((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] & ~(1 << ((index) & 0x7)))) 61425bb815Sopenharmony_ci 62425bb815Sopenharmony_ci/** 63425bb815Sopenharmony_ci * Set the value of a bit in a bitmap. 64425bb815Sopenharmony_ci */ 65425bb815Sopenharmony_ci#define ECMA_PROPERTY_HASHMAP_SET_BIT(byte_p, index) \ 66425bb815Sopenharmony_ci ((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] | (1 << ((index) & 0x7)))) 67425bb815Sopenharmony_ci 68425bb815Sopenharmony_ci/** 69425bb815Sopenharmony_ci * Create a new property hashmap for the object. 70425bb815Sopenharmony_ci * The object must not have a property hashmap. 71425bb815Sopenharmony_ci */ 72425bb815Sopenharmony_civoid 73425bb815Sopenharmony_ciecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ 74425bb815Sopenharmony_ci{ 75425bb815Sopenharmony_ci if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) != ECMA_PROP_HASHMAP_ALLOC_ON) 76425bb815Sopenharmony_ci { 77425bb815Sopenharmony_ci return; 78425bb815Sopenharmony_ci } 79425bb815Sopenharmony_ci 80425bb815Sopenharmony_ci jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; 81425bb815Sopenharmony_ci 82425bb815Sopenharmony_ci if (prop_iter_cp == JMEM_CP_NULL) 83425bb815Sopenharmony_ci { 84425bb815Sopenharmony_ci return; 85425bb815Sopenharmony_ci } 86425bb815Sopenharmony_ci 87425bb815Sopenharmony_ci uint32_t named_property_count = 0; 88425bb815Sopenharmony_ci 89425bb815Sopenharmony_ci while (prop_iter_cp != JMEM_CP_NULL) 90425bb815Sopenharmony_ci { 91425bb815Sopenharmony_ci ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); 92425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); 93425bb815Sopenharmony_ci 94425bb815Sopenharmony_ci for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) 95425bb815Sopenharmony_ci { 96425bb815Sopenharmony_ci ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[i]); 97425bb815Sopenharmony_ci 98425bb815Sopenharmony_ci if (type != ECMA_PROPERTY_TYPE_SPECIAL) 99425bb815Sopenharmony_ci { 100425bb815Sopenharmony_ci named_property_count++; 101425bb815Sopenharmony_ci } 102425bb815Sopenharmony_ci } 103425bb815Sopenharmony_ci prop_iter_cp = prop_iter_p->next_property_cp; 104425bb815Sopenharmony_ci } 105425bb815Sopenharmony_ci 106425bb815Sopenharmony_ci if (named_property_count < (ECMA_PROPERTY_HASMAP_MINIMUM_SIZE / 2)) 107425bb815Sopenharmony_ci { 108425bb815Sopenharmony_ci return; 109425bb815Sopenharmony_ci } 110425bb815Sopenharmony_ci 111425bb815Sopenharmony_ci /* The max_property_count must be power of 2. */ 112425bb815Sopenharmony_ci uint32_t max_property_count = ECMA_PROPERTY_HASMAP_MINIMUM_SIZE; 113425bb815Sopenharmony_ci 114425bb815Sopenharmony_ci /* At least 1/3 items must be NULL. */ 115425bb815Sopenharmony_ci while (max_property_count < (named_property_count + (named_property_count >> 1))) 116425bb815Sopenharmony_ci { 117425bb815Sopenharmony_ci max_property_count <<= 1; 118425bb815Sopenharmony_ci } 119425bb815Sopenharmony_ci 120425bb815Sopenharmony_ci size_t total_size = ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (max_property_count); 121425bb815Sopenharmony_ci 122425bb815Sopenharmony_ci ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) jmem_heap_alloc_block_null_on_error (total_size); 123425bb815Sopenharmony_ci 124425bb815Sopenharmony_ci if (hashmap_p == NULL) 125425bb815Sopenharmony_ci { 126425bb815Sopenharmony_ci return; 127425bb815Sopenharmony_ci } 128425bb815Sopenharmony_ci 129425bb815Sopenharmony_ci memset (hashmap_p, 0, total_size); 130425bb815Sopenharmony_ci 131425bb815Sopenharmony_ci hashmap_p->header.types[0] = ECMA_PROPERTY_TYPE_HASHMAP; 132425bb815Sopenharmony_ci hashmap_p->header.next_property_cp = object_p->u1.property_list_cp; 133425bb815Sopenharmony_ci hashmap_p->max_property_count = max_property_count; 134425bb815Sopenharmony_ci hashmap_p->null_count = max_property_count - named_property_count; 135425bb815Sopenharmony_ci hashmap_p->unused_count = max_property_count - named_property_count; 136425bb815Sopenharmony_ci 137425bb815Sopenharmony_ci jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); 138425bb815Sopenharmony_ci uint8_t *bits_p = (uint8_t *) (pair_list_p + max_property_count); 139425bb815Sopenharmony_ci uint32_t mask = max_property_count - 1; 140425bb815Sopenharmony_ci 141425bb815Sopenharmony_ci prop_iter_cp = object_p->u1.property_list_cp; 142425bb815Sopenharmony_ci ECMA_SET_NON_NULL_POINTER (object_p->u1.property_list_cp, hashmap_p); 143425bb815Sopenharmony_ci 144425bb815Sopenharmony_ci while (prop_iter_cp != JMEM_CP_NULL) 145425bb815Sopenharmony_ci { 146425bb815Sopenharmony_ci ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); 147425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); 148425bb815Sopenharmony_ci 149425bb815Sopenharmony_ci for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) 150425bb815Sopenharmony_ci { 151425bb815Sopenharmony_ci if (!ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i])) 152425bb815Sopenharmony_ci { 153425bb815Sopenharmony_ci continue; 154425bb815Sopenharmony_ci } 155425bb815Sopenharmony_ci 156425bb815Sopenharmony_ci ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p; 157425bb815Sopenharmony_ci 158425bb815Sopenharmony_ci uint32_t entry_index = ecma_string_get_property_name_hash (prop_iter_p->types[i], 159425bb815Sopenharmony_ci property_pair_p->names_cp[i]); 160425bb815Sopenharmony_ci uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; 161425bb815Sopenharmony_ci 162425bb815Sopenharmony_ci entry_index &= mask; 163425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 164425bb815Sopenharmony_ci /* Because max_property_count (power of 2) and step (a prime 165425bb815Sopenharmony_ci * number) are relative primes, all entries of the hasmap are 166425bb815Sopenharmony_ci * visited exactly once before the start entry index is reached 167425bb815Sopenharmony_ci * again. Furthermore because at least one NULL is present in 168425bb815Sopenharmony_ci * the hashmap, the while loop must be terminated before the 169425bb815Sopenharmony_ci * the starting index is reached again. */ 170425bb815Sopenharmony_ci uint32_t start_entry_index = entry_index; 171425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 172425bb815Sopenharmony_ci 173425bb815Sopenharmony_ci while (pair_list_p[entry_index] != ECMA_NULL_POINTER) 174425bb815Sopenharmony_ci { 175425bb815Sopenharmony_ci entry_index = (entry_index + step) & mask; 176425bb815Sopenharmony_ci 177425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 178425bb815Sopenharmony_ci JERRY_ASSERT (entry_index != start_entry_index); 179425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 180425bb815Sopenharmony_ci } 181425bb815Sopenharmony_ci 182425bb815Sopenharmony_ci ECMA_SET_NON_NULL_POINTER (pair_list_p[entry_index], property_pair_p); 183425bb815Sopenharmony_ci 184425bb815Sopenharmony_ci if (i != 0) 185425bb815Sopenharmony_ci { 186425bb815Sopenharmony_ci ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index); 187425bb815Sopenharmony_ci } 188425bb815Sopenharmony_ci } 189425bb815Sopenharmony_ci 190425bb815Sopenharmony_ci prop_iter_cp = prop_iter_p->next_property_cp; 191425bb815Sopenharmony_ci } 192425bb815Sopenharmony_ci} /* ecma_property_hashmap_create */ 193425bb815Sopenharmony_ci 194425bb815Sopenharmony_ci/** 195425bb815Sopenharmony_ci * Free the hashmap of the object. 196425bb815Sopenharmony_ci * The object must have a property hashmap. 197425bb815Sopenharmony_ci */ 198425bb815Sopenharmony_civoid 199425bb815Sopenharmony_ciecma_property_hashmap_free (ecma_object_t *object_p) /**< object */ 200425bb815Sopenharmony_ci{ 201425bb815Sopenharmony_ci /* Property hash must be exists and must be the first property. */ 202425bb815Sopenharmony_ci JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); 203425bb815Sopenharmony_ci 204425bb815Sopenharmony_ci ecma_property_header_t *property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, 205425bb815Sopenharmony_ci object_p->u1.property_list_cp); 206425bb815Sopenharmony_ci 207425bb815Sopenharmony_ci JERRY_ASSERT (property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP); 208425bb815Sopenharmony_ci 209425bb815Sopenharmony_ci ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) property_p; 210425bb815Sopenharmony_ci 211425bb815Sopenharmony_ci object_p->u1.property_list_cp = property_p->next_property_cp; 212425bb815Sopenharmony_ci 213425bb815Sopenharmony_ci jmem_heap_free_block (hashmap_p, 214425bb815Sopenharmony_ci ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (hashmap_p->max_property_count)); 215425bb815Sopenharmony_ci} /* ecma_property_hashmap_free */ 216425bb815Sopenharmony_ci 217425bb815Sopenharmony_ci/** 218425bb815Sopenharmony_ci * Insert named property into the hashmap. 219425bb815Sopenharmony_ci */ 220425bb815Sopenharmony_civoid 221425bb815Sopenharmony_ciecma_property_hashmap_insert (ecma_object_t *object_p, /**< object */ 222425bb815Sopenharmony_ci ecma_string_t *name_p, /**< name of the property */ 223425bb815Sopenharmony_ci ecma_property_pair_t *property_pair_p, /**< property pair */ 224425bb815Sopenharmony_ci int property_index) /**< property index in the pair (0 or 1) */ 225425bb815Sopenharmony_ci{ 226425bb815Sopenharmony_ci JERRY_ASSERT (property_pair_p != NULL); 227425bb815Sopenharmony_ci 228425bb815Sopenharmony_ci ecma_property_hashmap_t *hashmap_p = ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t, 229425bb815Sopenharmony_ci object_p->u1.property_list_cp); 230425bb815Sopenharmony_ci 231425bb815Sopenharmony_ci JERRY_ASSERT (hashmap_p->header.types[0] == ECMA_PROPERTY_TYPE_HASHMAP); 232425bb815Sopenharmony_ci 233425bb815Sopenharmony_ci /* The NULLs are reduced below 1/8 of the hashmap. */ 234425bb815Sopenharmony_ci if (hashmap_p->null_count < (hashmap_p->max_property_count >> 3)) 235425bb815Sopenharmony_ci { 236425bb815Sopenharmony_ci ecma_property_hashmap_free (object_p); 237425bb815Sopenharmony_ci ecma_property_hashmap_create (object_p); 238425bb815Sopenharmony_ci return; 239425bb815Sopenharmony_ci } 240425bb815Sopenharmony_ci 241425bb815Sopenharmony_ci JERRY_ASSERT (property_index < ECMA_PROPERTY_PAIR_ITEM_COUNT); 242425bb815Sopenharmony_ci 243425bb815Sopenharmony_ci uint32_t entry_index = ecma_string_hash (name_p); 244425bb815Sopenharmony_ci uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; 245425bb815Sopenharmony_ci uint32_t mask = hashmap_p->max_property_count - 1; 246425bb815Sopenharmony_ci entry_index &= mask; 247425bb815Sopenharmony_ci 248425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 249425bb815Sopenharmony_ci /* See the comment for this variable in ecma_property_hashmap_create. */ 250425bb815Sopenharmony_ci uint32_t start_entry_index = entry_index; 251425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 252425bb815Sopenharmony_ci 253425bb815Sopenharmony_ci jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); 254425bb815Sopenharmony_ci 255425bb815Sopenharmony_ci while (pair_list_p[entry_index] != ECMA_NULL_POINTER) 256425bb815Sopenharmony_ci { 257425bb815Sopenharmony_ci entry_index = (entry_index + step) & mask; 258425bb815Sopenharmony_ci 259425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 260425bb815Sopenharmony_ci JERRY_ASSERT (entry_index != start_entry_index); 261425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 262425bb815Sopenharmony_ci } 263425bb815Sopenharmony_ci 264425bb815Sopenharmony_ci ECMA_SET_NON_NULL_POINTER (pair_list_p[entry_index], property_pair_p); 265425bb815Sopenharmony_ci 266425bb815Sopenharmony_ci uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count); 267425bb815Sopenharmony_ci bits_p += (entry_index >> 3); 268425bb815Sopenharmony_ci mask = (uint32_t) (1 << (entry_index & 0x7)); 269425bb815Sopenharmony_ci 270425bb815Sopenharmony_ci if (!(*bits_p & mask)) 271425bb815Sopenharmony_ci { 272425bb815Sopenharmony_ci /* Deleted entries also has ECMA_NULL_POINTER 273425bb815Sopenharmony_ci * value, but they are not NULL values. */ 274425bb815Sopenharmony_ci hashmap_p->null_count--; 275425bb815Sopenharmony_ci JERRY_ASSERT (hashmap_p->null_count > 0); 276425bb815Sopenharmony_ci } 277425bb815Sopenharmony_ci 278425bb815Sopenharmony_ci hashmap_p->unused_count--; 279425bb815Sopenharmony_ci JERRY_ASSERT (hashmap_p->unused_count > 0); 280425bb815Sopenharmony_ci 281425bb815Sopenharmony_ci if (property_index == 0) 282425bb815Sopenharmony_ci { 283425bb815Sopenharmony_ci *bits_p = (uint8_t) ((*bits_p) & ~mask); 284425bb815Sopenharmony_ci } 285425bb815Sopenharmony_ci else 286425bb815Sopenharmony_ci { 287425bb815Sopenharmony_ci *bits_p = (uint8_t) ((*bits_p) | mask); 288425bb815Sopenharmony_ci } 289425bb815Sopenharmony_ci} /* ecma_property_hashmap_insert */ 290425bb815Sopenharmony_ci 291425bb815Sopenharmony_ci/** 292425bb815Sopenharmony_ci * Delete named property from the hashmap. 293425bb815Sopenharmony_ci * 294425bb815Sopenharmony_ci * @return ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP if hashmap should be recreated 295425bb815Sopenharmony_ci * ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP otherwise 296425bb815Sopenharmony_ci */ 297425bb815Sopenharmony_ciecma_property_hashmap_delete_status 298425bb815Sopenharmony_ciecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */ 299425bb815Sopenharmony_ci jmem_cpointer_t name_cp, /**< property name */ 300425bb815Sopenharmony_ci ecma_property_t *property_p) /**< property */ 301425bb815Sopenharmony_ci{ 302425bb815Sopenharmony_ci ecma_property_hashmap_t *hashmap_p = ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t, 303425bb815Sopenharmony_ci object_p->u1.property_list_cp); 304425bb815Sopenharmony_ci 305425bb815Sopenharmony_ci JERRY_ASSERT (hashmap_p->header.types[0] == ECMA_PROPERTY_TYPE_HASHMAP); 306425bb815Sopenharmony_ci 307425bb815Sopenharmony_ci hashmap_p->unused_count++; 308425bb815Sopenharmony_ci 309425bb815Sopenharmony_ci /* The NULLs are above 3/4 of the hashmap. */ 310425bb815Sopenharmony_ci if (hashmap_p->unused_count > ((hashmap_p->max_property_count * 3) >> 2)) 311425bb815Sopenharmony_ci { 312425bb815Sopenharmony_ci return ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP; 313425bb815Sopenharmony_ci } 314425bb815Sopenharmony_ci 315425bb815Sopenharmony_ci uint32_t entry_index = ecma_string_get_property_name_hash (*property_p, name_cp); 316425bb815Sopenharmony_ci uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; 317425bb815Sopenharmony_ci uint32_t mask = hashmap_p->max_property_count - 1; 318425bb815Sopenharmony_ci jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); 319425bb815Sopenharmony_ci uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count); 320425bb815Sopenharmony_ci 321425bb815Sopenharmony_ci entry_index &= mask; 322425bb815Sopenharmony_ci 323425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 324425bb815Sopenharmony_ci /* See the comment for this variable in ecma_property_hashmap_create. */ 325425bb815Sopenharmony_ci uint32_t start_entry_index = entry_index; 326425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 327425bb815Sopenharmony_ci 328425bb815Sopenharmony_ci while (true) 329425bb815Sopenharmony_ci { 330425bb815Sopenharmony_ci if (pair_list_p[entry_index] != ECMA_NULL_POINTER) 331425bb815Sopenharmony_ci { 332425bb815Sopenharmony_ci size_t offset = 0; 333425bb815Sopenharmony_ci 334425bb815Sopenharmony_ci if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) 335425bb815Sopenharmony_ci { 336425bb815Sopenharmony_ci offset = 1; 337425bb815Sopenharmony_ci } 338425bb815Sopenharmony_ci 339425bb815Sopenharmony_ci ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, 340425bb815Sopenharmony_ci pair_list_p[entry_index]); 341425bb815Sopenharmony_ci 342425bb815Sopenharmony_ci if ((property_pair_p->header.types + offset) == property_p) 343425bb815Sopenharmony_ci { 344425bb815Sopenharmony_ci JERRY_ASSERT (property_pair_p->names_cp[offset] == name_cp); 345425bb815Sopenharmony_ci 346425bb815Sopenharmony_ci pair_list_p[entry_index] = ECMA_NULL_POINTER; 347425bb815Sopenharmony_ci ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index); 348425bb815Sopenharmony_ci return ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP; 349425bb815Sopenharmony_ci } 350425bb815Sopenharmony_ci } 351425bb815Sopenharmony_ci else 352425bb815Sopenharmony_ci { 353425bb815Sopenharmony_ci /* Must be a deleted entry. */ 354425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)); 355425bb815Sopenharmony_ci } 356425bb815Sopenharmony_ci 357425bb815Sopenharmony_ci entry_index = (entry_index + step) & mask; 358425bb815Sopenharmony_ci 359425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 360425bb815Sopenharmony_ci JERRY_ASSERT (entry_index != start_entry_index); 361425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 362425bb815Sopenharmony_ci } 363425bb815Sopenharmony_ci} /* ecma_property_hashmap_delete */ 364425bb815Sopenharmony_ci 365425bb815Sopenharmony_ci/** 366425bb815Sopenharmony_ci * Find a named property. 367425bb815Sopenharmony_ci * 368425bb815Sopenharmony_ci * @return pointer to the property if found or NULL otherwise 369425bb815Sopenharmony_ci */ 370425bb815Sopenharmony_ciecma_property_t * 371425bb815Sopenharmony_ciecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ 372425bb815Sopenharmony_ci ecma_string_t *name_p, /**< property name */ 373425bb815Sopenharmony_ci jmem_cpointer_t *property_real_name_cp) /**< [out] property real name */ 374425bb815Sopenharmony_ci{ 375425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 376425bb815Sopenharmony_ci /* A sanity check in debug mode: a named property must be present 377425bb815Sopenharmony_ci * in both the property hashmap and in the property chain, or missing 378425bb815Sopenharmony_ci * from both data collection. The following code checks the property 379425bb815Sopenharmony_ci * chain, and sets the property_found variable. */ 380425bb815Sopenharmony_ci bool property_found = false; 381425bb815Sopenharmony_ci 382425bb815Sopenharmony_ci jmem_cpointer_t prop_iter_cp = hashmap_p->header.next_property_cp; 383425bb815Sopenharmony_ci 384425bb815Sopenharmony_ci while (prop_iter_cp != JMEM_CP_NULL && !property_found) 385425bb815Sopenharmony_ci { 386425bb815Sopenharmony_ci ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); 387425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); 388425bb815Sopenharmony_ci 389425bb815Sopenharmony_ci ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; 390425bb815Sopenharmony_ci 391425bb815Sopenharmony_ci for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) 392425bb815Sopenharmony_ci { 393425bb815Sopenharmony_ci if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i])) 394425bb815Sopenharmony_ci { 395425bb815Sopenharmony_ci if (ecma_string_compare_to_property_name (prop_iter_p->types[i], 396425bb815Sopenharmony_ci prop_pair_p->names_cp[i], 397425bb815Sopenharmony_ci name_p)) 398425bb815Sopenharmony_ci { 399425bb815Sopenharmony_ci /* Property is found */ 400425bb815Sopenharmony_ci property_found = true; 401425bb815Sopenharmony_ci break; 402425bb815Sopenharmony_ci } 403425bb815Sopenharmony_ci } 404425bb815Sopenharmony_ci } 405425bb815Sopenharmony_ci 406425bb815Sopenharmony_ci prop_iter_cp = prop_iter_p->next_property_cp; 407425bb815Sopenharmony_ci } 408425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 409425bb815Sopenharmony_ci 410425bb815Sopenharmony_ci uint32_t entry_index = ecma_string_hash (name_p); 411425bb815Sopenharmony_ci uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; 412425bb815Sopenharmony_ci uint32_t mask = hashmap_p->max_property_count - 1; 413425bb815Sopenharmony_ci jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); 414425bb815Sopenharmony_ci uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count); 415425bb815Sopenharmony_ci entry_index &= mask; 416425bb815Sopenharmony_ci 417425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 418425bb815Sopenharmony_ci /* See the comment for this variable in ecma_property_hashmap_create. */ 419425bb815Sopenharmony_ci uint32_t start_entry_index = entry_index; 420425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 421425bb815Sopenharmony_ci 422425bb815Sopenharmony_ci if (ECMA_IS_DIRECT_STRING (name_p)) 423425bb815Sopenharmony_ci { 424425bb815Sopenharmony_ci ecma_property_t prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (name_p); 425425bb815Sopenharmony_ci jmem_cpointer_t property_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (name_p); 426425bb815Sopenharmony_ci 427425bb815Sopenharmony_ci JERRY_ASSERT (prop_name_type > 0); 428425bb815Sopenharmony_ci 429425bb815Sopenharmony_ci while (true) 430425bb815Sopenharmony_ci { 431425bb815Sopenharmony_ci if (pair_list_p[entry_index] != ECMA_NULL_POINTER) 432425bb815Sopenharmony_ci { 433425bb815Sopenharmony_ci size_t offset = 0; 434425bb815Sopenharmony_ci if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) 435425bb815Sopenharmony_ci { 436425bb815Sopenharmony_ci offset = 1; 437425bb815Sopenharmony_ci } 438425bb815Sopenharmony_ci 439425bb815Sopenharmony_ci ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, 440425bb815Sopenharmony_ci pair_list_p[entry_index]); 441425bb815Sopenharmony_ci 442425bb815Sopenharmony_ci ecma_property_t *property_p = property_pair_p->header.types + offset; 443425bb815Sopenharmony_ci 444425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); 445425bb815Sopenharmony_ci 446425bb815Sopenharmony_ci if (property_pair_p->names_cp[offset] == property_name_cp 447425bb815Sopenharmony_ci && ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == prop_name_type) 448425bb815Sopenharmony_ci { 449425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 450425bb815Sopenharmony_ci JERRY_ASSERT (property_found); 451425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 452425bb815Sopenharmony_ci 453425bb815Sopenharmony_ci *property_real_name_cp = property_name_cp; 454425bb815Sopenharmony_ci return property_p; 455425bb815Sopenharmony_ci } 456425bb815Sopenharmony_ci } 457425bb815Sopenharmony_ci else 458425bb815Sopenharmony_ci { 459425bb815Sopenharmony_ci if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) 460425bb815Sopenharmony_ci { 461425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 462425bb815Sopenharmony_ci JERRY_ASSERT (!property_found); 463425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 464425bb815Sopenharmony_ci 465425bb815Sopenharmony_ci return NULL; 466425bb815Sopenharmony_ci } 467425bb815Sopenharmony_ci /* Otherwise it is a deleted entry. */ 468425bb815Sopenharmony_ci } 469425bb815Sopenharmony_ci 470425bb815Sopenharmony_ci entry_index = (entry_index + step) & mask; 471425bb815Sopenharmony_ci 472425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 473425bb815Sopenharmony_ci JERRY_ASSERT (entry_index != start_entry_index); 474425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 475425bb815Sopenharmony_ci } 476425bb815Sopenharmony_ci } 477425bb815Sopenharmony_ci 478425bb815Sopenharmony_ci while (true) 479425bb815Sopenharmony_ci { 480425bb815Sopenharmony_ci if (pair_list_p[entry_index] != ECMA_NULL_POINTER) 481425bb815Sopenharmony_ci { 482425bb815Sopenharmony_ci size_t offset = 0; 483425bb815Sopenharmony_ci if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) 484425bb815Sopenharmony_ci { 485425bb815Sopenharmony_ci offset = 1; 486425bb815Sopenharmony_ci } 487425bb815Sopenharmony_ci 488425bb815Sopenharmony_ci ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, 489425bb815Sopenharmony_ci pair_list_p[entry_index]); 490425bb815Sopenharmony_ci 491425bb815Sopenharmony_ci ecma_property_t *property_p = property_pair_p->header.types + offset; 492425bb815Sopenharmony_ci 493425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); 494425bb815Sopenharmony_ci 495425bb815Sopenharmony_ci if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_PTR) 496425bb815Sopenharmony_ci { 497425bb815Sopenharmony_ci ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_pair_p->names_cp[offset]); 498425bb815Sopenharmony_ci 499425bb815Sopenharmony_ci if (ecma_compare_ecma_non_direct_strings (prop_name_p, name_p)) 500425bb815Sopenharmony_ci { 501425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 502425bb815Sopenharmony_ci JERRY_ASSERT (property_found); 503425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 504425bb815Sopenharmony_ci 505425bb815Sopenharmony_ci *property_real_name_cp = property_pair_p->names_cp[offset]; 506425bb815Sopenharmony_ci return property_p; 507425bb815Sopenharmony_ci } 508425bb815Sopenharmony_ci } 509425bb815Sopenharmony_ci } 510425bb815Sopenharmony_ci else 511425bb815Sopenharmony_ci { 512425bb815Sopenharmony_ci if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) 513425bb815Sopenharmony_ci { 514425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 515425bb815Sopenharmony_ci JERRY_ASSERT (!property_found); 516425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 517425bb815Sopenharmony_ci 518425bb815Sopenharmony_ci return NULL; 519425bb815Sopenharmony_ci } 520425bb815Sopenharmony_ci /* Otherwise it is a deleted entry. */ 521425bb815Sopenharmony_ci } 522425bb815Sopenharmony_ci 523425bb815Sopenharmony_ci entry_index = (entry_index + step) & mask; 524425bb815Sopenharmony_ci 525425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 526425bb815Sopenharmony_ci JERRY_ASSERT (entry_index != start_entry_index); 527425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 528425bb815Sopenharmony_ci } 529425bb815Sopenharmony_ci} /* ecma_property_hashmap_find */ 530425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */ 531425bb815Sopenharmony_ci 532425bb815Sopenharmony_ci/** 533425bb815Sopenharmony_ci * @} 534425bb815Sopenharmony_ci * @} 535425bb815Sopenharmony_ci */ 536