summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler/core/codegen.c
diff options
context:
space:
mode:
authordearblue <[email protected]>2020-05-24 00:19:04 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2020-10-12 16:21:32 +0900
commita54a3df32c379a6953664f1d9241c731066915ec (patch)
tree37ef8811bfe2aaf8533253f6a1025a35bdc58d4d /mrbgems/mruby-compiler/core/codegen.c
parent3ad6bbc40c87f24819c6d8f25446bc74d348c822 (diff)
downloadmruby-a54a3df32c379a6953664f1d9241c731066915ec.tar.gz
mruby-a54a3df32c379a6953664f1d9241c731066915ec.zip
Extended mruby binary format
The catch handler table is combined with iseq block. This is to prevent the structure from growing by adding a field for the catch handler table to the `mrb_irep` structure. "iseq block" and "catch handler table": [number of catch handler table (2 bytes)] [number of byte code (4 bytes)] [iseq (any bytes)] [catch handlers (multiple of 7 bytes)] catch handler: [catch type (1 byte)] [begin offset (2 bytes)] [end offset (2 bytes)] [target offset (2 bytes)] catch type: enum mrb_catch_type (0 = rescue, 1 = ensure) begin offset: Includes the specified instruction address end offset: Does not include the specified instruction address target offset: replaces pc with the specified instruction address This table is not expanded by `read_irep_record_1()`. The necessary elements are expanded one by one when used.
Diffstat (limited to 'mrbgems/mruby-compiler/core/codegen.c')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 191895668..e55b6791d 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -11,6 +11,7 @@
#include <mruby.h>
#include <mruby/compile.h>
#include <mruby/proc.h>
+#include <mruby/dump.h>
#include <mruby/numeric.h>
#include <mruby/string.h>
#include <mruby/debug.h>
@@ -72,6 +73,7 @@ typedef struct scope {
mrb_pool_value *pool;
mrb_sym *syms;
mrb_irep **reps;
+ struct mrb_irep_catch_hander *catch_table;
uint32_t pcapa, scapa, rcapa;
uint16_t nlocals;
@@ -91,6 +93,15 @@ static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
static void loop_break(codegen_scope *s, node *tree);
static void loop_pop(codegen_scope *s, int val);
+/*
+ * The search for catch handlers starts at the end of the table in mrb_vm_run().
+ * Therefore, the next handler to be added must meet one of the following conditions.
+ * - Larger start position
+ * - Same start position but smaller end position
+ */
+static int catch_hander_new(codegen_scope *s);
+static void catch_hander_set(codegen_scope *s, int ent, enum mrb_catch_type type, uint32_t begin, uint32_t end, uint32_t target);
+
static void gen_assignment(codegen_scope *s, node *tree, int sp, int val);
static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
@@ -3082,9 +3093,18 @@ scope_finish(codegen_scope *s)
}
irep->flags = 0;
if (s->iseq) {
- irep->iseq = (const mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
+ size_t catchsize = sizeof(struct mrb_irep_catch_hander) * irep->clen;
+ irep->iseq = (const mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc + catchsize);
irep->ilen = s->pc;
+ if (irep->clen > 0) {
+ memcpy((void *)(irep->iseq + irep->ilen), s->catch_table, catchsize);
+ }
}
+ else {
+ irep->clen = 0;
+ }
+ mrb_free(s->mrb, s->catch_table);
+ s->catch_table = NULL;
irep->pool = (const mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*irep->plen);
irep->syms = (const mrb_sym*)codegen_realloc(s, s->syms, sizeof(mrb_sym)*irep->slen);
irep->reps = (const mrb_irep**)codegen_realloc(s, s->reps, sizeof(mrb_irep*)*irep->rlen);
@@ -3187,6 +3207,31 @@ loop_pop(codegen_scope *s, int val)
if (val) push();
}
+static int
+catch_hander_new(codegen_scope *s)
+{
+ size_t newsize = sizeof(struct mrb_irep_catch_hander) * (s->irep->clen + 1);
+ s->catch_table = (struct mrb_irep_catch_hander *)codegen_realloc(s, (void *)s->catch_table, newsize);
+ return s->irep->clen ++;
+}
+
+static void
+catch_hander_set(codegen_scope *s, int ent, enum mrb_catch_type type, uint32_t begin, uint32_t end, uint32_t target)
+{
+ struct mrb_irep_catch_hander *e;
+
+ mrb_assert(ent >= 0 && ent < s->irep->clen);
+ mrb_assert(begin < MAXARG_S);
+ mrb_assert(end < MAXARG_S);
+ mrb_assert(target < MAXARG_S);
+
+ e = &s->catch_table[ent];
+ uint8_to_bin(type, &e->type);
+ uint16_to_bin(begin, e->begin);
+ uint16_to_bin(end, e->end);
+ uint16_to_bin(target, e->target);
+}
+
static struct RProc*
generate_code(mrb_state *mrb, parser_state *p, int val)
{