summaryrefslogtreecommitdiffhomepage
path: root/src/dump.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 /src/dump.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 'src/dump.c')
-rw-r--r--src/dump.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/dump.c b/src/dump.c
index 6acba12c2..884c44dc6 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -274,12 +274,38 @@ write_syms_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf)
}
static size_t
+get_catch_table_block_size(mrb_state *mrb, const mrb_irep *irep)
+{
+ size_t size = 0;
+
+ size += sizeof(uint16_t); /* number of catch handler */
+ size += (sizeof(struct mrb_irep_catch_hander)) * irep->clen;
+
+ return size;
+}
+
+static ptrdiff_t
+write_catch_table_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf)
+{
+ uint8_t *cur = buf;
+ const struct mrb_irep_catch_hander *e = mrb_irep_catch_handler_table(irep);
+ mrb_static_assert1(sizeof(*e) == 7);
+
+ /* irep->clen has already been written before iseq block */
+ memcpy(cur, (const void *)e, sizeof(*e) * irep->clen);
+ cur += sizeof(*e) * irep->clen;
+
+ return cur - buf;
+}
+
+static size_t
get_irep_record_size_1(mrb_state *mrb, const mrb_irep *irep)
{
size_t size = 0;
size += get_irep_header_size(mrb);
size += get_iseq_block_size(mrb, irep);
+ size += get_catch_table_block_size(mrb, irep);
size += get_pool_block_size(mrb, irep);
size += get_syms_block_size(mrb, irep);
return size;
@@ -314,7 +340,13 @@ write_irep_record(mrb_state *mrb, const mrb_irep *irep, uint8_t *bin, size_t *ir
}
bin += write_irep_header(mrb, irep, bin);
+ /*
+ * The catch handler table is after iseq block, but the number of
+ * elements is placed before iseq block.
+ */
+ bin += uint16_to_bin(irep->clen, bin);
bin += write_iseq_block(mrb, irep, bin, flags);
+ bin += write_catch_table_block(mrb, irep, bin);
bin += write_pool_block(mrb, irep, bin);
bin += write_syms_block(mrb, irep, bin);