@@ -419,6 +419,18 @@ typedef union JSFloat64Union {
419
419
uint32_t u32[2];
420
420
} JSFloat64Union;
421
421
422
+ typedef enum {
423
+ JS_WEAK_REF_KIND_MAP,
424
+ } JSWeakRefKindEnum;
425
+
426
+ typedef struct JSWeakRefRecord {
427
+ JSWeakRefKindEnum kind;
428
+ struct JSWeakRefRecord *next_weak_ref;
429
+ union {
430
+ struct JSMapRecord *map_record;
431
+ } u;
432
+ } JSWeakRefRecord;
433
+
422
434
enum {
423
435
JS_ATOM_TYPE_STRING = 1,
424
436
JS_ATOM_TYPE_GLOBAL_SYMBOL,
@@ -449,7 +461,7 @@ struct JSString {
449
461
uint32_t hash : 30;
450
462
uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */
451
463
uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */
452
- struct JSMapRecord *first_weak_ref;
464
+ JSWeakRefRecord *first_weak_ref;
453
465
#ifdef DUMP_LEAKS
454
466
struct list_head link; /* string list */
455
467
#endif
@@ -802,7 +814,7 @@ struct JSObject {
802
814
JSShape *shape; /* prototype and property names + flag */
803
815
JSProperty *prop; /* array of properties */
804
816
/* byte offsets: 24/40 */
805
- struct JSMapRecord *first_weak_ref; /* XXX: use a bit and an external hash table? */
817
+ JSWeakRefRecord *first_weak_ref;
806
818
/* byte offsets: 28/48 */
807
819
union {
808
820
void *opaque;
@@ -1056,7 +1068,7 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p,
1056
1068
JSValueConst getter, JSValueConst setter,
1057
1069
int flags);
1058
1070
static int js_string_memcmp(const JSString *p1, const JSString *p2, int len);
1059
- static void reset_weak_ref(JSRuntime *rt, struct JSMapRecord **first_weak_ref);
1071
+ static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref);
1060
1072
static JSValue js_array_buffer_constructor3(JSContext *ctx,
1061
1073
JSValueConst new_target,
1062
1074
uint64_t len, JSClassID class_id,
@@ -43521,7 +43533,6 @@ typedef struct JSMapRecord {
43521
43533
int ref_count; /* used during enumeration to avoid freeing the record */
43522
43534
BOOL empty; /* TRUE if the record is deleted */
43523
43535
struct JSMapState *map;
43524
- struct JSMapRecord *next_weak_ref;
43525
43536
struct list_head link;
43526
43537
struct list_head hash_link;
43527
43538
JSValue key;
@@ -43754,7 +43765,7 @@ static void map_hash_resize(JSContext *ctx, JSMapState *s)
43754
43765
s->record_count_threshold = new_hash_size * 2;
43755
43766
}
43756
43767
43757
- static JSMapRecord **get_first_weak_ref(JSValueConst key)
43768
+ static JSWeakRefRecord **get_first_weak_ref(JSValueConst key)
43758
43769
{
43759
43770
switch (JS_VALUE_GET_TAG(key)) {
43760
43771
case JS_TAG_OBJECT:
@@ -43778,7 +43789,7 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
43778
43789
JSValueConst key)
43779
43790
{
43780
43791
uint32_t h;
43781
- JSMapRecord *mr, **pmr ;
43792
+ JSMapRecord *mr;
43782
43793
43783
43794
mr = js_malloc(ctx, sizeof(*mr));
43784
43795
if (!mr)
@@ -43787,10 +43798,18 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
43787
43798
mr->map = s;
43788
43799
mr->empty = FALSE;
43789
43800
if (s->is_weak) {
43790
- pmr = get_first_weak_ref(key);
43801
+ JSWeakRefRecord *wr, **pwr;
43802
+ wr = js_malloc(ctx, sizeof(*wr));
43803
+ if (!wr) {
43804
+ js_free(ctx, mr);
43805
+ return NULL;
43806
+ }
43807
+ wr->kind = JS_WEAK_REF_KIND_MAP;
43808
+ wr->u.map_record = mr;
43809
+ pwr = get_first_weak_ref(key);
43791
43810
/* Add the weak reference */
43792
- mr ->next_weak_ref = *pmr ;
43793
- *pmr = mr ;
43811
+ wr ->next_weak_ref = *pwr ;
43812
+ *pwr = wr ;
43794
43813
} else {
43795
43814
JS_DupValue(ctx, key);
43796
43815
}
@@ -43809,19 +43828,20 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
43809
43828
reference list. we don't use a doubly linked list to
43810
43829
save space, assuming a given object has few weak
43811
43830
references to it */
43812
- static void delete_weak_ref (JSRuntime *rt, JSMapRecord *mr)
43831
+ static void delete_map_weak_ref (JSRuntime *rt, JSMapRecord *mr)
43813
43832
{
43814
- JSMapRecord **pmr , *mr1 ;
43833
+ JSWeakRefRecord **pwr , *wr ;
43815
43834
43816
- pmr = get_first_weak_ref(mr->key);
43835
+ pwr = get_first_weak_ref(mr->key);
43817
43836
for(;;) {
43818
- mr1 = *pmr ;
43819
- assert(mr1 != NULL);
43820
- if (mr1 == mr)
43837
+ wr = *pwr ;
43838
+ assert(wr != NULL);
43839
+ if (wr->kind == JS_WEAK_REF_KIND_MAP && wr->u.map_record == mr)
43821
43840
break;
43822
- pmr = &mr1 ->next_weak_ref;
43841
+ pwr = &wr ->next_weak_ref;
43823
43842
}
43824
- *pmr = mr1->next_weak_ref;
43843
+ *pwr = wr->next_weak_ref;
43844
+ js_free_rt(rt, wr);
43825
43845
}
43826
43846
43827
43847
static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr)
@@ -43830,7 +43850,7 @@ static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr)
43830
43850
return;
43831
43851
list_del(&mr->hash_link);
43832
43852
if (s->is_weak) {
43833
- delete_weak_ref (rt, mr);
43853
+ delete_map_weak_ref (rt, mr);
43834
43854
} else {
43835
43855
JS_FreeValueRT(rt, mr->key);
43836
43856
}
@@ -43857,27 +43877,45 @@ static void map_decref_record(JSRuntime *rt, JSMapRecord *mr)
43857
43877
}
43858
43878
}
43859
43879
43860
- static void reset_weak_ref(JSRuntime *rt, struct JSMapRecord **first_weak_ref)
43880
+ static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref)
43861
43881
{
43862
- JSMapRecord *mr, *mr_next;
43882
+ JSWeakRefRecord *wr, *wr_next;
43883
+ JSMapRecord *mr;
43863
43884
JSMapState *s;
43864
43885
43865
43886
/* first pass to remove the records from the WeakMap/WeakSet
43866
43887
lists */
43867
- for(mr = *first_weak_ref; mr != NULL; mr = mr->next_weak_ref) {
43868
- s = mr->map;
43869
- assert(s->is_weak);
43870
- assert(!mr->empty); /* no iterator on WeakMap/WeakSet */
43871
- list_del(&mr->hash_link);
43872
- list_del(&mr->link);
43888
+ for(wr = *first_weak_ref; wr != NULL; wr = wr->next_weak_ref) {
43889
+ switch(wr->kind) {
43890
+ case JS_WEAK_REF_KIND_MAP: {
43891
+ mr = wr->u.map_record;
43892
+ s = mr->map;
43893
+ assert(s->is_weak);
43894
+ assert(!mr->empty); /* no iterator on WeakMap/WeakSet */
43895
+ list_del(&mr->hash_link);
43896
+ list_del(&mr->link);
43897
+ break;
43898
+ }
43899
+ default:
43900
+ abort();
43901
+ }
43873
43902
}
43874
43903
43875
43904
/* second pass to free the values to avoid modifying the weak
43876
43905
reference list while traversing it. */
43877
- for(mr = *first_weak_ref; mr != NULL; mr = mr_next) {
43878
- mr_next = mr->next_weak_ref;
43879
- JS_FreeValueRT(rt, mr->value);
43880
- js_free_rt(rt, mr);
43906
+ for(wr = *first_weak_ref; wr != NULL; wr = wr_next) {
43907
+ wr_next = wr->next_weak_ref;
43908
+ switch(wr->kind) {
43909
+ case JS_WEAK_REF_KIND_MAP: {
43910
+ mr = wr->u.map_record;
43911
+ JS_FreeValueRT(rt, mr->value);
43912
+ js_free_rt(rt, mr);
43913
+ break;
43914
+ }
43915
+ default:
43916
+ abort();
43917
+ }
43918
+ js_free_rt(rt, wr);
43881
43919
}
43882
43920
43883
43921
*first_weak_ref = NULL; /* fail safe */
@@ -44149,7 +44187,7 @@ static void js_map_finalizer(JSRuntime *rt, JSValue val)
44149
44187
mr = list_entry(el, JSMapRecord, link);
44150
44188
if (!mr->empty) {
44151
44189
if (s->is_weak)
44152
- delete_weak_ref (rt, mr);
44190
+ delete_map_weak_ref (rt, mr);
44153
44191
else
44154
44192
JS_FreeValueRT(rt, mr->key);
44155
44193
JS_FreeValueRT(rt, mr->value);
0 commit comments