diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-08-04 17:25:54 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-08-04 17:25:54 -0400 |
| commit | d7e3d399d6c494ae0b37d8abae25e813aff4316f (patch) | |
| tree | 1b4fb2bfa54fc8703fda7e04464e71b9daa3c743 | |
| parent | 43501f7bec61d8e8e4430c2226b86579d91a9450 (diff) | |
Fix up some edge cases with refcounting
| -rw-r--r-- | builtins/datatypes.h | 2 | ||||
| -rw-r--r-- | builtins/table.c | 8 | ||||
| -rw-r--r-- | compile.c | 4 |
3 files changed, 8 insertions, 6 deletions
diff --git a/builtins/datatypes.h b/builtins/datatypes.h index 5ac84be5..e73e3c16 100644 --- a/builtins/datatypes.h +++ b/builtins/datatypes.h @@ -34,6 +34,8 @@ typedef struct { uint32_t next_bucket; } bucket_t; +#define TABLE_MAX_DATA_REFCOUNT 3 + typedef struct { uint32_t count:31, last_free:31; uint8_t data_refcount:2; diff --git a/builtins/table.c b/builtins/table.c index f9623342..e0c94593 100644 --- a/builtins/table.c +++ b/builtins/table.c @@ -97,10 +97,10 @@ static inline void hshow(const table_t *t) static void maybe_copy_on_write(table_t *t, const TypeInfo *type) { - if (t->entries.data_refcount) + if (t->entries.data_refcount != 0) Array$compact(&t->entries, entry_size(type)); - if (t->bucket_info && t->bucket_info->data_refcount) { + if (t->bucket_info && t->bucket_info->data_refcount != 0) { int64_t size = sizeof(bucket_info_t) + sizeof(bucket_t[t->bucket_info->count]); t->bucket_info = memcpy(GC_MALLOC(size), t->bucket_info, size); t->bucket_info->data_refcount = 0; @@ -109,8 +109,8 @@ static void maybe_copy_on_write(table_t *t, const TypeInfo *type) public void Table$mark_copy_on_write(table_t *t) { - t->entries.data_refcount = 3; - if (t->bucket_info) t->bucket_info->data_refcount = 3; + ARRAY_INCREF(t->entries); + if (t->bucket_info) t->bucket_info->data_refcount = TABLE_MAX_DATA_REFCOUNT; } // Return address of value or NULL @@ -2134,7 +2134,7 @@ CORD compile(env_t *env, ast_t *ast) case TableType: { if (streq(f->field, "keys")) { return CORD_all("({ table_t *t = ", compile_to_pointer_depth(env, f->fielded, 1, false), ";\n" - "t->entries.data_refcount = 3;\n" + "ARRAY_INCREF(t->entries);\n" "t->entries; })"); } else if (streq(f->field, "values")) { auto table = Match(value_t, TableType); @@ -2143,7 +2143,7 @@ CORD compile(env_t *env, ast_t *ast) if (align > 1 && offset % align > 0) offset += align - (offset % align); return CORD_all("({ table_t *t = ", compile_to_pointer_depth(env, f->fielded, 1, false), ";\n" - "t->entries.data_refcount = 3;\n" + "ARRAY_INCREF(t->entries.data_refcount);\n" "(array_t){.data = t->entries.data + ", CORD_asprintf("%zu", offset), ",\n .length=t->entries.length,\n .stride=t->entries.stride,\n .data_refcount=3};})"); } else if (streq(f->field, "fallback")) { |
