3232#include <deemon/types.h> /* DREF, DeeObject, DeeTypeObject, Dee_TYPE, Dee_funptr_t, Dee_unlockinfo, OBJECT_HEAD */
3333
3434#include <hybrid/typecore.h> /* __BYTE_TYPE__ */
35+ #include <hybrid/overflow.h> /* __BYTE_TYPE__ */
3536
3637#include <stdbool.h> /* bool, false, true */
3738#include <stddef.h> /* NULL, offsetof, ptrdiff_t, size_t */
@@ -317,7 +318,8 @@ deepcopy_gcobject_malloc_impl(DeeDeepCopyContext *__restrict self,
317318 struct Dee_gc_head * result_head , * next ;
318319 ASSERT_OBJECT (ref );
319320 ASSERTF (DeeType_IsGC (Dee_TYPE (ref )), "Use deepcopy_object_malloc_impl()" );
320- num_bytes += Dee_GC_HEAD_SIZE ;
321+ if (OVERFLOW_UADD (num_bytes , Dee_GC_HEAD_SIZE , & num_bytes ))
322+ num_bytes = (size_t )-1 ;
321323 result_head = (struct Dee_gc_head * )deepcopy_heap_malloc (& self -> dcc_gcheap , num_bytes , do_try , do_bzero );
322324 if unlikely (!result_head )
323325 goto err ;
@@ -466,6 +468,8 @@ deepcopy_putpointer(DeeDeepCopyContext *__restrict self,
466468 }
467469 }
468470
471+ /* TODO: Only allow this part for static pointers! */
472+
469473 /* Assign pointer... */
470474 * deepcopy_ser2ptr (self , addrof_pointer , void const * ) = pointer ;
471475 return 0 ;
@@ -519,6 +523,7 @@ DeeDeepCopy_Init(DeeDeepCopyContext *__restrict self) {
519523 self -> dcc_heap = NULL ;
520524 self -> dcc_obheap = NULL ;
521525 self -> dcc_gcheap = NULL ;
526+ self -> dcc_uheap = NULL ;
522527 self -> dcc_ptrmapv = NULL ;
523528 self -> dcc_ptrmapc = 0 ;
524529 self -> dcc_ptrmapa = 0 ;
@@ -552,6 +557,16 @@ destroy_obheap(Dee_deepcopy_heap_t *heap, ptrdiff_t offsetof_object) {
552557 }
553558}
554559
560+ PRIVATE void DCALL
561+ destroy_uheap (struct Dee_deepcopy_uheap * heap ) {
562+ while (heap ) {
563+ struct Dee_deepcopy_uheap * next ;
564+ next = heap -> ddcuh_next ;
565+ Dee_deepcopy_uheap_destroy (heap );
566+ heap = next ;
567+ }
568+ }
569+
555570PUBLIC NONNULL ((1 )) void DCALL
556571DeeDeepCopy_Fini (DeeDeepCopyContext * __restrict self ) {
557572 size_t i ;
@@ -574,7 +589,9 @@ DeeDeepCopy_Fini(DeeDeepCopyContext *__restrict self) {
574589 destroy_heap (self -> dcc_heap );
575590 destroy_obheap (self -> dcc_obheap , 0 );
576591 destroy_obheap (self -> dcc_gcheap , offsetof(struct Dee_gc_head , gc_object ));
592+ destroy_uheap (self -> dcc_uheap );
577593
594+ /* For safety... */
578595 DBG_memset (self , 0xcc , sizeof (* self ));
579596}
580597
@@ -676,15 +693,66 @@ DeeDeepCopy_CopyObject(DeeDeepCopyContext *__restrict self,
676693 } else {
677694 int status ;
678695 size_t instance_size = DeeType_GetInstanceSize (tp );
679- if unlikely (!instance_size )
680- goto cannot_serialize ;
681-
682- /* Allocate buffer for object. */
683- out_addr = DeeType_IsGC (tp )
684- ? deepcopy_gcobject_malloc (self , instance_size , ob )
685- : deepcopy_object_malloc (self , instance_size , ob );
686- if unlikely (!out_addr )
687- goto err ;
696+ if unlikely (!instance_size ) {
697+ GenericObject * object_buffer ;
698+ struct Dee_deepcopy_uheap * uheap ;
699+ if (!tp -> tp_init .tp_alloc .tp_free ) {
700+ /* tp_instance_size == 0 + tp_free == NULL
701+ * -> probably a singleton
702+ * -> cannot serialize */
703+ goto cannot_serialize ;
704+ }
705+ uheap = Dee_deepcopy_uheap_alloc ();
706+ if unlikely (!uheap )
707+ goto err ;
708+
709+ /* Support custom allocators... */
710+ ASSERT (tp -> tp_init .tp_alloc .tp_alloc );
711+ object_buffer = (GenericObject * )((* tp -> tp_init .tp_alloc .tp_alloc )());
712+ if unlikely (!object_buffer ) {
713+ Dee_deepcopy_uheap_free (uheap );
714+ goto err ;
715+ }
716+ uheap -> ddcuh_base = Dee_AsObject (object_buffer );
717+ uheap -> ddcuh_free = tp -> tp_init .tp_alloc .tp_free ;
718+ uheap -> ddcuh_next = self -> dcc_uheap ;
719+ self -> dcc_uheap = uheap ;
720+ DeeObject_Init (object_buffer , tp );
721+
722+ if (DeeType_IsGC (tp )) {
723+ /* Insert GC head */
724+ struct Dee_gc_head * result_head , * next ;
725+ result_head = DeeGC_Head (object_buffer );
726+ result_head -> gc_pself = NULL ;
727+ if ((next = self -> dcc_gc_head ) != NULL ) {
728+ ASSERT (self -> dcc_gc_tail != NULL );
729+ next -> gc_pself = & result_head -> gc_next ;
730+ } else {
731+ ASSERT (self -> dcc_gc_tail == NULL );
732+ self -> dcc_gc_tail = result_head ;
733+ }
734+ result_head -> gc_next = next ;
735+ self -> dcc_gc_head = result_head ;
736+ /* Only able to map the object's basic header */
737+ instance_size = Dee_GC_OBJECT_OFFSET + sizeof (DeeObject );
738+ if unlikely (deepcopy_mappointer (self , DeeGC_Head (ob ),
739+ result_head , instance_size , false ))
740+ goto err ;
741+ } else {
742+ /* Only able to map the object's basic header */
743+ instance_size = sizeof (DeeObject );
744+ if unlikely (deepcopy_mappointer (self , ob , object_buffer , instance_size , false ))
745+ goto err ;
746+ }
747+ out_addr = deepcopy_ptr2ser (self , object_buffer );
748+ } else {
749+ /* Allocate buffer for object. */
750+ out_addr = DeeType_IsGC (tp )
751+ ? deepcopy_gcobject_malloc (self , instance_size , ob )
752+ : deepcopy_object_malloc (self , instance_size , ob );
753+ if unlikely (!Dee_SERADDR_ISOK (out_addr ))
754+ goto err ;
755+ }
688756
689757 /* NOTE: Standard fields have already been initialized by "deepcopy_[gc]object_malloc" */
690758 status = (* (Dee_tp_serialize_obj_t )tp_serialize )(ob , (DeeSerial * )self , out_addr );
@@ -719,6 +787,16 @@ cleanup_heap(Dee_deepcopy_heap_t *heap) {
719787}
720788#endif /* !CONFIG_EXPERIMENTAL_CUSTOM_HEAP */
721789
790+ PRIVATE void DCALL
791+ cleanup_uheap (struct Dee_deepcopy_uheap * heap ) {
792+ while (heap ) {
793+ struct Dee_deepcopy_uheap * next ;
794+ next = heap -> ddcuh_next ;
795+ Dee_deepcopy_uheap_free (heap );
796+ heap = next ;
797+ }
798+ }
799+
722800/* Finalize "self" in the sense of doing a COMMIT.
723801 *
724802 * This function behaves similar to `DeeDeepCopy_Fini()', but will also
@@ -737,6 +815,7 @@ DeeDeepCopy_Pack(/*inherit(always)*/DeeDeepCopyContext *__restrict self) {
737815 cleanup_heap (self -> dcc_obheap );
738816 cleanup_heap (self -> dcc_gcheap );
739817#endif /* !CONFIG_EXPERIMENTAL_CUSTOM_HEAP */
818+ cleanup_uheap (self -> dcc_uheap );
740819
741820 /* Free map tables. */
742821 Dee_Free (self -> dcc_ptrmapv );
0 commit comments