pike.git/
src/
stralloc.c
Branch:
Tag:
Non-build tags
All tags
No tags
2014-08-22
2014-08-22 18:51:55 by Arne Goedeke <el@laramies.com>
119e1e5f039d40ad9a1be2444a7e5b282310a9c6 (
123
lines) (+
87
/-
36
)
[
Show
|
Annotate
]
Branch:
arne/string_alloc
Strings: global const strings
268:
} #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");
631:
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);
752:
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;
769:
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.
1124:
{ 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
*
)
)
;
} } }
1638:
{ 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;
1676:
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);
1698:
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);
1826:
/* We now know that the string has the right character size */
-
if(a
->refs==1
)
+
if(
string_may_modify(
a)
)
{ /* One ref - destructive mode */
2314:
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;