/* ============================================================================
=head1 Allocation and deallocation of SVs.
+
An SV (or AV, HV, etc.) is allocated in two parts: the head (struct
sv, av, hv...) contains type and reference count information, and for
many types, a pointer to the body (struct xrv, xpv, xpviv...), which
/*
Here are mid-level routines that manage the allocation of bodies out
- of the various arenas. There are 5 kinds of arenas:
+ of the various arenas. There are 4 kinds of arenas:
1. SV-head arenas, which are discussed and handled above
2. regular body arenas
unused block of them is wasteful. Also, several svtypes dont have
bodies; the data fits into the sv-head itself. The arena-root
pointer thus has a few unused root-pointers (which may be hijacked
- later for arena types 4,5)
+ later for arena type 4)
3 differs from 2 as an optimization; some body types have several
unused fields in the front of the structure (which are kept in-place
are decremented to point at the unused 'ghost' memory, knowing that
the pointers are used with offsets to the real memory.
-
-=head1 SV-Body Allocation
-
-=cut
-
Allocation of SV-bodies is similar to SV-heads, differing as follows;
the allocation mechanism is used for many body types, so is somewhat
more complicated, it uses arena-sets, and has no need for still-live
#if defined(DEBUGGING) && defined(PERL_GLOBAL_STRUCT)
dVAR;
#endif
-#if defined(DEBUGGING) && !defined(PERL_GLOBAL_STRUCT_PRIVATE)
+#if defined(DEBUGGING) && !defined(PERL_GLOBAL_STRUCT)
static bool done_sanity_check;
- /* PERL_GLOBAL_STRUCT_PRIVATE cannot coexist with global
+ /* PERL_GLOBAL_STRUCT cannot coexist with global
* variables like done_sanity_check. */
if (!done_sanity_check) {
unsigned int i = SVt_LAST;
return sv_2mortal(newSVuv(PTR2UV(SvRV(sv))));
}
+/* int2str_table: lookup table containing string representations of all
+ * two digit numbers. For example, int2str_table.arr[0] is "00" and
+ * int2str_table.arr[12*2] is "12".
+ *
+ * We are going to read two bytes at a time, so we have to ensure that
+ * the array is aligned to a 2 byte boundary. That's why it was made a
+ * union with a dummy U16 member. */
+static const union {
+ char arr[200];
+ U16 dummy;
+} int2str_table = {{
+ '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6',
+ '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3',
+ '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0',
+ '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7',
+ '2', '8', '2', '9', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4',
+ '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1',
+ '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8',
+ '4', '9', '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5',
+ '5', '6', '5', '7', '5', '8', '5', '9', '6', '0', '6', '1', '6', '2',
+ '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
+ '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6',
+ '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3',
+ '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '9', '0',
+ '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7',
+ '9', '8', '9', '9'
+}};
+
/* uiv_2buf(): private routine for use by sv_2pv_flags(): print an IV or
* UV as a string towards the end of buf, and return pointers to start and
* end of it.
* We assume that buf is at least TYPE_CHARS(UV) long.
*/
-static char *
+PERL_STATIC_INLINE char *
S_uiv_2buf(char *const buf, const IV iv, UV uv, const int is_uv, char **const peob)
{
char *ptr = buf + TYPE_CHARS(UV);
char * const ebuf = ptr;
int sign;
+ U16 *word_ptr, *word_table;
PERL_ARGS_ASSERT_UIV_2BUF;
- if (is_uv)
+ /* ptr has to be properly aligned, because we will cast it to U16* */
+ assert(PTR2nat(ptr) % 2 == 0);
+ /* we are going to read/write two bytes at a time */
+ word_ptr = (U16*)ptr;
+ word_table = (U16*)int2str_table.arr;
+
+ if (UNLIKELY(is_uv))
sign = 0;
else if (iv >= 0) {
uv = iv;
sign = 0;
} else {
- uv = (iv == IV_MIN) ? (UV)iv : (UV)(-iv);
+ uv = -(UV)iv;
sign = 1;
}
- do {
- *--ptr = '0' + (char)(uv % 10);
- } while (uv /= 10);
+
+ while (uv > 99) {
+ *--word_ptr = word_table[uv % 100];
+ uv /= 100;
+ }
+ ptr = (char*)word_ptr;
+
+ if (uv < 10)
+ *--ptr = (char)uv + '0';
+ else {
+ *--word_ptr = word_table[uv];
+ ptr = (char*)word_ptr;
+ }
+
if (sign)
- *--ptr = '-';
+ *--ptr = '-';
+
*peob = ebuf;
return ptr;
}
/* I'm assuming that if both IV and NV are equally valid then
converting the IV is going to be more efficient */
const U32 isUIOK = SvIsUV(sv);
- char buf[TYPE_CHARS(UV)];
+ /* The purpose of this union is to ensure that arr is aligned on
+ a 2 byte boundary, because that is what uiv_2buf() requires */
+ union {
+ char arr[TYPE_CHARS(UV)];
+ U16 dummy;
+ } buf;
char *ebuf, *ptr;
STRLEN len;
if (SvTYPE(sv) < SVt_PVIV)
sv_upgrade(sv, SVt_PVIV);
- ptr = uiv_2buf(buf, SvIVX(sv), SvUVX(sv), isUIOK, &ebuf);
+ ptr = uiv_2buf(buf.arr, SvIVX(sv), SvUVX(sv), isUIOK, &ebuf);
len = ebuf - ptr;
/* inlined from sv_setpvn */
s = SvGROW_mutable(sv, len + 1);
}
if (SvCUR(sv) == 0) {
- if (extra) SvGROW(sv, extra);
+ if (extra) SvGROW(sv, extra + 1); /* Make sure is room for a trailing
+ byte */
} else { /* Assume Latin-1/EBCDIC */
/* This function could be much more efficient if we
* had a FLAG in SVs to signal if there are any variant
if (dtype < SVt_PVNV)
sv_upgrade(dstr, SVt_PVNV);
break;
+
+ case SVt_INVLIST:
+ invlist_clone(sstr, dstr);
+ break;
default:
{
const char * const type = sv_reftype(sstr,0);
sv_upgrade(dstr, SVt_REGEXP);
break;
- case SVt_INVLIST:
case SVt_PVLV:
case SVt_PVGV:
case SVt_PVMG:
SvCUR_set(sv, cur);
*SvEND(sv) = '\0';
}
- if (len) {
- } else {
- unshare_hek(SvSHARED_HEK_FROM_PV(pvx));
+ if (! len) {
+ unshare_hek(SvSHARED_HEK_FROM_PV(pvx));
}
#ifdef DEBUGGING
if (DEBUG_C_TEST)
/*
=for apidoc sv_insert
-Inserts a string at the specified offset/length within the SV. Similar to
-the Perl C<substr()> function. Handles get magic.
+Inserts and/or replaces a string at the specified offset/length within the SV.
+Similar to the Perl C<substr()> function, with C<littlelen> bytes starting at
+C<little> replacing C<len> bytes of the string in C<bigstr> starting at
+C<offset>. Handles get magic.
=for apidoc sv_insert_flags
* null assign is a placeholder. */
rslast = rslen ? rsptr[rslen - 1] : '\0';
- if (rspara) { /* have to do this both before and after */
- do { /* to make sure file boundaries work right */
- if (PerlIO_eof(fp))
- return 0;
- i = PerlIO_getc(fp);
- if (i != '\n') {
- if (i == -1)
- return 0;
- PerlIO_ungetc(fp,i);
- break;
- }
- } while (i != EOF);
+ if (rspara) { /* have to do this both before and after */
+ /* to make sure file boundaries work right */
+ while (1) {
+ if (PerlIO_eof(fp))
+ return 0;
+ i = PerlIO_getc(fp);
+ if (i != '\n') {
+ if (i == -1)
+ return 0;
+ PerlIO_ungetc(fp,i);
+ break;
+ }
+ }
}
/* See if we know enough about I/O mechanism to cheat it ! */
(C<\0>) and other binary data. The reference count for the SV is set to 1.
Note that if C<len> is zero, Perl will create a zero length (Perl) string. You
are responsible for ensuring that the source buffer is at least
-C<len> bytes long. If the C<s> argument is NULL the new SV will be
+C<len> bytes long. If the C<buffer> argument is NULL the new SV will be
undefined.
=cut
Creates a new SV which is an exact duplicate of the original SV.
(Uses C<sv_setsv>.)
+=for apidoc newSVsv_nomg
+
+Like C<newSVsv> but does not process get magic.
+
=cut
*/
SV *
-Perl_newSVsv(pTHX_ SV *const old)
+Perl_newSVsv_flags(pTHX_ SV *const old, I32 flags)
{
SV *sv;
return NULL;
}
/* Do this here, otherwise we leak the new SV if this croaks. */
- SvGETMAGIC(old);
+ if (flags & SV_GMAGIC)
+ SvGETMAGIC(old);
new_SV(sv);
- /* SV_NOSTEAL prevents TEMP buffers being, well, stolen, and saves games
- with SvTEMP_off and SvTEMP_on round a call to sv_setsv. */
- sv_setsv_flags(sv, old, SV_NOSTEAL);
+ sv_setsv_flags(sv, old, flags & ~SV_GMAGIC);
return sv;
}
void
Perl_sv_setpviv(pTHX_ SV *const sv, const IV iv)
{
- char buf[TYPE_CHARS(UV)];
+ /* The purpose of this union is to ensure that arr is aligned on
+ a 2 byte boundary, because that is what uiv_2buf() requires */
+ union {
+ char arr[TYPE_CHARS(UV)];
+ U16 dummy;
+ } buf;
char *ebuf;
- char * const ptr = uiv_2buf(buf, iv, 0, 0, &ebuf);
+ char * const ptr = uiv_2buf(buf.arr, iv, 0, 0, &ebuf);
PERL_ARGS_ASSERT_SV_SETPVIV;
esignbuf[esignlen++] = plus;
}
else {
- uv = (iv == IV_MIN) ? (UV)iv : (UV)(-iv);
+ uv = -(UV)iv;
esignbuf[esignlen++] = '-';
}
}
SvTAINT(sv);
+#ifdef USE_LOCALE_NUMERIC
+
if (lc_numeric_set) {
RESTORE_LC_NUMERIC(); /* Done outside loop, so don't have to
save/restore each iteration. */
}
+
+#endif
+
}
/* =========================================================================
if (PL_my_cxt_size) {
Newx(PL_my_cxt_list, PL_my_cxt_size, void *);
Copy(proto_perl->Imy_cxt_list, PL_my_cxt_list, PL_my_cxt_size, void *);
-#ifdef PERL_GLOBAL_STRUCT_PRIVATE
- Newx(PL_my_cxt_keys, PL_my_cxt_size, const char *);
- Copy(proto_perl->Imy_cxt_keys, PL_my_cxt_keys, PL_my_cxt_size, char *);
-#endif
}
else {
PL_my_cxt_list = (void**)NULL;
-#ifdef PERL_GLOBAL_STRUCT_PRIVATE
- PL_my_cxt_keys = (const char**)NULL;
-#endif
}
PL_modglobal = hv_dup_inc(proto_perl->Imodglobal, param);
PL_custom_op_names = hv_dup_inc(proto_perl->Icustom_op_names,param);
PL_setlocale_buf = NULL;
PL_setlocale_bufsize = 0;
- /* Unicode inversion lists */
- PL_InBitmap = sv_dup_inc(proto_perl->IInBitmap, param);
-
/* utf8 character class swashes */
- for (i = 0; i < POSIX_SWASH_COUNT; i++) {
- PL_utf8_swash_ptrs[i] = sv_dup_inc(proto_perl->Iutf8_swash_ptrs[i], param);
- }
PL_seen_deprecated_macro = hv_dup_inc(proto_perl->Iseen_deprecated_macro, param);
- PL_utf8_mark = sv_dup_inc(proto_perl->Iutf8_mark, param);
- PL_utf8_toupper = sv_dup_inc(proto_perl->Iutf8_toupper, param);
- PL_utf8_totitle = sv_dup_inc(proto_perl->Iutf8_totitle, param);
- PL_utf8_tolower = sv_dup_inc(proto_perl->Iutf8_tolower, param);
- PL_utf8_tofold = sv_dup_inc(proto_perl->Iutf8_tofold, param);
- PL_utf8_tosimplefold = sv_dup_inc(proto_perl->Iutf8_tosimplefold, param);
- PL_utf8_charname_begin = sv_dup_inc(proto_perl->Iutf8_charname_begin, param);
- PL_utf8_charname_continue = sv_dup_inc(proto_perl->Iutf8_charname_continue, param);
if (proto_perl->Ipsig_pend) {
Newxz(PL_psig_pend, SIG_SIZE, int);
PL_registered_mros = hv_dup_inc(proto_perl->Iregistered_mros, param);
PL_blockhooks = av_dup_inc(proto_perl->Iblockhooks, param);
- PL_utf8_foldclosures = hv_dup_inc(proto_perl->Iutf8_foldclosures, param);
/* Call the ->CLONE method, if it exists, for each of the stashes
identified by sv_dup() above.
void
Perl_init_constants(pTHX)
{
+ dVAR;
+
SvREFCNT(&PL_sv_undef) = SvREFCNT_IMMORTAL;
SvFLAGS(&PL_sv_undef) = SVf_READONLY|SVf_PROTECT|SVt_NULL;
SvANY(&PL_sv_undef) = NULL;