Skip to content

Commit 2eb2a83

Browse files
committed
Implement some missing serialize operators
Also fix a design flaw with how generic heap pointers are serialized
1 parent 8194e0c commit 2eb2a83

File tree

29 files changed

+521
-236
lines changed

29 files changed

+521
-236
lines changed

include/deemon/dec.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -358,23 +358,23 @@ struct Dee_dec_deptab {
358358
#define Dee_dec_deptab_init(self) \
359359
(void)((self)->ddpt_depv = NULL, (self)->ddpt_depc = (self)->ddpt_depa = 0)
360360

361-
struct Dee_dec_objtab_entry {
362-
DeeObject *dote_obj; /* [1..1] Address of some object that was already encoded */
363-
Dee_dec_addr32_t dote_off; /* Offset from `dw_base' to the `DeeObject *' where the object is written */
364-
Dee_dec_addr32_t dote_siz; /* # of bytes associated with this object */
361+
struct Dee_dec_ptrtab_entry {
362+
void *dpte_ptr; /* [1..1] Source address that was already encoded */
363+
Dee_dec_addr32_t dote_off; /* Offset from `dw_base' to where "dpte_ptr" was written */
364+
Dee_dec_addr32_t dote_siz; /* # of bytes associated with "dpte_ptr" */
365365
};
366-
#define Dee_dec_objtab_entry_getminaddr(self) ((__BYTE_TYPE__ *)(self)->dote_obj)
367-
#define Dee_dec_objtab_entry_getmaxaddr(self) ((__BYTE_TYPE__ *)(self)->dote_obj + (self)->dote_siz - 1)
366+
#define Dee_dec_ptrtab_entry_getminaddr(self) ((__BYTE_TYPE__ *)(self)->dpte_ptr)
367+
#define Dee_dec_ptrtab_entry_getmaxaddr(self) ((__BYTE_TYPE__ *)(self)->dpte_ptr + (self)->dote_siz - 1)
368368

369-
struct Dee_dec_objtab {
370-
struct Dee_dec_objtab_entry *dot_objv; /* [0..dot_objc][SORT(dote_obj ASC)][owned] List of already-encoded objects */
371-
size_t dot_objc; /* Amount of non-NULL key-item pairs. */
372-
size_t dot_obja; /* Amount of non-NULL key-item pairs. */
369+
struct Dee_dec_ptrtab {
370+
struct Dee_dec_ptrtab_entry *dpt_ptrv; /* [0..dpt_ptrc][SORT(dpte_ptr ASC)][owned] List of already-encoded objects */
371+
size_t dpt_ptrc; /* Amount of non-NULL key-item pairs. */
372+
size_t dpt_ptra; /* Amount of non-NULL key-item pairs. */
373373
};
374-
#define Dee_dec_objtab_init(self) \
375-
(void)((self)->dot_objv = NULL, (self)->dot_objc = (self)->dot_obja = 0)
376-
#define Dee_dec_objtab_fini(self) \
377-
Dee_Free((self)->dot_objv)
374+
#define Dee_dec_ptrtab_init(self) \
375+
(void)((self)->dpt_ptrv = NULL, (self)->dpt_ptrc = (self)->dpt_ptra = 0)
376+
#define Dee_dec_ptrtab_fini(self) \
377+
Dee_Free((self)->dpt_ptrv)
378378

379379
struct Dee_dec_fdeptab {
380380
__BYTE_TYPE__ *dfdt_depv; /* [0..dfdt_depc][owned] Flat array of `Dec_Dstr' (each aligned to `__ALIGNOF_SIZE_T__') */
@@ -411,7 +411,7 @@ typedef struct Dee_dec_writer {
411411
struct Dee_dec_fdeptab dw_fdeps; /* Table of dependent files */
412412
Dee_dec_addr32_t dw_gchead; /* [0..1] Offset to first `struct gc_head_link' (tracking for these objects must begin after relocations were done) */
413413
Dee_dec_addr32_t dw_gctail; /* [0..1] Offset to last `struct gc_head_link' (links between these objects were already established via `dw_srel') */
414-
struct Dee_dec_objtab dw_known; /* Table of known, already-encoded objects */
414+
struct Dee_dec_ptrtab dw_known; /* Table of known, already-encoded pointers */
415415
unsigned int dw_flags; /* Dec writer flags (set of `DeeDecWriter_F_*') */
416416
} DeeDecWriter;
417417

include/deemon/none-operator.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ DFUNDEF int (DCALL _DeeNone_reti0_6)(void *, void *, void *, void *, void *, voi
113113
#endif /* !DCALL_CALLER_CLEANUP */
114114

115115
/* Default no-op constructor callbacks (these should be used by TP_FABSTRACT types) */
116-
#define DeeNone_OperatorCtor (*(int (DCALL *)(DeeObject *__restrict))&_DeeNone_reti0_1)
117-
#define DeeNone_OperatorCopy (*(int (DCALL *)(DeeObject *__restrict, DeeObject *__restrict))&_DeeNone_reti0_2)
118-
#define DeeNone_OperatorWriteDec (*(int (DCALL *)(DeeObject *__restrict, struct Dee_serial *__restrict, Dee_seraddr_t))&_DeeNone_reti0_3)
116+
#define DeeNone_OperatorCtor (*(int (DCALL *)(DeeObject *__restrict))&_DeeNone_reti0_1)
117+
#define DeeNone_OperatorCopy (*(int (DCALL *)(DeeObject *__restrict, DeeObject *__restrict))&_DeeNone_reti0_2)
118+
#define DeeNone_OperatorSerialize (*(int (DCALL *)(DeeObject *__restrict, struct Dee_serial *__restrict, Dee_seraddr_t))&_DeeNone_reti0_3)
119119

120120
DECL_END
121121

include/deemon/serial.h

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,27 @@ struct Dee_serial_type {
7474
(DCALL *set_addr2mem)(DeeSerial *__restrict self, Dee_seraddr_t addr);
7575

7676
/* Allocate generic heap memory (as per "Dee_Malloc()")
77+
* @param: ref: When non-NULL, a reference pointer describing where data originates from.
78+
* This should **ONLY** be given when serializing "[owned][const]" fields of
79+
* a containing object (e.g. "DeeClassDescriptorObject::cd_clsop_list"), but
80+
* **MUST** be "NULL" when serializing "[owned][lock(...)]" fields (e.g.
81+
* "DeeListObject::l_list::ol_elemv").
82+
* The reason why this is needed is to allow later "DeeSerial_PutPointer()"
83+
* calls to connect the dots and understand that a given pointer actually
84+
* points into a block previously returned by `DeeSerial_Malloc()', similar
85+
* to how it can do so for `DeeSerial_ObjectMalloc()'
7786
* @return: * : Serialized address of heap buffer
7887
* @return: Dee_SERADDR_INVALID: Allocation failed (for "set_malloc" and "set_calloc": error was thrown) */
79-
WUNUSED_T NONNULL_T((1)) Dee_seraddr_t (DCALL *set_malloc)(DeeSerial *__restrict self, size_t num_bytes);
80-
WUNUSED_T NONNULL_T((1)) Dee_seraddr_t (DCALL *set_calloc)(DeeSerial *__restrict self, size_t num_bytes);
81-
WUNUSED_T NONNULL_T((1)) Dee_seraddr_t (DCALL *set_trymalloc)(DeeSerial *__restrict self, size_t num_bytes);
82-
WUNUSED_T NONNULL_T((1)) Dee_seraddr_t (DCALL *set_trycalloc)(DeeSerial *__restrict self, size_t num_bytes);
88+
WUNUSED_T NONNULL_T((1)) Dee_seraddr_t (DCALL *set_malloc)(DeeSerial *__restrict self, size_t num_bytes, /*0..1*/ void *ref);
89+
WUNUSED_T NONNULL_T((1)) Dee_seraddr_t (DCALL *set_calloc)(DeeSerial *__restrict self, size_t num_bytes, /*0..1*/ void *ref);
90+
WUNUSED_T NONNULL_T((1)) Dee_seraddr_t (DCALL *set_trymalloc)(DeeSerial *__restrict self, size_t num_bytes, /*0..1*/ void *ref);
91+
WUNUSED_T NONNULL_T((1)) Dee_seraddr_t (DCALL *set_trycalloc)(DeeSerial *__restrict self, size_t num_bytes, /*0..1*/ void *ref);
8392

8493
/* Free generic heap memory (as per "Dee_Free()")
8594
* Only allowed to be called for the most-recent non-Dee_SERADDR_INVALID
8695
* return value of one of the allocation functions above. Behavior is hard
8796
* undefined if you try to free a buffer that isn't the most recent one. */
88-
NONNULL_T((1)) void (DCALL *set_free)(DeeSerial *__restrict self, Dee_seraddr_t addr);
97+
NONNULL_T((1)) void (DCALL *set_free)(DeeSerial *__restrict self, Dee_seraddr_t addr, /*0..1*/ void *ref);
8998

9099
/* Allocate generic object heap memory (as per "DeeObject_Malloc()")
91100
* These functions will have automatically pre-initialized:
@@ -100,7 +109,7 @@ struct Dee_serial_type {
100109

101110
/* Free generic heap memory (as per "DeeObject_Free()")
102111
* Same restrictions of `set_free' regarding order of free() operations also apply to this */
103-
NONNULL_T((1)) void (DCALL *set_object_free)(DeeSerial *__restrict self, Dee_seraddr_t addr);
112+
NONNULL_T((1, 3)) void (DCALL *set_object_free)(DeeSerial *__restrict self, Dee_seraddr_t addr, DeeObject *__restrict ref);
104113

105114
/* Same as above, but must be used for GC-objects (as per "DeeGCObject_Malloc()") */
106115
WUNUSED_T NONNULL_T((1, 3)) Dee_seraddr_t (DCALL *set_gcobject_malloc)(DeeSerial *__restrict self, size_t num_bytes, DeeObject *__restrict ref);
@@ -109,7 +118,7 @@ struct Dee_serial_type {
109118
WUNUSED_T NONNULL_T((1, 3)) Dee_seraddr_t (DCALL *set_gcobject_trycalloc)(DeeSerial *__restrict self, size_t num_bytes, DeeObject *__restrict ref);
110119

111120
/* Free generic heap memory (as per "DeeGCObject_Free()") */
112-
NONNULL_T((1)) void (DCALL *set_gcobject_free)(DeeSerial *__restrict self, Dee_seraddr_t addr);
121+
NONNULL_T((1, 3)) void (DCALL *set_gcobject_free)(DeeSerial *__restrict self, Dee_seraddr_t addr, DeeObject *__restrict ref);
113122

114123
/* Serialize a `void *' field at `addrof_pointer' as being populated with the
115124
* effectively final value of `DeeSerial_Addr2Mem(self, addrof_target, void)'
@@ -166,12 +175,25 @@ struct Dee_serial {
166175
((T *)(*(self)->ser_type->set_addr2mem)(self, addr))
167176

168177
/* Allocate generic heap memory (as per "Dee_Malloc()")
178+
* @param: ref: When non-NULL, a reference pointer describing where data originates from.
179+
* This should **ONLY** be given when serializing "[owned][const]" fields of
180+
* a containing object (e.g. "DeeClassDescriptorObject::cd_clsop_list"), but
181+
* **MUST** be "NULL" when serializing "[owned][lock(...)]" fields (e.g.
182+
* "DeeListObject::l_list::ol_elemv").
183+
* The reason why this is needed is to allow later "DeeSerial_PutPointer()"
184+
* calls to connect the dots and understand that a given pointer actually
185+
* points into a block previously returned by `DeeSerial_Malloc()', similar
186+
* to how it can do so for `DeeSerial_ObjectMalloc()'
187+
* TLDR:
188+
* - If you use "DeeSerial_TryMalloc()" because of a lock, you probably want to pass "NULL"
189+
* - Otherwise, pass the [const] source pointer
190+
*
169191
* @return: * : Serialized address of heap buffer
170192
* @return: Dee_SERADDR_INVALID: Allocation failed (for "DeeSerial_Malloc" and "DeeSerial_Calloc": error was thrown) */
171-
#define DeeSerial_Malloc(self, num_bytes) (*(self)->ser_type->set_malloc)(self, num_bytes)
172-
#define DeeSerial_Calloc(self, num_bytes) (*(self)->ser_type->set_calloc)(self, num_bytes)
173-
#define DeeSerial_TryMalloc(self, num_bytes) (*(self)->ser_type->set_trymalloc)(self, num_bytes)
174-
#define DeeSerial_TryCalloc(self, num_bytes) (*(self)->ser_type->set_trycalloc)(self, num_bytes)
193+
#define DeeSerial_Malloc(self, num_bytes, ref) (*(self)->ser_type->set_malloc)(self, num_bytes, ref)
194+
#define DeeSerial_Calloc(self, num_bytes, ref) (*(self)->ser_type->set_calloc)(self, num_bytes, ref)
195+
#define DeeSerial_TryMalloc(self, num_bytes, ref) (*(self)->ser_type->set_trymalloc)(self, num_bytes, ref)
196+
#define DeeSerial_TryCalloc(self, num_bytes, ref) (*(self)->ser_type->set_trycalloc)(self, num_bytes, ref)
175197

176198
/* Free generic heap memory (as per "Dee_Free()")
177199
* Only allowed to be called for the most-recent non-Dee_SERADDR_INVALID
@@ -180,7 +202,7 @@ struct Dee_serial {
180202
*
181203
* NOTE: DON'T call this method for error-cleanup -- On error, the
182204
* owner of the serializer will free all allocated memory! */
183-
#define DeeSerial_Free(self, addr) (*(self)->ser_type->set_free)(self, addr)
205+
#define DeeSerial_Free(self, addr, ref) (*(self)->ser_type->set_free)(self, addr, ref)
184206

185207
/* Allocate generic object heap memory (as per "DeeObject_Malloc()")
186208
* These functions will have automatically pre-initialized:
@@ -198,7 +220,7 @@ struct Dee_serial {
198220
*
199221
* NOTE: DON'T call this method for error-cleanup -- On error, the
200222
* owner of the serializer will free all allocated memory! */
201-
#define DeeSerial_ObjectFree(self, addr) (*(self)->ser_type->set_object_free)(self, addr)
223+
#define DeeSerial_ObjectFree(self, addr, ref) (*(self)->ser_type->set_object_free)(self, addr, ref)
202224

203225
/* Same as above, but must be used for GC-objects (as per "DeeGCObject_Malloc()") */
204226
#define DeeSerial_GCObjectMalloc(self, num_bytes, ref) (*(self)->ser_type->set_gcobject_malloc)(self, num_bytes, Dee_AsObject(ref))
@@ -210,7 +232,7 @@ struct Dee_serial {
210232
*
211233
* NOTE: DON'T call this method for error-cleanup -- On error, the
212234
* owner of the serializer will free all allocated memory! */
213-
#define DeeSerial_GCObjectFree(self, addr) (*(self)->ser_type->set_gcobject_free)(self, addr)
235+
#define DeeSerial_GCObjectFree(self, addr, ref) (*(self)->ser_type->set_gcobject_free)(self, addr, ref)
214236

215237

216238
/* Serialize a `void *' field at `addrof_pointer' as being populated with the

src/deemon/compiler/asm/modgen.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ module_compile(struct Dee_serial *__restrict writer,
117117
} else {
118118
size_t i, count = current_rootscope->rs_bucketm + 1;
119119
Dee_seraddr_t out__mo_bucketv;
120-
struct Dee_module_symbol *in__mo_bucketv = current_rootscope->rs_bucketv;
121120
struct Dee_module_symbol *ou__mo_bucketv;
122-
out__mo_bucketv = DeeSerial_Malloc(writer, count * sizeof(struct Dee_module_symbol));
121+
struct Dee_module_symbol *in__mo_bucketv = current_rootscope->rs_bucketv;
122+
out__mo_bucketv = DeeSerial_Malloc(writer, count * sizeof(struct Dee_module_symbol), NULL);
123123
if (!Dee_SERADDR_ISOK(out__mo_bucketv))
124124
goto err;
125125
if (DeeSerial_PutAddr(writer, ADDROF(mo_bucketv), out__mo_bucketv))
@@ -162,7 +162,7 @@ module_compile(struct Dee_serial *__restrict writer,
162162
uint16_t count = current_rootscope->rs_importc;
163163
Dee_seraddr_t out__mo_importv;
164164
DREF DeeModuleObject **ou__mo_importv;
165-
out__mo_importv = DeeSerial_Malloc(writer, count * sizeof(DREF DeeModuleObject *));
165+
out__mo_importv = DeeSerial_Malloc(writer, count * sizeof(DREF DeeModuleObject *), NULL);
166166
if (!Dee_SERADDR_ISOK(out__mo_importv))
167167
goto err;
168168
if (DeeSerial_PutAddr(writer, ADDROF(mo_importv), out__mo_importv))

src/deemon/execute/code.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,7 +2618,7 @@ DFUNDEF WUNUSED ATTR_INS(3, 4) NONNULL((1)) int
26182618
(DCALL DeeSerial_XPutObjectVectorDup)(DeeSerial *__restrict writer, Dee_seraddr_t addr,
26192619
DeeObject *const *objv, size_t objc) {
26202620
size_t i;
2621-
Dee_seraddr_t md_addr = DeeSerial_Malloc(writer, objc * sizeof(DREF DeeObject *));
2621+
Dee_seraddr_t md_addr = DeeSerial_Malloc(writer, objc * sizeof(DREF DeeObject *), (void *)objv);
26222622
if (!Dee_SERADDR_ISOK(md_addr))
26232623
goto err;
26242624
for (i = 0; i < objc; ++i) {
@@ -2679,14 +2679,13 @@ code_serialize(DeeCodeObject *__restrict self, DeeSerial *__restrict writer) {
26792679
goto err;
26802680
}
26812681
if (self->co_exceptv) {
2682-
struct except_handler *out_exceptv, *in_exceptv;
2682+
struct except_handler *out_exceptv, *in_exceptv = self->co_exceptv;
26832683
uint16_t i, exceptc = self->co_exceptc;
26842684
size_t sizeof_exceptv = exceptc * sizeof(struct except_handler);
2685-
Dee_seraddr_t addrof_out_exceptv = DeeSerial_Malloc(writer, sizeof_exceptv);
2685+
Dee_seraddr_t addrof_out_exceptv = DeeSerial_Malloc(writer, sizeof_exceptv, in_exceptv);
26862686
if (!Dee_SERADDR_ISOK(addrof_out_exceptv))
26872687
goto err;
26882688
out_exceptv = DeeSerial_Addr2Mem(writer, addrof_out_exceptv, struct except_handler);
2689-
in_exceptv = self->co_exceptv;
26902689
for (i = 0; i < exceptc; ++i) {
26912690
out_exceptv[i] = in_exceptv[i];
26922691
if (in_exceptv[i].eh_mask) {

0 commit comments

Comments
 (0)