From a953aca586d48d6f0b2c4db3572de328ed6d85e8 Mon Sep 17 00:00:00 2001 From: Daniel Dragan Date: Fri, 10 Oct 2014 13:29:33 -0400 Subject: optimize & rmv from public API Perl_tmps_grow and related code Previously in PUSH_EXTEND_MORTAL__SV_C, "PL_tmps_ix + 1" would execute twice, once for the nonmutable if(>=), then again after the potential tmps_grow call. tmps_grow has an unused return register/void proto, put it to use by returning ix. Also change tmps_grow to take the result of "PL_tmps_ix + the constant (usually 1) or non-constant (EXTEND_MORTAL)". This avoid having to put the constant twice in machine code, once for the if test, 2nd time for extend length param for tmps_grow call. For non-constant/EXTEND_MORTAL usage, it allows the C optimizer to have the length var to go out of liveness sooner if possible. Also the var used for the if(>=) test is more likely to be in a register than length var. So "if test variable" is closer on hand to the CPU than length var. In some cases, if non-const len var isn't used again, it becomes the "ix" variable by having PL_tmps_ix added to it. Change sv_2mortal to return sv instead of NULL to remove a unique branch/block of machine code that assigns 0 to return variable (Visual C didn't figure out return sv == returned NULL, not sv). See also [perl #121845]. --- scope.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'scope.c') diff --git a/scope.c b/scope.c index 1084484e92..9fd2546b2d 100644 --- a/scope.c +++ b/scope.c @@ -132,15 +132,34 @@ Perl_savestack_grow_cnt(pTHX_ I32 need) #undef GROW -void -Perl_tmps_grow(pTHX_ SSize_t n) +/* The original function was called Perl_tmps_grow and was removed from public + API, Perl_tmps_grow_p is the replacement and it used in public macros but + isn't public itself. + + Perl_tmps_grow_p takes a proposed ix. A proposed ix is PL_tmps_ix + extend_by, + where the result of (PL_tmps_ix + extend_by) is >= PL_tmps_max + Upon return, PL_tmps_stack[ix] will be a valid address. For machine code + optimization and register usage reasons, the proposed ix passed into + tmps_grow is returned to the caller which the caller can then use to write + an SV * to PL_tmps_stack[ix]. If the caller was using tmps_grow in + pre-extend mode (EXTEND_MORTAL macro), then it ignores the return value of + tmps_grow. Note, tmps_grow DOES NOT write ix to PL_tmps_ix, the caller + must assign ix or ret val of tmps_grow to PL_temps_ix themselves if that is + appropriate. The assignment to PL_temps_ix can happen before or after + tmps_grow call since tmps_grow doesn't look at PL_tmps_ix. + */ + +SSize_t +Perl_tmps_grow_p(pTHX_ SSize_t ix) { + SSize_t extend_to = ix; #ifndef STRESS_REALLOC - if (n < 128) - n = (PL_tmps_max < 512) ? 128 : 512; + if (ix - PL_tmps_max < 128) + extend_to += (PL_tmps_max < 512) ? 128 : 512; #endif - PL_tmps_max = PL_tmps_ix + n + 1; + PL_tmps_max = extend_to + 1; Renew(PL_tmps_stack, PL_tmps_max, SV*); + return ix; } -- cgit v1.2.1