ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/PApp-SQL/SQL.xs
(Generate patch)

Comparing PApp-SQL/SQL.xs (file contents):
Revision 1.23 by root, Sun Jun 21 05:14:18 2009 UTC vs.
Revision 1.24 by root, Mon Feb 13 05:59:55 2012 UTC

5/* import some stuff from DBIXS.h and DBI.xs */ 5/* import some stuff from DBIXS.h and DBI.xs */
6#define DBIXS_VERSION 93 6#define DBIXS_VERSION 93
7#define DBI_MAGIC '~' 7#define DBI_MAGIC '~'
8 8
9#define DBISTATE_PERLNAME "DBI::_dbistate" 9#define DBISTATE_PERLNAME "DBI::_dbistate"
10#define DBISTATE_ADDRSV (perl_get_sv(DBISTATE_PERLNAME, 0x05)) 10#define DBISTATE_ADDRSV (perl_get_sv (DBISTATE_PERLNAME, 0x05))
11#define DBIS_PUBLISHED_LVALUE (*(INT2PTR(dbistate_t**, &SvIVX(DBISTATE_ADDRSV)))) 11#define DBIS_PUBLISHED_LVALUE (*(INT2PTR(dbistate_t**, &SvIVX(DBISTATE_ADDRSV))))
12
13static SV *sql_varchar, *sql_integer, *sql_double;
14static SV *tmp_iv;
12 15
13struct dbistate_st { 16struct dbistate_st {
14#define DBISTATE_VERSION 94 /* Must change whenever dbistate_t does */ 17#define DBISTATE_VERSION 94 /* Must change whenever dbistate_t does */
15 /* this must be the first member in structure */ 18 /* this must be the first member in structure */
16 void (*check_version) _((const char *name, 19 void (*check_version) _((const char *name,
57 60
58static SV * 61static SV *
59sql_upgrade_utf8 (SV *sv) 62sql_upgrade_utf8 (SV *sv)
60{ 63{
61#if CAN_UTF8 64#if CAN_UTF8
62 if (SvPOK (sv)) 65 if (SvPOKp (sv))
63 sv_utf8_upgrade (sv); 66 sv_utf8_upgrade (sv);
64#endif 67#endif
65 return sv; 68 return sv;
66} 69}
67 70
68static SV * 71static SV *
69mortalcopy_and_maybe_force_utf8(int utf8, SV *sv) 72mortalcopy_and_maybe_force_utf8(int utf8, SV *sv)
70{ 73{
71 sv = sv_mortalcopy (sv); 74 sv = sv_mortalcopy (sv);
72#if CAN_UTF8 75#if CAN_UTF8
73 if (utf8 && SvPOK (sv)) 76 if (utf8 && SvPOKp (sv))
74 SvUTF8_on (sv); 77 SvUTF8_on (sv);
75#endif 78#endif
76 return sv; 79 return sv;
77} 80}
78 81
79#define maybe_upgrade_utf8(utf8,sv) ((utf8) ? sql_upgrade_utf8 (sv) : (sv)) 82#define maybe_upgrade_utf8(utf8,sv) ((utf8) ? sql_upgrade_utf8 (sv) : (sv))
80 83
81#define is_dbh(sv) ((sv) && sv_isobject (sv) && sv_derived_from ((sv), "DBI::db")) 84#define is_dbh(sv) ((sv) && sv_isobject (sv) && sv_derived_from ((sv), "DBI::db"))
82 85
86typedef struct mc_node
87{
88 struct mc_node *next;
89 HV *stash;
90 U32 gen;
91
92 /* DBH */
93 SV *prepare;
94
95 /* STH */
96 SV *execute;
97 SV *bind_param;
98 SV *bind_columns;
99 SV *fetchrow_arrayref;
100 SV *fetchall_arrayref;
101 SV *finish;
102} mc_node;
103
104static mc_node *first;
105
106static mc_node *
107mc_find (HV *stash)
108{
109 mc_node *mc;
110 U32 gen = PL_sub_generation;
111
112#ifdef HvMROMETA
113 gen += HvMROMETA (stash)->cache_gen;
114#endif
115
116 for (mc = first; mc; mc = mc->next)
117 if (mc->stash == stash && mc->gen == gen)
118 return mc;
119
120 if (!mc)
121 {
122 Newz (0, mc, 1, mc_node);
123 mc->stash = stash;
124
125 mc->next = first;
126 first = mc;
127 }
128 else
129 {
130 mc->execute =
131 mc->bind_param =
132 mc->bind_columns =
133 mc->fetchrow_arrayref =
134 mc->fetchall_arrayref =
135 mc->finish = 0;
136 }
137
138 mc->gen = gen;
139
140 return mc;
141}
142
143static void
144mc_cache (mc_node *mc, SV **method, const char *name)
145{
146 *method = (SV *)gv_fetchmethod_autoload (mc->stash, name, 0);
147
148 if (!method)
149 croak ("%s: method not found in stash, pelase report.", name);
150}
151
152#define mc_cache(mc, method) mc_cache ((mc), &((mc)->method), # method)
153
83typedef struct lru_node { 154typedef struct lru_node
155{
84 struct lru_node *next; 156 struct lru_node *next;
85 struct lru_node *prev; 157 struct lru_node *prev;
86 U32 hash; /* bit 31 is used to mark active nodes */ 158
159 U32 hash;
87 SV *dbh; 160 SV *dbh;
88 SV *sql; 161 SV *sql;
89 162
90 SV *sth; 163 SV *sth;
91 imp_sth *sth_imp; 164 imp_sth *sth_imp;
92#if 0 /* method cache */ 165
93 GV *execute; 166 mc_node *mc;
94 GV *bind_columns;
95 GV *fetch;
96 GV *finish;
97#endif
98} lru_node; 167} lru_node;
99 168
100static lru_node lru_list; 169static lru_node lru_list;
101static int lru_size; 170static int lru_size;
102static int lru_maxsize; 171static int lru_maxsize;
103 172
104#define lru_init() lru_list.next = &lru_list; lru_list.prev = &lru_list /* other fields are zero */ 173#define lru_init() lru_list.next = &lru_list; lru_list.prev = &lru_list /* other fields are zero */
105 174
106/* this is primitive, yet effective */ 175/* this is primitive, yet effective */
107/* the returned value must never be zero (or bad things will happen) */ 176/* the returned value must never be zero (or bad things will happen) */
108#define lru_hash \ 177static U32
109 do { \ 178lru_hash (SV *dbh, SV *sql)
110 hash = (((U32)(long)dbh)>>4); \ 179{
111 hash += *statement; \ 180 STRLEN i, l;
112 hash += len; \ 181 char *b = SvPV (sql, l);
113 } while (0) 182 U32 hash = 2166136261;
183
184 hash = (hash ^ (U32)dbh) * 16777619U;
185 hash = (hash ^ l) * 16777619U;
186
187 for (i = 7; i < l; i += i >> 2)
188 hash = (hash ^ b [i]) * 16777619U;
189
190 return hash;
191}
114 192
115/* fetch and "use" */ 193/* fetch and "use" */
116/* could be done using a single call (we could call prepare!) */ 194static lru_node *
117static SV *
118lru_fetch (SV *dbh, SV *sql) 195lru_fetch (SV *dbh, SV *sql)
119{ 196{
120 lru_node *n; 197 lru_node *n;
121
122 U32 hash; 198 U32 hash;
123 STRLEN len;
124 char *statement = SvPV (sql, len);
125 199
126 dbh = SvRV (dbh); 200 dbh = SvRV (dbh);
127 201 hash = lru_hash (dbh, sql);
128 lru_hash;
129 202
130 n = &lru_list; 203 n = &lru_list;
131 do { 204 do {
132 n = n->next; 205 n = n->next;
133 206
145 n->next = lru_list.next; 218 n->next = lru_list.next;
146 n->prev = &lru_list; 219 n->prev = &lru_list;
147 lru_list.next->prev = n; 220 lru_list.next->prev = n;
148 lru_list.next = n; 221 lru_list.next = n;
149 222
150 return sv_2mortal (SvREFCNT_inc (n->sth)); 223 return n;
151} 224}
152 225
153static void 226static void
154lru_trim (void) 227lru_trim (void)
155{ 228{
172 } 245 }
173} 246}
174 247
175/* store a not-yet existing entry(!) */ 248/* store a not-yet existing entry(!) */
176static void 249static void
177lru_store (SV *dbh, SV *sql, SV *sth) 250lru_store (SV *dbh, SV *sql, SV *sth, mc_node *mc)
178{ 251{
179 lru_node *n; 252 lru_node *n;
180 U32 hash; 253 U32 hash;
181 STRLEN len;
182 char *statement;
183 254
184 if (!lru_maxsize) 255 if (!lru_maxsize)
185 return; 256 return;
186 257
187 statement = SvPV (sql, len);
188 dbh = SvRV (dbh); 258 dbh = SvRV (dbh);
189 259 hash = lru_hash (dbh, sql);
190 lru_hash;
191 260
192 lru_size++; 261 lru_size++;
193 lru_trim (); 262 lru_trim ();
194 263
195 New (0, n, 1, lru_node); 264 New (0, n, 1, lru_node);
197 n->hash = hash; 266 n->hash = hash;
198 n->dbh = dbh; SvREFCNT_inc (dbh); /* note: this is the dbi hash itself, not the reference */ 267 n->dbh = dbh; SvREFCNT_inc (dbh); /* note: this is the dbi hash itself, not the reference */
199 n->sql = newSVsv (sql); 268 n->sql = newSVsv (sql);
200 n->sth = sth; SvREFCNT_inc (sth); 269 n->sth = sth; SvREFCNT_inc (sth);
201 n->sth_imp = sth_get_imp (sth); 270 n->sth_imp = sth_get_imp (sth);
271 n->mc = mc;
202 272
203 n->next = lru_list.next; 273 n->next = lru_list.next;
204 n->prev = &lru_list; 274 n->prev = &lru_list;
205 lru_list.next->prev = n; 275 lru_list.next->prev = n;
206 lru_list.next = n; 276 lru_list.next = n;
216 } 286 }
217} 287}
218 288
219static GV *sql_exec; 289static GV *sql_exec;
220static GV *DBH; 290static GV *DBH;
221static SV *sv_prepare, *sv_execute, *sv_bind_columns,
222 *sv_fetchrow_arrayref, *sv_fetchall_arrayref,
223 *sv_finish;
224 291
225#define newconstpv(str) newSVpvn ((str), sizeof (str)) 292#define newconstpv(str) newSVpvn ((str), sizeof (str))
226 293
227MODULE = PApp::SQL PACKAGE = PApp::SQL 294MODULE = PApp::SQL PACKAGE = PApp::SQL
228 295
234 301
235 /* this is actually wrong, we should call the check member, apparently */ 302 /* this is actually wrong, we should call the check member, apparently */
236 assert (dbis->version == DBISTATE_VERSION); 303 assert (dbis->version == DBISTATE_VERSION);
237 assert (dbis->xs_version == DBIXS_VERSION); 304 assert (dbis->xs_version == DBIXS_VERSION);
238 305
306 tmp_iv = newSViv (0);
307
239 sql_exec = gv_fetchpv ("PApp::SQL::sql_exec", TRUE, SVt_PV); 308 sql_exec = gv_fetchpv ("PApp::SQL::sql_exec", TRUE, SVt_PV);
240 DBH = gv_fetchpv ("PApp::SQL::DBH" , TRUE, SVt_PV); 309 DBH = gv_fetchpv ("PApp::SQL::DBH" , TRUE, SVt_PV);
241
242 if (!sv_prepare)
243 {
244 sv_prepare = newconstpv ("prepare");
245 sv_execute = newconstpv ("execute");
246 sv_bind_columns = newconstpv ("bind_columns");
247 sv_fetchrow_arrayref = newconstpv ("fetchrow_arrayref");
248 sv_fetchall_arrayref = newconstpv ("fetchall_arrayref");
249 sv_finish = newconstpv ("finish");
250 }
251 310
252 /* apache might BOOT: twice :( */ 311 /* apache might BOOT: twice :( */
253 if (lru_size) 312 if (lru_size)
254 lru_cachesize (0); 313 lru_cachesize (0);
255 314
256 lru_init (); 315 lru_init ();
257 lru_cachesize (50); 316 lru_cachesize (100);
258} 317}
318
319void
320boot2 (SV *t_str, SV *t_int, SV *t_dbl)
321 CODE:
322 sql_varchar = newSVsv (t_str);
323 sql_integer = newSVsv (t_int);
324 sql_double = newSVsv (t_dbl);
259 325
260int 326int
261cachesize(size = -1) 327cachesize(size = -1)
262 int size 328 int size
263 CODE: 329 CODE:
280{ 346{
281 if (items == 0) 347 if (items == 0)
282 croak ("Usage: sql_exec [database-handle,] [bind-var-refs,... ] \"sql-statement\", [arguments, ...]"); 348 croak ("Usage: sql_exec [database-handle,] [bind-var-refs,... ] \"sql-statement\", [arguments, ...]");
283 else 349 else
284 { 350 {
351 int i;
285 int arg = 0; 352 int arg = 0;
353 int first_execution = 0;
286 int bind_first, bind_last; 354 int bind_first, bind_last;
287 int count; 355 int count;
356 lru_node *lru;
288 SV *dbh = ST(0); 357 SV *dbh = ST(0);
289 SV *sth; 358 SV *sth;
290 SV *sql; 359 SV *sql;
291 SV *execute; 360 SV *execute;
361 mc_node *mc;
292 STRLEN dc, dd; /* dummy */ 362 STRLEN dc, dd; /* dummy */
363 I32 orig_stack = SP - PL_stack_base;
293 364
294 /* save our arguments against destruction through function calls */ 365 /* save our arguments against destruction through function calls */
295 SP += items; 366 SP += items;
296 367
297 /* first check wether we should use an explicit db handle */ 368 /* first check wether we should use an explicit db handle */
337 sv_catpv (neu, " limit 1"); 408 sv_catpv (neu, " limit 1");
338 sql = neu; 409 sql = neu;
339 ix -= 4; /* sql_fetch */ 410 ix -= 4; /* sql_fetch */
340 } 411 }
341 412
413 /* now prepare all parameters, by unmagicalising them and upgrading them */
414 for (i = arg; i < items; ++i)
415 {
416 SV *sv = ST (i);
417
418 /* we sv_mortalcopy magical values since DBI seems to have a memory
419 * leak when magical values are passed into execute().
420 */
421 if (SvMAGICAL (sv))
422 ST (i) = sv = sv_mortalcopy (sv);
423
424 if ((ix & 1) && SvPOKp (sv) && !SvUTF8 (sv))
425 {
426 ST (i) = sv = sv_mortalcopy (sv);
427 sv_utf8_upgrade (sv);
428 }
429 }
430
342 /* check cache for existing statement handle */ 431 /* check cache for existing statement handle */
432 lru = SvCUR (sql) <= MAX_CACHED_STATEMENT_SIZE
343 sth = lru_fetch (dbh, sql); 433 ? lru_fetch (dbh, sql)
434 : 0;
344 if (!sth) 435 if (!lru)
345 { 436 {
437 mc = mc_find (SvSTASH (SvRV (dbh)));
438
439 if (!mc->prepare)
440 mc_cache (mc, prepare);
441
346 PUSHMARK (SP); 442 PUSHMARK (SP);
347 EXTEND (SP, 2); 443 EXTEND (SP, 2);
348 PUSHs (dbh); 444 PUSHs (dbh);
349 PUSHs (sql); 445 PUSHs (sql);
350 PUTBACK; 446 PUTBACK;
351 count = call_sv (sv_prepare, G_METHOD | G_SCALAR); 447 count = call_sv (mc->prepare, G_SCALAR);
352 SPAGAIN; 448 SPAGAIN;
353 449
354 if (count != 1) 450 if (count != 1)
355 croak ("sql_exec: unable to prepare() statement '%s': %s", 451 croak ("sql_exec: unable to prepare() statement '%s': %s",
356 SvPV (sql, dc), 452 SvPV (sql, dc),
357 SvPV (get_sv ("DBI::errstr", TRUE), dd)); 453 SvPV (get_sv ("DBI::errstr", TRUE), dd));
358 454
359 sth = POPs; 455 sth = POPs;
360 456
457 mc = mc_find (SvSTASH (SvRV (sth)));
458
459 if (!mc->bind_param)
460 {
461 mc_cache (mc, bind_param);
462 mc_cache (mc, execute);
463 mc_cache (mc, finish);
464 }
465
361 if (SvLEN (sql) < MAX_CACHED_STATEMENT_SIZE) 466 if (SvCUR (sql) <= MAX_CACHED_STATEMENT_SIZE)
362 lru_store (dbh, sql, sth); 467 lru_store (dbh, sql, sth, mc);
363 }
364 468
365 PUSHMARK (SP); 469 /* on first execution we unfortunately need to use bind_param
366 EXTEND (SP, items - arg + 1); 470 * to mark any numeric parameters as such.
367 PUSHs (sth);
368 while (items > arg)
369 {
370 SV *sv = ST(arg);
371 /* we sv_mortalcopy magical values since DBI seems to have a memory
372 * leak when magical values are passed into execute().
373 */ 471 */
374 PUSHs (maybe_upgrade_utf8 (ix & 1, SvMAGICAL(sv) ? sv_mortalcopy(sv) : sv)); 472 SvIV_set (tmp_iv, 0);
473
474 while (items > arg)
475 {
476 SV *sv = ST (arg);
477 /* we sv_mortalcopy magical values since DBI seems to have a memory
478 * leak when magical values are passed into execute().
479 */
480
481 PUSHMARK (SP);
482 EXTEND (SP, 4);
483 PUSHs (sth);
484 SvIVX (tmp_iv)++;
485 PUSHs (tmp_iv);
486 PUSHs (sv);
487
488 PUSHs (
489 SvPOKp (sv) ? sql_varchar
490 : SvNOKp (sv) ? sql_double
491 : SvIOKp (sv) ? sql_integer
492 : sql_varchar
493 );
494
495 PUTBACK;
496 call_sv (mc->bind_param, G_VOID);
497 SPAGAIN;
498
375 arg++; 499 arg++;
500 }
501
502 /* now use execute without any arguments */
503 PUSHMARK (SP);
504 EXTEND (SP, 1);
505 PUSHs (sth);
506 }
507 else
508 {
509 sth = sv_2mortal (SvREFCNT_inc (lru->sth));
510 mc = lru->mc;
511
512 /* we have previously executed this statement, so we
513 * use the cached types and use execute with arguments.
514 */
515
516 PUSHMARK (SP);
517 EXTEND (SP, items - arg + 1);
518 PUSHs (sth);
519 while (items > arg)
520 {
521 SV *sv = ST (arg);
522 PUSHs (ST (arg));
523 arg++;
524 }
376 } 525 }
377 526
378 PUTBACK; 527 PUTBACK;
379 /* { static GV *execute; 528 /* { static GV *execute;
380 if (!execute) execute = gv_fetchmethod_autoload(SvSTASH(SvRV(sth)), "execute", 0); 529 if (!execute) execute = gv_fetchmethod_autoload(SvSTASH(SvRV(sth)), "execute", 0);
381 count = call_sv(GvCV(execute), G_SCALAR); 530 count = call_sv(GvCV(execute), G_SCALAR);
382 }*/ 531 }*/
383 count = call_sv (sv_execute, G_METHOD | G_SCALAR); 532 count = call_sv (mc->execute, G_SCALAR);
384 SPAGAIN; 533 SPAGAIN;
385 534
386 if (count != 1) 535 if (count != 1)
387 croak ("sql_exec: execute() didn't return any value ('%s'): %s", 536 croak ("sql_exec: execute() didn't return any value ('%s'): %s",
388 SvPV (sql, dc), 537 SvPV (sql, dc),
393 if (!SvTRUE (execute)) 542 if (!SvTRUE (execute))
394 croak ("sql_exec: unable to execute statement '%s' (%s)", 543 croak ("sql_exec: unable to execute statement '%s' (%s)",
395 SvPV (sql, dc), 544 SvPV (sql, dc),
396 SvPV (get_sv ("DBI::errstr", TRUE), dd)); 545 SvPV (get_sv ("DBI::errstr", TRUE), dd));
397 546
398 sv_setsv (GvSV(sql_exec), execute); 547 sv_setsv (GvSV (sql_exec), execute);
399 548
400 if (bind_first != bind_last) 549 if (bind_first != bind_last)
401 { 550 {
402 PUSHMARK (SP); 551 PUSHMARK (SP);
403 EXTEND (SP, bind_last - bind_first + 2); 552 EXTEND (SP, bind_last - bind_first + 2);
410 PUSHs (ST(bind_first)); 559 PUSHs (ST(bind_first));
411 bind_first++; 560 bind_first++;
412 } while (bind_first != bind_last); 561 } while (bind_first != bind_last);
413 562
414 PUTBACK; 563 PUTBACK;
564
565 if (!mc->bind_columns)
566 mc_cache (mc, bind_columns);
567
415 count = call_sv (sv_bind_columns, G_METHOD | G_SCALAR); 568 count = call_sv (mc->bind_columns, G_SCALAR);
569
416 SPAGAIN; 570 SPAGAIN;
417 571
418 if (count != 1) 572 if (count != 1)
419 croak ("sql_exec: bind_columns() didn't return any value ('%s'): %s", 573 croak ("sql_exec: bind_columns() didn't return any value ('%s'): %s",
420 SvPV (sql, dc), 574 SvPV (sql, dc),
426 SvPV (get_sv ("DBI::errstr", TRUE), dd)); 580 SvPV (get_sv ("DBI::errstr", TRUE), dd));
427 581
428 POPs; 582 POPs;
429 } 583 }
430 584
431 /* restore our arguments again */
432 SP -= items;
433
434 if ((ix & ~1) == 2) 585 if ((ix & ~1) == 2)
435 { /* sql_fetch */ 586 { /* sql_fetch */
436 SV *row; 587 SV *row;
437 588
438 PUSHMARK (SP); 589 PUSHMARK (SP);
439 XPUSHs (sth); 590 XPUSHs (sth);
440 PUTBACK; 591 PUTBACK;
592
593 if (!mc->fetchrow_arrayref)
594 mc_cache (mc, fetchrow_arrayref);
595
441 count = call_sv (sv_fetchrow_arrayref, G_METHOD | G_SCALAR); 596 count = call_sv (mc->fetchrow_arrayref, G_SCALAR);
442 SPAGAIN; 597 SPAGAIN;
443 598
444 if (count != 1) 599 if (count != 1)
445 abort (); 600 abort ();
446 601
447 row = POPs; 602 row = POPs;
603
604 SP = PL_stack_base + orig_stack;
448 605
449 if (SvROK (row)) 606 if (SvROK (row))
450 { 607 {
451 AV *av; 608 AV *av;
452 609
456 /* no thing */ 613 /* no thing */
457 break; 614 break;
458 case G_SCALAR: 615 case G_SCALAR:
459 /* the first element */ 616 /* the first element */
460 XPUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, *av_fetch ((AV *)SvRV (row), 0, 1))); 617 XPUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, *av_fetch ((AV *)SvRV (row), 0, 1)));
618 count = 1;
461 break; 619 break;
462 case G_ARRAY: 620 case G_ARRAY:
463 av = (AV *)SvRV (row); 621 av = (AV *)SvRV (row);
464 count = AvFILL (av) + 1; 622 count = AvFILL (av) + 1;
465 EXTEND (SP, count); 623 EXTEND (SP, count);
477 SV *rows; 635 SV *rows;
478 636
479 PUSHMARK (SP); 637 PUSHMARK (SP);
480 XPUSHs (sth); 638 XPUSHs (sth);
481 PUTBACK; 639 PUTBACK;
640
641 if (!mc->fetchall_arrayref)
642 mc_cache (mc, fetchall_arrayref);
643
482 count = call_sv (sv_fetchall_arrayref, G_METHOD | G_SCALAR); 644 count = call_sv (mc->fetchall_arrayref, G_SCALAR);
483 SPAGAIN; 645 SPAGAIN;
484 646
485 if (count != 1) 647 if (count != 1)
486 abort (); 648 abort ();
487 649
488 rows = POPs; 650 rows = POPs;
651
652 SP = PL_stack_base + orig_stack;
489 653
490 if (SvROK (rows)) 654 if (SvROK (rows))
491 { 655 {
492 AV *av = (AV *)SvRV (rows); 656 AV *av = (AV *)SvRV (rows);
493 count = AvFILL (av) + 1; 657 count = AvFILL (av) + 1;
505 PUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, AvARRAY (av)[arg])); 669 PUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, AvARRAY (av)[arg]));
506 } 670 }
507 } 671 }
508 } 672 }
509 else 673 else
674 {
675 SP = PL_stack_base + orig_stack;
510 XPUSHs (sth); 676 XPUSHs (sth);
677 }
511 678
512 if (ix > 1 || GIMME_V == G_VOID) 679 if (ix > 1 || GIMME_V == G_VOID)
513 { 680 {
681 orig_stack = SP - PL_stack_base;
682
514 PUSHMARK (SP); 683 PUSHMARK (SP);
515 XPUSHs (sth); 684 XPUSHs (sth);
516 PUTBACK; 685 PUTBACK;
686
687 if (!mc->finish)
688 mc_cache (mc, finish);
689
517 (void) call_sv (sv_finish, G_METHOD | G_DISCARD); 690 call_sv (mc->finish, G_DISCARD);
518 SPAGAIN; 691 SPAGAIN;
692
693 SP = PL_stack_base + orig_stack;
519 } 694 }
520 } 695 }
521} 696}
522 697
523 698

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines