Ticket #1015: clone.patch

File clone.patch, 9.8 KB (added by whiteknight, 5 years ago)

patch that fixes the clone issue using a new "clone registry" API. PGE fails to build with this however

  • src/pmc.c

     
    4242    UINTVAL flags) 
    4343        __attribute__nonnull__(1); 
    4444 
     45static void Parrot_pmc_free_clone_node(PARROT_INTERP, 
     46    ARGMOD(PMC_clone_node *root)) 
     47        __attribute__nonnull__(1) 
     48        __attribute__nonnull__(2) 
     49        FUNC_MODIFIES(*root); 
     50 
    4551PARROT_CANNOT_RETURN_NULL 
     52static PMC_clone_node * Parrot_pmc_insert_clone_node(PARROT_INTERP, 
     53    ARGMOD(PMC_clone_node * node), 
     54    ARGIN(PMC * data), 
     55    ARGIN(PMC *clone)) 
     56        __attribute__nonnull__(1) 
     57        __attribute__nonnull__(2) 
     58        __attribute__nonnull__(3) 
     59        __attribute__nonnull__(4) 
     60        FUNC_MODIFIES(* node); 
     61 
     62PARROT_CANNOT_RETURN_NULL 
     63static PMC_clone_node * Parrot_pmc_new_clone_node(PARROT_INTERP, 
     64    ARGIN(PMC *self), 
     65    ARGIN(PMC *clone)) 
     66        __attribute__nonnull__(1) 
     67        __attribute__nonnull__(2) 
     68        __attribute__nonnull__(3); 
     69 
     70PARROT_CANNOT_RETURN_NULL 
    4671static PMC* pmc_reuse_no_init(PARROT_INTERP, 
    4772    ARGIN(PMC *pmc), 
    4873    INTVAL new_type, 
     
    5681       PARROT_ASSERT_ARG(interp) 
    5782#define ASSERT_ARGS_get_new_pmc_header __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
    5883       PARROT_ASSERT_ARG(interp) 
     84#define ASSERT_ARGS_Parrot_pmc_free_clone_node __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     85       PARROT_ASSERT_ARG(interp) \ 
     86    || PARROT_ASSERT_ARG(root) 
     87#define ASSERT_ARGS_Parrot_pmc_insert_clone_node __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     88       PARROT_ASSERT_ARG(interp) \ 
     89    || PARROT_ASSERT_ARG(node) \ 
     90    || PARROT_ASSERT_ARG(data) \ 
     91    || PARROT_ASSERT_ARG(clone) 
     92#define ASSERT_ARGS_Parrot_pmc_new_clone_node __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     93       PARROT_ASSERT_ARG(interp) \ 
     94    || PARROT_ASSERT_ARG(self) \ 
     95    || PARROT_ASSERT_ARG(clone) 
    5996#define ASSERT_ARGS_pmc_reuse_no_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
    6097       PARROT_ASSERT_ARG(interp) \ 
    6198    || PARROT_ASSERT_ARG(pmc) 
     
    938975 
    939976/* 
    940977 
     978=item C<INTVAL Parrot_pmc_start_clone_registry(PARROT_INTERP, PMC *self, PMC *clone)> 
     979 
     980=item C<void Parrot_pmc_clear_clone_registry(PARROT_INTERP)> 
     981 
     982 
     983*/ 
     984 
     985PARROT_CAN_RETURN_NULL 
     986PMC_clone_node * 
     987Parrot_pmc_create_clone_registry(PARROT_INTERP, ARGIN(PMC *self)) 
     988{ 
     989    ASSERT_ARGS(Parrot_pmc_create_clone_registry) 
     990 
     991    if(interp->clone_registry) 
     992        return NULL; 
     993    else { 
     994        PMC_clone_node * const root = 
     995            (PMC_clone_node *)Parrot_gc_allocate_fixed_size_storage(interp, sizeof (PMC_clone_node)); 
     996        root->old = self; 
     997        root->bigger = NULL; 
     998        root->smaller = NULL; 
     999        interp->clone_registry = root; 
     1000        return root; 
     1001    } 
     1002} 
     1003 
     1004void 
     1005Parrot_pmc_set_clone_node(PARROT_INTERP, ARGIN(PMC_clone_node * node), ARGIN(PMC * clone)) 
     1006{ 
     1007    ASSERT_ARGS(Parrot_pmc_set_clone_node) 
     1008    if(node == NULL) 
     1009        return; 
     1010    node->clone = clone; 
     1011} 
     1012 
     1013PARROT_CAN_RETURN_NULL 
     1014PMC * 
     1015Parrot_pmc_find_registered_clone(PARROT_INTERP, ARGIN(PMC *self)) 
     1016{ 
     1017    ASSERT_ARGS(Parrot_pmc_find_registered_clone) 
     1018    PMC_clone_node * node = interp->clone_registry; 
     1019    while (node != NULL) { 
     1020        PMC * const old = node->old; 
     1021        if (old == self) 
     1022            return node->clone; 
     1023        else if (old < self) 
     1024            node = node->bigger; 
     1025        else 
     1026            node = node->smaller; 
     1027    } 
     1028    return NULL; 
     1029} 
     1030 
     1031PARROT_CANNOT_RETURN_NULL 
     1032static PMC_clone_node * 
     1033Parrot_pmc_insert_clone_node(PARROT_INTERP, ARGMOD(PMC_clone_node * node), ARGIN(PMC * data), ARGIN(PMC *clone)) 
     1034{ 
     1035    ASSERT_ARGS(Parrot_pmc_insert_clone_node) 
     1036    if (node == NULL) 
     1037        return Parrot_pmc_new_clone_node(interp, data, clone); 
     1038    else { 
     1039        PMC * const old = node->old; 
     1040        if (data > old) 
     1041            node->bigger = Parrot_pmc_insert_clone_node(interp, node->bigger, data, clone); 
     1042        else 
     1043            node->smaller = Parrot_pmc_insert_clone_node(interp, node->smaller, data, clone); 
     1044    } 
     1045} 
     1046 
     1047PARROT_CANNOT_RETURN_NULL 
     1048static PMC_clone_node * 
     1049Parrot_pmc_new_clone_node(PARROT_INTERP, ARGIN(PMC *self), ARGIN(PMC *clone)) 
     1050{ 
     1051    ASSERT_ARGS(Parrot_pmc_new_clone_node) 
     1052    PMC_clone_node * const node = Parrot_gc_allocate_fixed_size_storage(interp, sizeof (PMC_clone_node)); 
     1053    node->old = self; 
     1054    node->clone = clone; 
     1055    node->bigger = NULL; 
     1056    node->smaller = NULL; 
     1057    return node; 
     1058} 
     1059 
     1060void 
     1061Parrot_pmc_cleanup_clone_registry(PARROT_INTERP, ARGMOD(PMC_clone_node *root)) 
     1062{ 
     1063    ASSERT_ARGS(Parrot_pmc_cleanup_clone_registry) 
     1064    Parrot_pmc_free_clone_node(interp, root); 
     1065    interp->clone_registry = NULL; 
     1066} 
     1067 
     1068static void 
     1069Parrot_pmc_free_clone_node(PARROT_INTERP, ARGMOD(PMC_clone_node *root)) 
     1070{ 
     1071    ASSERT_ARGS(Parrot_pmc_free_clone_node) 
     1072    if (root->bigger != NULL) 
     1073        Parrot_pmc_free_clone_node(interp, root->bigger); 
     1074    if (root->smaller != NULL) 
     1075        Parrot_pmc_free_clone_node(interp, root->smaller); 
     1076    Parrot_gc_free_fixed_size_storage(interp, sizeof (PMC_clone_node), root); 
     1077} 
     1078 
     1079/* 
     1080 
    9411081=back 
    9421082 
    9431083=head1 SEE ALSO 
  • src/interp/inter_create.c

     
    130130        interp = mem_allocate_zeroed_typed(Interp); 
    131131 
    132132    interp->lo_var_ptr = NULL; 
     133    interp->clone_registry = NULL; 
    133134 
    134135    /* the last interpreter (w/o) parent has to cleanup globals 
    135136     * so remember parent if any */ 
  • src/pmc/hash.pmc

     
    434434*/ 
    435435 
    436436    VTABLE PMC *clone() { 
    437         PMC * const dest = pmc_new(INTERP, SELF->vtable->base_type); 
     437        PMC_clone_node * const node = Parrot_pmc_create_clone_registry(INTERP, SELF); 
     438        PMC * dest = Parrot_pmc_find_registered_clone(INTERP, SELF); 
     439        if (!dest) { 
     440            dest = pmc_new(INTERP, SELF->vtable->base_type); 
     441            if (node) 
     442                Parrot_pmc_set_clone_node(INTERP, node, dest); 
     443            parrot_hash_clone(INTERP, (Hash *)SELF.get_pointer(), 
     444                (Hash *)VTABLE_get_pointer(INTERP, dest)); 
     445        } 
     446        if (node) 
     447            Parrot_pmc_cleanup_clone_registry(INTERP, node); 
    438448 
    439         parrot_hash_clone(INTERP, (Hash *)SELF.get_pointer(), 
    440                    (Hash *)VTABLE_get_pointer(INTERP, dest)); 
    441  
    442449        return dest; 
    443450    } 
    444451 
  • include/parrot/pmc.h

     
    1919 
    2020#define PARROT_MAX_CLASSES 100 
    2121 
     22 
    2223/* HEADERIZER BEGIN: src/pmc.c */ 
    2324/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
    2425 
     
    132133INTVAL get_new_vtable_index(PARROT_INTERP) 
    133134        __attribute__nonnull__(1); 
    134135 
     136void Parrot_pmc_cleanup_clone_registry(PARROT_INTERP, 
     137    ARGMOD(PMC_clone_node *root)) 
     138        __attribute__nonnull__(1) 
     139        __attribute__nonnull__(2) 
     140        FUNC_MODIFIES(*root); 
     141 
     142PARROT_CAN_RETURN_NULL 
     143PMC_clone_node * Parrot_pmc_create_clone_registry(PARROT_INTERP, 
     144    ARGIN(PMC *self)) 
     145        __attribute__nonnull__(1) 
     146        __attribute__nonnull__(2); 
     147 
     148PARROT_CAN_RETURN_NULL 
     149PMC * Parrot_pmc_find_registered_clone(PARROT_INTERP, ARGIN(PMC *self)) 
     150        __attribute__nonnull__(1) 
     151        __attribute__nonnull__(2); 
     152 
     153void Parrot_pmc_set_clone_node(PARROT_INTERP, 
     154    ARGIN(PMC_clone_node * node), 
     155    ARGIN(PMC * clone)) 
     156        __attribute__nonnull__(1) 
     157        __attribute__nonnull__(2) 
     158        __attribute__nonnull__(3); 
     159 
    135160void temporary_pmc_free(PARROT_INTERP, ARGMOD(PMC *pmc)) 
    136161        __attribute__nonnull__(1) 
    137162        __attribute__nonnull__(2) 
     
    187212    || PARROT_ASSERT_ARG(name) 
    188213#define ASSERT_ARGS_get_new_vtable_index __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
    189214       PARROT_ASSERT_ARG(interp) 
     215#define ASSERT_ARGS_Parrot_pmc_cleanup_clone_registry \ 
     216     __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     217       PARROT_ASSERT_ARG(interp) \ 
     218    || PARROT_ASSERT_ARG(root) 
     219#define ASSERT_ARGS_Parrot_pmc_create_clone_registry \ 
     220     __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     221       PARROT_ASSERT_ARG(interp) \ 
     222    || PARROT_ASSERT_ARG(self) 
     223#define ASSERT_ARGS_Parrot_pmc_find_registered_clone \ 
     224     __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     225       PARROT_ASSERT_ARG(interp) \ 
     226    || PARROT_ASSERT_ARG(self) 
     227#define ASSERT_ARGS_Parrot_pmc_set_clone_node __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
     228       PARROT_ASSERT_ARG(interp) \ 
     229    || PARROT_ASSERT_ARG(node) \ 
     230    || PARROT_ASSERT_ARG(clone) 
    190231#define ASSERT_ARGS_temporary_pmc_free __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 
    191232       PARROT_ASSERT_ARG(interp) \ 
    192233    || PARROT_ASSERT_ARG(pmc) 
  • include/parrot/interpreter.h

     
    177177 */ 
    178178#define CURRENT_CONTEXT(interp) ((interp)->ctx) 
    179179 
     180typedef struct _PMC_clone_node { 
     181    struct _PMC_clone_registry *bigger; 
     182    struct _PMC_clone_registry *smaller; 
     183    PMC* old; 
     184    PMC* clone; 
     185} PMC_clone_node; 
    180186 
    181187typedef struct _context_mem { 
    182188    void **free_list;               /* array of free-lists, per size free slots */ 
     
    309315     * inside the invoke these get moved to the context structure */ 
    310316    PMC *current_cont;                        /* the return continuation PMC */ 
    311317    PMC *current_object;                      /* invocant, if a method call */ 
     318    PMC_clone_node *clone_registry;           /* registry to prevent cycles while cloning */ 
    312319}; 
    313320 
    314321/* typedef struct parrot_interp_t Interp;    done in parrot.h so that