pike.git / src / stralloc.c

version» Context lines:

pike.git/src/stralloc.c:261:       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 const struct pike_string *debug_check_size_shift(const struct pike_string *a, -  int shift) + 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;   }   #endif      #define CONVERT(FROM,TO) \    void PIKE_CONCAT4(convert_,FROM,_to_,TO) (PIKE_CONCAT(p_wchar,TO) *to, \    const PIKE_CONCAT(p_wchar,FROM) *from, \
pike.git/src/stralloc.c:624:    if(old_base)    free(old_base);   }      /* Allocation of strings */      #define STRING_BLOCK 2048      static struct block_allocator string_allocator = BA_INIT(sizeof(struct pike_string), STRING_BLOCK);    - static INLINE int string_is_short(const struct pike_string * s) { -  return !!(s->flags & STRING_IS_SHORT); - } -  +    static void free_unlinked_pike_string(struct pike_string * s) { -  size_t bytes = (s->len+1) << s->size_shift; +     -  if (string_is_short(s)) { -  ba_free(&string_allocator, s->str); -  } else { +  switch (s->flags & STRING_ALLOC_MASK) { +  case STRING_ALLOC_MALLOC:    free(s->str); -  +  break; +  case STRING_ALLOC_BA: +  ba_free(&string_allocator, s->str); +  break;    }       ba_free(&string_allocator, s);   }      /* 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)   {
pike.git/src/stralloc.c:745: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    extern int d_flag;    if(d_flag>10)    verify_shared_strings_tables();   #endif   #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); -  t->flags = STRING_NOT_HASHED|STRING_NOT_SHARED; +  /* we mark the string as static here, to avoid double free if the allocations +  * fail +  */ +  t->flags = STRING_NOT_HASHED|STRING_NOT_SHARED|STRING_ALLOC_STATIC;    if (bytes <= sizeof(struct pike_string)) {    t->str = ba_alloc(&string_allocator); -  t->flags |= STRING_IS_SHORT; -  } else t->str = xalloc(bytes); - #ifdef ATOMIC_SVALUE -  t->ref_type = T_STRING; - #endif +  t->flags |= STRING_ALLOC_BA; +  } else { +  t->str = xalloc(bytes); +  t->flags |= STRING_ALLOC_MALLOC; +  }    t->refs = 0;    add_ref(t); /* For DMALLOC */    t->len=len;    t->size_shift=shift;    DO_IF_DEBUG(t->next = NULL);    low_set_index(t,len,0);    return t;   }    -  + PMOD_EXPORT struct pike_string * make_static_string(const char * str, size_t len, +  enum size_shift shift) { +  struct pike_string * t = ba_alloc(&string_allocator); +  +  t->flags = STRING_NOT_HASHED|STRING_NOT_SHARED|STRING_ALLOC_STATIC; +  t->str = str; +  t->refs = 0; +  t->len = len; +  t->size_shift = shift; +  add_ref(t); /* For DMALLOC */ +  +  return t; + } +  + PMOD_EXPORT struct pike_string * make_shared_static_string(const char *str, size_t len, +  enum size_shift shift) + { +  struct pike_string *s; +  ptrdiff_t h = StrHash(str, len); +  +  s = internal_findstring(str,len,shift,h); +  +  if (!s) { +  s = make_static_string(str, len, shift); +  link_pike_string(s, h); +  } else { +  add_ref(s); +  } +  +  return s; + } +    /*    * This function assumes that the shift size is already the minimum it    * can be.    */   struct pike_string *low_end_shared_string(struct pike_string *s)   {    ptrdiff_t len;    size_t h=0;    struct pike_string *s2;   
pike.git/src/stralloc.c:1117:    long bytes_distinct_strings[8] = {0,0,0,0,0,0,0,0};    long overhead_bytes[8] = {0,0,0,0,0,0,0,0};    unsigned INT32 e;    struct pike_string *p;    for(e=0;e<htable_size;e++)    {    for(p=base_table[e];p;p=p->next)    {    int key = p->size_shift;    num_distinct_strings[key]++; -  bytes_distinct_strings[key] += -  DO_ALIGN(p->len << p->size_shift, sizeof(void *)); +  alloced_bytes[key] += p->refs*sizeof(struct pike_string);    alloced_strings[key] += p->refs; -  if (string_is_short(p)) { +  if (string_is_block_allocated(p)) {    alloced_bytes[key] += -  p->refs*DO_ALIGN((p->len+3) << p->size_shift,sizeof(void *)); +  p->refs*sizeof(struct pike_string);    } else { -  alloced_bytes[key] += p->refs*sizeof(struct pike_string); +  alloced_bytes[key] += +  p->refs*DO_ALIGN((p->len+3) << p->size_shift,sizeof(void *));    }    }    }    string_builder_sprintf(&s,    "\nShared string hash table:\n"    "-------------------------\n"    "\n"    "Type Count Distinct Bytes Actual Overhead %%\n"    "------------------------------------------------------------\n");    for(e = 0; e < 8; e++) {
pike.git/src/stralloc.c:1631:    return a->len - b->len;    }    }   }      struct pike_string *realloc_unlinked_string(struct pike_string *a,    ptrdiff_t size)   {    char * s = NULL;    size_t nbytes = (size_t)(size+1) << a->size_shift; +  size_t obytes = (size_t)(a->len+1) << a->size_shift;    -  switch (string_is_short(a) | ((nbytes <= sizeof(struct pike_string)) << 1)) { -  case 0: +  switch ((a->flags & STRING_ALLOC_MASK) | (nbytes <= sizeof(struct pike_string))) { +  case STRING_ALLOC_MALLOC:    s=realloc(a->str, nbytes);    if (!s)    Pike_error("Out of memory in realloc_unlinked_string. Could not allocate %"PRINTSIZET" bytes.\n",    nbytes);    break; -  case 1: { // old string was short -  size_t obytes = (size_t)(a->len+1) << a->size_shift; +  case STRING_ALLOC_BA: // old string was short    s = xalloc(nbytes); -  a->flags &= ~STRING_IS_SHORT; +  a->flags &= ~STRING_ALLOC_MASK; +  a->flags |= STRING_ALLOC_MALLOC;    memcpy(s, a->str, obytes);    ba_free(&string_allocator, a->str);    break; -  } -  case 2: // new string is short +  case STRING_ALLOC_MALLOC|1:    s = ba_alloc(&string_allocator); -  a->flags |= STRING_IS_SHORT; +  a->flags &= ~STRING_ALLOC_MASK; +  a->flags |= STRING_ALLOC_BA;    memcpy(s, a->str, nbytes);    free(a->str);    break; -  case 3: // both are short +  case STRING_ALLOC_BA|1: // both are short    goto done; -  +  case STRING_ALLOC_STATIC: +  s = xalloc(nbytes); +  a->flags &= ~STRING_ALLOC_MASK; +  a->flags |= STRING_ALLOC_MALLOC; +  memcpy(s, a->str, obytes); +  break; +  case STRING_ALLOC_STATIC|1: +  s = ba_alloc(&string_allocator); +  a->flags &= ~STRING_ALLOC_MASK; +  a->flags |= STRING_ALLOC_BA; +  memcpy(s, a->str, obytes); +  break; + #ifdef PIKE_DEBUG +  default: +  Pike_fatal("encountered string with unknown allocation type %d\n", +  a->flags & STRING_ALLOC_MASK); + #endif    }       a->str = s;   done:    a->len=size;    low_set_index(a,size,0);       return a;   }      /* Returns an unlinked string ready for end_shared_string */   static struct pike_string *realloc_shared_string(struct pike_string *a,    ptrdiff_t size)   { -  if(a->refs==1) +  if(string_may_modify(a))    {    unlink_pike_string(a);    return realloc_unlinked_string(a, size);    }else{    struct pike_string *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->flags |= a->flags & STRING_CHECKED_MASK;    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->flags |= (a->flags & STRING_CHECKED_MASK);    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!
pike.git/src/stralloc.c:1819:    convert_2_to_1((p_wchar1 *)b->str,STR2(a),a->len);    STR1(b)[index]=c;    free_string(a);    return end_shared_string(b);    }    }    }          /* We now know that the string has the right character size */ -  if(a->refs==1) +  if(string_may_modify(a))    {    /* One ref - destructive mode */       unlink_pike_string(a);    low_set_index(a, index, c);    CLEAR_STRING_CHECKED(a);       if((((unsigned int)index) >= hash_prefix_len) && (index < a->len-8) )    {    struct pike_string *old;
pike.git/src/stralloc.c:2307:    to->s->len = from->s->len;    MEMCPY (to->s->str, from->s->str, (from->s->len + 1) << from->s->size_shift);    to->known_shift = from->known_shift;   }      /* str becomes invalid if successful (i.e. nonzero returned),    * otherwise nothing happens. */   PMOD_EXPORT int init_string_builder_with_string (struct string_builder *s,    struct pike_string *str)   { -  if (str->refs == 1 && !string_is_short(str)) { +  if (string_may_modify(str)) {    /* Unlink the string and use it as buffer directly. */    unlink_pike_string (str);    str->flags = STRING_NOT_SHARED;    s->s = str;    s->malloced = str->len;    s->known_shift = str->size_shift;    return 1;    }    return 0;   }