-
Notifications
You must be signed in to change notification settings - Fork 560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Perl_do_print: stringify an SVt_IV IV/UV more efficiently #22927
base: blead
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2205,11 +2205,25 @@ Perl_do_print(pTHX_ SV *sv, PerlIO *fp) | |
return TRUE; | ||
if (SvTYPE(sv) == SVt_IV && SvIOK(sv)) { | ||
assert(!SvGMAGICAL(sv)); | ||
if (SvIsUV(sv)) | ||
PerlIO_printf(fp, "%" UVuf, (UV)SvUVX(sv)); | ||
else | ||
PerlIO_printf(fp, "%" IVdf, (IV)SvIVX(sv)); | ||
return !PerlIO_error(fp); | ||
bool happy = TRUE; | ||
|
||
/* Adapted from Perl_sv_2pv_flags */ | ||
const U32 isUIOK = SvIsUV(sv); | ||
/* 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; | ||
UV tempuv = SvUVX(sv); | ||
ptr = uiv_2buf(buf.arr, SvIVX(sv), tempuv, isUIOK, &ebuf); | ||
len = ebuf - ptr; | ||
|
||
if (len && (PerlIO_write(fp,ptr,len) == 0)) | ||
happy = FALSE; | ||
Comment on lines
+2224
to
+2225
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be bool happy = !(len && PerlIO_write(fp, ptr, len) == 0); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was copied from the |
||
return happy ? !PerlIO_error(fp) : FALSE; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be return happy && !PerlIO_error(fp); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was copied from the |
||
} | ||
else { | ||
STRLEN len; | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1003,6 +1003,89 @@ Perl_sv_setpv_freshbuf(pTHX_ SV *const sv) | |
return SvPVX(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 = {{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this symbol be visible in external (C/XS) code? Because at the moment it is an unprefixed identifier (no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. I'm not sure how best to handle it. Happy to take advice. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guarding it inside a |
||
'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() was originally a private routine in sv.c for use by | ||
* sv_2pv_flags(), but its usefulness elsewhere was noted, and it was | ||
* moved out here. It prints 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. | ||
*/ | ||
|
||
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; | ||
|
||
/* 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 { | ||
/* Using 0- here to silence bogus warning from MS VC */ | ||
uv = (UV) (0 - (UV) iv); | ||
sign = 1; | ||
} | ||
|
||
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 = '-'; | ||
|
||
*peob = ebuf; | ||
return ptr; | ||
} | ||
|
||
/* | ||
* ex: set ts=8 sts=4 sw=4 et: | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is
happy
declared so far away from its first use?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mirroring the
else
branch ofPerl_do_print
. I kept it it the same for consistency. Happy to change both instances in a follow-up commit.