pike.git / src / stralloc.c

version» Context lines:

pike.git/src/stralloc.c:19:   #include "operators.h"   #include "pike_float.h"   #include "block_allocator.h"   #include "port.h"      #include <errno.h>   #include <float.h>   #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   #undef LONG_MAX   #undef ULONG_MAX   #define LONG_MIN INT_MIN   #define LONG_MAX INT_MAX   #define ULONG_MAX UINT_MAX   #endif   
pike.git/src/stralloc.c:76:   #define UNLOCK_BUCKET(HVAL) do { \    size_t hval__=(HVAL); \    mt_unlock(BUCKETLOCK(hval__)); \   }while(0)      #else   #define LOCK_BUCKET(HVAL)   #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   static unsigned int HASH_PREFIX=64;   static unsigned int need_more_hash_prefix_depth=0;   #endif      /* Force a new hashkey to be generated early during init. */   static unsigned int need_new_hashkey_depth=0xffff;   static size_t hashkey = 0xa55aa55a;
pike.git/src/stralloc.c:317: Inside #if defined(PIKE_DEBUG)
   pos, s->len-1);    } else {    Pike_fatal("Attempt to index the empty string with %"PRINTPTRDIFFT"d.\n",    pos);    }    }       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   PMOD_EXPORT struct pike_string *debug_check_size_shift(struct pike_string *a,    int shift)   {    if(a->size_shift != shift)    Pike_fatal("Wrong STRX macro used!\n");    return a;   }
pike.git/src/stralloc.c:479:   {    return index_shared_string(s,s->len);   }   #else   #define locate_problem(X)   #endif /* PIKE_DEBUG */      /* 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;   #endif    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)    {    debug_dump_pike_string(curr, 70);    locate_problem(has_zero_refs);    Pike_fatal("String with no references.\n");    }   #endif    debug_malloc_touch(curr);    -  if (hval == curr->hval && -  len==curr->len && -  size_shift==curr->size_shift && +  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 */    }    depth++;   #ifndef HASH_PREFIX    if (curr->len > (ptrdiff_t)HASH_PREFIX)    prefix_depth++;   #endif    }    if (depth > need_new_hashkey_depth) {
pike.git/src/stralloc.c:662:   /* Allocation of strings */      /* Without the str at the end, to get the size of the header. */   struct pike_string_hdr {    PIKE_STRING_CONTENTS;   };      /* 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]; - }; + static struct block_allocator string_allocator = BA_INIT(sizeof(struct short_pike_string0), SHORT_STRING_BLOCK);    - 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) -  +    #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); \    } \    } while(0)      /* note that begin_shared_string expects the _exact_ size of the string,    * not the maximum size    */   PMOD_EXPORT struct pike_string *debug_begin_shared_string(size_t len)   {    struct pike_string *t;   #ifdef PIKE_DEBUG    extern int d_flag;    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;    }   #ifdef ATOMIC_SVALUE    t->ref_type = T_STRING;   #endif    t->refs = 0;    add_ref(t); /* For DMALLOC */    t->str[len]=0;    t->len=len;
pike.git/src/stralloc.c:767:       LOCK_BUCKET(hval);    h=HMODULO(hval);    s->next = base_table[h];    base_table[h] = s;    s->hval=hval;    s->flags &= ~(STRING_NOT_HASHED|STRING_NOT_SHARED);    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    */       /* This could in theory have a pretty ugly complexity    * /Hubbe    */      #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);    return;    }    for(h=1;h<BUCKET_LOCKS;h++) mt_lock(bucket_locks+h);   #endif       /* 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",    HASH_PREFIX);   #endif /* 0 */    }    /* NOTE: No need to update to the correct values, since that will    * be done on demand.    */    need_new_hashkey_depth = 0;
pike.git/src/stralloc.c:855:   }      PMOD_EXPORT struct pike_string *debug_begin_wide_shared_string(size_t len, int shift)   {    struct pike_string *t = NULL;   #ifdef PIKE_DEBUG    extern int d_flag;    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) +    sizeof(struct pike_string_hdr));    t->flags = STRING_NOT_HASHED|STRING_NOT_SHARED;    }   #ifdef ATOMIC_SVALUE    t->ref_type = T_STRING;   #endif    t->refs = 0;
pike.git/src/stralloc.c:1799:    return a->len - b->len;    }    }   }      struct pike_string *realloc_unlinked_string(struct pike_string *a,    ptrdiff_t size)   {    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 {    MEMCPY(r->str, a->str, size<<a->size_shift);    }    free_string(a);    }       r->len=size;    low_set_index(r,size,0);
pike.git/src/stralloc.c:1836:   }      /* Returns an unlinked string ready for end_shared_string */   static struct pike_string *realloc_shared_string(struct pike_string *a,    ptrdiff_t size)   {    struct pike_string *r;    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;    }   }      struct pike_string *new_realloc_shared_string(struct pike_string *a, INT32 size, int shift)   {    struct pike_string *r;    if(shift == a->size_shift) return realloc_shared_string(a,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;   }         /* Modify one index in a shared string    * Not suitable for building new strings or changing multiple characters    * within a string!    *    * Phew, this function become complicated when I inserted magic for wide
pike.git/src/stralloc.c:2081:    set_flags_for_add( ret, a->flags, a->min, a->max, b );    return low_end_shared_string(ret);   }      PMOD_EXPORT struct pike_string *add_and_free_shared_strings(struct pike_string *a,    struct pike_string *b)   {    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;    return end_shared_string(a);    }else{    struct pike_string *ret=add_shared_strings(a,b);    free_string(a);    free_string(b);    return ret;    }
pike.git/src/stralloc.c:2374: Inside #if defined(DO_PIKE_CLEANUP)
     #ifdef DO_PIKE_CLEANUP    ba_destroy(string_allocator+0);    ba_destroy(string_allocator+1);    ba_destroy(string_allocator+2);   #endif /* DO_PIKE_CLEANUP */   }      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)   {    unsigned INT32 e;    size_t num_=0, size_=0;    if(!base_table)    {    *num=*size=0;    return;