diff options
| author | KOBAYASHI Shuji <[email protected]> | 2019-08-20 18:49:55 +0900 |
|---|---|---|
| committer | KOBAYASHI Shuji <[email protected]> | 2019-08-20 18:49:55 +0900 |
| commit | 8157672a29e50756b9709022e8f66da73cd92c2b (patch) | |
| tree | 3fbec1e5e92d6c1a5fc3f28d9f649f2a17ea2fdc | |
| parent | b836fd05dd084ac9e61c918cf1757b425c4d271b (diff) | |
| download | mruby-8157672a29e50756b9709022e8f66da73cd92c2b.tar.gz mruby-8157672a29e50756b9709022e8f66da73cd92c2b.zip | |
Use `RBasic` padding for embedded string on 64-bit CPU
On 64-bit CPU, there is padding in `RBasic`, so reorder the fields and use
it as buffer of embedded string. This change allows 4 more bytes to be
embedded on 64-bit CPU.
However, an incompatibility will occur if `RString::as::ary` is accessed
directly because `RString` structure has changed.
| -rw-r--r-- | include/mruby/object.h | 6 | ||||
| -rw-r--r-- | include/mruby/string.h | 11 | ||||
| -rw-r--r-- | src/gc.c | 2 | ||||
| -rw-r--r-- | src/string.c | 6 |
4 files changed, 15 insertions, 10 deletions
diff --git a/include/mruby/object.h b/include/mruby/object.h index 48dcc4977..1cb4ca6e8 100644 --- a/include/mruby/object.h +++ b/include/mruby/object.h @@ -8,11 +8,11 @@ #define MRUBY_OBJECT_H #define MRB_OBJECT_HEADER \ + struct RClass *c; \ + struct RBasic *gcnext; \ enum mrb_vtype tt:8; \ uint32_t color:3; \ - uint32_t flags:21; \ - struct RClass *c; \ - struct RBasic *gcnext + uint32_t flags:21 #define MRB_FLAG_TEST(obj, flag) ((obj)->flags & (flag)) diff --git a/include/mruby/string.h b/include/mruby/string.h index ab29be421..84a6c4665 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -16,7 +16,8 @@ MRB_BEGIN_DECL extern const char mrb_digitmap[]; -#define RSTRING_EMBED_LEN_MAX ((mrb_int)(sizeof(void*) * 3 - 1)) +#define RSTRING_EMBED_LEN_MAX \ + ((mrb_int)(sizeof(void*) * 3 + sizeof(void*) - 32 / CHAR_BIT - 1)) struct RString { MRB_OBJECT_HEADER; @@ -30,9 +31,12 @@ struct RString { } aux; char *ptr; } heap; - char ary[RSTRING_EMBED_LEN_MAX + 1]; } as; }; +struct RStringEmbed { + MRB_OBJECT_HEADER; + char ary[]; +}; #define RSTR_SET_TYPE_FLAG(s, type) (RSTR_UNSET_TYPE_FLAG(s), (s)->flags |= MRB_STR_##type) #define RSTR_UNSET_TYPE_FLAG(s) ((s)->flags &= ~(MRB_STR_TYPE_MASK|MRB_STR_EMBED_LEN_MASK)) @@ -53,11 +57,12 @@ struct RString { (s)->as.heap.len = (mrb_int)(n);\ }\ } while (0) +#define RSTR_EMBED_PTR(s) (((struct RStringEmbed*)(s))->ary) #define RSTR_EMBED_LEN(s)\ (mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT) #define RSTR_EMBEDDABLE_P(len) ((len) <= RSTRING_EMBED_LEN_MAX) -#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? (s)->as.ary : (s)->as.heap.ptr) +#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_PTR(s) : (s)->as.heap.ptr) #define RSTR_LEN(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_LEN(s) : (s)->as.heap.len) #define RSTR_CAPA(s) (RSTR_EMBED_P(s) ? RSTRING_EMBED_LEN_MAX : (s)->as.heap.aux.capa) @@ -521,7 +521,7 @@ MRB_API struct RBasic* mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) { struct RBasic *p; - static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } }; + static const RVALUE RVALUE_zero = { { { NULL, NULL, MRB_TT_FALSE } } }; mrb_gc *gc = &mrb->gc; if (cls) { diff --git a/src/string.c b/src/string.c index 72e14ede9..cacf48821 100644 --- a/src/string.c +++ b/src/string.c @@ -54,8 +54,8 @@ str_init_normal(mrb_state *mrb, struct RString *s, const char *p, size_t len) static void str_init_embed(struct RString *s, const char *p, size_t len) { - if (p) memcpy(s->as.ary, p, len); - s->as.ary[len] = '\0'; + if (p) memcpy(RSTR_EMBED_PTR(s), p, len); + RSTR_EMBED_PTR(s)[len] = '\0'; RSTR_SET_TYPE_FLAG(s, EMBED); RSTR_SET_EMBED_LEN(s, len); } @@ -188,7 +188,7 @@ resize_capa(mrb_state *mrb, struct RString *s, size_t capacity) #endif if (RSTR_EMBED_P(s)) { if (!RSTR_EMBEDDABLE_P(capacity)) { - str_init_normal_capa(mrb, s, s->as.ary, RSTR_EMBED_LEN(s), capacity); + str_init_normal_capa(mrb, s, RSTR_EMBED_PTR(s), RSTR_EMBED_LEN(s), capacity); } } else { |
