summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2020-06-09 14:39:38 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2020-10-12 16:21:08 +0900
commitd428fa0c4acfe4f70ab534d420052c193bd83281 (patch)
tree903e5ab41d1c358e3b512be90d36837e54580e29 /src
parentdaa37be5495393ce3e4654e00e44099f627e6cd4 (diff)
downloadmruby-d428fa0c4acfe4f70ab534d420052c193bd83281.tar.gz
mruby-d428fa0c4acfe4f70ab534d420052c193bd83281.zip
Replace entire `irep->pool`.
Changes: - `pool format is completely replaced - supported types: `STR`, `INT32`, `INT64`, `FLOAT` - `FLOAT` may be replaced by binary representation in the future - insert `NUL` after string literals in `mrb` files - `irep->pool` no longer store values in `mrb_value` - instead it stores in `mrb_pool_value` - less allocation - `mrb_irep` can be stored in ROM
Diffstat (limited to 'src')
-rw-r--r--src/codedump.c37
-rw-r--r--src/dump.c123
-rw-r--r--src/etc.c11
-rw-r--r--src/load.c77
-rw-r--r--src/state.c16
-rw-r--r--src/string.c26
-rw-r--r--src/vm.c43
7 files changed, 183 insertions, 150 deletions
diff --git a/src/codedump.c b/src/codedump.c
index 14cca8553..fd73f3104 100644
--- a/src/codedump.c
+++ b/src/codedump.c
@@ -115,10 +115,21 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
print_lv_ab(mrb, irep, a, b);
break;
CASE(OP_LOADL, BB):
- {
- mrb_value v = irep->pool[b];
- mrb_value s = mrb_inspect(mrb, v);
- printf("OP_LOADL\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
+ switch (irep->pool[b].tt) {
+ case IREP_TT_FLOAT:
+ printf("OP_LOADL\tR%d\tL(%d)\t; %f", a, b, (double)irep->pool[b].u.f);
+ break;
+ case IREP_TT_INT32:
+ printf("OP_LOADL\tR%d\tL(%d)\t; %" PRId32, a, b, irep->pool[b].u.i32);
+ break;
+#ifdef MRB_INT64
+ case IREP_TT_INT64:
+ printf("OP_LOADL\tR%d\tL(%d)\t; %" PRId64, a, b, irep->pool[b].u.i64);
+ break;
+#endif
+ default:
+ printf("OP_LOADL\tR%d\tL(%d)\t", a, b);
+ break;
}
print_lv_a(mrb, irep, a);
break;
@@ -404,10 +415,11 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
print_lv_a(mrb, irep, a);
break;
CASE(OP_STRING, BB):
- {
- mrb_value v = irep->pool[b];
- mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
- printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
+ if ((irep->pool[b].tt & IREP_TT_NFLAG) == 0) {
+ printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, irep->pool[b].u.str);
+ }
+ else {
+ printf("OP_STRING\tR%d\tL(%d)\t", a, b);
}
print_lv_a(mrb, irep, a);
break;
@@ -453,10 +465,11 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
print_lv_a(mrb, irep, a);
break;
CASE(OP_ERR, B):
- {
- mrb_value v = irep->pool[a];
- mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
- printf("OP_ERR\t%s\n", RSTRING_PTR(s));
+ if ((irep->pool[a].tt & IREP_TT_NFLAG) == 0) {
+ printf("OP_ERR\t%s\n", irep->pool[a].u.str);
+ }
+ else {
+ printf("OP_ERR\tL(%d)\n", a);
}
break;
CASE(OP_EPUSH, B):
diff --git a/src/dump.c b/src/dump.c
index 093e4c256..a1c539e50 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -90,14 +90,12 @@ write_iseq_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf, uint8_t fla
#ifndef MRB_WITHOUT_FLOAT
static mrb_value
-float_to_str(mrb_state *mrb, mrb_value flt)
+float_to_str(mrb_state *mrb, mrb_float f)
{
- mrb_float f = mrb_float(flt);
-
if (isinf(f)) {
return f < 0 ? mrb_str_new_lit(mrb, "I") : mrb_str_new_lit(mrb, "i");
}
- return mrb_float_to_str(mrb, flt, MRB_FLOAT_FMT);
+ return mrb_float_to_str(mrb, mrb_float_value(mrb, f), MRB_FLOAT_FMT);
}
#endif
@@ -106,45 +104,50 @@ get_pool_block_size(mrb_state *mrb, const mrb_irep *irep)
{
int pool_no;
size_t size = 0;
- mrb_value str;
- size += sizeof(uint32_t); /* plen */
- size += irep->plen * (sizeof(uint8_t) + sizeof(uint16_t)); /* len(n) */
+ size += sizeof(uint16_t); /* plen */
+ size += irep->plen * sizeof(uint8_t); /* len(n) */
for (pool_no = 0; pool_no < irep->plen; pool_no++) {
int ai = mrb_gc_arena_save(mrb);
- switch (mrb_type(irep->pool[pool_no])) {
- case MRB_TT_FIXNUM:
- str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
+ switch (irep->pool[pool_no].tt) {
+ case IREP_TT_INT64:
+#ifdef MRB_INT64
{
- mrb_int len = RSTRING_LEN(str);
- mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
- size += (size_t)len;
+ int64_t i = irep->pool[pool_no].u.i64;
+
+ if (i < INT32_MIN || INT32_MAX < i)
+ size += 8;
+ else
+ size += 4;
}
break;
+#else
+ /* fall through */
+#endif
+ case IREP_TT_INT32:
+ size += 4; /* 32bits = 4bytes */
+ break;
+ case IREP_TT_FLOAT:
#ifndef MRB_WITHOUT_FLOAT
- case MRB_TT_FLOAT:
- str = float_to_str(mrb, irep->pool[pool_no]);
{
+ mrb_value str = float_to_str(mrb, irep->pool[pool_no].u.f);
mrb_int len = RSTRING_LEN(str);
mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
size += (size_t)len;
}
- break;
#endif
+ break;
- case MRB_TT_STRING:
+ default: /* packed IREP_TT_STRING */
{
- mrb_int len = RSTRING_LEN(irep->pool[pool_no]);
+ mrb_int len = irep->pool[pool_no].tt >> 1; /* unpack length */
mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
- size += (size_t)len;
+ size += (size_t)len+1;
}
break;
-
- default:
- break;
}
mrb_gc_arena_restore(mrb, ai);
}
@@ -157,48 +160,64 @@ write_pool_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf)
{
int pool_no;
uint8_t *cur = buf;
- uint16_t len;
- mrb_value str;
- const char *char_ptr;
+ int len;
+ const char *ptr;
- cur += uint32_to_bin(irep->plen, cur); /* number of pool */
+ cur += uint16_to_bin(irep->plen, cur); /* number of pool */
for (pool_no = 0; pool_no < irep->plen; pool_no++) {
int ai = mrb_gc_arena_save(mrb);
- switch (mrb_type(irep->pool[pool_no])) {
- case MRB_TT_FIXNUM:
- cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */
- str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
+ switch (irep->pool[pool_no].tt) {
+#ifdef MRB_INT64
+ case IREP_TT_INT64:
+ {
+ int64_t i = irep->pool[pool_no].u.i64;
+ if (i < INT32_MIN || INT32_MAX < i) {
+ cur += uint8_to_bin(IREP_TT_INT64, cur); /* data type */
+ cur += uint32_to_bin((uint32_t)((i>>32) & 0xffffffff), cur); /* i64 hi */
+ cur += uint32_to_bin((uint32_t)((i ) & 0xffffffff), cur); /* i64 lo */
+ }
+ else {
+ cur += uint8_to_bin(IREP_TT_INT32, cur); /* data type */
+ cur += uint32_to_bin(irep->pool[pool_no].u.i32, cur); /* i32 */
+ }
+ }
+ break;
+#endif
+ case IREP_TT_INT32:
+ cur += uint8_to_bin(IREP_TT_INT32, cur); /* data type */
+ cur += uint32_to_bin(irep->pool[pool_no].u.i32, cur); /* i32 */
break;
-#ifndef MRB_WITHOUT_FLOAT
- case MRB_TT_FLOAT:
+ case IREP_TT_FLOAT:
cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */
- str = float_to_str(mrb, irep->pool[pool_no]);
- break;
+#ifndef MRB_WITHOUT_FLOAT
+ {
+ mrb_value str = float_to_str(mrb, irep->pool[pool_no].u.f);
+ ptr = RSTRING_PTR(str);
+ len = RSTRING_LEN(str);
+ mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX);
+ cur += uint16_to_bin((uint16_t)len, cur); /* data length */
+ memcpy(cur, ptr, (size_t)len);
+ cur += len;
+ }
+#else
+ cur += uint16_to_bin(0, cur); /* zero length */
#endif
-
- case MRB_TT_STRING:
- cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */
- str = irep->pool[pool_no];
break;
- default:
- continue;
- }
-
- char_ptr = RSTRING_PTR(str);
- {
- mrb_int tlen = RSTRING_LEN(str);
- mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX);
- len = (uint16_t)tlen;
+ default: /* string */
+ cur += uint8_to_bin(IREP_TT_STR, cur); /* data type */
+ ptr = irep->pool[pool_no].u.str;
+ len = irep->pool[pool_no].tt>>2;
+ mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX);
+ cur += uint16_to_bin((uint16_t)len, cur); /* data length */
+ memcpy(cur, ptr, (size_t)len);
+ cur += len;
+ *cur++ = '\0';
+ break;
}
-
- cur += uint16_to_bin(len, cur); /* data length */
- memcpy(cur, char_ptr, (size_t)len);
- cur += len;
-
mrb_gc_arena_restore(mrb, ai);
}
diff --git a/src/etc.c b/src/etc.c
index 74b9ab03b..99cdc0157 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -158,17 +158,6 @@ mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f)
MRB_SET_FROZEN_FLAG(v.value.bp);
return v;
}
-
-MRB_API mrb_value
-mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f)
-{
- struct RFloat *nf = (struct RFloat *)mrb_malloc(mrb, sizeof(struct RFloat));
- nf->tt = MRB_TT_FLOAT;
- nf->c = mrb->float_class;
- nf->f = f;
- MRB_SET_FROZEN_FLAG(nf);
- return mrb_obj_value(nf);
-}
#endif /* MRB_WITHOUT_FLOAT */
#endif /* MRB_WORD_BOXING */
diff --git a/src/load.c b/src/load.c
index d47027350..39644c34b 100644
--- a/src/load.c
+++ b/src/load.c
@@ -73,10 +73,10 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
uint16_t tt, pool_data_len, snl;
int plen;
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
- mrb_value *pool;
+ mrb_pool_value *pool;
mrb_sym *syms;
+ mrb_int ai = mrb_gc_arena_save(mrb);
mrb_irep *irep = mrb_add_irep(mrb);
- int ai = mrb_gc_arena_save(mrb);
irep_obj->data = irep;
@@ -120,51 +120,81 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
}
/* POOL BLOCK */
- plen = bin_to_uint32(src); /* number of pool */
- src += sizeof(uint32_t);
+ plen = bin_to_uint16(src); /* number of pool */
+ src += sizeof(uint16_t);
if (plen > 0) {
if (SIZE_ERROR_MUL(plen, sizeof(mrb_value))) {
return NULL;
}
- irep->pool = pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * plen);
+ irep->pool = pool = (mrb_pool_value*)mrb_calloc(mrb, sizeof(mrb_pool_value), plen);
for (i = 0; i < plen; i++) {
- const char *s;
mrb_bool st = (flags & FLAG_SRC_MALLOC)==0;
tt = *src++; /* pool TT */
- pool_data_len = bin_to_uint16(src); /* pool data length */
- src += sizeof(uint16_t);
- s = (const char*)src;
- src += pool_data_len;
switch (tt) { /* pool data */
- case IREP_TT_FIXNUM: {
- mrb_value num = mrb_str_len_to_inum(mrb, s, pool_data_len, 10, FALSE);
-#ifdef MRB_WITHOUT_FLOAT
- pool[i] = num;
+ case IREP_TT_INT32:
+ {
+ mrb_int v = (int32_t)bin_to_uint32(src);
+ src += sizeof(uint32_t);
+#ifdef MRB_INT64
+ pool[i].tt = IREP_TT_INT64;
+ pool[i].u.i64 = (int64_t)v;
#else
- pool[i] = mrb_float_p(num)? mrb_float_pool(mrb, mrb_float(num)) : num;
+ pool[i].tt = IREP_TT_INT32;
+ pool[i].u.i32 = v;
#endif
}
break;
+ case IREP_TT_INT64:
+#ifdef MRB_INT64
+ {
+ uint64_t i = bin_to_uint32(src);
+ src += sizeof(uint32_t);
+ i <<= 32;
+ i |= bin_to_uint32(src);
+ src += sizeof(uint32_t);
+ pool[i].u.i64 = (int64_t)i;
+ }
+#else
+ return NULL; /* INT64 not supported on MRB_INT32 */
+#endif
+ break;
-#ifndef MRB_WITHOUT_FLOAT
case IREP_TT_FLOAT:
- pool[i] = mrb_float_pool(mrb, str_to_double(mrb, s, pool_data_len));
+#ifndef MRB_WITHOUT_FLOAT
+ pool[i].tt = tt;
+ pool_data_len = bin_to_uint16(src); /* pool data length */
+ src += sizeof(uint16_t);
+ pool[i].u.f = str_to_double(mrb, (const char*)src, pool_data_len);
+ src += pool_data_len;
break;
+#else
+ return NULL; /* MRB_WITHOUT_FLOAT */
#endif
- case IREP_TT_STRING:
- pool[i] = mrb_str_pool(mrb, s, pool_data_len, st);
+ case IREP_TT_STR:
+ pool_data_len = bin_to_uint16(src); /* pool data length */
+ src += sizeof(uint16_t);
+ if (st) {
+ pool[i].tt = (pool_data_len<<2) | IREP_TT_SSTR;
+ pool[i].u.str = (const char*)src;
+ }
+ else {
+ char *p;
+ pool[i].tt = (pool_data_len<<2) | IREP_TT_STR;
+ p = (char*)mrb_malloc(mrb, pool_data_len+1);
+ memcpy(p, src, pool_data_len+1);
+ pool[i].u.str = (const char*)p;
+ }
+ src += pool_data_len + 1;
break;
default:
/* should not happen */
- pool[i] = mrb_nil_value();
- break;
+ return NULL;
}
- irep->plen++;
- mrb_gc_arena_restore(mrb, ai);
+ irep->plen = i+1;
}
}
@@ -193,7 +223,6 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
syms[i] = mrb_intern_static(mrb, (char *)src, snl);
}
src += snl + 1;
-
mrb_gc_arena_restore(mrb, ai);
}
}
diff --git a/src/state.c b/src/state.c
index 323532363..7a1283fa6 100644
--- a/src/state.c
+++ b/src/state.c
@@ -144,18 +144,14 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
if (irep->flags & MRB_IREP_NO_FREE) return;
if (!(irep->flags & MRB_ISEQ_NO_FREE))
mrb_free(mrb, (void*)irep->iseq);
- if (irep->pool) for (i=0; i<irep->plen; i++) {
- if (mrb_string_p(irep->pool[i])) {
- mrb_gc_free_str(mrb, RSTRING(irep->pool[i]));
- mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
+ if (irep->pool) {
+ for (i=0; i<irep->plen; i++) {
+ if ((irep->pool[i].tt & 3) == IREP_TT_STR) {
+ mrb_free(mrb, (void*)irep->pool[i].u.str);
+ }
}
-#if defined(MRB_WORD_BOXING) && !defined(MRB_WITHOUT_FLOAT)
- else if (mrb_float_p(irep->pool[i])) {
- mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
- }
-#endif
+ mrb_free(mrb, (void*)irep->pool);
}
- mrb_free(mrb, (void*)irep->pool);
mrb_free(mrb, (void*)irep->syms);
if (irep->reps) {
for (i=0; i<irep->rlen; i++) {
diff --git a/src/string.c b/src/string.c
index 97795221c..73e514f41 100644
--- a/src/string.c
+++ b/src/string.c
@@ -583,9 +583,6 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s)
else if (RSTR_FSHARED_P(orig)) {
str_init_fshared(orig, s, orig->as.heap.aux.fshared);
}
- else if (mrb_frozen_p(orig) && !RSTR_POOL_P(orig)) {
- str_init_fshared(orig, s, orig);
- }
else {
if (orig->as.heap.aux.capa > orig->as.heap.len) {
orig->as.heap.ptr = (char *)mrb_realloc(mrb, orig->as.heap.ptr, len+1);
@@ -597,29 +594,6 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s)
}
mrb_value
-mrb_str_pool(mrb_state *mrb, const char *p, mrb_int len, mrb_bool nofree)
-{
- struct RString *s = (struct RString *)mrb_malloc(mrb, sizeof(struct RString));
-
- s->tt = MRB_TT_STRING;
- s->c = mrb->string_class;
- s->flags = 0;
-
- if (RSTR_EMBEDDABLE_P(len)) {
- str_init_embed(s, p, len);
- }
- else if (nofree) {
- str_init_nofree(s, p, len);
- }
- else {
- str_init_normal(mrb, s, p, len);
- }
- RSTR_SET_POOL_FLAG(s);
- MRB_SET_FROZEN_FLAG(s);
- return mrb_obj_value(s);
-}
-
-mrb_value
mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
struct RString *orig, *s;
diff --git a/src/vm.c b/src/vm.c
index 064086fb9..c3fa12d3d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -966,7 +966,7 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *pc)
/* mrb_assert(MRB_PROC_CFUNC_P(proc)) */
const mrb_code *pc0 = pc;
const mrb_irep *irep = proc->body.irep;
- const mrb_value *pool = irep->pool;
+ const mrb_pool_value *pool = irep->pool;
const mrb_sym *syms = irep->syms;
mrb_code insn;
int ai = mrb_gc_arena_save(mrb);
@@ -1013,17 +1013,25 @@ RETRY_TRY_BLOCK:
}
CASE(OP_LOADL, BB) {
-#ifdef MRB_WORD_BOXING
- mrb_value val = pool[b];
-#ifndef MRB_WITHOUT_FLOAT
- if (mrb_float_p(val)) {
- val = mrb_float_value(mrb, mrb_float(val));
- }
+ switch (pool[b].tt) { /* number */
+ case IREP_TT_INT32:
+ regs[a] = mrb_fixnum_value((mrb_int)pool[b].u.i32);
+ break;
+#ifdef MRB_INT64
+ case IREP_TT_INT64:
+ regs[a] = mrb_fixnum_value((mrb_int)pool[b].u.i64);
+ break;
#endif
- regs[a] = val;
-#else
- regs[a] = pool[b];
+#ifndef MRB_WITHOUT_FLOAT
+ case IREP_TT_FLOAT:
+ regs[a] = mrb_float_value(mrb, pool[b].u.f);
+ break;
#endif
+ default:
+ /* should not happen (tt:string) */
+ regs[a] = mrb_nil_value();
+ break;
+ }
NEXT;
}
@@ -2499,9 +2507,13 @@ RETRY_TRY_BLOCK:
}
CASE(OP_STRING, BB) {
- mrb_value str = mrb_str_dup(mrb, pool[b]);
-
- regs[a] = str;
+ size_t len = pool[b].tt >> 2;
+ if (pool[b].tt & IREP_TT_SFLAG) {
+ regs[a] = mrb_str_new_static(mrb, pool[b].u.str, len);
+ }
+ else {
+ regs[a] = mrb_str_new(mrb, pool[b].u.str, len);
+ }
mrb_gc_arena_restore(mrb, ai);
NEXT;
}
@@ -2703,10 +2715,11 @@ RETRY_TRY_BLOCK:
}
CASE(OP_ERR, B) {
- mrb_value msg = mrb_str_dup(mrb, pool[a]);
+ size_t len = pool[a].tt >> 2;
mrb_value exc;
- exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
+ mrb_assert((pool[a].tt&IREP_TT_NFLAG)==0);
+ exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, pool[a].u.str, len);
ERR_PC_SET(mrb);
mrb_exc_set(mrb, exc);
goto L_RAISE;