74
74
# define THR_newSVsv_cow (sv ) newSVsv_flags((sv), SV_GMAGIC|SV_NOSTEAL)
75
75
#endif
76
76
77
+ /* PL_op->op_private & OPpENTERSUB_HASTARG feature was added in
78
+
79
+ d30110745a - Ilya Zakharevich -8/26/1999 11:33:01 PM - 5.5.61
80
+ Speeding up XSUB calls up to 66%
81
+ Addendum: it's "only" 33% speedup.
82
+
83
+ These 3 are highly optimized version of 3 macros from pp.h that were
84
+ purpose made mostly for EU::PXS's private use, but we DO NOT want to execute
85
+ a slower sv_newmortal() + sv_set_i_u_n_v_mg(), instead of
86
+ sv_2mortal(newSV_i_u_n_v()).
87
+
88
+ These macros do not put the new SV* on the stack. Caller is responsible for
89
+ that.
90
+
91
+ Arg _nsv is an uninitialized SV* variable, a new SV* will be placed in
92
+ the _nsv var. SvREFCNT()/SV* lifecycle details are handled by the macro.
93
+ The caller IS NOT allowed to execute a "sv_2mortal(_nsv);" on the new SV*.
94
+
95
+ sv_set_i_u_n_v_mg() is required to a huge amount of safety checks like
96
+ de-COW PVs RVs, COWs, sv_upgrade(), copy old SV body contents to a higher
97
+ order SV body, etc.
98
+
99
+ Also if G_LIST context, we do not want Perl_leave_adjust_stacks() to create
100
+ a mortal copy of our PAD SV* TARG. Example of returning a dXSTARG, and
101
+ Perl_leave_adjust_stacks() instantly makes a mortal dup of it is this code
102
+ $self->logtime(time());
103
+ */
104
+
105
+
106
+
107
+ /* set TARG to the IV value i. If do_taint is false,
108
+ * assume that PL_tainted can never be true */
109
+ #define TMR_TARGi (_nsv , i , do_taint ) \
110
+ STMT_START { \
111
+ IV TARGi_iv = i; \
112
+ if (GIMME_V == G_LIST || !(PL_op->op_private & OPpENTERSUB_HASTARG)) \
113
+ _nsv = sv_2mortal(newSViv(TARGi_iv)); \
114
+ else { \
115
+ _nsv = PAD_SV(PL_op->op_targ); \
116
+ if (LIKELY( \
117
+ ((SvFLAGS(_nsv) & (SVTYPEMASK|SVf_THINKFIRST|SVf_IVisUV)) == SVt_IV) \
118
+ & (do_taint ? !TAINT_get : 1))) \
119
+ { \
120
+ /* Cheap SvIOK_only(). \
121
+ * Assert that flags which SvIOK_only() would test or \
122
+ * clear can't be set, because we're SVt_IV */ \
123
+ assert (!(SvFLAGS (_nsv ) & \
124
+ (SVf_OOK |SVf_UTF8 |(SVf_OK & ~(SVf_IOK |SVp_IOK ))))); \
125
+ SvFLAGS (_nsv ) |= (SVf_IOK |SVp_IOK ); \
126
+ /* SvIV_set() where sv_any points to head */ \
127
+ _nsv -> sv_u .svu_iv = TARGi_iv ; \
128
+ } \
129
+ else \
130
+ sv_setiv_mg (_nsv , TARGi_iv ); \
131
+ } \
132
+ } STMT_END
133
+
134
+ /* set TARG to the UV value u. If do_taint is false,
135
+ * assume that PL_tainted can never be true */
136
+ #define TMR_TARGu (_nsv , u , do_taint ) \
137
+ STMT_START { \
138
+ UV TARGu_uv = u ; \
139
+ if (GIMME_V == G_LIST || !(PL_op -> op_private & OPpENTERSUB_HASTARG )) \
140
+ _nsv = sv_2mortal (newSVuv (TARGu_uv )); \
141
+ else { \
142
+ _nsv = PAD_SV (PL_op -> op_targ ); \
143
+ if (LIKELY ( \
144
+ ((SvFLAGS (_nsv ) & (SVTYPEMASK |SVf_THINKFIRST |SVf_IVisUV )) == SVt_IV ) \
145
+ & (do_taint ? !TAINT_get : 1 ) \
146
+ & (TARGu_uv <= (UV )IV_MAX ))) \
147
+ { \
148
+ /* Cheap SvIOK_only(). \
149
+ * Assert that flags which SvIOK_only() would test or \
150
+ * clear can't be set, because we're SVt_IV */ \
151
+ assert (!(SvFLAGS (_nsv ) & \
152
+ (SVf_OOK |SVf_UTF8 |(SVf_OK & ~(SVf_IOK |SVp_IOK ))))); \
153
+ SvFLAGS (_nsv ) |= (SVf_IOK |SVp_IOK ); \
154
+ /* SvIV_set() where sv_any points to head */ \
155
+ _nsv -> sv_u .svu_iv = TARGu_uv ; \
156
+ } \
157
+ else \
158
+ sv_setuv_mg (_nsv , TARGu_uv ); \
159
+ } \
160
+ } STMT_END
161
+
162
+ /* set TARG to the NV value n. If do_taint is false,
163
+ * assume that PL_tainted can never be true */
164
+ #define TMR_TARGn (_nsv , n , do_taint ) \
165
+ STMT_START { \
166
+ NV TARGn_nv = n ; \
167
+ if (GIMME_V == G_LIST || !(PL_op -> op_private & OPpENTERSUB_HASTARG )) \
168
+ _nsv = sv_2mortal (newSVnv (TARGn_nv )); \
169
+ else { \
170
+ _nsv = PAD_SV (PL_op -> op_targ ); \
171
+ if (LIKELY ( \
172
+ ((SvFLAGS (_nsv ) & (SVTYPEMASK |SVf_THINKFIRST )) == SVt_NV ) \
173
+ & (do_taint ? !TAINT_get : 1 ))) \
174
+ { \
175
+ /* Cheap SvNOK_only(). \
176
+ * Assert that flags which SvNOK_only() would test or \
177
+ * clear can't be set, because we're SVt_NV */ \
178
+ assert (!(SvFLAGS (_nsv ) & \
179
+ (SVf_OOK |SVf_UTF8 |(SVf_OK & ~(SVf_NOK |SVp_NOK ))))); \
180
+ SvFLAGS (_nsv ) |= (SVf_NOK |SVp_NOK ); \
181
+ SvNV_set (_nsv , TARGn_nv ); \
182
+ } \
183
+ else \
184
+ sv_setnv_mg (_nsv , TARGn_nv ); \
185
+ } \
186
+ } STMT_END
187
+
77
188
#define IV_1E6 1000000
78
189
#define IV_1E7 10000000
79
190
#define IV_1E9 1000000000
@@ -1143,11 +1254,13 @@ INCLUDE: const-xs.inc
1143
1254
1144
1255
#if defined(HAS_USLEEP ) && defined(HAS_GETTIMEOFDAY )
1145
1256
1146
- NV
1257
+ void
1147
1258
usleep (useconds )
1148
1259
NV useconds
1149
1260
PREINIT :
1150
1261
struct timeval Ta , Tb ;
1262
+ SV * rsv ;
1263
+ NV RETVAL ;
1151
1264
CODE :
1152
1265
gettimeofday (& Ta , NULL );
1153
1266
if (items > 0 ) {
@@ -1173,17 +1286,19 @@ usleep(useconds)
1173
1286
printf ("[%ld %ld] [%ld %ld]\n" , Tb .tv_sec , Tb .tv_usec , Ta .tv_sec , Ta .tv_usec );
1174
1287
# endif
1175
1288
RETVAL = NV_1E6 * (Tb .tv_sec - Ta .tv_sec )+ (NV )((IV )Tb .tv_usec - (IV )Ta .tv_usec );
1176
-
1177
- OUTPUT :
1178
- RETVAL
1289
+ TMR_TARGn ( rsv , RETVAL , 1 );
1290
+ SETs ( rsv );
1291
+ return ; /* no PUTBACK no PUSH, 1 in, 1 out */
1179
1292
1180
1293
# if defined(TIME_HIRES_NANOSLEEP )
1181
1294
1182
- NV
1295
+ void
1183
1296
nanosleep (nsec )
1184
1297
NV nsec
1185
1298
PREINIT :
1186
1299
struct timespec sleepfor , unslept ;
1300
+ SV * rsv ;
1301
+ NV RETVAL ;
1187
1302
CODE :
1188
1303
if (nsec < 0.0 )
1189
1304
croak ("%s(%" NVgf "%s" , "Time::HiRes::nanosleep" , nsec ,
@@ -1194,8 +1309,9 @@ nanosleep(nsec)
1194
1309
} else {
1195
1310
RETVAL = nsec_without_unslept (& sleepfor , & unslept );
1196
1311
}
1197
- OUTPUT :
1198
- RETVAL
1312
+ TMR_TARGn (rsv , RETVAL , 1 );
1313
+ SETs (rsv );
1314
+ return ; /* no PUTBACK no PUSH, 1 in, 1 out */
1199
1315
1200
1316
# else /* #if defined(TIME_HIRES_NANOSLEEP) */
1201
1317
@@ -1211,11 +1327,13 @@ nanosleep(nsec)
1211
1327
1212
1328
# endif /* #if defined(TIME_HIRES_NANOSLEEP) */
1213
1329
1214
- NV
1330
+ void
1215
1331
sleep (...)
1216
1332
PREINIT :
1217
1333
struct timeval Ta , Tb ;
1218
- CODE :
1334
+ SV * rsv ;
1335
+ NV RETVAL ;
1336
+ PPCODE :
1219
1337
gettimeofday (& Ta , NULL );
1220
1338
if (items > 0 ) {
1221
1339
NV seconds = SvNV (ST (0 ));
@@ -1250,9 +1368,10 @@ sleep(...)
1250
1368
printf ("[%ld %ld] [%ld %ld]\n" , Tb .tv_sec , Tb .tv_usec , Ta .tv_sec , Ta .tv_usec );
1251
1369
# endif
1252
1370
RETVAL = (NV )(Tb .tv_sec - Ta .tv_sec )+ 0.000001 * (NV )(Tb .tv_usec - Ta .tv_usec );
1253
-
1254
- OUTPUT :
1255
- RETVAL
1371
+ TMR_TARGn (rsv , RETVAL , 1 );
1372
+ PUSHs (rsv );
1373
+ PUTBACK ;
1374
+ return ;
1256
1375
1257
1376
#else /* #if defined(HAS_USLEEP) && defined(HAS_GETTIMEOFDAY) */
1258
1377
@@ -1270,11 +1389,14 @@ usleep(useconds)
1270
1389
1271
1390
#ifdef HAS_UALARM
1272
1391
1273
- IV
1392
+ void
1274
1393
ualarm (useconds ,uinterval = 0 )
1275
1394
int useconds
1276
1395
int uinterval
1277
- CODE :
1396
+ PREINIT :
1397
+ SV * rsv ;
1398
+ IV RETVAL ;
1399
+ PPCODE :
1278
1400
if (useconds < 0 || uinterval < 0 )
1279
1401
croak ("%s(%d, %d%s" ,
1280
1402
"Time::HiRes::ualarm" , useconds , uinterval ,
@@ -1298,15 +1420,19 @@ ualarm(useconds,uinterval=0)
1298
1420
1299
1421
RETVAL = ualarm (useconds , uinterval );
1300
1422
# endif
1423
+ TMR_TARGi (rsv , RETVAL , 1 );
1424
+ PUSHs (rsv );
1425
+ PUTBACK ;
1426
+ return ;
1301
1427
1302
- OUTPUT :
1303
- RETVAL
1304
-
1305
- NV
1428
+ void
1306
1429
alarm (seconds ,interval = 0 )
1307
1430
NV seconds
1308
1431
NV interval
1309
- CODE :
1432
+ PREINIT :
1433
+ SV * rsv ;
1434
+ NV RETVAL ;
1435
+ PPCODE :
1310
1436
if (seconds < 0.0 || interval < 0.0 )
1311
1437
croak ("%s (%" NVgf ", %" NVgf "%s ",
1312
1438
"Time ::HiRes ::alarm ", seconds , interval ,
@@ -1348,9 +1474,10 @@ alarm(seconds,interval=0)
1348
1474
RETVAL = (NV )ualarm ( useconds , uinterval ) / NV_1E6 ;
1349
1475
# endif
1350
1476
}
1351
-
1352
- OUTPUT :
1353
- RETVAL
1477
+ TMR_TARGn (rsv , RETVAL , 1 );
1478
+ PUSHs (rsv );
1479
+ PUTBACK ;
1480
+ return ;
1354
1481
1355
1482
#else /* #ifdef HAS_UALARM */
1356
1483
@@ -1387,6 +1514,7 @@ gettimeofday()
1387
1514
PREINIT :
1388
1515
struct timeval Tp ;
1389
1516
int status ;
1517
+ OP * const op = PL_op ;
1390
1518
U8 is_G_LIST = GIMME_V == G_LIST ;
1391
1519
PPCODE :
1392
1520
if (is_G_LIST )
@@ -1399,15 +1527,41 @@ gettimeofday()
1399
1527
PUSHs (sv_2mortal (newSViv (sec )));
1400
1528
PUSHs (sv_2mortal (newSViv (usec )));
1401
1529
} else {
1530
+ /* no Perl_leave_adjust_stacks() hazard here,
1531
+ only a PP vs call_sv() hazard */
1402
1532
NV nv = Tp .tv_sec + (Tp .tv_usec / NV_1E6 );
1403
- PUSHs (sv_2mortal (newSVnv (nv )));
1533
+ const U8 do_taint = 1 ;
1534
+ NV TARGn_nv = nv ;
1535
+ SV * rsv ;
1536
+ if (op -> op_private & OPpENTERSUB_HASTARG ) {
1537
+ rsv = PAD_SV (op -> op_targ );
1538
+ if (LIKELY (
1539
+ ((SvFLAGS (rsv ) & (SVTYPEMASK |SVf_THINKFIRST )) == SVt_NV )
1540
+ & (do_taint ? !TAINT_get : 1 )))
1541
+ {
1542
+ /* Cheap SvNOK_only().
1543
+ * Assert that flags which SvNOK_only() would test or
1544
+ * clear can't be set, because we're SVt_NV */
1545
+ assert (!(SvFLAGS (rsv ) &
1546
+ (SVf_OOK |SVf_UTF8 |(SVf_OK & ~(SVf_NOK |SVp_NOK )))));
1547
+ SvFLAGS (rsv ) |= (SVf_NOK |SVp_NOK );
1548
+ SvNV_set (rsv , TARGn_nv );
1549
+ }
1550
+ else
1551
+ sv_setnv_mg (rsv , TARGn_nv );
1552
+ }
1553
+ else
1554
+ rsv = sv_2mortal (newSVnv (TARGn_nv ));
1555
+ PUSHs (rsv );
1404
1556
}
1405
1557
}
1406
1558
1407
- NV
1559
+ void
1408
1560
time ()
1409
1561
PREINIT :
1410
1562
struct timeval Tp ;
1563
+ SV * rsv ;
1564
+ NV RETVAL ;
1411
1565
CODE :
1412
1566
int status ;
1413
1567
status = gettimeofday (& Tp , NULL );
@@ -1416,8 +1570,10 @@ time()
1416
1570
} else {
1417
1571
RETVAL = -1.0 ;
1418
1572
}
1419
- OUTPUT :
1420
- RETVAL
1573
+ TMR_TARGn (rsv , RETVAL , 1 );
1574
+ PUSHs (rsv ); /* 0 in, 1 out, entersub guarenteed 1 slot */
1575
+ PUTBACK ;
1576
+ return ;
1421
1577
1422
1578
#endif /* #ifdef HAS_GETTIMEOFDAY */
1423
1579
@@ -1579,22 +1735,25 @@ utime(accessed, modified, ...)
1579
1735
1580
1736
#if defined(TIME_HIRES_CLOCK_GETTIME )
1581
1737
1582
- NV
1738
+ void
1583
1739
clock_gettime (clock_id = CLOCK_REALTIME )
1584
1740
clockid_t clock_id
1585
1741
PREINIT :
1586
1742
struct timespec ts ;
1587
1743
int status ;
1588
- CODE :
1744
+ SV * rsv ;
1745
+ NV RETVAL ;
1746
+ PPCODE :
1589
1747
# ifdef TIME_HIRES_CLOCK_GETTIME_SYSCALL
1590
1748
status = syscall (SYS_clock_gettime , clock_id , & ts );
1591
1749
# else
1592
1750
status = clock_gettime (clock_id , & ts );
1593
1751
# endif
1594
1752
RETVAL = status == 0 ? ts .tv_sec + (NV ) ts .tv_nsec / NV_1E9 : -1 ;
1595
-
1596
- OUTPUT :
1597
- RETVAL
1753
+ TMR_TARGn (rsv , RETVAL , 1 );
1754
+ PUSHs (rsv ); /* 0 or 1 in, 1 out, PPCODE: did rewind */
1755
+ PUTBACK ;
1756
+ return ;
1598
1757
1599
1758
#else /* if defined(TIME_HIRES_CLOCK_GETTIME) */
1600
1759
0 commit comments