From e9117b46c881fb9f385b60217e1c0211d0954168 Mon Sep 17 00:00:00 2001 From: Per Hedbor <ph@opera.com> Date: Tue, 25 Feb 2014 14:24:24 +0100 Subject: [PATCH] Unified INDEX_CHARP and generic_extract (and thus index_shared_string) In non-debug mode indexing a shared string is now the same thing as doing the old INDEX_CHARP, and thus actually noticeably faster. However, INDEX_CHARP will be slower in debug mode since it will check if the size_shift is >2. That seems rather harmless, though, since debug mode is seldom used when performance matters. --- src/stralloc.c | 60 +++++++++++++++++++++++--------------------------- src/stralloc.h | 39 +++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 37 deletions(-) diff --git a/src/stralloc.c b/src/stralloc.c index 006f3e3a26..f025fb8af0 100644 --- a/src/stralloc.c +++ b/src/stralloc.c @@ -256,38 +256,6 @@ static INLINE int min_magnitude(p_wchar2 c) return 2; } -static INLINE p_wchar2 generic_extract (const void *str, int size, ptrdiff_t pos) -{ - switch(size) - { - case 0: return ((p_wchar0 *)str)[pos]; - case 1: return ((p_wchar1 *)str)[pos]; - case 2: return ((p_wchar2 *)str)[pos]; - } -#ifdef PIKE_DEBUG - Pike_fatal("Illegal shift size!\n"); -#endif - return 0; -} - -PMOD_EXPORT p_wchar2 index_shared_string(struct pike_string *s, - ptrdiff_t pos) -{ -#ifdef PIKE_DEBUG - if(pos > s->len || pos<0) { - if (s->len) { - Pike_fatal("String index %"PRINTPTRDIFFT"d is out of " - "range 0..%"PRINTPTRDIFFT"d.\n", - pos, s->len-1); - } else { - Pike_fatal("Attempt to index the empty string with %"PRINTPTRDIFFT"d.\n", - pos); - } - } -#endif - return generic_extract(s->str,s->size_shift,pos); -} - void low_set_index(struct pike_string *s, ptrdiff_t pos, int value) { #ifdef PIKE_DEBUG @@ -409,6 +377,34 @@ PMOD_EXPORT void pike_string_cpy(PCHARP to, struct pike_string *from) #define DM(X) #endif +PMOD_EXPORT p_wchar2 index_shared_string(struct pike_string *s, + ptrdiff_t pos) +{ + if(pos > s->len || pos<0) { + if (s->len) { + Pike_fatal("String index %"PRINTPTRDIFFT"d is out of " + "range 0..%"PRINTPTRDIFFT"d.\n", + pos, s->len-1); + } else { + Pike_fatal("Attempt to index the empty string with %"PRINTPTRDIFFT"d.\n", + pos); + } + } + return generic_extract(s->str,s->size_shift,pos); +} + +PMOD_EXPORT p_wchar2 generic_extract (const void *str, int size, ptrdiff_t pos) +{ + switch(size) + { + case 0: return ((p_wchar0 *)str)[pos]; + case 1: return ((p_wchar1 *)str)[pos]; + case 2: return ((p_wchar2 *)str)[pos]; + } + Pike_fatal("Unsupported string shift: %d\n", size); + return 0; +} + static void locate_problem(int (*isproblem)(struct pike_string *)) { unsigned INT32 e; diff --git a/src/stralloc.h b/src/stralloc.h index 829c121096..e1d4f681dc 100644 --- a/src/stralloc.h +++ b/src/stralloc.h @@ -16,6 +16,12 @@ #define STRUCT_PIKE_STRING_DECLARED #endif +enum size_shift { + eightbit=0, + sixteenbit=1, + thirtytwobit=2, +}; + #ifdef ATOMIC_SVALUE #define PIKE_STRING_CONTENTS \ INT32 refs; \ @@ -31,7 +37,7 @@ #define PIKE_STRING_CONTENTS \ INT32 refs; \ unsigned char flags; \ - unsigned char size_shift; \ + enum size_shift size_shift:8; \ unsigned char min; \ unsigned char max; \ ptrdiff_t len; /* Not counting terminating NUL. */ \ @@ -115,8 +121,33 @@ struct pike_string *debug_findstring(const struct pike_string *foo); #define STR2(X) ((p_wchar2 *)(X)->str) #endif -#define INDEX_CHARP(PTR,IND,SHIFT) \ - ((SHIFT)==0?((p_wchar0 *)(PTR))[(IND)]:(SHIFT)==1?((p_wchar1 *)(PTR))[(IND)]:((p_wchar2 *)(PTR))[(IND)]) +#ifndef PIKE_DEBUG +static p_wchar2 generic_extract (const void *str, int size, ptrdiff_t pos) ATTRIBUTE((pure)); + +static p_wchar2 generic_extract (const void *str, int size, ptrdiff_t pos) +{ +/* this gives better code than a lot of other versions I have tested. + +When inlined the ret/eax is of course somewhat different, it can be +less or more optimal, but this is at least actually smaller than the +expanded code for INDEX_CHARP. +*/ + if( LIKELY(size == 0) ) return ((p_wchar0 *)str)[pos]; + if( LIKELY(size == 1) ) return ((p_wchar1 *)str)[pos]; + return ((p_wchar2 *)str)[pos]; +} + +static INLINE p_wchar2 index_shared_string(struct pike_string *s, ptrdiff_t pos) +{ + return generic_extract(s->str,s->size_shift,pos); +} +#else +PMOD_EXPORT p_wchar2 generic_extract (const void *str, int size, ptrdiff_t pos); +PMOD_EXPORT p_wchar2 index_shared_string(struct pike_string *s, + ptrdiff_t pos) +#endif + +#define INDEX_CHARP(PTR,IND,SHIFT) generic_extract(PTR,SHIFT,IND) #define SET_INDEX_CHARP(PTR,IND,SHIFT,VAL) \ ((SHIFT)==0? \ @@ -259,8 +290,6 @@ INT32 PIKE_CONCAT4(compare_,FROM,_to_,TO)(const PIKE_CONCAT(p_wchar,TO) *to, con PMOD_EXPORT extern struct pike_string *empty_pike_string; /* Prototypes begin here */ -PMOD_EXPORT p_wchar2 index_shared_string(struct pike_string *s, - ptrdiff_t pos); void low_set_index(struct pike_string *s, ptrdiff_t pos, int value); PMOD_EXPORT struct pike_string *debug_check_size_shift(struct pike_string *a,int shift); CONVERT(0,1) -- GitLab