]> git.vpit.fr Git - perl/modules/indirect.git/blob - indirect.xs
Replace STATIC by static
[perl/modules/indirect.git] / indirect.xs
1 /* This file is part of the indirect Perl module.
2  * See http://search.cpan.org/dist/indirect/ */
3
4 #define PERL_NO_GET_CONTEXT
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8
9 #define __PACKAGE__     "indirect"
10 #define __PACKAGE_LEN__ (sizeof(__PACKAGE__)-1)
11
12 /* --- Compatibility wrappers ---------------------------------------------- */
13
14 #ifndef NOOP
15 # define NOOP
16 #endif
17
18 #ifndef dNOOP
19 # define dNOOP
20 #endif
21
22 #ifndef Newx
23 # define Newx(v, n, c) New(0, v, n, c)
24 #endif
25
26 #ifndef SvPV_const
27 # define SvPV_const SvPV
28 #endif
29
30 #ifndef SvPV_nolen_const
31 # define SvPV_nolen_const SvPV_nolen
32 #endif
33
34 #ifndef SvPVX_const
35 # define SvPVX_const SvPVX
36 #endif
37
38 #ifndef SvREFCNT_inc_simple_void_NN
39 # ifdef SvREFCNT_inc_simple_NN
40 #  define SvREFCNT_inc_simple_void_NN SvREFCNT_inc_simple_NN
41 # else
42 #  define SvREFCNT_inc_simple_void_NN SvREFCNT_inc
43 # endif
44 #endif
45
46 #ifndef sv_catpvn_nomg
47 # define sv_catpvn_nomg sv_catpvn
48 #endif
49
50 #ifndef mPUSHp
51 # define mPUSHp(P, L) PUSHs(sv_2mortal(newSVpvn((P), (L))))
52 #endif
53
54 #ifndef mPUSHu
55 # define mPUSHu(U) PUSHs(sv_2mortal(newSVuv(U)))
56 #endif
57
58 #ifndef HvNAME_get
59 # define HvNAME_get(H) HvNAME(H)
60 #endif
61
62 #ifndef HvNAMELEN_get
63 # define HvNAMELEN_get(H) strlen(HvNAME_get(H))
64 #endif
65
66 #ifndef OpSIBLING
67 # ifdef OP_SIBLING
68 #  define OpSIBLING(O) OP_SIBLING(O)
69 # else
70 #  define OpSIBLING(O) ((O)->op_sibling)
71 # endif
72 #endif
73
74 #define I_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S))))))
75
76 #if I_HAS_PERL(5, 10, 0) || defined(PL_parser)
77 # ifndef PL_linestr
78 #  define PL_linestr PL_parser->linestr
79 # endif
80 # ifndef PL_bufptr
81 #  define PL_bufptr PL_parser->bufptr
82 # endif
83 # ifndef PL_oldbufptr
84 #  define PL_oldbufptr PL_parser->oldbufptr
85 # endif
86 # ifndef PL_lex_inwhat
87 #  define PL_lex_inwhat PL_parser->lex_inwhat
88 # endif
89 #else
90 # ifndef PL_linestr
91 #  define PL_linestr PL_Ilinestr
92 # endif
93 # ifndef PL_bufptr
94 #  define PL_bufptr PL_Ibufptr
95 # endif
96 # ifndef PL_oldbufptr
97 #  define PL_oldbufptr PL_Ioldbufptr
98 # endif
99 # ifndef PL_lex_inwhat
100 #  define PL_lex_inwhat PL_Ilex_inwhat
101 # endif
102 #endif
103
104 #ifndef I_WORKAROUND_REQUIRE_PROPAGATION
105 # define I_WORKAROUND_REQUIRE_PROPAGATION !I_HAS_PERL(5, 10, 1)
106 #endif
107
108 /* ... Thread safety and multiplicity ...................................... */
109
110 /* Safe unless stated otherwise in Makefile.PL */
111 #ifndef I_FORKSAFE
112 # define I_FORKSAFE 1
113 #endif
114
115 #ifndef I_MULTIPLICITY
116 # if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT)
117 #  define I_MULTIPLICITY 1
118 # else
119 #  define I_MULTIPLICITY 0
120 # endif
121 #endif
122 #if I_MULTIPLICITY && !defined(tTHX)
123 # define tTHX PerlInterpreter*
124 #endif
125
126 #if I_MULTIPLICITY && defined(USE_ITHREADS) && defined(dMY_CXT) && defined(MY_CXT) && defined(START_MY_CXT) && defined(MY_CXT_INIT) && (defined(MY_CXT_CLONE) || defined(dMY_CXT_SV))
127 # define I_THREADSAFE 1
128 # ifndef MY_CXT_CLONE
129 #  define MY_CXT_CLONE \
130     dMY_CXT_SV;                                                      \
131     my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1)); \
132     Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t); \
133     sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
134 # endif
135 #else
136 # define I_THREADSAFE 0
137 # undef  dMY_CXT
138 # define dMY_CXT      dNOOP
139 # undef  MY_CXT
140 # define MY_CXT       indirect_globaldata
141 # undef  START_MY_CXT
142 # define START_MY_CXT static my_cxt_t MY_CXT;
143 # undef  MY_CXT_INIT
144 # define MY_CXT_INIT  NOOP
145 # undef  MY_CXT_CLONE
146 # define MY_CXT_CLONE NOOP
147 #endif
148
149 #if defined(OP_CHECK_MUTEX_LOCK) && defined(OP_CHECK_MUTEX_UNLOCK)
150 # define I_CHECK_MUTEX_LOCK   OP_CHECK_MUTEX_LOCK
151 # define I_CHECK_MUTEX_UNLOCK OP_CHECK_MUTEX_UNLOCK
152 #else
153 # define I_CHECK_MUTEX_LOCK   OP_REFCNT_LOCK
154 # define I_CHECK_MUTEX_UNLOCK OP_REFCNT_UNLOCK
155 #endif
156
157 typedef OP *(*indirect_ck_t)(pTHX_ OP *);
158
159 #ifdef wrap_op_checker
160
161 # define indirect_ck_replace(T, NC, OCP) wrap_op_checker((T), (NC), (OCP))
162
163 #else
164
165 static void indirect_ck_replace(pTHX_ OPCODE type, indirect_ck_t new_ck, indirect_ck_t *old_ck_p) {
166 #define indirect_ck_replace(T, NC, OCP) indirect_ck_replace(aTHX_ (T), (NC), (OCP))
167  I_CHECK_MUTEX_LOCK;
168  if (!*old_ck_p) {
169   *old_ck_p      = PL_check[type];
170   PL_check[type] = new_ck;
171  }
172  I_CHECK_MUTEX_UNLOCK;
173 }
174
175 #endif
176
177 static void indirect_ck_restore(pTHX_ OPCODE type, indirect_ck_t *old_ck_p) {
178 #define indirect_ck_restore(T, OCP) indirect_ck_restore(aTHX_ (T), (OCP))
179  I_CHECK_MUTEX_LOCK;
180  if (*old_ck_p) {
181   PL_check[type] = *old_ck_p;
182   *old_ck_p      = 0;
183  }
184  I_CHECK_MUTEX_UNLOCK;
185 }
186
187 /* --- Helpers ------------------------------------------------------------- */
188
189 /* ... Thread-safe hints ................................................... */
190
191 #if I_WORKAROUND_REQUIRE_PROPAGATION
192
193 typedef struct {
194  SV *code;
195  IV  require_tag;
196 } indirect_hint_t;
197
198 #define I_HINT_STRUCT 1
199
200 #define I_HINT_CODE(H) ((H)->code)
201
202 #define I_HINT_FREE(H) {   \
203  indirect_hint_t *h = (H); \
204  SvREFCNT_dec(h->code);    \
205  PerlMemShared_free(h);    \
206 }
207
208 #else  /*  I_WORKAROUND_REQUIRE_PROPAGATION */
209
210 typedef SV indirect_hint_t;
211
212 #define I_HINT_STRUCT 0
213
214 #define I_HINT_CODE(H) (H)
215
216 #define I_HINT_FREE(H) SvREFCNT_dec(H);
217
218 #endif /* !I_WORKAROUND_REQUIRE_PROPAGATION */
219
220 #if I_THREADSAFE
221
222 #define PTABLE_NAME        ptable_hints
223 #define PTABLE_VAL_FREE(V) I_HINT_FREE(V)
224
225 #define pPTBL  pTHX
226 #define pPTBL_ pTHX_
227 #define aPTBL  aTHX
228 #define aPTBL_ aTHX_
229
230 #include "ptable.h"
231
232 #define ptable_hints_store(T, K, V) ptable_hints_store(aTHX_ (T), (K), (V))
233 #define ptable_hints_free(T)        ptable_hints_free(aTHX_ (T))
234
235 #endif /* I_THREADSAFE */
236
237 /* Define the op->str ptable here because we need to be able to clean it during
238  * thread cleanup. */
239
240 typedef struct {
241  char   *buf;
242  STRLEN  pos;
243  STRLEN  size;
244  STRLEN  len;
245  line_t  line;
246 } indirect_op_info_t;
247
248 #define PTABLE_NAME        ptable
249 #define PTABLE_VAL_FREE(V) if (V) { Safefree(((indirect_op_info_t *) (V))->buf); Safefree(V); }
250
251 #define pPTBL  pTHX
252 #define pPTBL_ pTHX_
253 #define aPTBL  aTHX
254 #define aPTBL_ aTHX_
255
256 #include "ptable.h"
257
258 #define ptable_store(T, K, V) ptable_store(aTHX_ (T), (K), (V))
259 #define ptable_delete(T, K)   ptable_delete(aTHX_ (T), (K))
260 #define ptable_clear(T)       ptable_clear(aTHX_ (T))
261 #define ptable_free(T)        ptable_free(aTHX_ (T))
262
263 #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION
264
265 typedef struct {
266 #if I_THREADSAFE
267  ptable *tbl; /* It really is a ptable_hints */
268  tTHX    owner;
269 #endif
270  ptable *map;
271  SV     *global_code;
272 } my_cxt_t;
273
274 START_MY_CXT
275
276 #if I_THREADSAFE
277
278 typedef struct {
279  ptable *tbl;
280 #if I_HAS_PERL(5, 13, 2)
281  CLONE_PARAMS *params;
282 #else
283  CLONE_PARAMS params;
284 #endif
285 } indirect_ptable_clone_ud;
286
287 #if I_HAS_PERL(5, 13, 2)
288 # define indirect_ptable_clone_ud_init(U, T, O) \
289    (U).tbl    = (T); \
290    (U).params = Perl_clone_params_new((O), aTHX)
291 # define indirect_ptable_clone_ud_deinit(U) Perl_clone_params_del((U).params)
292 # define indirect_dup_inc(S, U)             SvREFCNT_inc(sv_dup((S), (U)->params))
293 #else
294 # define indirect_ptable_clone_ud_init(U, T, O) \
295    (U).tbl               = (T);     \
296    (U).params.stashes    = newAV(); \
297    (U).params.flags      = 0;       \
298    (U).params.proto_perl = (O)
299 # define indirect_ptable_clone_ud_deinit(U) SvREFCNT_dec((U).params.stashes)
300 # define indirect_dup_inc(S, U)             SvREFCNT_inc(sv_dup((S), &((U)->params)))
301 #endif
302
303 static void indirect_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) {
304  indirect_ptable_clone_ud *ud = ud_;
305  indirect_hint_t          *h1 = ent->val;
306  indirect_hint_t          *h2;
307
308 #if I_HINT_STRUCT
309
310  h2              = PerlMemShared_malloc(sizeof *h2);
311  h2->code        = indirect_dup_inc(h1->code, ud);
312 #if I_WORKAROUND_REQUIRE_PROPAGATION
313  h2->require_tag = PTR2IV(indirect_dup_inc(INT2PTR(SV *, h1->require_tag), ud));
314 #endif
315
316 #else  /*  I_HINT_STRUCT */
317
318  h2 = indirect_dup_inc(h1, ud);
319
320 #endif /* !I_HINT_STRUCT */
321
322  ptable_hints_store(ud->tbl, ent->key, h2);
323 }
324
325 static void indirect_thread_cleanup(pTHX_ void *ud) {
326  dMY_CXT;
327
328  SvREFCNT_dec(MY_CXT.global_code);
329  MY_CXT.global_code = NULL;
330  ptable_free(MY_CXT.map);
331  MY_CXT.map = NULL;
332  ptable_hints_free(MY_CXT.tbl);
333  MY_CXT.tbl = NULL;
334 }
335
336 static int indirect_endav_free(pTHX_ SV *sv, MAGIC *mg) {
337  SAVEDESTRUCTOR_X(indirect_thread_cleanup, NULL);
338
339  return 0;
340 }
341
342 static MGVTBL indirect_endav_vtbl = {
343  0,
344  0,
345  0,
346  0,
347  indirect_endav_free
348 #if MGf_COPY
349  , 0
350 #endif
351 #if MGf_DUP
352  , 0
353 #endif
354 #if MGf_LOCAL
355  , 0
356 #endif
357 };
358
359 #endif /* I_THREADSAFE */
360
361 #if I_WORKAROUND_REQUIRE_PROPAGATION
362 static IV indirect_require_tag(pTHX) {
363 #define indirect_require_tag() indirect_require_tag(aTHX)
364  const CV *cv, *outside;
365
366  cv = PL_compcv;
367
368  if (!cv) {
369   /* If for some reason the pragma is operational at run-time, try to discover
370    * the current cv in use. */
371   const PERL_SI *si;
372
373   for (si = PL_curstackinfo; si; si = si->si_prev) {
374    I32 cxix;
375
376    for (cxix = si->si_cxix; cxix >= 0; --cxix) {
377     const PERL_CONTEXT *cx = si->si_cxstack + cxix;
378
379     switch (CxTYPE(cx)) {
380      case CXt_SUB:
381      case CXt_FORMAT:
382       /* The propagation workaround is only needed up to 5.10.0 and at that
383        * time format and sub contexts were still identical. And even later the
384        * cv members offsets should have been kept the same. */
385       cv = cx->blk_sub.cv;
386       goto get_enclosing_cv;
387      case CXt_EVAL:
388       cv = cx->blk_eval.cv;
389       goto get_enclosing_cv;
390      default:
391       break;
392     }
393    }
394   }
395
396   cv = PL_main_cv;
397  }
398
399 get_enclosing_cv:
400  for (outside = CvOUTSIDE(cv); outside; outside = CvOUTSIDE(cv))
401   cv = outside;
402
403  return PTR2IV(cv);
404 }
405 #endif /* I_WORKAROUND_REQUIRE_PROPAGATION */
406
407 static SV *indirect_tag(pTHX_ SV *value) {
408 #define indirect_tag(V) indirect_tag(aTHX_ (V))
409  indirect_hint_t *h;
410  SV              *code = NULL;
411 #if I_THREADSAFE
412  dMY_CXT;
413
414  if (!MY_CXT.tbl)
415   return newSViv(0);
416 #endif /* I_THREADSAFE */
417
418  if (SvROK(value)) {
419   value = SvRV(value);
420   if (SvTYPE(value) >= SVt_PVCV) {
421    code = value;
422    SvREFCNT_inc_simple_void_NN(code);
423   }
424  }
425
426 #if I_HINT_STRUCT
427  h = PerlMemShared_malloc(sizeof *h);
428  h->code        = code;
429 # if I_WORKAROUND_REQUIRE_PROPAGATION
430  h->require_tag = indirect_require_tag();
431 # endif /* I_WORKAROUND_REQUIRE_PROPAGATION */
432 #else  /*  I_HINT_STRUCT */
433  h = code;
434 #endif /* !I_HINT_STRUCT */
435
436 #if I_THREADSAFE
437  /* We only need for the key to be an unique tag for looking up the value later
438   * Allocated memory provides convenient unique identifiers, so that's why we
439   * use the hint as the key itself. */
440  ptable_hints_store(MY_CXT.tbl, h, h);
441 #endif /* I_THREADSAFE */
442
443  return newSViv(PTR2IV(h));
444 }
445
446 static SV *indirect_detag(pTHX_ const SV *hint) {
447 #define indirect_detag(H) indirect_detag(aTHX_ (H))
448  indirect_hint_t *h;
449 #if I_THREADSAFE || I_WORKAROUND_REQUIRE_PROPAGATION
450  dMY_CXT;
451 #endif
452
453 #if I_THREADSAFE
454  if (!MY_CXT.tbl)
455   return NULL;
456 #endif /* I_THREADSAFE */
457
458  h = INT2PTR(indirect_hint_t *, SvIVX(hint));
459 #if I_THREADSAFE
460  h = ptable_fetch(MY_CXT.tbl, h);
461 #endif /* I_THREADSAFE */
462
463 #if I_WORKAROUND_REQUIRE_PROPAGATION
464  if (indirect_require_tag() != h->require_tag)
465   return MY_CXT.global_code;
466 #endif /* I_WORKAROUND_REQUIRE_PROPAGATION */
467
468  return I_HINT_CODE(h);
469 }
470
471 static U32 indirect_hash = 0;
472
473 static SV *indirect_hint(pTHX) {
474 #define indirect_hint() indirect_hint(aTHX)
475  SV *hint = NULL;
476
477  if (IN_PERL_RUNTIME)
478   return NULL;
479
480 #if I_HAS_PERL(5, 10, 0) || defined(PL_parser)
481  if (!PL_parser)
482   return NULL;
483 #endif
484
485 #ifdef cop_hints_fetch_pvn
486  hint = cop_hints_fetch_pvn(PL_curcop, __PACKAGE__, __PACKAGE_LEN__,
487                                                               indirect_hash, 0);
488 #elif I_HAS_PERL(5, 9, 5)
489  hint = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
490                                        NULL,
491                                        __PACKAGE__, __PACKAGE_LEN__,
492                                        0,
493                                        indirect_hash);
494 #else
495  {
496   SV **val = hv_fetch(GvHV(PL_hintgv), __PACKAGE__, __PACKAGE_LEN__, 0);
497   if (val)
498    hint = *val;
499  }
500 #endif
501
502  if (hint && SvIOK(hint))
503   return indirect_detag(hint);
504  else {
505   dMY_CXT;
506   return MY_CXT.global_code;
507  }
508 }
509
510 /* ... op -> source position ............................................... */
511
512 static void indirect_map_store(pTHX_ const OP *o, STRLEN pos, SV *sv, line_t line) {
513 #define indirect_map_store(O, P, N, L) indirect_map_store(aTHX_ (O), (P), (N), (L))
514  indirect_op_info_t *oi;
515  const char *s;
516  STRLEN len;
517  dMY_CXT;
518
519  /* No need to check for MY_CXT.map != NULL because this code path is always
520   * guarded by indirect_hint(). */
521
522  if (!(oi = ptable_fetch(MY_CXT.map, o))) {
523   Newx(oi, 1, indirect_op_info_t);
524   ptable_store(MY_CXT.map, o, oi);
525   oi->buf  = NULL;
526   oi->size = 0;
527  }
528
529  if (sv) {
530   s = SvPV_const(sv, len);
531  } else {
532   s   = "{";
533   len = 1;
534  }
535
536  if (len > oi->size) {
537   Safefree(oi->buf);
538   Newx(oi->buf, len, char);
539   oi->size = len;
540  }
541  Copy(s, oi->buf, len, char);
542
543  oi->len  = len;
544  oi->pos  = pos;
545  oi->line = line;
546 }
547
548 static const indirect_op_info_t *indirect_map_fetch(pTHX_ const OP *o) {
549 #define indirect_map_fetch(O) indirect_map_fetch(aTHX_ (O))
550  dMY_CXT;
551
552  /* No need to check for MY_CXT.map != NULL because this code path is always
553   * guarded by indirect_hint(). */
554
555  return ptable_fetch(MY_CXT.map, o);
556 }
557
558 static void indirect_map_delete(pTHX_ const OP *o) {
559 #define indirect_map_delete(O) indirect_map_delete(aTHX_ (O))
560  dMY_CXT;
561
562  if (MY_CXT.map)
563   ptable_delete(MY_CXT.map, o);
564 }
565
566 /* --- Check functions ----------------------------------------------------- */
567
568 static int indirect_find(pTHX_ SV *name_sv, const char *line_bufptr, STRLEN *name_pos) {
569 #define indirect_find(NSV, LBP, NP) indirect_find(aTHX_ (NSV), (LBP), (NP))
570  STRLEN      name_len, line_len;
571  const char *name, *name_end;
572  const char *line, *line_end;
573  const char *p;
574
575  line     = SvPV_const(PL_linestr, line_len);
576  line_end = line + line_len;
577
578  name = SvPV_const(name_sv, name_len);
579  if (name_len >= 1 && *name == '$') {
580   ++name;
581   --name_len;
582   while (line_bufptr < line_end && *line_bufptr != '$')
583    ++line_bufptr;
584   if (line_bufptr >= line_end)
585    return 0;
586  }
587  name_end = name + name_len;
588
589  p = line_bufptr;
590  while (1) {
591   p = ninstr(p, line_end, name, name_end);
592   if (!p)
593    return 0;
594   if (!isALNUM(p[name_len]))
595    break;
596   /* p points to a word that has name as prefix, skip the rest of the word */
597   p += name_len + 1;
598   while (isALNUM(*p))
599    ++p;
600  }
601
602  *name_pos = p - line;
603
604  return 1;
605 }
606
607 /* ... ck_const ............................................................ */
608
609 static OP *(*indirect_old_ck_const)(pTHX_ OP *) = 0;
610
611 static OP *indirect_ck_const(pTHX_ OP *o) {
612  o = indirect_old_ck_const(aTHX_ o);
613
614  if (indirect_hint()) {
615   SV *sv = cSVOPo_sv;
616
617   if (SvPOK(sv) && (SvTYPE(sv) >= SVt_PV)) {
618    STRLEN pos;
619
620    if (indirect_find(sv, PL_oldbufptr, &pos)) {
621     STRLEN len;
622
623     /* If the constant is equal to the current package name, try to look for
624      * a "__PACKAGE__" coming before what we got. We only need to check this
625      * when we already had a match because __PACKAGE__ can only appear in
626      * direct method calls ("new __PACKAGE__" is a syntax error). */
627     len = SvCUR(sv);
628     if (PL_curstash
629         && len == (STRLEN) HvNAMELEN_get(PL_curstash)
630         && memcmp(SvPVX(sv), HvNAME_get(PL_curstash), len) == 0) {
631      STRLEN pos_pkg;
632      SV    *pkg = sv_newmortal();
633      sv_setpvn(pkg, "__PACKAGE__", sizeof("__PACKAGE__")-1);
634
635      if (indirect_find(pkg, PL_oldbufptr, &pos_pkg) && pos_pkg < pos) {
636       sv  = pkg;
637       pos = pos_pkg;
638      }
639     }
640
641     indirect_map_store(o, pos, sv, CopLINE(&PL_compiling));
642     return o;
643    }
644   }
645  }
646
647  indirect_map_delete(o);
648  return o;
649 }
650
651 /* ... ck_rv2sv ............................................................ */
652
653 static OP *(*indirect_old_ck_rv2sv)(pTHX_ OP *) = 0;
654
655 static OP *indirect_ck_rv2sv(pTHX_ OP *o) {
656  if (indirect_hint()) {
657   OP *op = cUNOPo->op_first;
658   SV *sv;
659   const char *name = NULL;
660   STRLEN pos, len;
661   OPCODE type = (OPCODE) op->op_type;
662
663   switch (type) {
664    case OP_GV:
665    case OP_GVSV: {
666     GV *gv = cGVOPx_gv(op);
667     name = GvNAME(gv);
668     len  = GvNAMELEN(gv);
669     break;
670    }
671    default:
672     if ((PL_opargs[type] & OA_CLASS_MASK) == OA_SVOP) {
673      SV *nsv = cSVOPx_sv(op);
674      if (SvPOK(nsv) && (SvTYPE(nsv) >= SVt_PV))
675       name = SvPV_const(nsv, len);
676     }
677   }
678   if (!name)
679    goto done;
680
681   sv = sv_2mortal(newSVpvn("$", 1));
682   sv_catpvn_nomg(sv, name, len);
683   if (!indirect_find(sv, PL_oldbufptr, &pos)) {
684    /* If it failed, retry without the current stash */
685    const char *stash = HvNAME_get(PL_curstash);
686    STRLEN stashlen = HvNAMELEN_get(PL_curstash);
687
688    if ((len < stashlen + 2) || strnNE(name, stash, stashlen)
689        || name[stashlen] != ':' || name[stashlen+1] != ':') {
690     /* Failed again ? Try to remove main */
691     stash = "main";
692     stashlen = 4;
693     if ((len < stashlen + 2) || strnNE(name, stash, stashlen)
694         || name[stashlen] != ':' || name[stashlen+1] != ':')
695      goto done;
696    }
697
698    sv_setpvn(sv, "$", 1);
699    stashlen += 2;
700    sv_catpvn_nomg(sv, name + stashlen, len - stashlen);
701    if (!indirect_find(sv, PL_oldbufptr, &pos))
702     goto done;
703   }
704
705   o = indirect_old_ck_rv2sv(aTHX_ o);
706
707   indirect_map_store(o, pos, sv, CopLINE(&PL_compiling));
708   return o;
709  }
710
711 done:
712  o = indirect_old_ck_rv2sv(aTHX_ o);
713
714  indirect_map_delete(o);
715  return o;
716 }
717
718 /* ... ck_padany ........................................................... */
719
720 static OP *(*indirect_old_ck_padany)(pTHX_ OP *) = 0;
721
722 static OP *indirect_ck_padany(pTHX_ OP *o) {
723  o = indirect_old_ck_padany(aTHX_ o);
724
725  if (indirect_hint()) {
726   SV *sv;
727   const char *s = PL_oldbufptr, *t = PL_bufptr - 1;
728
729   while (s < t && isSPACE(*s)) ++s;
730   if (*s == '$' && ++s <= t) {
731    while (s < t && isSPACE(*s)) ++s;
732    while (s < t && isSPACE(*t)) --t;
733    sv = sv_2mortal(newSVpvn("$", 1));
734    sv_catpvn_nomg(sv, s, t - s + 1);
735    indirect_map_store(o, s - SvPVX_const(PL_linestr),
736                          sv, CopLINE(&PL_compiling));
737    return o;
738   }
739  }
740
741  indirect_map_delete(o);
742  return o;
743 }
744
745 /* ... ck_scope ............................................................ */
746
747 static OP *(*indirect_old_ck_scope)  (pTHX_ OP *) = 0;
748 static OP *(*indirect_old_ck_lineseq)(pTHX_ OP *) = 0;
749
750 static OP *indirect_ck_scope(pTHX_ OP *o) {
751  OP *(*old_ck)(pTHX_ OP *) = 0;
752
753  switch (o->op_type) {
754   case OP_SCOPE:   old_ck = indirect_old_ck_scope;   break;
755   case OP_LINESEQ: old_ck = indirect_old_ck_lineseq; break;
756  }
757  o = old_ck(aTHX_ o);
758
759  if (indirect_hint()) {
760   indirect_map_store(o, PL_oldbufptr - SvPVX_const(PL_linestr),
761                         NULL, CopLINE(&PL_compiling));
762   return o;
763  }
764
765  indirect_map_delete(o);
766  return o;
767 }
768
769 /* We don't need to clean the map entries for leave ops because they can only
770  * be created by mutating from a lineseq. */
771
772 /* ... ck_method ........................................................... */
773
774 static OP *(*indirect_old_ck_method)(pTHX_ OP *) = 0;
775
776 static OP *indirect_ck_method(pTHX_ OP *o) {
777  if (indirect_hint()) {
778   OP *op = cUNOPo->op_first;
779
780   /* Indirect method call is only possible when the method is a bareword, so
781    * don't trip up on $obj->$meth. */
782   if (op && op->op_type == OP_CONST) {
783    const indirect_op_info_t *oi = indirect_map_fetch(op);
784    STRLEN pos;
785    line_t line;
786    SV *sv;
787
788    if (!oi)
789     goto done;
790
791    sv   = sv_2mortal(newSVpvn(oi->buf, oi->len));
792    pos  = oi->pos;
793    /* Keep the old line so that we really point to the first line of the
794     * expression. */
795    line = oi->line;
796
797    o = indirect_old_ck_method(aTHX_ o);
798    /* o may now be a method_named */
799
800    indirect_map_store(o, pos, sv, line);
801    return o;
802   }
803  }
804
805 done:
806  o = indirect_old_ck_method(aTHX_ o);
807
808  indirect_map_delete(o);
809  return o;
810 }
811
812 /* ... ck_method_named ..................................................... */
813
814 /* "use foo/no foo" compiles its call to import/unimport directly to a
815  * method_named op. */
816
817 static OP *(*indirect_old_ck_method_named)(pTHX_ OP *) = 0;
818
819 static OP *indirect_ck_method_named(pTHX_ OP *o) {
820  if (indirect_hint()) {
821   STRLEN pos;
822   line_t line;
823   SV *sv;
824
825   sv = cSVOPo_sv;
826   if (!SvPOK(sv) || (SvTYPE(sv) < SVt_PV))
827    goto done;
828   sv = sv_mortalcopy(sv);
829
830   if (!indirect_find(sv, PL_oldbufptr, &pos))
831    goto done;
832   line = CopLINE(&PL_compiling);
833
834   o = indirect_old_ck_method_named(aTHX_ o);
835
836   indirect_map_store(o, pos, sv, line);
837   return o;
838  }
839
840 done:
841  o = indirect_old_ck_method_named(aTHX_ o);
842
843  indirect_map_delete(o);
844  return o;
845 }
846
847 /* ... ck_entersub ......................................................... */
848
849 static OP *(*indirect_old_ck_entersub)(pTHX_ OP *) = 0;
850
851 static OP *indirect_ck_entersub(pTHX_ OP *o) {
852  SV *code = indirect_hint();
853
854  o = indirect_old_ck_entersub(aTHX_ o);
855
856  if (code) {
857   const indirect_op_info_t *moi, *ooi;
858   OP     *mop, *oop;
859   LISTOP *lop;
860
861   oop = o;
862   do {
863    lop = (LISTOP *) oop;
864    if (!(lop->op_flags & OPf_KIDS))
865     goto done;
866    oop = lop->op_first;
867   } while (oop->op_type != OP_PUSHMARK);
868   oop = OpSIBLING(oop);
869   mop = lop->op_last;
870
871   if (!oop)
872    goto done;
873
874   switch (oop->op_type) {
875    case OP_CONST:
876    case OP_RV2SV:
877    case OP_PADSV:
878    case OP_SCOPE:
879    case OP_LEAVE:
880     break;
881    default:
882     goto done;
883   }
884
885   if (mop->op_type == OP_METHOD)
886    mop = cUNOPx(mop)->op_first;
887   else if (mop->op_type != OP_METHOD_NAMED)
888    goto done;
889
890   moi = indirect_map_fetch(mop);
891   if (!moi)
892    goto done;
893
894   ooi = indirect_map_fetch(oop);
895   if (!ooi)
896    goto done;
897
898   /* When positions are identical, the method and the object must have the
899    * same name. But it also means that it is an indirect call, as "foo->foo"
900    * results in different positions. */
901   if (   moi->line < ooi->line
902       || (moi->line == ooi->line && moi->pos <= ooi->pos)) {
903    SV *file;
904    dSP;
905
906    ENTER;
907    SAVETMPS;
908
909 #ifdef USE_ITHREADS
910    file = sv_2mortal(newSVpv(CopFILE(&PL_compiling), 0));
911 #else
912    file = sv_mortalcopy(CopFILESV(&PL_compiling));
913 #endif
914
915    PUSHMARK(SP);
916    EXTEND(SP, 4);
917    mPUSHp(ooi->buf, ooi->len);
918    mPUSHp(moi->buf, moi->len);
919    PUSHs(file);
920    mPUSHu(moi->line);
921    PUTBACK;
922
923    call_sv(code, G_VOID);
924
925    PUTBACK;
926
927    FREETMPS;
928    LEAVE;
929   }
930  }
931
932 done:
933  return o;
934 }
935
936 static U32 indirect_initialized = 0;
937
938 static void indirect_teardown(pTHX_ void *root) {
939  if (!indirect_initialized)
940   return;
941
942 #if I_MULTIPLICITY
943  if (aTHX != root)
944   return;
945 #endif
946
947  {
948   dMY_CXT;
949   ptable_free(MY_CXT.map);
950   MY_CXT.map = NULL;
951 #if I_THREADSAFE
952   ptable_hints_free(MY_CXT.tbl);
953   MY_CXT.tbl = NULL;
954 #endif
955  }
956
957  indirect_ck_restore(OP_CONST,   &indirect_old_ck_const);
958  indirect_ck_restore(OP_RV2SV,   &indirect_old_ck_rv2sv);
959  indirect_ck_restore(OP_PADANY,  &indirect_old_ck_padany);
960  indirect_ck_restore(OP_SCOPE,   &indirect_old_ck_scope);
961  indirect_ck_restore(OP_LINESEQ, &indirect_old_ck_lineseq);
962
963  indirect_ck_restore(OP_METHOD,       &indirect_old_ck_method);
964  indirect_ck_restore(OP_METHOD_NAMED, &indirect_old_ck_method_named);
965  indirect_ck_restore(OP_ENTERSUB,     &indirect_old_ck_entersub);
966
967  indirect_initialized = 0;
968 }
969
970 static void indirect_setup(pTHX) {
971 #define indirect_setup() indirect_setup(aTHX)
972  if (indirect_initialized)
973   return;
974
975  {
976   MY_CXT_INIT;
977 #if I_THREADSAFE
978   MY_CXT.tbl         = ptable_new();
979   MY_CXT.owner       = aTHX;
980 #endif
981   MY_CXT.map         = ptable_new();
982   MY_CXT.global_code = NULL;
983  }
984
985  indirect_ck_replace(OP_CONST,   indirect_ck_const,  &indirect_old_ck_const);
986  indirect_ck_replace(OP_RV2SV,   indirect_ck_rv2sv,  &indirect_old_ck_rv2sv);
987  indirect_ck_replace(OP_PADANY,  indirect_ck_padany, &indirect_old_ck_padany);
988  indirect_ck_replace(OP_SCOPE,   indirect_ck_scope,  &indirect_old_ck_scope);
989  indirect_ck_replace(OP_LINESEQ, indirect_ck_scope,  &indirect_old_ck_lineseq);
990
991  indirect_ck_replace(OP_METHOD,       indirect_ck_method,
992                                       &indirect_old_ck_method);
993  indirect_ck_replace(OP_METHOD_NAMED, indirect_ck_method_named,
994                                       &indirect_old_ck_method_named);
995  indirect_ck_replace(OP_ENTERSUB,     indirect_ck_entersub,
996                                       &indirect_old_ck_entersub);
997
998 #if I_MULTIPLICITY
999  call_atexit(indirect_teardown, aTHX);
1000 #else
1001  call_atexit(indirect_teardown, NULL);
1002 #endif
1003
1004  indirect_initialized = 1;
1005 }
1006
1007 static U32 indirect_booted = 0;
1008
1009 /* --- XS ------------------------------------------------------------------ */
1010
1011 MODULE = indirect      PACKAGE = indirect
1012
1013 PROTOTYPES: ENABLE
1014
1015 BOOT:
1016 {
1017  if (!indirect_booted++) {
1018   HV *stash;
1019
1020   PERL_HASH(indirect_hash, __PACKAGE__, __PACKAGE_LEN__);
1021
1022   stash = gv_stashpvn(__PACKAGE__, __PACKAGE_LEN__, 1);
1023   newCONSTSUB(stash, "I_THREADSAFE", newSVuv(I_THREADSAFE));
1024   newCONSTSUB(stash, "I_FORKSAFE",   newSVuv(I_FORKSAFE));
1025  }
1026
1027  indirect_setup();
1028 }
1029
1030 #if I_THREADSAFE
1031
1032 void
1033 CLONE(...)
1034 PROTOTYPE: DISABLE
1035 PREINIT:
1036  ptable *t;
1037  SV     *global_code_dup;
1038  GV     *gv;
1039 PPCODE:
1040  {
1041   indirect_ptable_clone_ud ud;
1042   dMY_CXT;
1043   t = ptable_new();
1044   indirect_ptable_clone_ud_init(ud, t, MY_CXT.owner);
1045   ptable_walk(MY_CXT.tbl, indirect_ptable_clone, &ud);
1046   global_code_dup = indirect_dup_inc(MY_CXT.global_code, &ud);
1047   indirect_ptable_clone_ud_deinit(ud);
1048  }
1049  {
1050   MY_CXT_CLONE;
1051   MY_CXT.map         = ptable_new();
1052   MY_CXT.tbl         = t;
1053   MY_CXT.owner       = aTHX;
1054   MY_CXT.global_code = global_code_dup;
1055  }
1056  gv = gv_fetchpv(__PACKAGE__ "::_THREAD_CLEANUP", 0, SVt_PVCV);
1057  if (gv) {
1058   CV *cv = GvCV(gv);
1059   if (!PL_endav)
1060    PL_endav = newAV();
1061   SvREFCNT_inc(cv);
1062   if (!av_store(PL_endav, av_len(PL_endav) + 1, (SV *) cv))
1063    SvREFCNT_dec(cv);
1064   sv_magicext((SV *) PL_endav, NULL, PERL_MAGIC_ext, &indirect_endav_vtbl, NULL, 0);
1065  }
1066  XSRETURN(0);
1067
1068 void
1069 _THREAD_CLEANUP(...)
1070 PROTOTYPE: DISABLE
1071 PPCODE:
1072  indirect_thread_cleanup(aTHX_ NULL);
1073  XSRETURN(0);
1074
1075 #endif
1076
1077 SV *
1078 _tag(SV *value)
1079 PROTOTYPE: $
1080 CODE:
1081  RETVAL = indirect_tag(value);
1082 OUTPUT:
1083  RETVAL
1084
1085 void
1086 _global(SV *code)
1087 PROTOTYPE: $
1088 PPCODE:
1089  if (!SvOK(code))
1090   code = NULL;
1091  else if (SvROK(code))
1092   code = SvRV(code);
1093  {
1094   dMY_CXT;
1095   SvREFCNT_dec(MY_CXT.global_code);
1096   MY_CXT.global_code = SvREFCNT_inc(code);
1097  }
1098  XSRETURN(0);