Ticket #1015: clone.patch
| File clone.patch, 9.8 KB (added by whiteknight, 4 years ago) |
|---|
-
src/pmc.c
42 42 UINTVAL flags) 43 43 __attribute__nonnull__(1); 44 44 45 static 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 45 51 PARROT_CANNOT_RETURN_NULL 52 static 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 62 PARROT_CANNOT_RETURN_NULL 63 static 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 70 PARROT_CANNOT_RETURN_NULL 46 71 static PMC* pmc_reuse_no_init(PARROT_INTERP, 47 72 ARGIN(PMC *pmc), 48 73 INTVAL new_type, … … 56 81 PARROT_ASSERT_ARG(interp) 57 82 #define ASSERT_ARGS_get_new_pmc_header __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 58 83 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) 59 96 #define ASSERT_ARGS_pmc_reuse_no_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 60 97 PARROT_ASSERT_ARG(interp) \ 61 98 || PARROT_ASSERT_ARG(pmc) … … 938 975 939 976 /* 940 977 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 985 PARROT_CAN_RETURN_NULL 986 PMC_clone_node * 987 Parrot_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 1004 void 1005 Parrot_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 1013 PARROT_CAN_RETURN_NULL 1014 PMC * 1015 Parrot_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 1031 PARROT_CANNOT_RETURN_NULL 1032 static PMC_clone_node * 1033 Parrot_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 1047 PARROT_CANNOT_RETURN_NULL 1048 static PMC_clone_node * 1049 Parrot_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 1060 void 1061 Parrot_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 1068 static void 1069 Parrot_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 941 1081 =back 942 1082 943 1083 =head1 SEE ALSO -
src/interp/inter_create.c
130 130 interp = mem_allocate_zeroed_typed(Interp); 131 131 132 132 interp->lo_var_ptr = NULL; 133 interp->clone_registry = NULL; 133 134 134 135 /* the last interpreter (w/o) parent has to cleanup globals 135 136 * so remember parent if any */ -
src/pmc/hash.pmc
434 434 */ 435 435 436 436 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); 438 448 439 parrot_hash_clone(INTERP, (Hash *)SELF.get_pointer(),440 (Hash *)VTABLE_get_pointer(INTERP, dest));441 442 449 return dest; 443 450 } 444 451 -
include/parrot/pmc.h
19 19 20 20 #define PARROT_MAX_CLASSES 100 21 21 22 22 23 /* HEADERIZER BEGIN: src/pmc.c */ 23 24 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 24 25 … … 132 133 INTVAL get_new_vtable_index(PARROT_INTERP) 133 134 __attribute__nonnull__(1); 134 135 136 void 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 142 PARROT_CAN_RETURN_NULL 143 PMC_clone_node * Parrot_pmc_create_clone_registry(PARROT_INTERP, 144 ARGIN(PMC *self)) 145 __attribute__nonnull__(1) 146 __attribute__nonnull__(2); 147 148 PARROT_CAN_RETURN_NULL 149 PMC * Parrot_pmc_find_registered_clone(PARROT_INTERP, ARGIN(PMC *self)) 150 __attribute__nonnull__(1) 151 __attribute__nonnull__(2); 152 153 void 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 135 160 void temporary_pmc_free(PARROT_INTERP, ARGMOD(PMC *pmc)) 136 161 __attribute__nonnull__(1) 137 162 __attribute__nonnull__(2) … … 187 212 || PARROT_ASSERT_ARG(name) 188 213 #define ASSERT_ARGS_get_new_vtable_index __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 189 214 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) 190 231 #define ASSERT_ARGS_temporary_pmc_free __attribute__unused__ int _ASSERT_ARGS_CHECK = \ 191 232 PARROT_ASSERT_ARG(interp) \ 192 233 || PARROT_ASSERT_ARG(pmc) -
include/parrot/interpreter.h
177 177 */ 178 178 #define CURRENT_CONTEXT(interp) ((interp)->ctx) 179 179 180 typedef 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; 180 186 181 187 typedef struct _context_mem { 182 188 void **free_list; /* array of free-lists, per size free slots */ … … 309 315 * inside the invoke these get moved to the context structure */ 310 316 PMC *current_cont; /* the return continuation PMC */ 311 317 PMC *current_object; /* invocant, if a method call */ 318 PMC_clone_node *clone_registry; /* registry to prevent cycles while cloning */ 312 319 }; 313 320 314 321 /* typedef struct parrot_interp_t Interp; done in parrot.h so that
