summaryrefslogtreecommitdiffhomepage
path: root/src/load.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2020-10-15 18:31:06 +0900
committerGitHub <[email protected]>2020-10-15 18:31:06 +0900
commit9cebddf9fe83ae0acde6f64f291fa3c9fc22880f (patch)
tree6f9ca4f2941c3da48a504c937719adca36e4cdfe /src/load.c
parent8c276f95be2f4e9deed73f08125a23a6746cb517 (diff)
parent21e07d61138a87891dc780efaa28e6c76a39378f (diff)
downloadmruby-9cebddf9fe83ae0acde6f64f291fa3c9fc22880f.tar.gz
mruby-9cebddf9fe83ae0acde6f64f291fa3c9fc22880f.zip
Merge pull request #5084 from mruby/mruby3
Mruby3
Diffstat (limited to 'src/load.c')
-rw-r--r--src/load.c191
1 files changed, 117 insertions, 74 deletions
diff --git a/src/load.c b/src/load.c
index 247d511df..c1a8c4c87 100644
--- a/src/load.c
+++ b/src/load.c
@@ -15,6 +15,7 @@
#include <mruby/debug.h>
#include <mruby/error.h>
#include <mruby/data.h>
+#include <mruby/endian.h>
#if SIZE_MAX < UINT32_MAX
# error size_t must be at least 32 bits wide
@@ -26,31 +27,32 @@
#define SIZE_ERROR_MUL(nmemb, size) ((size_t)(nmemb) > SIZE_MAX / (size))
static size_t
-skip_padding(const uint8_t *buf)
-{
- const size_t align = MRB_DUMP_ALIGNMENT;
- return -(intptr_t)buf & (align-1);
-}
-
-static size_t
offset_crc_body(void)
{
struct rite_binary_header header;
return ((uint8_t *)header.binary_crc - (uint8_t *)&header) + sizeof(header.binary_crc);
}
-#ifndef MRB_WITHOUT_FLOAT
-double mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck);
-
+#ifndef MRB_NO_FLOAT
static double
-str_to_double(mrb_state *mrb, const char *p, size_t len)
+str_to_double(mrb_state *mrb, const char *p)
{
- /* `i`, `inf`, `infinity` */
- if (len > 0 && p[0] == 'i') return INFINITY;
-
- /* `I`, `-inf`, `-infinity` */
- if (p[0] == 'I' || (len > 1 && p[0] == '-' && p[1] == 'i')) return -INFINITY;
- return mrb_str_len_to_dbl(mrb, p, len, TRUE);
+ /* dump IEEE754 little endian binary */
+ union {
+ char s[sizeof(double)];
+ double f;
+ } u;
+
+ if (littleendian) {
+ memcpy(u.s, p, sizeof(double));
+ }
+ else {
+ size_t i;
+ for (i=0; i<sizeof(double); i++) {
+ u.s[i] = p[sizeof(double)-i-1];
+ }
+ }
+ return u.f;
}
#endif
@@ -73,8 +75,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_irep *irep = mrb_add_irep(mrb);
+ mrb_pool_value *pool;
+ mrb_sym *syms;
int ai = mrb_gc_arena_save(mrb);
+ mrb_irep *irep = mrb_add_irep(mrb);
irep_obj->data = irep;
@@ -94,110 +98,137 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
src += sizeof(uint16_t);
/* Binary Data Section */
- /* ISEQ BLOCK */
- irep->ilen = (uint16_t)bin_to_uint32(src);
- src += sizeof(uint32_t);
- src += skip_padding(src);
+ /* ISEQ BLOCK (and CATCH HANDLER TABLE BLOCK) */
+ irep->clen = bin_to_uint16(src); /* number of catch handler */
+ src += sizeof(uint16_t);
+ irep->ilen = bin_to_uint16(src);
+ src += sizeof(uint16_t);
if (irep->ilen > 0) {
+ size_t data_len = sizeof(mrb_code) * irep->ilen +
+ sizeof(struct mrb_irep_catch_handler) * irep->clen;
+ mrb_static_assert1(sizeof(struct mrb_irep_catch_handler) == 7);
if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) {
return NULL;
}
if ((flags & FLAG_SRC_MALLOC) == 0) {
irep->iseq = (mrb_code*)src;
- src += sizeof(mrb_code) * irep->ilen;
irep->flags |= MRB_ISEQ_NO_FREE;
}
else {
- size_t data_len = sizeof(mrb_code) * irep->ilen;
void *buf = mrb_malloc(mrb, data_len);
irep->iseq = (mrb_code *)buf;
memcpy(buf, src, data_len);
- src += data_len;
}
+ src += data_len;
}
/* 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 = (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
- irep->pool[i] = num;
+ case IREP_TT_INT32:
+ {
+ mrb_int v = (int32_t)bin_to_uint32(src);
+ src += sizeof(uint32_t);
+#ifdef MRB_64BIT
+ pool[i].tt = IREP_TT_INT64;
+ pool[i].u.i64 = (int64_t)v;
#else
- irep->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_64BIT
+ {
+ 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;
+ }
+ break;
+#else
+ return NULL; /* INT64 not supported on MRB_32BIT */
+#endif
-#ifndef MRB_WITHOUT_FLOAT
case IREP_TT_FLOAT:
- irep->pool[i] = mrb_float_pool(mrb, str_to_double(mrb, s, pool_data_len));
+#ifndef MRB_NO_FLOAT
+ pool[i].tt = tt;
+ pool[i].u.f = str_to_double(mrb, (const char*)src);
+ src += sizeof(double);
break;
+#else
+ return NULL; /* MRB_NO_FLOAT */
#endif
- case IREP_TT_STRING:
- irep->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 */
- irep->pool[i] = mrb_nil_value();
- break;
+ return NULL;
}
- irep->plen++;
- mrb_gc_arena_restore(mrb, ai);
+ irep->plen = i+1;
}
}
/* SYMS BLOCK */
- irep->slen = (uint16_t)bin_to_uint32(src); /* syms length */
- src += sizeof(uint32_t);
+ irep->slen = bin_to_uint16(src); /* syms length */
+ src += sizeof(uint16_t);
if (irep->slen > 0) {
if (SIZE_ERROR_MUL(irep->slen, sizeof(mrb_sym))) {
return NULL;
}
- irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen);
+ irep->syms = syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen);
for (i = 0; i < irep->slen; i++) {
snl = bin_to_uint16(src); /* symbol name length */
src += sizeof(uint16_t);
if (snl == MRB_DUMP_NULL_SYM_LEN) {
- irep->syms[i] = 0;
+ syms[i] = 0;
continue;
}
if (flags & FLAG_SRC_MALLOC) {
- irep->syms[i] = mrb_intern(mrb, (char *)src, snl);
+ syms[i] = mrb_intern(mrb, (char *)src, snl);
}
else {
- irep->syms[i] = mrb_intern_static(mrb, (char *)src, snl);
+ syms[i] = mrb_intern_static(mrb, (char *)src, snl);
}
src += snl + 1;
-
mrb_gc_arena_restore(mrb, ai);
}
}
- irep->reps = (mrb_irep**)mrb_calloc(mrb, irep->rlen, sizeof(mrb_irep*));
-
diff = src - bin;
mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
*len = (size_t)diff;
@@ -213,6 +244,7 @@ read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
int ai = mrb_gc_arena_save(mrb);
mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags);
+ mrb_irep **reps;
int i;
mrb_gc_arena_restore(mrb, ai);
@@ -220,15 +252,17 @@ read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
return NULL;
}
+ reps = (mrb_irep**)mrb_calloc(mrb, irep->rlen, sizeof(mrb_irep*));
+ irep->reps = (const mrb_irep**)reps;
irep_obj->data = irep;
bin += *len;
for (i=0; i<irep->rlen; i++) {
size_t rlen;
- irep->reps[i] = read_irep_record(mrb, bin, &rlen, flags);
+ reps[i] = read_irep_record(mrb, bin, &rlen, flags);
mrb_gc_arena_restore(mrb, ai);
- if (irep->reps[i] == NULL) {
+ if (reps[i] == NULL) {
return NULL;
}
bin += rlen;
@@ -257,25 +291,26 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
size_t record_size;
uint16_t f_idx;
int i;
+ mrb_irep_debug_info *debug;
if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; }
- irep->debug_info = (mrb_irep_debug_info*)mrb_calloc(mrb, 1, sizeof(mrb_irep_debug_info));
- irep->debug_info->pc_count = (uint32_t)irep->ilen;
+ irep->debug_info = debug = (mrb_irep_debug_info*)mrb_calloc(mrb, 1, sizeof(mrb_irep_debug_info));
+ debug->pc_count = (uint32_t)irep->ilen;
record_size = (size_t)bin_to_uint32(bin);
bin += sizeof(uint32_t);
- irep->debug_info->flen = bin_to_uint16(bin);
- irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*));
+ debug->flen = bin_to_uint16(bin);
+ debug->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*));
bin += sizeof(uint16_t);
- for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
+ for (f_idx = 0; f_idx < debug->flen; ++f_idx) {
mrb_irep_debug_info_file *file;
uint16_t filename_idx;
file = (mrb_irep_debug_info_file *)mrb_calloc(mrb, 1, sizeof(*file));
- irep->debug_info->files[f_idx] = file;
+ debug->files[f_idx] = file;
file->start_pos = bin_to_uint32(bin);
bin += sizeof(uint32_t);
@@ -329,7 +364,7 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
size_t len;
int ret;
- ret = read_debug_record(mrb, bin, irep->reps[i], &len, filenames, filenames_len);
+ ret = read_debug_record(mrb, bin, (mrb_irep*)irep->reps[i], &len, filenames, filenames_len);
if (ret != MRB_DUMP_OK) return ret;
bin += len;
}
@@ -393,34 +428,31 @@ static int
read_lv_record(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, size_t *record_len, mrb_sym const *syms, uint32_t syms_len)
{
const uint8_t *bin = start;
+ mrb_sym *lv;
ptrdiff_t diff;
int i;
- irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (irep->nlocals - 1));
+ irep->lv = lv = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (irep->nlocals - 1));
for (i = 0; i + 1< irep->nlocals; ++i) {
uint16_t const sym_idx = bin_to_uint16(bin);
bin += sizeof(uint16_t);
if (sym_idx == RITE_LV_NULL_MARK) {
- irep->lv[i].name = 0;
- irep->lv[i].r = 0;
+ lv[i] = 0;
}
else {
if (sym_idx >= syms_len) {
return MRB_DUMP_GENERAL_FAILURE;
}
- irep->lv[i].name = syms[sym_idx];
-
- irep->lv[i].r = bin_to_uint16(bin);
+ lv[i] = syms[sym_idx];
}
- bin += sizeof(uint16_t);
}
for (i = 0; i < irep->rlen; ++i) {
size_t len;
int ret;
- ret = read_lv_record(mrb, bin, irep->reps[i], &len, syms, syms_len);
+ ret = read_lv_record(mrb, bin, (mrb_irep*)irep->reps[i], &len, syms, syms_len);
if (ret != MRB_DUMP_OK) return ret;
bin += len;
}
@@ -491,7 +523,12 @@ read_binary_header(const uint8_t *bin, size_t bufsize, size_t *bin_size, uint16_
return MRB_DUMP_INVALID_FILE_HEADER;
}
- if (memcmp(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)) != 0) {
+ /* if major version is different, they are incompatible */
+ if (memcmp(header->major_version, RITE_BINARY_MAJOR_VER, sizeof(header->major_version)) != 0) {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+ /* if minor version is different, we can accept the older version */
+ if (memcmp(header->minor_version, RITE_BINARY_MINOR_VER, sizeof(header->minor_version)) <= 0) {
return MRB_DUMP_INVALID_FILE_HEADER;
}
@@ -587,7 +624,7 @@ void mrb_exc_set(mrb_state *mrb, mrb_value exc);
static void
irep_error(mrb_state *mrb)
{
- mrb_exc_set(mrb, mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "irep load error"));
+ mrb_exc_set(mrb, mrb_exc_new_lit(mrb, E_SCRIPT_ERROR, "irep load error"));
}
void mrb_codedump_all(mrb_state*, struct RProc*);
@@ -642,6 +679,12 @@ mrb_load_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize)
return mrb_load_irep_buf_cxt(mrb, buf, bufsize, NULL);
}
+MRB_API mrb_value
+mrb_load_proc(mrb_state *mrb, const struct RProc *proc)
+{
+ return mrb_vm_run(mrb, proc, mrb_top_self(mrb), 0);
+}
+
#ifndef MRB_DISABLE_STDIO
mrb_irep*