From a54a3df32c379a6953664f1d9241c731066915ec Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 24 May 2020 00:19:04 +0900 Subject: 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. --- include/mruby/irep.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'include') diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 0a5b3f1a3..430602279 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -39,13 +39,31 @@ typedef struct mrb_pool_value { } u; } mrb_pool_value; +enum mrb_catch_type { + MRB_CATCH_RESCUE = 0, + MRB_CATCH_ENSURE = 1, +}; + +struct mrb_irep_catch_hander { + uint8_t type; /* enum mrb_catch_type */ + uint8_t begin[2]; /* The starting address to match the hander. Includes this. */ + uint8_t end[2]; /* The endpoint address that matches the hander. Not Includes this. */ + uint8_t target[2]; /* The address to jump to if a match is made. */ +}; + /* Program data array struct */ typedef struct mrb_irep { uint16_t nlocals; /* Number of local variables */ uint16_t nregs; /* Number of register variables */ + uint16_t clen; /* Number of catch handlers */ uint8_t flags; const mrb_code *iseq; + /* + * A catch handler table is placed after the iseq entity. + * The reason it doesn't add fields to the structure is to keep the mrb_irep structure from bloating. + * The catch handler table can be obtained with `mrb_irep_catch_handler_table(irep)`. + */ const mrb_pool_value *pool; const mrb_sym *syms; const struct mrb_irep * const *reps; @@ -107,6 +125,17 @@ struct mrb_insn_data { struct mrb_insn_data mrb_decode_insn(const mrb_code *pc); +static inline const struct mrb_irep_catch_hander * +mrb_irep_catch_handler_table(const struct mrb_irep *irep) +{ + if (irep->clen > 0) { + return (const struct mrb_irep_catch_hander *)(irep->iseq + irep->ilen); + } + else { + return (const struct mrb_irep_catch_hander *)NULL; + } +} + MRB_END_DECL #endif /* MRUBY_IREP_H */ -- cgit v1.2.3