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