Skip to content

Commit 2d92a68

Browse files
committed
Create WORTH_PER_WORD_LOOP(), WORTH_PER_WORD_LOOP_BINMODE()
There are several places in the perl core that, for performance, use word-at-a-time operations on byte data when the data to be processed is long enough to overcome the extra setup overhead required. The code that does this is not immediately obvious, and is currently repeated at each such place. This macro creates two macros that encapsulate this logic, making each place that uses them easier to read. One macro is for data that isn't dependent on the character set. The other is for character data. EBCDIC data is not suitable for per-word operation, so the this macro always returns false on an EBCDIC platform. This allows for the removal of some EBCDIC #ifdefs in our code base.
1 parent 0762960 commit 2d92a68

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

inline.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,48 @@ Perl_valid_utf8_to_uv(const U8 *s, STRLEN *retlen)
14751475
/* Evaluates to 0 if 'x' is at a word boundary; otherwise evaluates to 1 */
14761476
# define PERL_IS_SUBWORD_ADDR(x) (BYTES_REMAINING_IN_WORD(x) != 0)
14771477

1478+
/* Some tasks that are byte-oriented can be done as well a full word-at-a-time,
1479+
* running 8 times faster on an 8-byte word, for example. But there is
1480+
* generally extra setup required to do this, and byte-at-a-time must be used
1481+
* anyway to get to the next word boundary. This macro calculates whether the
1482+
* trade-off is worth doing. If not, it returns NULL; if so, it returns a
1483+
* pointer to the first byte of the next word. Code using this is typically
1484+
* structured like:
1485+
* U8 * next_word_boundary = WORTH_PER_LOOP()
1486+
* if (next_word_boundary) {
1487+
* loop per-byte until next_word_boundary
1488+
* loop per-word until less than a word left before upper boundary
1489+
* }
1490+
* loop per-byte until reach final boundary
1491+
*
1492+
* 's' is the current position in the string
1493+
* 'e' is the upper string bound
1494+
* 'full_words_needed' is the caller's determination of where to make the
1495+
* trade-off between per-byte and per-word. Only if the number of words
1496+
* in the input string is at least this many, does the macro return
1497+
* non-NULL.
1498+
*
1499+
* Because of EBCDIC, there are two forms of this macro.
1500+
* WORTH_PER_WORD_LOOP_BINMODE() is for use when the data being examined is
1501+
* not dependent on the character set. The more usual form is plain
1502+
* WORTH_PER_WORD_LOOP() for character data. Because EBCDIC needs an extra
1503+
* transformation, per-word operations are not appropriate on it, so the macro
1504+
* always returns NULL, meaning don't use a per-word loop on an EBCDIC
1505+
* platform. */
1506+
# define WORTH_PER_WORD_LOOP_BINMODE(s, e, full_words_needed) \
1507+
/* Note multiple evaluations of 's' */ \
1508+
( ( ( (s) + BYTES_REMAINING_IN_WORD(s) \
1509+
+ (full_words_needed) * PERL_WORDSIZE) < (e) ) \
1510+
? ((s) + BYTES_REMAINING_IN_WORD(s)) \
1511+
: NULL)
1512+
1513+
# ifdef EBCDIC
1514+
# define WORTH_PER_WORD_LOOP(s, e, f) NULL
1515+
# else
1516+
# define WORTH_PER_WORD_LOOP(s, e, f) \
1517+
WORTH_PER_WORD_LOOP_BINMODE(s, e, f)
1518+
# endif
1519+
14781520
/*
14791521
=for apidoc is_utf8_invariant_string
14801522
=for apidoc_item is_utf8_invariant_string_loc

0 commit comments

Comments
 (0)