[svn:parrot] r49018 - in trunk: include/parrot src/string
nwellnhof at svn.parrot.org
nwellnhof at svn.parrot.org
Wed Sep 15 15:18:32 UTC 2010
Author: nwellnhof
Date: Wed Sep 15 15:18:32 2010
New Revision: 49018
URL: https://trac.parrot.org/parrot/changeset/49018
Log:
[str] Introduce growable strings
This greatly speeds up the concatenation of a long and a short string.
Modified:
trunk/include/parrot/pobj.h
trunk/src/string/api.c
Modified: trunk/include/parrot/pobj.h
==============================================================================
--- trunk/include/parrot/pobj.h Wed Sep 15 14:14:49 2010 (r49017)
+++ trunk/include/parrot/pobj.h Wed Sep 15 15:18:32 2010 (r49018)
@@ -135,6 +135,8 @@
PObj_is_string_FLAG = POBJ_FLAG(8),
/* PObj is a PMC */
PObj_is_PMC_FLAG = POBJ_FLAG(9),
+ /* PObj is a copy of a string that doesn't own the string buffer */
+ PObj_is_string_copy_FLAG = POBJ_FLAG(10),
/* the PMC is a shared PMC */
PObj_is_PMC_shared_FLAG = POBJ_FLAG(11), /* Same as PObj_is_shared_FLAG */
/* PObj is otherwise shared */
@@ -246,6 +248,10 @@
#define PObj_is_string_SET(o) PObj_flag_SET(is_string, o)
#define PObj_is_string_CLEAR(o) PObj_flag_CLEAR(is_string, o)
+#define PObj_is_string_copy_TEST(o) PObj_flag_TEST(is_string_copy, o)
+#define PObj_is_string_copy_SET(o) PObj_flag_SET(is_string_copy, o)
+#define PObj_is_string_copy_CLEAR(o) PObj_flag_CLEAR(is_string_copy, o)
+
#define PObj_sysmem_TEST(o) PObj_flag_TEST(sysmem, o)
#define PObj_sysmem_SET(o) PObj_flag_SET(sysmem, o)
#define PObj_sysmem_CLEAR(o) PObj_flag_CLEAR(sysmem, o)
@@ -318,6 +324,10 @@
(PObj_sysmem_FLAG | PObj_on_free_list_FLAG | \
PObj_constant_FLAG | PObj_external_FLAG)))
+#define PObj_is_growable_TESTALL(o) (!(PObj_get_FLAGS(o) & \
+ (PObj_sysmem_FLAG | PObj_is_string_copy_FLAG | \
+ PObj_constant_FLAG | PObj_external_FLAG)))
+
#define PObj_custom_mark_destroy_SETALL(o) do { \
PObj_custom_mark_SET(o); \
PObj_custom_destroy_SET(o); \
Modified: trunk/src/string/api.c
==============================================================================
--- trunk/src/string/api.c Wed Sep 15 14:14:49 2010 (r49017)
+++ trunk/src/string/api.c Wed Sep 15 15:18:32 2010 (r49018)
@@ -377,6 +377,9 @@
/* Clear live flag. It might be set on constant strings */
PObj_live_CLEAR(d);
+ /* Set the string copy flag */
+ PObj_is_string_copy_SET(d);
+
/* Now check that buffer allocated from pool and affected by compacting */
if (is_movable && Buffer_bufstart(s)) {
/* If so, mark it as shared */
@@ -450,16 +453,42 @@
/* calc usable and total bytes */
total_length = a->bufused + b->bufused;
- dest = Parrot_str_new_noinit(interp, total_length);
- PARROT_ASSERT(enc);
- dest->encoding = enc;
+ if (PObj_is_growable_TESTALL(a)
+ && a->strstart + total_length <=
+ (char *)Buffer_bufstart(a) + Buffer_buflen(a)) {
+ /* String a is growable and there's enough space in the buffer */
+ DECL_CONST_CAST;
+
+ dest = Parrot_str_copy(interp, a);
+
+ /* Switch string copy flags */
+ PObj_is_string_copy_SET(PARROT_const_cast(STRING *, a));
+ PObj_is_string_copy_CLEAR(dest);
- /* Copy A first */
- mem_sys_memcopy(dest->strstart, a->strstart, a->bufused);
+ /* Append b */
+ mem_sys_memcopy(dest->strstart + dest->bufused,
+ b->strstart, b->bufused);
- /* Tack B on the end of A */
- mem_sys_memcopy((void *)((ptrcast_t)dest->strstart + a->bufused),
- b->strstart, b->bufused);
+ dest->hashval = 0;
+ }
+ else {
+ if (4 * b->bufused < a->bufused) {
+ /* Preallocate more memory if we're appending a short string to
+ a long string */
+ total_length += total_length >> 1;
+ }
+
+ dest = Parrot_str_new_noinit(interp, total_length);
+ PARROT_ASSERT(enc);
+ dest->encoding = enc;
+
+ /* Copy A first */
+ mem_sys_memcopy(dest->strstart, a->strstart, a->bufused);
+
+ /* Tack B on the end of A */
+ mem_sys_memcopy((void *)((ptrcast_t)dest->strstart + a->bufused),
+ b->strstart, b->bufused);
+ }
dest->bufused = a->bufused + b->bufused;
dest->strlen = a->strlen + b->strlen;
More information about the parrot-commits
mailing list