diff --git a/src/operators.c b/src/operators.c index 1ebcb8cdf4af0710463af68ab37996870580ac20..f1d686bb9caefdeac55317a6cf69f0deed49ef51 100644 --- a/src/operators.c +++ b/src/operators.c @@ -1555,7 +1555,6 @@ PMOD_EXPORT void f_add(INT32 args) PCHARP buf; ptrdiff_t tmp; int max_shift=0; - unsigned char tmp_flags, tmp_min, tmp_max; if(args==1) return; size=0; @@ -1579,16 +1578,7 @@ PMOD_EXPORT void f_add(INT32 args) } tmp=sp[-args].u.string->len; - tmp_flags = sp[-args].u.string->flags; - tmp_min = sp[-args].u.string->min; - tmp_max = sp[-args].u.string->max; - r=new_realloc_shared_string(sp[-args].u.string,size,max_shift); - - r->flags |= tmp_flags & ~15; - r->min = tmp_min; - r->max = tmp_max; - mark_free_svalue (sp - args); buf=MKPCHARP_STR_OFF(r,tmp); for(e=-args+1;e<0;e++) diff --git a/src/stralloc.c b/src/stralloc.c index cf8d98e569477ff6010fa4ce156ff11bbdfba08a..4b2752d39d5e351e563375f8314e89247f9ade84 100644 --- a/src/stralloc.c +++ b/src/stralloc.c @@ -26,22 +26,11 @@ #include <ctype.h> #include <math.h> -/* #define STRALLOC_USE_PRIMES */ - -#ifdef STRALLOC_USE_PRIMES - -#define SET_HSIZE(X) htable_size=hashprimes[(X)] -#define HMODULO(X) ((X) % htable_size) - -#else - #define SET_HSIZE(X) htable_mask=(htable_size=(1<<(X)))-1 #define HMODULO(X) ((X) & (htable_mask)) static unsigned INT32 htable_mask; -#endif - #if (SIZEOF_LONG == 4) && defined(_LP64) /* Kludge for gcc and the system header files not using the same model... */ #undef LONG_MIN @@ -83,8 +72,7 @@ static PIKE_MUTEX_T *bucket_locks; #define UNLOCK_BUCKET(HVAL) #endif /* PIKE_RUN_UNLOCKED */ -#define BEGIN_HASH_SIZE 997 -#define MAX_AVG_LINK_LENGTH 2 +#define BEGIN_HASH_SIZE 1024 /* Experimental dynamic hash length */ #ifndef HASH_PREFIX @@ -324,17 +312,14 @@ void low_set_index(struct pike_string *s, ptrdiff_t pos, int value) if(pos == s->len && value) Pike_fatal("string zero termination foul!\n"); #endif - switch(s->size_shift) - { - case 0: STR0(s)[pos]=value; break; - case 1: STR1(s)[pos]=value; break; - case 2: STR2(s)[pos]=value; break; -#ifdef PIKE_DEBUG - default: - Pike_fatal("Illegal shift size!\n"); -#endif - } s->flags |= STRING_NOT_HASHED; + + if(!s->size_shift) + STR0(s)[pos]=value; + else if(s->size_shift == 1) + STR1(s)[pos]=value; + else + STR2(s)[pos]=value; } #ifdef PIKE_DEBUG @@ -486,12 +471,13 @@ static int improper_zero_termination(struct pike_string *s) /* Find a string in the shared string table. * This assumes that the string is minimized!!!! */ -static INLINE struct pike_string *internal_findstring(const char *s, +static struct pike_string *internal_findstring(const char *s, ptrdiff_t len, int size_shift, size_t hval) { - struct pike_string *curr,**prev, **base; + struct pike_string *curr; +//,**prev, **base; unsigned int depth=0; #ifndef HASH_PREFIX unsigned int prefix_depth=0; @@ -499,7 +485,7 @@ static INLINE struct pike_string *internal_findstring(const char *s, size_t h; LOCK_BUCKET(hval); h=HMODULO(hval); - for(base = prev = base_table + h;( curr=*prev ); prev=&curr->next) + for(curr = base_table[h]; curr; curr = curr->next) { #ifdef PIKE_DEBUG if(curr->refs<1) @@ -511,15 +497,15 @@ static INLINE struct pike_string *internal_findstring(const char *s, #endif debug_malloc_touch(curr); - if (hval == curr->hval && - len==curr->len && - size_shift==curr->size_shift && - ( curr->str == s || - !MEMCMP(curr->str, s,len<<size_shift))) /* found it */ + if ( len == curr->len && + size_shift == curr->size_shift && + hval == curr->hval && + ( curr->str == s || + !MEMCMP(curr->str, s,len<<size_shift))) /* found it */ { - *prev = curr->next; - curr->next = *base; - *base = curr; + /* *prev = curr->next; */ + /* curr->next = *base; */ + /* *base = curr; */ UNLOCK_BUCKET(hval); return curr; /* pointer to string */ } @@ -669,52 +655,19 @@ struct pike_string_hdr { /* Allocate some fixed string sizes with BLOCK_ALLOC. */ #define SHORT_STRING_BLOCK 256 -#define SHORT_STRING_THRESHOLD 15 /* % 4 === -1 */ + +#define SHORT_STRING_THRESHOLD 15 struct short_pike_string0 { PIKE_STRING_CONTENTS; p_wchar0 str[SHORT_STRING_THRESHOLD+1]; }; -struct short_pike_string1 { - PIKE_STRING_CONTENTS; - p_wchar1 str[SHORT_STRING_THRESHOLD+1]; -}; - -struct short_pike_string2 { - PIKE_STRING_CONTENTS; - p_wchar2 str[SHORT_STRING_THRESHOLD+1]; -}; - -static struct block_allocator string_allocator[] = { - BA_INIT(sizeof(struct short_pike_string0), SHORT_STRING_BLOCK), - BA_INIT(sizeof(struct short_pike_string1), SHORT_STRING_BLOCK), - BA_INIT(sizeof(struct short_pike_string2), SHORT_STRING_BLOCK) -}; - -static struct pike_string * alloc_short_pike_string(unsigned int shift) { - struct pike_string * s = (struct pike_string *)ba_alloc(string_allocator+shift); - -#ifdef ATOMIC_SVALUE - s->ref_type = T_STRING; -#endif - s->refs = 0; - add_ref(s); /* For DMALLOC */ - s->flags = STRING_NOT_HASHED|STRING_NOT_SHARED|STRING_IS_SHORT; - return s; -} - -#define really_free_short_pike_string(s) do { \ - DO_IF_DEBUG( \ - if (s->size_shift > 2) \ - Pike_fatal("Unsupported string shift: %d\n", s->size_shift); \ - ) \ - ba_free(string_allocator + s->size_shift, s); \ - } while(0) +static struct block_allocator string_allocator = BA_INIT(sizeof(struct short_pike_string0), SHORT_STRING_BLOCK); #define free_unlinked_pike_string(s) do { \ - if (s->len <= SHORT_STRING_THRESHOLD) { \ - really_free_short_pike_string(s); \ + if (s->flags & STRING_IS_SHORT) { \ + ba_free(&string_allocator, s); \ } else { \ debug_free((char *)s, DMALLOC_LOCATION(), 1); \ } \ @@ -731,10 +684,12 @@ PMOD_EXPORT struct pike_string *debug_begin_shared_string(size_t len) if(d_flag>10) verify_shared_strings_tables(); #endif - if (len <= SHORT_STRING_THRESHOLD) { - t=(struct pike_string *)ba_alloc(string_allocator); + if (len <= SHORT_STRING_THRESHOLD) + { + t=(struct pike_string *)ba_alloc(&string_allocator); t->flags = STRING_NOT_HASHED | STRING_NOT_SHARED | STRING_IS_SHORT; - } else { + } else + { t=(struct pike_string *)xalloc(len + 1 + sizeof(struct pike_string_hdr)); t->flags = STRING_NOT_HASHED | STRING_NOT_SHARED; } @@ -774,26 +729,26 @@ static void link_pike_string(struct pike_string *s, size_t hval) num_strings++; UNLOCK_BUCKET(hval); - if(num_strings > MAX_AVG_LINK_LENGTH * htable_size) { + if(num_strings > htable_size) { stralloc_rehash(); } #ifndef HASH_PREFIX /* These heuristics might require tuning! /Hubbe */ - if((need_more_hash_prefix_depth > MAX_AVG_LINK_LENGTH * 4) || - (need_new_hashkey_depth > MAX_AVG_LINK_LENGTH * 128)) + if((need_more_hash_prefix_depth > 4) || + (need_new_hashkey_depth > 128)) { /* Changed heuristic 2005-01-17: * * Increase HASH_PREFIX if there's some bucket containing - * more than MAX_AVG_LINK_LENGTH * 4 strings that are longer + * more than 4 strings that are longer * than HASH_PREFIX. * /grubba * * Changed heuristic 2011-12-30: * * Generate a new hash key if there's some bucket containing - * more than MAX_AVG_LINK_LENGTH * 16 strings. This ought to + * more than 16 strings. This ought to * suffice to alleviate the #hashdos vulnerability. * * /grubba @@ -805,7 +760,7 @@ static void link_pike_string(struct pike_string *s, size_t hval) #ifdef PIKE_RUN_UNLOCKED mt_lock(bucket_locks); - if(need_more_hash_prefix_depth <= MAX_AVG_LINK_DEPTH * 4) + if(need_more_hash_prefix_depth <= 4) { /* Someone got here before us */ mt_lock(bucket_locks); @@ -817,7 +772,7 @@ static void link_pike_string(struct pike_string *s, size_t hval) /* A simple mixing function. */ hashkey ^= (hashkey << 5) | (current_time.tv_sec ^ current_time.tv_usec); - if (need_more_hash_prefix_depth > MAX_AVG_LINK_LENGTH * 4) { + if (need_more_hash_prefix_depth > 4) { HASH_PREFIX=HASH_PREFIX*2; #if 0 fprintf(stderr, "Doubling HASH_PREFIX to %d and rehashing\n", @@ -862,12 +817,12 @@ PMOD_EXPORT struct pike_string *debug_begin_wide_shared_string(size_t len, int s if(d_flag>10) verify_shared_strings_tables(); #endif - if (len <= SHORT_STRING_THRESHOLD) { + if ((len<<shift) <= SHORT_STRING_THRESHOLD) { #ifdef PIKE_DEBUG if (shift > 2) Pike_fatal("Unsupported string shift: %d\n", shift); #endif /* PIKE_DEBUG */ - t=(struct pike_string *)ba_alloc(string_allocator+shift); + t=(struct pike_string *)ba_alloc(&string_allocator); t->flags = STRING_NOT_HASHED|STRING_NOT_SHARED|STRING_IS_SHORT; } else { t=(struct pike_string *)xalloc(((len + 1)<<shift) + @@ -1806,22 +1761,26 @@ struct pike_string *realloc_unlinked_string(struct pike_string *a, { struct pike_string *r = NULL; - if (a->len <= SHORT_STRING_THRESHOLD) { - if (size <= SHORT_STRING_THRESHOLD) { + if (a->flags & STRING_IS_SHORT ) + { + if (size <= SHORT_STRING_THRESHOLD/(1<<a->size_shift)) { /* There's already space enough. */ a->len = size; low_set_index(a, size, 0); return a; } - } else if (size > SHORT_STRING_THRESHOLD) { + } else { r=(struct pike_string *)realloc((char *)a, sizeof(struct pike_string_hdr)+ ((size+1)<<a->size_shift)); } - + if(!r) { r=begin_wide_shared_string(size, a->size_shift); + r->flags |= a->flags & ~15; + r->min = a->min; + r->max = a->max; if (a->len <= size) { MEMCPY(r->str, a->str, a->len<<a->size_shift); } else { @@ -1843,11 +1802,13 @@ static struct pike_string *realloc_shared_string(struct pike_string *a, if(a->refs==1) { unlink_pike_string(a); - CLEAR_STRING_CHECKED(a); return realloc_unlinked_string(a, size); }else{ r=begin_wide_shared_string(size,a->size_shift); MEMCPY(r->str, a->str, a->len<<a->size_shift); + r->flags |= a->flags & ~15; + r->min = a->min; + r->max = a->max; free_string(a); return r; } @@ -1860,6 +1821,9 @@ struct pike_string *new_realloc_shared_string(struct pike_string *a, INT32 size, r=begin_wide_shared_string(size,shift); pike_string_cpy(MKPCHARP_STR(r),a); + r->flags |= (a->flags & ~15); + r->min = a->min; + r->max = a->max; free_string(a); return r; } @@ -2088,11 +2052,8 @@ PMOD_EXPORT struct pike_string *add_and_free_shared_strings(struct pike_string * ptrdiff_t alen = a->len; if(a->size_shift == b->size_shift) { - unsigned char aflags = a->flags; - unsigned char amin = a->min; - unsigned char amax = a->max; a = realloc_shared_string(a, alen + b->len); - set_flags_for_add( a, aflags, amin, amax, b ); + update_flags_for_add( a, b ); MEMCPY(a->str+(alen<<a->size_shift),b->str,b->len<<b->size_shift); free_string(b); a->flags |= STRING_NOT_HASHED; @@ -2381,26 +2342,15 @@ void cleanup_shared_string_table(void) static INLINE size_t memory_in_string (struct pike_string *s) { - if (s->len <= SHORT_STRING_THRESHOLD) - switch (s->size_shift) { - case 0: return sizeof (struct short_pike_string0); - case 1: return sizeof (struct short_pike_string1); - default: return sizeof (struct short_pike_string2); - } + if (s->flags & STRING_IS_SHORT ) + return sizeof (struct short_pike_string0); else return sizeof (struct pike_string_hdr) + ((s->len + 1) << s->size_shift); } void count_memory_in_short_pike_strings(size_t *num, size_t *size) { - size_t num_=0, size_=0; - ba_count_all(string_allocator, num, size); - ba_count_all(string_allocator+1, &num_, &size_); - *num += num_; - *size += size_; - ba_count_all(string_allocator+2, &num_, &size_); - *num += num_; - *size += size_; + ba_count_all(&string_allocator, num, size); } void count_memory_in_strings(size_t *num, size_t *size)