1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-21 04:00:19 +02:00

bytevector inlinedness indicated by flag, not length

* libguile/bytevectors.h (SCM_BYTEVECTOR_INLINE_P): Change to check a
  flag instead of checking the length of the bytevector.

* libguile/bytevectors.c (make_bytevector_from_buffer): Handle the len
  <= inline threshold case as well. Set the inline flag as appropriate.
  (make_bytevector): Updat the inline flag as appropriate.
  (scm_c_take_bytevector): Just dispatch to make_bytevector_from_buffer.
  (scm_i_shrink_bytevector): Update the inline flag as appropriate.
  Update the length when shrinking an already-inlined vector.
  (STRING_TO_UTF): Fix some indentation.
This commit is contained in:
Andy Wingo 2009-07-18 13:46:29 +02:00
parent ac8ed3db31
commit f332089ed4
2 changed files with 41 additions and 39 deletions

View file

@ -177,10 +177,15 @@
scm_t_bits scm_tc16_bytevector; scm_t_bits scm_tc16_bytevector;
#define SCM_BYTEVECTOR_SET_LENGTH(_bv, _len) \ #define SCM_BYTEVECTOR_INLINE_THRESHOLD (2 * sizeof (SCM))
#define SCM_BYTEVECTOR_INLINEABLE_SIZE_P(_size) \
((_size) <= SCM_BYTEVECTOR_INLINE_THRESHOLD)
#define SCM_BYTEVECTOR_SET_LENGTH(_bv, _len) \
SCM_SET_SMOB_DATA ((_bv), (scm_t_bits) (_len)) SCM_SET_SMOB_DATA ((_bv), (scm_t_bits) (_len))
#define SCM_BYTEVECTOR_SET_CONTENTS(_bv, _buf) \ #define SCM_BYTEVECTOR_SET_CONTENTS(_bv, _buf) \
SCM_SET_SMOB_DATA_2 ((_bv), (scm_t_bits) (_buf)) SCM_SET_SMOB_DATA_2 ((_bv), (scm_t_bits) (_buf))
#define SCM_BYTEVECTOR_SET_INLINE(bv) \
SCM_SET_SMOB_FLAGS (bv, SCM_SMOB_FLAGS (bv) | SCM_F_BYTEVECTOR_INLINE)
/* The empty bytevector. */ /* The empty bytevector. */
SCM scm_null_bytevector = SCM_UNSPECIFIED; SCM scm_null_bytevector = SCM_UNSPECIFIED;
@ -189,28 +194,40 @@ SCM scm_null_bytevector = SCM_UNSPECIFIED;
static inline SCM static inline SCM
make_bytevector_from_buffer (size_t len, signed char *contents) make_bytevector_from_buffer (size_t len, signed char *contents)
{ {
/* Assuming LEN > SCM_BYTEVECTOR_INLINE_THRESHOLD. */ SCM ret;
SCM_RETURN_NEWSMOB2 (scm_tc16_bytevector, len, contents); if (!SCM_BYTEVECTOR_INLINEABLE_SIZE_P (len))
SCM_NEWSMOB2 (ret, scm_tc16_bytevector, len, contents);
else
{
SCM_NEWSMOB2 (ret, scm_tc16_bytevector, len, NULL);
SCM_BYTEVECTOR_SET_INLINE (ret);
if (contents)
{
memcpy (SCM_BYTEVECTOR_CONTENTS (ret), contents, len);
scm_gc_free (contents, len, SCM_GC_BYTEVECTOR);
}
}
return ret;
} }
static inline SCM static inline SCM
make_bytevector (size_t len) make_bytevector (size_t len)
{ {
SCM bv;
if (SCM_UNLIKELY (len == 0)) if (SCM_UNLIKELY (len == 0))
bv = scm_null_bytevector; return scm_null_bytevector;
if (SCM_BYTEVECTOR_INLINEABLE_SIZE_P (len))
{
SCM ret;
SCM_NEWSMOB2 (ret, scm_tc16_bytevector, len, NULL);
SCM_BYTEVECTOR_SET_INLINE (ret);
return ret;
}
else else
{ {
signed char *contents = NULL; void *buf = scm_gc_malloc (len, SCM_GC_BYTEVECTOR);
return make_bytevector_from_buffer (len, buf);
if (!SCM_BYTEVECTOR_INLINEABLE_SIZE_P (len))
contents = (signed char *) scm_gc_malloc (len, SCM_GC_BYTEVECTOR);
bv = make_bytevector_from_buffer (len, contents);
} }
return bv;
} }
/* Return a new bytevector of size LEN octets. */ /* Return a new bytevector of size LEN octets. */
@ -225,22 +242,7 @@ scm_c_make_bytevector (size_t len)
SCM SCM
scm_c_take_bytevector (signed char *contents, size_t len) scm_c_take_bytevector (signed char *contents, size_t len)
{ {
SCM bv; return make_bytevector_from_buffer (len, contents);
if (SCM_UNLIKELY (SCM_BYTEVECTOR_INLINEABLE_SIZE_P (len)))
{
/* Copy CONTENTS into an "in-line" buffer, then free CONTENTS. */
signed char *c_bv;
bv = make_bytevector (len);
c_bv = SCM_BYTEVECTOR_CONTENTS (bv);
memcpy (c_bv, contents, len);
scm_gc_free (contents, len, SCM_GC_BYTEVECTOR);
}
else
bv = make_bytevector_from_buffer (len, contents);
return bv;
} }
/* Shrink BV to C_NEW_LEN (which is assumed to be smaller than its current /* Shrink BV to C_NEW_LEN (which is assumed to be smaller than its current
@ -261,6 +263,7 @@ scm_i_shrink_bytevector (SCM bv, size_t c_new_len)
if (SCM_BYTEVECTOR_INLINEABLE_SIZE_P (c_new_len)) if (SCM_BYTEVECTOR_INLINEABLE_SIZE_P (c_new_len))
{ {
/* Copy to the in-line buffer and free the current buffer. */ /* Copy to the in-line buffer and free the current buffer. */
SCM_BYTEVECTOR_SET_INLINE (bv);
c_new_bv = SCM_BYTEVECTOR_CONTENTS (bv); c_new_bv = SCM_BYTEVECTOR_CONTENTS (bv);
memcpy (c_new_bv, c_bv, c_new_len); memcpy (c_new_bv, c_bv, c_new_len);
scm_gc_free (c_bv, c_len, SCM_GC_BYTEVECTOR); scm_gc_free (c_bv, c_len, SCM_GC_BYTEVECTOR);
@ -273,6 +276,8 @@ scm_i_shrink_bytevector (SCM bv, size_t c_new_len)
SCM_BYTEVECTOR_SET_CONTENTS (bv, c_new_bv); SCM_BYTEVECTOR_SET_CONTENTS (bv, c_new_bv);
} }
} }
else
SCM_BYTEVECTOR_SET_LENGTH (bv, c_new_len);
return bv; return bv;
} }
@ -1898,8 +1903,7 @@ utf_encoding_name (char *name, size_t utf_width, SCM endianness)
scm_list_1 (str), err); \ scm_list_1 (str), err); \
else \ else \
/* C_UTF is null-terminated. */ \ /* C_UTF is null-terminated. */ \
utf = scm_c_take_bytevector ((signed char *) c_utf, \ utf = scm_c_take_bytevector ((signed char *) c_utf, c_utf_len); \
c_utf_len); \
\ \
return (utf); return (utf);

View file

@ -116,13 +116,11 @@ SCM_API SCM scm_utf32_to_string (SCM, SCM);
i.e., without allocating memory beside the SMOB itself (a double cell). i.e., without allocating memory beside the SMOB itself (a double cell).
This optimization is necessary since small bytevectors are expected to be This optimization is necessary since small bytevectors are expected to be
common. */ common. */
#define SCM_BYTEVECTOR_P(_bv) \ #define SCM_BYTEVECTOR_P(_bv) \
SCM_SMOB_PREDICATE (scm_tc16_bytevector, _bv) SCM_SMOB_PREDICATE (scm_tc16_bytevector, _bv)
#define SCM_BYTEVECTOR_INLINE_THRESHOLD (2 * sizeof (SCM)) #define SCM_F_BYTEVECTOR_INLINE 0x1
#define SCM_BYTEVECTOR_INLINEABLE_SIZE_P(_size) \ #define SCM_BYTEVECTOR_INLINE_P(_bv) \
((_size) <= SCM_BYTEVECTOR_INLINE_THRESHOLD) (SCM_SMOB_FLAGS (_bv) & SCM_F_BYTEVECTOR_INLINE)
#define SCM_BYTEVECTOR_INLINE_P(_bv) \
(SCM_BYTEVECTOR_INLINEABLE_SIZE_P (SCM_BYTEVECTOR_LENGTH (_bv)))
/* Hint that is passed to `scm_gc_malloc ()' and friends. */ /* Hint that is passed to `scm_gc_malloc ()' and friends. */
#define SCM_GC_BYTEVECTOR "bytevector" #define SCM_GC_BYTEVECTOR "bytevector"