remove deprecation notice for TT #449
[parrot.git] / src / pmc_freeze.c
blobe928f7f5f45d55b2c004c3bb1b5561f39bbf9def
1 /*
2 Copyright (C) 2001-2010, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc_freeze.c - Freeze and thaw functionality
9 =head1 DESCRIPTION
11 Thawing PMCs uses a list with (maximum) size of the amount of PMCs to
12 keep track of retrieved PMCs.
14 The individual information of PMCs is frozen/thawed by their vtables.
16 To avoid recursion, the whole functionality is driven by
17 C<< pmc->vtable->visit >>, which is called for the first PMC initially.
18 Container PMCs call a "todo-callback" for all contained PMCs. The
19 individual action vtable (freeze/thaw) is then called for all todo-PMCs.
21 =cut
25 #include "parrot/parrot.h"
26 #include "pmc/pmc_callcontext.h"
27 #include "pmc_freeze.str"
29 /* when thawing a string longer then this size, we first do a GC run and then
30 * block GC - the system can't give us more headers */
32 #define THAW_BLOCK_GC_SIZE 100000
34 /* HEADERIZER HFILE: include/parrot/pmc_freeze.h */
38 =head2 Public Interface
40 =over 4
42 =item C<STRING* Parrot_freeze(PARROT_INTERP, PMC *pmc)>
44 Freeze using either method.
46 =cut
50 PARROT_EXPORT
51 PARROT_WARN_UNUSED_RESULT
52 PARROT_CANNOT_RETURN_NULL
53 STRING*
54 Parrot_freeze(PARROT_INTERP, ARGIN(PMC *pmc))
56 ASSERT_ARGS(Parrot_freeze)
57 PMC * const image = Parrot_pmc_new(interp, enum_class_ImageIO);
58 VTABLE_set_pmc(interp, image, pmc);
59 return VTABLE_get_string(interp, image);
64 =item C<STRING * Parrot_freeze_pbc(PARROT_INTERP, PMC *pmc, const
65 PackFile_ConstTable *pf)>
67 Freeze to a PackFile.
69 =cut
73 PARROT_EXPORT
74 PARROT_WARN_UNUSED_RESULT
75 PARROT_CAN_RETURN_NULL
76 STRING *
77 Parrot_freeze_pbc(PARROT_INTERP, ARGIN(PMC *pmc), ARGIN(const PackFile_ConstTable *pf))
79 ASSERT_ARGS(Parrot_freeze_pbc)
80 PMC *visitor;
82 PMC * const pf_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct);
83 VTABLE_set_pointer(interp, pf_pmc, (void *)pf);
85 visitor = Parrot_pmc_new_init(interp, enum_class_ImageIO, pf_pmc);
86 VTABLE_set_pmc(interp, visitor, pmc);
88 return VTABLE_get_string(interp, visitor);
94 =item C<UINTVAL Parrot_freeze_size(PARROT_INTERP, PMC *pmc)>
96 Get the size of an image to be frozen without allocating a large buffer.
98 =cut
102 PARROT_EXPORT
103 PARROT_WARN_UNUSED_RESULT
104 UINTVAL
105 Parrot_freeze_size(PARROT_INTERP, ARGIN(PMC *pmc))
107 ASSERT_ARGS(Parrot_freeze_size)
108 UINTVAL int_result;
109 PMC *pmc_result;
110 PMC * const visitor = Parrot_pmc_new(interp, enum_class_ImageIOSize);
111 VTABLE_set_pmc(interp, visitor, pmc);
112 pmc_result = VTABLE_get_pmc(interp, visitor);
113 int_result = VTABLE_get_integer(interp, pmc_result);
114 return int_result;
119 =item C<UINTVAL Parrot_freeze_pbc_size(PARROT_INTERP, PMC *pmc, const
120 PackFile_ConstTable *pf)>
122 Get the size of an image if it were created using C<Parrot_freeze_pbc>.
124 =cut
128 PARROT_EXPORT
129 PARROT_WARN_UNUSED_RESULT
130 UINTVAL
131 Parrot_freeze_pbc_size(PARROT_INTERP, ARGIN(PMC *pmc), ARGIN(const PackFile_ConstTable *pf))
133 ASSERT_ARGS(Parrot_freeze_pbc_size)
134 PMC *pf_pmc, *visitor, *pmc_result;
136 pf_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct);
137 VTABLE_set_pointer(interp, pf_pmc, (void *)pf);
139 visitor = Parrot_pmc_new_init(interp, enum_class_ImageIOSize, pf_pmc);
140 VTABLE_set_pmc(interp, visitor, pmc);
142 pmc_result = VTABLE_get_pmc(interp, visitor);
143 return VTABLE_get_integer(interp, pmc_result);
149 =item C<PMC * Parrot_freeze_strings(PARROT_INTERP, PMC *pmc)>
151 Get the strings of a PMC to be frozen.
153 =cut
157 PARROT_EXPORT
158 PARROT_WARN_UNUSED_RESULT
159 PARROT_CANNOT_RETURN_NULL
160 PMC *
161 Parrot_freeze_strings(PARROT_INTERP, ARGIN(PMC *pmc))
163 ASSERT_ARGS(Parrot_freeze_strings)
164 PMC * const visitor = Parrot_pmc_new(interp, enum_class_ImageIOStrings);
165 VTABLE_set_pmc(interp, visitor, pmc);
166 return VTABLE_get_pmc(interp, visitor);
172 =item C<PMC* Parrot_thaw(PARROT_INTERP, STRING *image)>
174 Thaws a PMC. Called from the C<thaw> opcode.
176 For now it seems cheaper to use a list for remembering contained
177 aggregates. We could of course decide dynamically, which strategy to
178 use, e.g.: given a big image, the first thawed item is a small
179 aggregate. This implies, it probably contains (or some big strings) more
180 nested containers, for which another approach could be a win.
182 =cut
186 PARROT_EXPORT
187 PARROT_WARN_UNUSED_RESULT
188 PARROT_CANNOT_RETURN_NULL
189 PMC*
190 Parrot_thaw(PARROT_INTERP, ARGIN(STRING *image))
192 ASSERT_ARGS(Parrot_thaw)
194 PMC * const info = Parrot_pmc_new(interp, enum_class_ImageIO);
195 int gc_block = 0;
196 PMC *result;
199 * if we are thawing a lot of PMCs, it's cheaper to do
200 * a GC run first and then block GC - the limit should be
201 * chosen so that no more then one GC run would be triggered
203 * XXX
205 * md5_3.pir shows a segfault during thawing the config hash
206 * info->thaw_ptr becomes invalid - seems that the hash got
207 * collected under us.
209 if (1 || (Parrot_str_byte_length(interp, image) > THAW_BLOCK_GC_SIZE)) {
210 Parrot_block_GC_mark(interp);
211 Parrot_block_GC_sweep(interp);
212 gc_block = 1;
215 VTABLE_set_string_native(interp, info, image);
216 result = VTABLE_get_pmc(interp, info);
218 if (gc_block) {
219 Parrot_unblock_GC_mark(interp);
220 Parrot_unblock_GC_sweep(interp);
223 return result;
229 =item C<PMC* Parrot_thaw_pbc(PARROT_INTERP, STRING *image, PackFile_ConstTable
230 *pf)>
232 Thaw a pmc frozen by Parrot_freeze_pbc.
234 =cut
238 PARROT_EXPORT
239 PARROT_WARN_UNUSED_RESULT
240 PARROT_CAN_RETURN_NULL
241 PMC*
242 Parrot_thaw_pbc(PARROT_INTERP, ARGIN(STRING *image), ARGIN(PackFile_ConstTable *pf))
244 ASSERT_ARGS(Parrot_thaw_pbc)
245 PMC *info, *pf_pmc, *result;
247 pf_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct);
248 VTABLE_set_pointer(interp, pf_pmc, pf);
250 info = Parrot_pmc_new_init(interp, enum_class_ImageIO, pf_pmc);
252 /* TODO
253 * Find out what broken code depends on blocking GC here and fix it, regardless of performance
254 * wins.
256 Parrot_block_GC_mark(interp);
257 Parrot_block_GC_sweep(interp);
259 VTABLE_set_string_native(interp, info, image);
260 result = VTABLE_get_pmc(interp, info);
262 Parrot_unblock_GC_mark(interp);
263 Parrot_unblock_GC_sweep(interp);
265 return result;
270 =item C<PMC* Parrot_thaw_constants(PARROT_INTERP, STRING *image)>
272 Thaws constants, used by PackFile for unpacking PMC constants.
273 This is a lie. It does nothing different from Parrot_thaw at the moment.
275 =cut
279 PARROT_EXPORT
280 PARROT_WARN_UNUSED_RESULT
281 PARROT_CANNOT_RETURN_NULL
282 PMC*
283 Parrot_thaw_constants(PARROT_INTERP, ARGIN(STRING *image))
285 ASSERT_ARGS(Parrot_thaw_constants)
286 return Parrot_thaw(interp, image);
292 =item C<PMC* Parrot_clone(PARROT_INTERP, PMC *pmc)>
294 There are for sure shortcuts to clone faster, e.g. always thaw the image
295 immediately or use a special callback. For now we just thaw a frozen PMC.
297 =cut
301 PARROT_EXPORT
302 PARROT_WARN_UNUSED_RESULT
303 PARROT_CAN_RETURN_NULL
304 PMC*
305 Parrot_clone(PARROT_INTERP, ARGIN(PMC *pmc))
307 ASSERT_ARGS(Parrot_clone)
308 return VTABLE_clone(interp, pmc);
313 =item C<void Parrot_visit_loop_visit(PARROT_INTERP, PMC *info)>
315 Iterate a visitor PMC visiting each encountered target PMC.
317 =cut
321 void
322 Parrot_visit_loop_visit(PARROT_INTERP, ARGIN(PMC *info))
324 ASSERT_ARGS(Parrot_visit_loop_visit)
326 INTVAL i;
327 const INTVAL action = VTABLE_get_integer(interp, info);
328 PMC * const todo = VTABLE_get_iter(interp, info);
330 /* can't cache upper limit, visit may append items */
331 for (i = 0; i < VTABLE_elements(interp, todo); ++i) {
332 PMC * const current = VTABLE_get_pmc_keyed_int(interp, todo, i);
333 if (!current)
334 Parrot_ex_throw_from_c_args(interp, NULL, 1,
335 "NULL current PMC in visit_loop_todo_list");
337 PARROT_ASSERT(current->vtable);
339 if (action == VISIT_FREEZE_NORMAL)
340 VTABLE_freeze(interp, current, info);
341 else
342 VTABLE_thaw(interp, current, info);
344 VTABLE_visit(interp, current, info);
346 VISIT_PMC(interp, info, PMC_metadata(current));
352 =item C<void Parrot_visit_loop_thawfinish(PARROT_INTERP, PMC *info)>
354 Iterate a visitor PMC thawfinishing each encountered target PMC.
356 =cut
360 void
361 Parrot_visit_loop_thawfinish(PARROT_INTERP, ARGIN(PMC *info))
363 ASSERT_ARGS(Parrot_visit_loop_thawfinish)
365 /* call thawfinish for each processed PMC */
367 * Thaw in reverse order. We have to fully thaw younger PMCs
368 * before use them in older.
370 * XXX There are no younger or older pmcs in a directed graph
371 * that allows cycles. Any code that requires a specific
372 * order here is likely broken.
375 PMC * const todo = VTABLE_get_iter(interp, info);
376 const INTVAL n = VTABLE_elements(interp, todo);
377 int i;
379 for (i = n-1; i >= 0; --i) {
380 PMC *current = VTABLE_get_pmc_keyed_int(interp, todo, i);
381 if (!PMC_IS_NULL(current))
382 VTABLE_thawfinish(interp, current, info);
388 =back
390 =head1 TODO
392 The seen-hash version for freezing might go away sometime.
394 =head1 SEE ALSO
396 Lot of discussion on p6i and F<docs/dev/pmc_freeze.pod>.
398 =cut
404 * Local variables:
405 * c-file-style: "parrot"
406 * End:
407 * vim: expandtab shiftwidth=4: