Commit a84ab127 authored by KOBAYASHI Shuji's avatar KOBAYASHI Shuji

Prioritize embedded string over nofree (or normal) string

Prioritize embedded string in the following functions:

- `str_new_static`
- `str_new`
- `mrb_str_new_capa`
- `mrb_str_pool`

The reasons are as follows:

- Consistency with `mrb_str_byte_subseq` and `str_replace`.
- Memory locality increases and may be slightly faster.
- No conversion cost to embedded string when modifying the string.
parent def79258
...@@ -32,7 +32,7 @@ const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; ...@@ -32,7 +32,7 @@ const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
#define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class)) #define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class))
static void static struct RString*
str_init_normal_capa(mrb_state *mrb, struct RString *s, str_init_normal_capa(mrb_state *mrb, struct RString *s,
const char *p, size_t len, size_t capa) const char *p, size_t len, size_t capa)
{ {
...@@ -43,33 +43,36 @@ str_init_normal_capa(mrb_state *mrb, struct RString *s, ...@@ -43,33 +43,36 @@ str_init_normal_capa(mrb_state *mrb, struct RString *s,
s->as.heap.len = (mrb_int)len; s->as.heap.len = (mrb_int)len;
s->as.heap.aux.capa = (mrb_int)capa; s->as.heap.aux.capa = (mrb_int)capa;
RSTR_UNSET_TYPE_FLAG(s); RSTR_UNSET_TYPE_FLAG(s);
return s;
} }
static void static struct RString*
str_init_normal(mrb_state *mrb, struct RString *s, const char *p, size_t len) str_init_normal(mrb_state *mrb, struct RString *s, const char *p, size_t len)
{ {
str_init_normal_capa(mrb, s, p, len, len); return str_init_normal_capa(mrb, s, p, len, len);
} }
static void static struct RString*
str_init_embed(struct RString *s, const char *p, size_t len) str_init_embed(struct RString *s, const char *p, size_t len)
{ {
if (p) memcpy(RSTR_EMBED_PTR(s), p, len); if (p) memcpy(RSTR_EMBED_PTR(s), p, len);
RSTR_EMBED_PTR(s)[len] = '\0'; RSTR_EMBED_PTR(s)[len] = '\0';
RSTR_SET_TYPE_FLAG(s, EMBED); RSTR_SET_TYPE_FLAG(s, EMBED);
RSTR_SET_EMBED_LEN(s, len); RSTR_SET_EMBED_LEN(s, len);
return s;
} }
static void static struct RString*
str_init_nofree(struct RString *s, const char *p, size_t len) str_init_nofree(struct RString *s, const char *p, size_t len)
{ {
s->as.heap.ptr = (char *)p; s->as.heap.ptr = (char *)p;
s->as.heap.len = (mrb_int)len; s->as.heap.len = (mrb_int)len;
s->as.heap.aux.capa = 0; /* nofree */ s->as.heap.aux.capa = 0; /* nofree */
RSTR_SET_TYPE_FLAG(s, NOFREE); RSTR_SET_TYPE_FLAG(s, NOFREE);
return s;
} }
static void static struct RString*
str_init_shared(mrb_state *mrb, const struct RString *orig, struct RString *s, mrb_shared_string *shared) str_init_shared(mrb_state *mrb, const struct RString *orig, struct RString *s, mrb_shared_string *shared)
{ {
if (shared) { if (shared) {
...@@ -85,56 +88,55 @@ str_init_shared(mrb_state *mrb, const struct RString *orig, struct RString *s, m ...@@ -85,56 +88,55 @@ str_init_shared(mrb_state *mrb, const struct RString *orig, struct RString *s, m
s->as.heap.len = orig->as.heap.len; s->as.heap.len = orig->as.heap.len;
s->as.heap.aux.shared = shared; s->as.heap.aux.shared = shared;
RSTR_SET_TYPE_FLAG(s, SHARED); RSTR_SET_TYPE_FLAG(s, SHARED);
return s;
} }
static void static struct RString*
str_init_fshared(const struct RString *orig, struct RString *s, struct RString *fshared) str_init_fshared(const struct RString *orig, struct RString *s, struct RString *fshared)
{ {
s->as.heap.ptr = orig->as.heap.ptr; s->as.heap.ptr = orig->as.heap.ptr;
s->as.heap.len = orig->as.heap.len; s->as.heap.len = orig->as.heap.len;
s->as.heap.aux.fshared = fshared; s->as.heap.aux.fshared = fshared;
RSTR_SET_TYPE_FLAG(s, FSHARED); RSTR_SET_TYPE_FLAG(s, FSHARED);
return s;
} }
static void static struct RString*
str_init(mrb_state *mrb, struct RString *s, const char *p, size_t len) str_init_modifiable(mrb_state *mrb, struct RString *s, const char *p, size_t len)
{ {
if (RSTR_EMBEDDABLE_P(len)) { if (RSTR_EMBEDDABLE_P(len)) {
str_init_embed(s, p, len); return str_init_embed(s, p, len);
} }
else { else {
str_init_normal(mrb, s, p, len); return str_init_normal(mrb, s, p, len);
} }
} }
static struct RString* static struct RString*
str_new_static(mrb_state *mrb, const char *p, size_t len) str_new_static(mrb_state *mrb, const char *p, size_t len)
{ {
struct RString *s; if (RSTR_EMBEDDABLE_P(len)) {
return str_init_embed(mrb_obj_alloc_string(mrb), p, len);
}
if (len >= MRB_INT_MAX) { if (len >= MRB_INT_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
} }
s = mrb_obj_alloc_string(mrb); return str_init_nofree(mrb_obj_alloc_string(mrb), p, len);
str_init_nofree(s, p, len);
return s;
} }
static struct RString* static struct RString*
str_new(mrb_state *mrb, const char *p, size_t len) str_new(mrb_state *mrb, const char *p, size_t len)
{ {
struct RString *s; if (RSTR_EMBEDDABLE_P(len)) {
return str_init_embed(mrb_obj_alloc_string(mrb), p, len);
}
if (len >= MRB_INT_MAX) { if (len >= MRB_INT_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
} }
if (p && mrb_ro_data_p(p)) { if (p && mrb_ro_data_p(p)) {
return str_new_static(mrb, p, len); return str_init_nofree(mrb_obj_alloc_string(mrb), p, len);
} }
s = mrb_obj_alloc_string(mrb); return str_init_normal(mrb, mrb_obj_alloc_string(mrb), p, len);
str_init(mrb, s, p, len);
return s;
} }
static inline void static inline void
...@@ -157,12 +159,15 @@ mrb_str_new_capa(mrb_state *mrb, size_t capa) ...@@ -157,12 +159,15 @@ mrb_str_new_capa(mrb_state *mrb, size_t capa)
{ {
struct RString *s; struct RString *s;
s = mrb_obj_alloc_string(mrb); if (RSTR_EMBEDDABLE_P(capa)) {
s = str_init_embed(mrb_obj_alloc_string(mrb), NULL, 0);
if (capa >= MRB_INT_MAX) { }
else if (capa >= MRB_INT_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string capacity size too big"); mrb_raise(mrb, E_ARGUMENT_ERROR, "string capacity size too big");
} }
str_init_normal_capa(mrb, s, NULL, 0, capa); else {
s = str_init_normal_capa(mrb, mrb_obj_alloc_string(mrb), NULL, 0, capa);
}
return mrb_obj_value(s); return mrb_obj_value(s);
} }
...@@ -553,11 +558,14 @@ mrb_str_pool(mrb_state *mrb, mrb_value str) ...@@ -553,11 +558,14 @@ mrb_str_pool(mrb_state *mrb, mrb_value str)
s->c = mrb->string_class; s->c = mrb->string_class;
s->flags = 0; s->flags = 0;
if (RSTR_NOFREE_P(orig)) { if (RSTR_EMBEDDABLE_P(len)) {
str_init_embed(s, p, len);
}
else if (RSTR_NOFREE_P(orig)) {
str_init_nofree(s, p, len); str_init_nofree(s, p, len);
} }
else { else {
str_init(mrb, s, p, len); str_init_normal(mrb, s, p, len);
} }
RSTR_SET_POOL_FLAG(s); RSTR_SET_POOL_FLAG(s);
MRB_SET_FROZEN_FLAG(s); MRB_SET_FROZEN_FLAG(s);
...@@ -808,12 +816,12 @@ mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s) ...@@ -808,12 +816,12 @@ mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s)
mrb_free(mrb, shared); mrb_free(mrb, shared);
} }
else { else {
str_init(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len); str_init_modifiable(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
str_decref(mrb, shared); str_decref(mrb, shared);
} }
} }
else if (RSTR_NOFREE_P(s) || RSTR_FSHARED_P(s)) { else if (RSTR_NOFREE_P(s) || RSTR_FSHARED_P(s)) {
str_init(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len); str_init_modifiable(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
} }
} }
...@@ -2937,7 +2945,8 @@ mrb_init_string(mrb_state *mrb) ...@@ -2937,7 +2945,8 @@ mrb_init_string(mrb_state *mrb)
{ {
struct RClass *s; struct RClass *s;
mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << 5), "pointer size too big for embedded string"); mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << MRB_STR_EMBED_LEN_BITSIZE),
"pointer size too big for embedded string");
mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */ mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */
MRB_SET_INSTANCE_TT(s, MRB_TT_STRING); MRB_SET_INSTANCE_TT(s, MRB_TT_STRING);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment