+PERL_STATIC_INLINE void
+Perl_rpp_push_1(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_PUSH_1;
+
+ *++PL_stack_sp = sv;
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ SvREFCNT_inc_simple_void_NN(sv);
+#endif
+}
+
+PERL_STATIC_INLINE void
+Perl_rpp_push_IMM(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_PUSH_IMM;
+
+ assert(SvIMMORTAL(sv));
+ *++PL_stack_sp = sv;
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+#endif
+}
+
+PERL_STATIC_INLINE void
+Perl_rpp_push_2(pTHX_ SV *sv1, SV *sv2)
+{
+ PERL_ARGS_ASSERT_RPP_PUSH_2;
+
+ *++PL_stack_sp = sv1;
+ *++PL_stack_sp = sv2;
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ SvREFCNT_inc_simple_void_NN(sv1);
+ SvREFCNT_inc_simple_void_NN(sv2);
+#endif
+}
+
+PERL_STATIC_INLINE void
+Perl_rpp_xpush_1(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_XPUSH_1;
+
+ rpp_extend(1);
+ rpp_push_1(sv);
+}
+
+PERL_STATIC_INLINE void
+Perl_rpp_xpush_IMM(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_XPUSH_IMM;
+
+ rpp_extend(1);
+ rpp_push_IMM(sv);
+}
+
+PERL_STATIC_INLINE void
+Perl_rpp_xpush_2(pTHX_ SV *sv1, SV *sv2)
+{
+ PERL_ARGS_ASSERT_RPP_XPUSH_2;
+
+ rpp_extend(2);
+ rpp_push_2(sv1, sv2);
+}
+
+
+/*
+=for apidoc rpp_push_1_norc
+
+Push C<sv> onto the stack without incrementing its reference count, and
+update C<PL_stack_sp>. On non-PERL_RC_STACK builds, mortalise too.
+
+This is most useful where an SV has just been created and already has a
+reference count of 1, but has not yet been anchored anywhere.
+
+=cut
+*/
+
+PERL_STATIC_INLINE void
+Perl_rpp_push_1_norc(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_PUSH_1;
+
+ *++PL_stack_sp = sv;
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+#else
+ sv_2mortal(sv);
+#endif
+}
+
+
+/*
+=for apidoc rpp_replace_1_1
+=for apidoc_item rpp_replace_1_1_NN
+=for apidoc_item rpp_replace_1_IMM_NN
+
+Replace the current top stack item with C<sv>, while suitably adjusting
+reference counts. Equivalent to rpp_popfree_1(); rpp_push_1(sv), but
+is more efficient and handles both SVs being the same.
+
+The C<_NN> variant assumes that the pointer on the stack to the SV being
+freed is non-NULL.
+
+The C<IMM_NN> variant is like the C<_NN> variant, but in addition, assumes
+that the single argument is an immortal such as <&PL_sv_undef> and, for
+efficiency, will skip incrementing its reference count.
+
+=cut
+*/
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_1_1(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_1_1;
+
+ assert(sv);
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ SV *oldsv = *PL_stack_sp;
+ *PL_stack_sp = sv;
+ SvREFCNT_inc_simple_void_NN(sv);
+ SvREFCNT_dec(oldsv);
+#else
+ *PL_stack_sp = sv;
+#endif
+}
+
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_1_1_NN(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_1_1_NN;
+
+ assert(sv);
+ assert(*PL_stack_sp);
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ SV *oldsv = *PL_stack_sp;
+ *PL_stack_sp = sv;
+ SvREFCNT_inc_simple_void_NN(sv);
+ SvREFCNT_dec_NN(oldsv);
+#else
+ *PL_stack_sp = sv;
+#endif
+}
+
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_1_IMM_NN(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_1_IMM_NN;
+
+ assert(sv);
+ assert(SvIMMORTAL(sv));
+ assert(*PL_stack_sp);
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ SV *oldsv = *PL_stack_sp;
+ *PL_stack_sp = sv;
+ SvREFCNT_dec_NN(oldsv);
+#else
+ *PL_stack_sp = sv;
+#endif
+}
+
+
+/*
+=for apidoc rpp_replace_2_1
+=for apidoc_item rpp_replace_2_1_NN
+=for apidoc_item rpp_replace_2_IMM_NN
+
+Replace the current top to stacks item with C<sv>, while suitably
+adjusting reference counts. Equivalent to rpp_popfree_2(); rpp_push_1(sv),
+but is more efficient and handles SVs being the same.
+
+The C<_NN> variant assumes that the pointers on the stack to the SVs being
+freed are non-NULL.
+
+The C<IMM_NN> variant is like the C<_NN> variant, but in addition, assumes
+that the single argument is an immortal such as <&PL_sv_undef> and, for
+efficiency, will skip incrementing its reference count.
+=cut
+*/
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_2_1(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_2_1;
+
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ /* replace PL_stack_sp[-1] first; leave PL_stack_sp[0] in place while
+ * we free [-1], so if an exception occurs, [0] will still be freed.
+ */
+ SV *oldsv = PL_stack_sp[-1];
+ PL_stack_sp[-1] = sv;
+ SvREFCNT_inc_simple_void_NN(sv);
+ SvREFCNT_dec(oldsv);
+ oldsv = *PL_stack_sp--;
+ SvREFCNT_dec(oldsv);
+#else
+ *--PL_stack_sp = sv;
+#endif
+}
+
+
+/* Private helper function for _NN and _IMM_NN variants.
+ * Assumes sv has already had its ref count incremented,
+ * ready for being put on the stack.
+ * Intended to be small and fast, since it's inlined into many hot parts of
+ * code.
+ */
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_2_1_COMMON(pTHX_ SV *sv)
+{
+
+ assert(sv);
+#ifdef PERL_RC_STACK
+ SV *sv2 = *PL_stack_sp--;
+ assert(sv2);
+ SV *sv1 = *PL_stack_sp;
+ assert(sv1);
+
+ *PL_stack_sp = sv;
+ assert(rpp_stack_is_rc());
+ U32 rc1 = SvREFCNT(sv1);
+ U32 rc2 = SvREFCNT(sv2);
+ /* This expression is intended to be true if either of rc1 or rc2 has
+ * the value 0 or 1, but using only a single branch test, rather
+ * than the two branches that a compiler would plant for a boolean
+ * expression. We are working on the assumption that, most of the
+ * time, neither of the args to a binary function will need to be
+ * freed - they're likely to lex vars, or PADTMPs or whatever.
+ * So give the CPU a single branch that is rarely taken. */
+ if (UNLIKELY( !(rc1>>1) + !(rc2>>1) ))
+ /* at least one of the old SVs needs freeing. Do it the long way */
+ Perl_rpp_free_2_(aTHX_ sv1, sv2, rc1, rc2);
+ else {
+ SvREFCNT(sv1) = rc1 - 1;
+ SvREFCNT(sv2) = rc2 - 1;
+ }
+#else
+ *--PL_stack_sp = sv;
+#endif
+}
+
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_2_1_NN(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_2_1_NN;
+
+ assert(sv);
+#ifdef PERL_RC_STACK
+ SvREFCNT_inc_simple_void_NN(sv);
+#endif
+ rpp_replace_2_1_COMMON(sv);
+}
+
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_2_IMM_NN(pTHX_ SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_2_IMM_NN;
+
+ assert(sv);
+ assert(SvIMMORTAL(sv));
+ rpp_replace_2_1_COMMON(sv);
+}
+
+
+/*
+=for apidoc rpp_replace_at
+
+Replace the SV at address sp within the stack with C<sv>, while suitably
+adjusting reference counts. Equivalent to C<*sp = sv>, except with proper
+reference count handling.
+
+=cut
+*/
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_at(pTHX_ SV **sp, SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_AT;
+
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ SV *oldsv = *sp;
+ *sp = sv;
+ SvREFCNT_inc_simple_void_NN(sv);
+ SvREFCNT_dec(oldsv);
+#else
+ *sp = sv;
+#endif
+}
+
+
+/*
+=for apidoc rpp_replace_at_NN
+
+A variant of rpp_replace_at() which assumes that the SV pointer on the
+stack is non-NULL.
+
+=cut
+*/
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_at_NN(pTHX_ SV **sp, SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_AT_NN;
+
+ assert(sv);
+ assert(*sp);
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ SV *oldsv = *sp;
+ *sp = sv;
+ SvREFCNT_inc_simple_void_NN(sv);
+ SvREFCNT_dec_NN(oldsv);
+#else
+ *sp = sv;
+#endif
+}
+
+
+/*
+=for apidoc rpp_replace_at_norc
+
+Replace the SV at address sp within the stack with C<sv>, while suitably
+adjusting the reference count of the old SV. Equivalent to C<*sp = sv>,
+except with proper reference count handling.
+
+C<sv>'s reference count doesn't get incremented. On non-C<PERL_RC_STACK>
+builds, it gets mortalised too.
+
+This is most useful where an SV has just been created and already has a
+reference count of 1, but has not yet been anchored anywhere.
+
+=cut
+*/
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_at_norc(pTHX_ SV **sp, SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_AT_NORC;
+
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ SV *oldsv = *sp;
+ *sp = sv;
+ SvREFCNT_dec(oldsv);
+#else
+ *sp = sv;
+ sv_2mortal(sv);
+#endif
+}
+
+
+/*
+=for apidoc rpp_replace_at_norc_NN
+
+A variant of rpp_replace_at_norc() which assumes that the SV pointer on the
+stack is non-NULL.
+
+=cut
+*/
+
+PERL_STATIC_INLINE void
+Perl_rpp_replace_at_norc_NN(pTHX_ SV **sp, SV *sv)
+{
+ PERL_ARGS_ASSERT_RPP_REPLACE_AT_NORC_NN;
+
+ assert(*sp);
+#ifdef PERL_RC_STACK
+ assert(rpp_stack_is_rc());
+ SV *oldsv = *sp;
+ *sp = sv;
+ SvREFCNT_dec_NN(oldsv);
+#else
+ *sp = sv;
+ sv_2mortal(sv);
+#endif
+}
+
+
+/*
+=for apidoc rpp_context
+
+Impose void, scalar or list context on the stack.
+First, pop C<extra> items off the stack, then when C<gimme> is:
+C<G_LIST>: return as-is.
+C<G_VOID>: pop everything back to C<mark>
+C<G_SCALAR>: move the top stack item (or C<&PL_sv_undef> if none) to
+C<mark+1> and free everything above it.
+
+=cut
+*/
+
+PERL_STATIC_INLINE void
+Perl_rpp_context(pTHX_ SV **mark, U8 gimme, SSize_t extra)
+{
+ PERL_ARGS_ASSERT_RPP_CONTEXT;
+ assert(extra >= 0);
+ assert(mark <= PL_stack_sp - extra);
+
+ if (gimme == G_LIST)
+ mark = PL_stack_sp - extra;
+ else if (gimme == G_SCALAR) {
+ SV **svp = PL_stack_sp - extra;
+ mark++;
+ if (mark > svp) {
+ /* empty list (plus extra) */
+ rpp_popfree_to(svp);
+ rpp_extend(1);
+ *++PL_stack_sp = &PL_sv_undef;
+ return;
+ }
+ /* swap top and bottom list items */
+ SV *top = *svp;
+ *svp = *mark;
+ *mark = top;
+ }
+ rpp_popfree_to(mark);
+}
+
+
+
+
+/*
+=for apidoc rpp_try_AMAGIC_1
+=for apidoc_item rpp_try_AMAGIC_2
+
+Check whether either of the one or two SVs at the top of the stack is
+magical or a ref, and in either case handle it specially: invoke get
+magic, call an overload method, or replace a ref with a temporary numeric
+value, as appropriate. If this function returns true, it indicates that
+the correct return value is already on the stack. Intended to be used at
+the beginning of the PP function for unary or binary ops.
+
+=cut
+*/
+
+PERL_STATIC_INLINE bool
+Perl_rpp_try_AMAGIC_1(pTHX_ int method, int flags)
+{
+ return UNLIKELY((SvFLAGS(*PL_stack_sp) & (SVf_ROK|SVs_GMG)))
+ && Perl_try_amagic_un(aTHX_ method, flags);
+}
+
+PERL_STATIC_INLINE bool
+Perl_rpp_try_AMAGIC_2(pTHX_ int method, int flags)
+{
+ return UNLIKELY(((SvFLAGS(PL_stack_sp[-1])|SvFLAGS(PL_stack_sp[0]))
+ & (SVf_ROK|SVs_GMG)))
+ && Perl_try_amagic_bin(aTHX_ method, flags);
+}
+
+
+/*
+=for apidoc rpp_stack_is_rc
+
+Returns a boolean value indicating whether the stack is currently
+reference-counted. Note that if the stack is split (bottom half RC, top
+half non-RC), this function returns false, even if the top half currently
+contains zero items.
+
+=cut
+*/
+
+PERL_STATIC_INLINE bool
+Perl_rpp_stack_is_rc(pTHX)
+{
+#ifdef PERL_RC_STACK
+ return AvREAL(PL_curstack) && !PL_curstackinfo->si_stack_nonrc_base;
+#else
+ return 0;
+#endif
+
+}
+
+
+/*
+=for apidoc rpp_is_lone
+
+Indicates whether the stacked SV C<sv> (assumed to be not yet popped off
+the stack) is only kept alive due to a single reference from the argument
+stack and/or and the temps stack.
+
+This can used for example to decide whether the copying of return values
+in rvalue context can be skipped, or whether it shouldn't be assigned to
+in lvalue context.
+
+=cut
+*/
+
+
+PERL_STATIC_INLINE bool
+Perl_rpp_is_lone(pTHX_ SV *sv)
+{
+#ifdef PERL_RC_STACK
+ /* note that rpp_is_lone() can be used in wrapped pp functions,
+ * where technically the stack is no longer ref-counted; but because
+ * the args are non-RC copies of RC args further down the stack, we
+ * can't be in a *completely* non-ref stack.
+ */
+ assert(AvREAL(PL_curstack));
+#endif
+
+ return SvREFCNT(sv) <= cBOOL(SvTEMP(sv))
+#ifdef PERL_RC_STACK
+ + 1
+ && !SvIMMORTAL(sv) /* PL_sv_undef etc are never stealable */
+#endif
+ ;
+}
+
+
+/*
+=for apidoc rpp_invoke_xs
+
+Call the XS function associated with C<cv>. Wraps the call if necessary to
+handle XS functions which are not aware of reference-counted stacks.
+
+=cut
+*/
+
+
+PERL_STATIC_INLINE void
+Perl_rpp_invoke_xs(pTHX_ CV *cv)
+{
+ PERL_ARGS_ASSERT_RPP_INVOKE_XS;
+
+#ifdef PERL_RC_STACK
+ if (!CvXS_RCSTACK(cv))
+ Perl_xs_wrap(aTHX_ CvXSUB(cv), cv);
+ else
+#endif
+ CvXSUB(cv)(aTHX_ cv);
+}
+
+
+
+
+/* ----------------------------- regexp.h ----------------------------- */
+
+/* PVLVs need to act as a superset of all scalar types - they are basically
+ * PVMGs with a few extra fields.
+ * REGEXPs are first class scalars, but have many fields that can't be copied
+ * into a PVLV body.
+ *
+ * Hence we take a different approach - instead of a copy, PVLVs store a pointer
+ * back to the original body. To avoid increasing the size of PVLVs just for the
+ * rare case of REGEXP assignment, this pointer is stored in the memory usually
+ * used for SvLEN(). Hence the check for SVt_PVLV below, and the ? : ternary to
+ * read the pointer from the two possible locations. The macro SvLEN() wraps the
+ * access to the union's member xpvlenu_len, but there is no equivalent macro
+ * for wrapping the union's member xpvlenu_rx, hence the direct reference here.
+ *
+ * See commit df6b4bd56551f2d3 for more details. */
+
+PERL_STATIC_INLINE struct regexp *
+Perl_ReANY(const REGEXP * const re)
+{
+ XPV* const p = (XPV*)SvANY(re);
+
+ PERL_ARGS_ASSERT_REANY;
+ assert(isREGEXP(re));
+
+ return SvTYPE(re) == SVt_PVLV ? p->xpv_len_u.xpvlenu_rx
+ : (struct regexp *)p;
+}
+
+/* ------------------------------- utf8.h ------------------------------- */
+
+/*
+=for apidoc_section $unicode
+*/
+
+PERL_STATIC_INLINE void
+Perl_append_utf8_from_native_byte(const U8 byte, U8** dest)
+{
+ /* Takes an input 'byte' (Latin1 or EBCDIC) and appends it to the UTF-8
+ * encoded string at '*dest', updating '*dest' to include it */
+
+ PERL_ARGS_ASSERT_APPEND_UTF8_FROM_NATIVE_BYTE;
+
+ if (NATIVE_BYTE_IS_INVARIANT(byte))
+ *((*dest)++) = byte;
+ else {
+ *((*dest)++) = UTF8_EIGHT_BIT_HI(byte);
+ *((*dest)++) = UTF8_EIGHT_BIT_LO(byte);
+ }
+}
+
+/*
+=for apidoc valid_utf8_to_uvchr
+Like C<L<perlapi/utf8_to_uvchr_buf>>, but should only be called when it is
+known that the next character in the input UTF-8 string C<s> is well-formed
+(I<e.g.>, it passes C<L<perlapi/isUTF8_CHAR>>. Surrogates, non-character code
+points, and non-Unicode code points are allowed.
+
+=cut
+
+ */
+
+PERL_STATIC_INLINE UV
+Perl_valid_utf8_to_uvchr(const U8 *s, STRLEN *retlen)
+{
+ const UV expectlen = UTF8SKIP(s);
+ const U8* send = s + expectlen;
+ UV uv = *s;
+
+ PERL_ARGS_ASSERT_VALID_UTF8_TO_UVCHR;
+
+ if (retlen) {
+ *retlen = expectlen;
+ }
+
+ /* An invariant is trivially returned */
+ if (expectlen == 1) {
+ return uv;
+ }
+
+ /* Remove the leading bits that indicate the number of bytes, leaving just
+ * the bits that are part of the value */
+ uv = NATIVE_UTF8_TO_I8(uv) & UTF_START_MASK(expectlen);
+
+ /* Now, loop through the remaining bytes, accumulating each into the
+ * working total as we go. (I khw tried unrolling the loop for up to 4
+ * bytes, but there was no performance improvement) */
+ for (++s; s < send; s++) {
+ uv = UTF8_ACCUMULATE(uv, *s);
+ }
+
+ return UNI_TO_NATIVE(uv);
+
+}
+
+/*
+=for apidoc is_utf8_invariant_string
+
+Returns TRUE if the first C<len> bytes of the string C<s> are the same
+regardless of the UTF-8 encoding of the string (or UTF-EBCDIC encoding on
+EBCDIC machines); otherwise it returns FALSE. That is, it returns TRUE if they
+are UTF-8 invariant. On ASCII-ish machines, all the ASCII characters and only
+the ASCII characters fit this definition. On EBCDIC machines, the ASCII-range
+characters are invariant, but so also are the C1 controls.
+
+If C<len> is 0, it will be calculated using C<strlen(s)>, (which means if you
+use this option, that C<s> can't have embedded C<NUL> characters and has to
+have a terminating C<NUL> byte).
+
+See also
+C<L</is_utf8_string>>,
+C<L</is_utf8_string_flags>>,
+C<L</is_utf8_string_loc>>,
+C<L</is_utf8_string_loc_flags>>,
+C<L</is_utf8_string_loclen>>,
+C<L</is_utf8_string_loclen_flags>>,
+C<L</is_utf8_fixed_width_buf_flags>>,
+C<L</is_utf8_fixed_width_buf_loc_flags>>,
+C<L</is_utf8_fixed_width_buf_loclen_flags>>,
+C<L</is_strict_utf8_string>>,
+C<L</is_strict_utf8_string_loc>>,
+C<L</is_strict_utf8_string_loclen>>,
+C<L</is_c9strict_utf8_string>>,
+C<L</is_c9strict_utf8_string_loc>>,
+and
+C<L</is_c9strict_utf8_string_loclen>>.
+
+=cut
+
+*/
+
+#define is_utf8_invariant_string(s, len) \