@@ -45960,7 +45960,7 @@ typedef struct JSMapRecord {
4596045960 struct JSMapState *map;
4596145961 struct JSMapRecord *next_weak_ref;
4596245962 struct list_head link;
45963- struct list_head hash_link ;
45963+ struct JSMapRecord *hash_next ;
4596445964 JSValue key;
4596545965 JSValue value;
4596645966} JSMapRecord;
@@ -45969,7 +45969,7 @@ typedef struct JSMapState {
4596945969 BOOL is_weak; /* TRUE if WeakSet/WeakMap */
4597045970 struct list_head records; /* list of JSMapRecord.link */
4597145971 uint32_t record_count;
45972- struct list_head *hash_table;
45972+ JSMapRecord * *hash_table;
4597345973 uint32_t hash_size; /* must be a power of two */
4597445974 uint32_t record_count_threshold; /* count at which a hash table
4597545975 resize is needed */
@@ -45998,10 +45998,9 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
4599845998 s->is_weak = is_weak;
4599945999 JS_SetOpaque(obj, s);
4600046000 s->hash_size = 1;
46001- s->hash_table = js_malloc (ctx, sizeof(s->hash_table[0]) * s->hash_size);
46001+ s->hash_table = js_mallocz (ctx, sizeof(s->hash_table[0]) * s->hash_size);
4600246002 if (!s->hash_table)
4600346003 goto fail;
46004- init_list_head(&s->hash_table[0]);
4600546004 s->record_count_threshold = 4;
4600646005
4600746006 arr = JS_UNDEFINED;
@@ -46100,7 +46099,7 @@ static JSValueConst map_normalize_key(JSContext *ctx, JSValueConst key)
4610046099}
4610146100
4610246101/* XXX: better hash ? */
46103- static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
46102+ static uint32_t map_hash_key(JSValueConst key)
4610446103{
4610546104 uint32_t tag = JS_VALUE_GET_NORM_TAG(key);
4610646105 uint32_t h;
@@ -46158,12 +46157,10 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
4615846157static JSMapRecord *map_find_record(JSContext *ctx, JSMapState *s,
4615946158 JSValueConst key)
4616046159{
46161- struct list_head *el;
4616246160 JSMapRecord *mr;
4616346161 uint32_t h;
46164- h = map_hash_key(ctx, key) & (s->hash_size - 1);
46165- list_for_each(el, &s->hash_table[h]) {
46166- mr = list_entry(el, JSMapRecord, hash_link);
46162+ h = map_hash_key(key) & (s->hash_size - 1);
46163+ for(mr = s->hash_table[h]; mr != NULL; mr = mr->hash_next) {
4616746164 if (js_same_value_zero(ctx, mr->key, key))
4616846165 return mr;
4616946166 }
@@ -46172,10 +46169,10 @@ static JSMapRecord *map_find_record(JSContext *ctx, JSMapState *s,
4617246169
4617346170static void map_hash_resize(JSContext *ctx, JSMapState *s)
4617446171{
46175- uint32_t new_hash_size, i, h;
46172+ uint32_t new_hash_size, h;
4617646173 size_t slack;
46177- struct list_head *new_hash_table, * el;
46178- JSMapRecord *mr;
46174+ struct list_head *el;
46175+ JSMapRecord *mr, **new_hash_table ;
4617946176
4618046177 /* XXX: no reporting of memory allocation failure */
4618146178 if (s->hash_size == 1)
@@ -46187,14 +46184,14 @@ static void map_hash_resize(JSContext *ctx, JSMapState *s)
4618746184 if (!new_hash_table)
4618846185 return;
4618946186
46190- for(i = 0; i < new_hash_size; i++)
46191- init_list_head(&new_hash_table[i]);
46187+ memset(new_hash_table, 0, sizeof(new_hash_table[0]) * new_hash_size);
4619246188
4619346189 list_for_each(el, &s->records) {
4619446190 mr = list_entry(el, JSMapRecord, link);
4619546191 if (!mr->empty) {
46196- h = map_hash_key(ctx, mr->key) & (new_hash_size - 1);
46197- list_add_tail(&mr->hash_link, &new_hash_table[h]);
46192+ h = map_hash_key(mr->key) & (new_hash_size - 1);
46193+ mr->hash_next = new_hash_table[h];
46194+ new_hash_table[h] = mr;
4619846195 }
4619946196 }
4620046197 s->hash_table = new_hash_table;
@@ -46223,8 +46220,9 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
4622346220 JS_DupValue(ctx, key);
4622446221 }
4622546222 mr->key = (JSValue)key;
46226- h = map_hash_key(ctx, key) & (s->hash_size - 1);
46227- list_add_tail(&mr->hash_link, &s->hash_table[h]);
46223+ h = map_hash_key(key) & (s->hash_size - 1);
46224+ mr->hash_next = s->hash_table[h];
46225+ s->hash_table[h] = mr;
4622846226 list_add_tail(&mr->link, &s->records);
4622946227 s->record_count++;
4623046228 if (s->record_count >= s->record_count_threshold) {
@@ -46236,7 +46234,7 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
4623646234/* Remove the weak reference from the object weak
4623746235 reference list. we don't use a doubly linked list to
4623846236 save space, assuming a given object has few weak
46239- references to it */
46237+ references to it */
4624046238static void delete_weak_ref(JSRuntime *rt, JSMapRecord *mr)
4624146239{
4624246240 JSMapRecord **pmr, *mr1;
@@ -46254,11 +46252,12 @@ static void delete_weak_ref(JSRuntime *rt, JSMapRecord *mr)
4625446252 *pmr = mr1->next_weak_ref;
4625546253}
4625646254
46255+ /* warning: the record must be removed from the hash table before */
4625746256static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr)
4625846257{
4625946258 if (mr->empty)
4626046259 return;
46261- list_del(&mr->hash_link);
46260+
4626246261 if (s->is_weak) {
4626346262 delete_weak_ref(rt, mr);
4626446263 } else {
@@ -46289,16 +46288,31 @@ static void map_decref_record(JSRuntime *rt, JSMapRecord *mr)
4628946288
4629046289static void reset_weak_ref(JSRuntime *rt, JSObject *p)
4629146290{
46292- JSMapRecord *mr, *mr_next;
46291+ JSMapRecord *mr, *mr_next, **pmr, *mr1 ;
4629346292 JSMapState *s;
46294-
46293+ uint32_t h;
46294+ JSValue key;
46295+
4629546296 /* first pass to remove the records from the WeakMap/WeakSet
4629646297 lists */
46298+ key = JS_MKPTR(JS_TAG_OBJECT, p);
4629746299 for(mr = p->first_weak_ref; mr != NULL; mr = mr->next_weak_ref) {
4629846300 s = mr->map;
4629946301 assert(s->is_weak);
4630046302 assert(!mr->empty); /* no iterator on WeakMap/WeakSet */
46301- list_del(&mr->hash_link);
46303+
46304+ /* remove the record from hash table */
46305+ h = map_hash_key(key) & (s->hash_size - 1);
46306+ pmr = &s->hash_table[h];
46307+ for(;;) {
46308+ mr1 = *pmr;
46309+ assert(mr1 != NULL);
46310+ if (mr1 == mr)
46311+ break;
46312+ pmr = &mr1->hash_next;
46313+ }
46314+ *pmr = mr->hash_next;
46315+
4630246316 list_del(&mr->link);
4630346317 }
4630446318
@@ -46376,15 +46390,28 @@ static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val,
4637646390 int argc, JSValueConst *argv, int magic)
4637746391{
4637846392 JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);
46379- JSMapRecord *mr;
46393+ JSMapRecord *mr, **pmr ;
4638046394 JSValueConst key;
46395+ uint32_t h;
4638146396
4638246397 if (!s)
4638346398 return JS_EXCEPTION;
4638446399 key = map_normalize_key(ctx, argv[0]);
46385- mr = map_find_record(ctx, s, key);
46386- if (!mr)
46387- return JS_FALSE;
46400+
46401+ h = map_hash_key(key) & (s->hash_size - 1);
46402+ pmr = &s->hash_table[h];
46403+ for(;;) {
46404+ mr = *pmr;
46405+ if (mr == NULL)
46406+ return JS_FALSE;
46407+ if (js_same_value_zero(ctx, mr->key, key))
46408+ break;
46409+ pmr = &mr->hash_next;
46410+ }
46411+
46412+ /* remove from the hash table */
46413+ *pmr = mr->hash_next;
46414+
4638846415 map_delete_record(ctx->rt, s, mr);
4638946416 return JS_TRUE;
4639046417}
@@ -46398,6 +46425,10 @@ static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val,
4639846425
4639946426 if (!s)
4640046427 return JS_EXCEPTION;
46428+
46429+ /* remove from the hash table */
46430+ memset(s->hash_table, 0, sizeof(s->hash_table[0]) * s->hash_size);
46431+
4640146432 list_for_each_safe(el, el1, &s->records) {
4640246433 mr = list_entry(el, JSMapRecord, link);
4640346434 map_delete_record(ctx->rt, s, mr);
0 commit comments