ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/clone.c
Revision: 1.8
Committed: Wed Jul 1 07:58:45 2009 UTC (14 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-6_512, rel-6_513, rel-6_511, rel-6_09, rel-6_514, rel-6_0, rel-5_23, rel-5_24, rel-5_25, rel-6_5, rel-6_32, rel-6_33, rel-6_31, rel-6_36, rel-6_37, rel-5_162, rel-5_2, rel-6_38, rel-6_39, rel-6_10, rel-6_51, rel-6_52, rel-6_53, rel-6_54, rel-6_55, rel-6_56, rel-6_57, rel-6_03, rel-6_02, rel-5_151, rel-5_22, rel-5_17, rel-5_16, rel-5_37, rel-5_36, rel-6_23, rel-6_08, rel-6_07, rel-6_06, rel-6_05, rel-6_04, rel-6_29, rel-6_28, rel-6_01, rel-6_43, rel-6_42, rel-6_41, rel-6_47, rel-6_46, rel-6_45, rel-6_44, rel-6_49, rel-6_48, rel-5_371, rel-5_372, rel-5_161, HEAD
Changes since 1.7: +11 -4 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /* clone implementation, big, slow, useless, but not pointless */
2    
3     static AV *
4 root 1.5 clone_av (pTHX_ AV *av)
5 root 1.1 {
6     int i;
7     AV *nav = newAV ();
8    
9     av_fill (nav, AvFILLp (av));
10    
11     for (i = 0; i <= AvFILLp (av); ++i)
12     AvARRAY (nav)[i] = SvREFCNT_inc (AvARRAY (av)[i]);
13    
14     return nav;
15     }
16    
17     static struct coro *
18 root 1.5 coro_clone (pTHX_ struct coro *coro)
19 root 1.1 {
20     perl_slots *slot, *nslot;
21     struct coro *ncoro;
22    
23     if (coro->flags & (CF_RUNNING | CF_NEW))
24     croak ("Coro::State::clone cannot clone new or running states, caught");
25    
26     if (coro->cctx)
27     croak ("Coro::State::clone cannot clone a state running on a custom C context, caught");
28    
29 root 1.6 /* TODO: maybe check slf_frame for prpeare_rransfer/check_nop? */
30    
31 root 1.1 slot = coro->slot;
32    
33     if (slot->curstackinfo->si_type != PERLSI_MAIN)
34     croak ("Coro::State::clone cannot clone a state running on a non-main stack, caught");
35    
36     Newz (0, ncoro, 1, struct coro);
37     Newz (0, nslot, 1, perl_slots);
38    
39     /* copy first, then fixup */
40     *ncoro = *coro;
41     *nslot = *slot;
42     ncoro->slot = nslot;
43    
44     nslot->curstackinfo = new_stackinfo (slot->stack_max - slot->stack_sp + 1, slot->curstackinfo->si_cxmax);
45     nslot->curstackinfo->si_type = PERLSI_MAIN;
46     nslot->curstackinfo->si_cxix = slot->curstackinfo->si_cxix;
47     nslot->curstack = nslot->curstackinfo->si_stack;
48     ncoro->mainstack = nslot->curstack;
49    
50     nslot->stack_base = AvARRAY (nslot->curstack);
51     nslot->stack_sp = nslot->stack_base + (slot->stack_sp - slot->stack_base);
52     nslot->stack_max = nslot->stack_base + AvMAX (nslot->curstack);
53    
54     Copy (slot->stack_base, nslot->stack_base, slot->stack_sp - slot->stack_base + 1, SV *);
55     Copy (slot->curstackinfo->si_cxstack, nslot->curstackinfo->si_cxstack, nslot->curstackinfo->si_cxix + 1, PERL_CONTEXT);
56    
57     New (50, nslot->tmps_stack, nslot->tmps_max, SV *);
58     Copy (slot->tmps_stack, nslot->tmps_stack, slot->tmps_ix + 1, SV *);
59    
60     New (54, nslot->markstack, slot->markstack_max - slot->markstack + 1, I32);
61     nslot->markstack_ptr = nslot->markstack + (slot->markstack_ptr - slot->markstack);
62     nslot->markstack_max = nslot->markstack + (slot->markstack_max - slot->markstack);
63     Copy (slot->markstack, nslot->markstack, slot->markstack_ptr - slot->markstack + 1, I32);
64    
65     #ifdef SET_MARK_OFFSET
66     //SET_MARK_OFFSET; /*TODO*/
67     #endif
68    
69     New (54, nslot->scopestack, slot->scopestack_max, I32);
70     Copy (slot->scopestack, nslot->scopestack, slot->scopestack_ix + 1, I32);
71    
72     New (54, nslot->savestack, nslot->savestack_max, ANY);
73     Copy (slot->savestack, nslot->savestack, slot->savestack_ix + 1, ANY);
74    
75     #if !PERL_VERSION_ATLEAST (5,10,0)
76 root 1.5 New (54, nslot->retstack, nslot->retstack_max, OP *);
77 root 1.1 Copy (slot->retstack, nslot->retstack, slot->retstack_max, OP *);
78     #endif
79    
80     /* first fix up the padlists, by walking up our own saved state */
81     {
82     SV **sp = nslot->stack_sp;
83     AV *av;
84     CV *cv;
85     int i;
86    
87     /* now do the ugly restore mess */
88     while (expect_true (cv = (CV *)POPs))
89     {
90 root 1.6 /* cv will be refcnt_inc'ed twice by the following two loops */
91 root 1.1 POPs;
92    
93 root 1.6 /* need to clone the padlist */
94 root 1.7 /* this simplistic hack is most likely wrong */
95 root 1.5 av = clone_av (aTHX_ (AV *)TOPs);
96 root 1.1 AvREAL_off (av);
97    
98     for (i = 1; i <= AvFILLp (av); ++i)
99     {
100     SvREFCNT_dec (AvARRAY (av)[i]);
101 root 1.5 AvARRAY (av)[i] = (SV *)clone_av (aTHX_ (AV *)AvARRAY (av)[i]);
102 root 1.4 AvREIFY_only (AvARRAY (av)[i]);
103 root 1.1 }
104    
105     TOPs = (SV *)av;
106    
107     POPs;
108     }
109     }
110    
111     /* easy things first, mortals */
112     {
113     int i;
114    
115     for (i = 0; i <= nslot->tmps_ix; ++i)
116     SvREFCNT_inc (nslot->tmps_stack [i]);
117     }
118    
119     /* now fix up the context stack, modelled after cx_dup */
120     {
121     I32 cxix = nslot->curstackinfo->si_cxix;
122     PERL_CONTEXT *ccstk = nslot->curstackinfo->si_cxstack;
123    
124     while (expect_true (cxix >= 0))
125     {
126     PERL_CONTEXT *cx = &ccstk[cxix--];
127    
128     switch (CxTYPE (cx))
129     {
130     case CXt_SUBST:
131     croak ("Coro::State::clone cannot clone a state inside a substitution context, caught");
132    
133     case CXt_SUB:
134     if (cx->blk_sub.olddepth == 0)
135     SvREFCNT_inc ((SV *)cx->blk_sub.cv);
136 root 1.3
137 root 1.1 if (cx->blk_sub.hasargs)
138     {
139     SvREFCNT_inc ((SV *)cx->blk_sub.argarray);
140     SvREFCNT_inc ((SV *)cx->blk_sub.savearray);
141     }
142     break;
143    
144     case CXt_EVAL:
145     SvREFCNT_inc ((SV *)cx->blk_eval.old_namesv);
146     SvREFCNT_inc ((SV *)cx->blk_eval.cur_text);
147     break;
148    
149     case CXt_LOOP:
150     /*TODO: cx->blk_loop.iterdata*/
151     SvREFCNT_inc ((SV *)cx->blk_loop.itersave);
152     SvREFCNT_inc ((SV *)cx->blk_loop.iterlval);
153     SvREFCNT_inc ((SV *)cx->blk_loop.iterary);
154     break;
155    
156     case CXt_FORMAT:
157     croak ("Coro::State::clone cannot clone a state inside a format, caught");
158     break;
159    
160     /* BLOCK, NULL etc. */
161     }
162     }
163     }
164    
165     /* now fix up the save stack */
166     /* modelled after ss_dup */
167    
168     #define POPINT(ss,ix) ((ss)[--(ix)].any_i32)
169     #define TOPINT(ss,ix) ((ss)[ix].any_i32)
170     #define POPLONG(ss,ix) ((ss)[--(ix)].any_long)
171     #define TOPLONG(ss,ix) ((ss)[ix].any_long)
172     #define POPIV(ss,ix) ((ss)[--(ix)].any_iv)
173     #define TOPIV(ss,ix) ((ss)[ix].any_iv)
174     #define POPBOOL(ss,ix) ((ss)[--(ix)].any_bool)
175     #define TOPBOOL(ss,ix) ((ss)[ix].any_bool)
176     #define POPPTR(ss,ix) ((ss)[--(ix)].any_ptr)
177     #define TOPPTR(ss,ix) ((ss)[ix].any_ptr)
178     #define POPDPTR(ss,ix) ((ss)[--(ix)].any_dptr)
179     #define TOPDPTR(ss,ix) ((ss)[ix].any_dptr)
180     #define POPDXPTR(ss,ix) ((ss)[--(ix)].any_dxptr)
181     #define TOPDXPTR(ss,ix) ((ss)[ix].any_dxptr)
182    
183     {
184     ANY * const ss = nslot->savestack;
185     const I32 max = nslot->savestack_max;
186     I32 ix = nslot->savestack_ix;
187 root 1.8 void *any_ptr;
188 root 1.1
189     while (ix > 0)
190     {
191     const I32 type = POPINT (ss, ix);
192    
193     switch (type)
194     {
195     case SAVEt_HELEM: /* hash element */
196     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
197     /* fall through */
198     case SAVEt_ITEM: /* normal string */
199     case SAVEt_SV: /* scalar reference */
200     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
201     /* fall through */
202     case SAVEt_FREESV:
203     case SAVEt_MORTALIZESV:
204     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
205     break;
206    
207     case SAVEt_SHARED_PVREF: /* char* in shared space */
208     abort ();
209     #if 0
210     c = (char *) POPPTR (ss, ix);
211     TOPPTR (ss, ix) = savesharedpv (c);
212     ptr = POPPTR (ss, ix);
213     TOPPTR (ss, ix) = any_dup (ptr, proto_perl);
214     #endif
215     break;
216     case SAVEt_GENERIC_SVREF: /* generic sv */
217     case SAVEt_SVREF: /* scalar reference */
218     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
219     POPPTR (ss, ix);
220     break;
221    
222     case SAVEt_HV: /* hash reference */
223     case SAVEt_AV: /* array reference */
224     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
225     /* fall through */
226     case SAVEt_COMPPAD:
227     case SAVEt_NSTAB:
228     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
229     break;
230    
231     case SAVEt_INT: /* int reference */
232     POPPTR (ss, ix);
233     POPINT (ss, ix);
234     break;
235    
236     case SAVEt_LONG: /* long reference */
237     POPPTR (ss, ix);
238     /* fall through */
239     case SAVEt_CLEARSV:
240     POPLONG (ss, ix);
241     break;
242    
243     case SAVEt_I32: /* I32 reference */
244     case SAVEt_I16: /* I16 reference */
245     case SAVEt_I8: /* I8 reference */
246     case SAVEt_COP_ARYBASE: /* call CopARYBASE_set */
247     POPPTR (ss, ix);
248     POPINT (ss, ix);
249     break;
250    
251     case SAVEt_IV: /* IV reference */
252     POPPTR (ss, ix);
253     POPIV (ss, ix);
254     break;
255    
256     case SAVEt_HPTR: /* HV* reference */
257     case SAVEt_APTR: /* AV* reference */
258     case SAVEt_SPTR: /* SV* reference */
259     POPPTR (ss, ix);
260     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
261     break;
262    
263     case SAVEt_VPTR: /* random* reference */
264     POPPTR (ss, ix);
265     POPPTR (ss, ix);
266     break;
267     case SAVEt_GENERIC_PVREF: /* generic char* */
268     case SAVEt_PPTR: /* char* reference */
269     POPPTR (ss, ix);
270 root 1.8 any_ptr = POPPTR (ss, ix);
271     TOPPTR (ss, ix) = savepv ((char *) any_ptr);
272 root 1.1 break;
273    
274     case SAVEt_GP: /* scalar reference */
275     ((GP *) POPPTR (ss, ix))->gp_refcnt++;
276     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
277     break;
278    
279     case SAVEt_FREEOP:
280     abort ();
281     #if 0
282     ptr = POPPTR (ss, ix);
283     if (ptr && (((OP *) ptr)->op_private & OPpREFCOUNTED))
284     {
285     /* these are assumed to be refcounted properly */
286     OP *o;
287    
288     switch (((OP *) ptr)->op_type)
289     {
290     case OP_LEAVESUB:
291     case OP_LEAVESUBLV:
292     case OP_LEAVEEVAL:
293     case OP_LEAVE:
294     case OP_SCOPE:
295     case OP_LEAVEWRITE:
296     TOPPTR (ss, ix) = ptr;
297     o = (OP *) ptr;
298     OP_REFCNT_LOCK;
299     (void) OpREFCNT_inc (o);
300     OP_REFCNT_UNLOCK;
301     break;
302     default:
303     TOPPTR (ss, ix) = NULL;
304     break;
305     }
306     }
307     else
308     TOPPTR (ss, ix) = NULL;
309     #endif
310     break;
311    
312     case SAVEt_FREEPV:
313 root 1.8 any_ptr = POPPTR (ss, ix);
314     TOPPTR (ss, ix) = savepv ((char *) any_ptr);
315 root 1.1 break;
316    
317     case SAVEt_DELETE:
318     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
319 root 1.8 any_ptr = POPPTR (ss, ix);
320     TOPPTR (ss, ix) = savepv ((char *) any_ptr);
321 root 1.1 /* fall through */
322     case SAVEt_STACK_POS: /* Position on Perl stack */
323     POPINT (ss, ix);
324     break;
325    
326     case SAVEt_DESTRUCTOR:
327     POPPTR (ss, ix);
328     POPDPTR (ss, ix);
329     break;
330    
331     case SAVEt_DESTRUCTOR_X:
332     POPPTR (ss, ix);
333     POPDXPTR (ss, ix);
334     break;
335    
336     case SAVEt_REGCONTEXT:
337     case SAVEt_ALLOC:
338 root 1.8 {
339     I32 ni = POPINT (ss, ix);
340     ix = ni;
341     }
342 root 1.1 break;
343    
344     case SAVEt_AELEM: /* array element */
345     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
346     POPINT (ss, ix);
347     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
348     break;
349     case SAVEt_OP:
350     POPPTR (ss, ix);
351     break;
352     case SAVEt_HINTS:
353     abort ();
354     #if 0
355     {
356     int i = POPINT (ss, ix);
357     void *ptr = POPPTR (ss, ix);
358     if (ptr)
359     ((struct refcounted_he *)ptr)->refcounted_he_refcnt++;
360    
361     if (i & HINT_LOCALIZE_HH)
362     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
363     }
364     #endif
365     break;
366    
367     case SAVEt_PADSV:
368     POPLONG (ss, ix);
369     POPPTR (ss, ix);
370     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
371     break;
372    
373     case SAVEt_BOOL:
374     POPPTR (ss, ix);
375     POPBOOL (ss, ix);
376     break;
377    
378     case SAVEt_SET_SVFLAGS:
379     POPINT (ss, ix);
380     POPINT (ss, ix);
381     SvREFCNT_inc ((SV *) POPPTR (ss, ix));
382     break;
383    
384     case SAVEt_RE_STATE:
385     abort ();
386     #if 0
387     {
388     const struct re_save_state *const old_state = (struct re_save_state *) (ss + ix - SAVESTACK_ALLOC_FOR_RE_SAVE_STATE);
389     struct re_save_state *const new_state = (struct re_save_state *) (ss + ix - SAVESTACK_ALLOC_FOR_RE_SAVE_STATE);
390    
391     Copy (old_state, new_state, 1, struct re_save_state);
392    
393     ix -= SAVESTACK_ALLOC_FOR_RE_SAVE_STATE;
394    
395     new_state->re_state_bostr = pv_dup (old_state->re_state_bostr);
396     new_state->re_state_reginput = pv_dup (old_state->re_state_reginput);
397     new_state->re_state_regeol = pv_dup (old_state->re_state_regeol);
398     new_state->re_state_regoffs = (regexp_paren_pair *) any_dup (old_state->re_state_regoffs, proto_perl);
399     new_state->re_state_reglastparen = (U32 *) any_dup (old_state->re_state_reglastparen, proto_perl);
400     new_state->re_state_reglastcloseparen = (U32 *) any_dup (old_state->re_state_reglastcloseparen, proto_perl);
401     /* XXX This just has to be broken. The old save_re_context
402     code did SAVEGENERICPV(PL_reg_start_tmp);
403     PL_reg_start_tmp is char **.
404     Look above to what the dup code does for
405     SAVEt_GENERIC_PVREF
406     It can never have worked.
407     So this is merely a faithful copy of the exiting bug: */
408     new_state->re_state_reg_start_tmp = (char **) pv_dup ((char *) old_state->re_state_reg_start_tmp);
409     /* I assume that it only ever "worked" because no-one called
410     (pseudo)fork while the regexp engine had re-entered itself.
411     */
412     #ifdef PERL_OLD_COPY_ON_WRITE
413     new_state->re_state_nrs = sv_dup (old_state->re_state_nrs, param);
414     #endif
415     new_state->re_state_reg_magic = (MAGIC *) any_dup (old_state->re_state_reg_magic, proto_perl);
416     new_state->re_state_reg_oldcurpm = (PMOP *) any_dup (old_state->re_state_reg_oldcurpm, proto_perl);
417     new_state->re_state_reg_curpm = (PMOP *) any_dup (old_state->re_state_reg_curpm, proto_perl);
418     new_state->re_state_reg_oldsaved = pv_dup (old_state->re_state_reg_oldsaved);
419     new_state->re_state_reg_poscache = pv_dup (old_state->re_state_reg_poscache);
420     new_state->re_state_reg_starttry = pv_dup (old_state->re_state_reg_starttry);
421     break;
422     }
423     #endif
424    
425     case SAVEt_COMPILE_WARNINGS:
426     abort ();
427     #if 0
428     ptr = POPPTR (ss, ix);
429     TOPPTR (ss, ix) = DUP_WARNINGS ((STRLEN *) ptr);
430     break;
431     #endif
432    
433     case SAVEt_PARSER:
434     abort ();
435     #if 0
436     ptr = POPPTR (ss, ix);
437     TOPPTR (ss, ix) = parser_dup ((const yy_parser *) ptr, param);
438     break;
439     #endif
440     default:
441     croak ("panic: ss_dup inconsistency (%" IVdf ")", (IV) type);
442     }
443     }
444     }
445    
446     SvREFCNT_inc (nslot->defsv);
447     SvREFCNT_inc (nslot->defav);
448     SvREFCNT_inc (nslot->errsv);
449     SvREFCNT_inc (nslot->irsgv);
450    
451     SvREFCNT_inc (nslot->defoutgv);
452     SvREFCNT_inc (nslot->rs);
453     SvREFCNT_inc (nslot->compcv);
454     SvREFCNT_inc (nslot->diehook);
455     SvREFCNT_inc (nslot->warnhook);
456    
457     SvREFCNT_inc (ncoro->startcv);
458     SvREFCNT_inc (ncoro->args);
459     SvREFCNT_inc (ncoro->except);
460    
461     return ncoro;
462     }