mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Make OP_JMP* operand address to be relative.
Jump target address is `operand (16bit)` + `address of next instruction`. In addition, `ilen` was made `uint32_t` so that `iseq` length limitation of 65536 is removed. Only jump target address should be within signed 16bit (-32768 .. 32767).
This commit is contained in:
@@ -137,6 +137,11 @@ No more operand extention
|
||||
* `OP_EXT2`
|
||||
* `OP_EXT3`
|
||||
|
||||
## Changed Instructions
|
||||
|
||||
Jump addresses used to be specified by absolute offset from the start of `iseq`. Now they are relative offset from the address of the next instruction.
|
||||
|
||||
|
||||
## `Random` now use `xoshiro128++`.
|
||||
|
||||
For better and faster random number generation.
|
||||
|
||||
@@ -73,7 +73,8 @@ typedef struct mrb_irep {
|
||||
/* debug info */
|
||||
struct mrb_irep_debug_info* debug_info;
|
||||
|
||||
uint16_t ilen, plen, slen;
|
||||
uint32_t ilen;
|
||||
uint16_t plen, slen;
|
||||
uint8_t rlen;
|
||||
uint32_t refcnt;
|
||||
} mrb_irep;
|
||||
|
||||
+4
-4
@@ -49,10 +49,10 @@ OPCODE(GETMCNST, BB) /* R(a) = R(a)::Syms(b) */
|
||||
OPCODE(SETMCNST, BB) /* R(a+1)::Syms(b) = R(a) */
|
||||
OPCODE(GETUPVAR, BBB) /* R(a) = uvget(b,c) */
|
||||
OPCODE(SETUPVAR, BBB) /* uvset(b,c,R(a)) */
|
||||
OPCODE(JMP, S) /* pc=a */
|
||||
OPCODE(JMPIF, BS) /* if R(a) pc=b */
|
||||
OPCODE(JMPNOT, BS) /* if !R(a) pc=b */
|
||||
OPCODE(JMPNIL, BS) /* if R(a)==nil pc=b */
|
||||
OPCODE(JMP, S) /* pc+=a */
|
||||
OPCODE(JMPIF, BS) /* if R(a) pc+=b */
|
||||
OPCODE(JMPNOT, BS) /* if !R(a) pc+=b */
|
||||
OPCODE(JMPNIL, BS) /* if R(a)==nil pc+=b */
|
||||
OPCODE(JMPUW, S) /* unwind_and_jump_to(a) */
|
||||
OPCODE(EXCEPT, B) /* R(a) = exc */
|
||||
OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */
|
||||
|
||||
@@ -39,7 +39,8 @@ enum looptype {
|
||||
|
||||
struct loopinfo {
|
||||
enum looptype type;
|
||||
int pc0, pc1, pc2, pc3, acc;
|
||||
uint32_t pc0, pc1, pc2, pc3;
|
||||
int acc;
|
||||
struct loopinfo *prev;
|
||||
};
|
||||
|
||||
@@ -53,9 +54,9 @@ typedef struct scope {
|
||||
node *lv;
|
||||
|
||||
uint16_t sp;
|
||||
uint16_t pc;
|
||||
uint16_t lastpc;
|
||||
uint16_t lastlabel;
|
||||
uint32_t pc;
|
||||
uint32_t lastpc;
|
||||
uint32_t lastlabel;
|
||||
int ainfo:15;
|
||||
mrb_bool mscope:1;
|
||||
|
||||
@@ -168,13 +169,15 @@ new_label(codegen_scope *s)
|
||||
static void
|
||||
emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
|
||||
{
|
||||
if (pc >= MAXARG_S || s->icapa >= MAXARG_S) {
|
||||
codegen_error(s, "too big code block");
|
||||
}
|
||||
if (pc >= s->icapa) {
|
||||
s->icapa *= 2;
|
||||
if (s->icapa > MAXARG_S) {
|
||||
s->icapa = MAXARG_S;
|
||||
if (pc == UINT32_MAX) {
|
||||
codegen_error(s, "too big code block");
|
||||
}
|
||||
if (pc >= UINT32_MAX / 2) {
|
||||
pc = UINT32_MAX;
|
||||
}
|
||||
else {
|
||||
s->icapa *= 2;
|
||||
}
|
||||
s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
|
||||
if (s->lines) {
|
||||
@@ -358,22 +361,39 @@ no_peephole(codegen_scope *s)
|
||||
return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
genjmp(codegen_scope *s, mrb_code i, uint16_t pc)
|
||||
static void
|
||||
gen_jmpdst(codegen_scope *s, uint32_t pc)
|
||||
{
|
||||
uint16_t pos;
|
||||
if (pc == 0) {
|
||||
gen_S(s, 0);
|
||||
}
|
||||
else {
|
||||
uint32_t pos2 = s->pc+2;
|
||||
int32_t off = pc - pos2;
|
||||
|
||||
if (off > INT16_MAX || INT16_MIN > off) {
|
||||
codegen_error(s, "too big jmp offset");
|
||||
}
|
||||
gen_S(s, (uint16_t)off);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
genjmp(codegen_scope *s, mrb_code i, uint32_t pc)
|
||||
{
|
||||
uint32_t pos;
|
||||
|
||||
s->lastpc = s->pc;
|
||||
gen_B(s, i);
|
||||
pos = s->pc;
|
||||
gen_S(s, pc);
|
||||
gen_jmpdst(s, pc);
|
||||
return pos;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val)
|
||||
static uint32_t
|
||||
genjmp2(codegen_scope *s, mrb_code i, uint16_t a, uint32_t pc, int val)
|
||||
{
|
||||
uint16_t pos;
|
||||
uint32_t pos;
|
||||
|
||||
if (!no_peephole(s) && !val) {
|
||||
struct mrb_insn_data data = mrb_last_insn(s);
|
||||
@@ -393,7 +413,7 @@ genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val)
|
||||
gen_B(s, i);
|
||||
gen_B(s, (uint8_t)a);
|
||||
pos = s->pc;
|
||||
gen_S(s, pc);
|
||||
gen_jmpdst(s, pc);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
@@ -496,19 +516,26 @@ gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dispatch(codegen_scope *s, uint16_t pos0)
|
||||
static uint32_t
|
||||
dispatch(codegen_scope *s, uint32_t pos0)
|
||||
{
|
||||
uint16_t newpos;
|
||||
int32_t pos1 = pos0 + 2;
|
||||
int32_t offset;
|
||||
int16_t newpos;
|
||||
|
||||
offset = s->pc - pos1;
|
||||
if (offset > INT16_MAX) {
|
||||
codegen_error(s, "too big jmp offset");
|
||||
}
|
||||
s->lastlabel = s->pc;
|
||||
newpos = PEEK_S(s->iseq+pos0);
|
||||
emit_S(s, pos0, s->pc);
|
||||
return newpos;
|
||||
newpos = (int16_t)PEEK_S(s->iseq+pos0);
|
||||
emit_S(s, pos0, (uint16_t)offset);
|
||||
if (newpos == 0) return 0;
|
||||
return pos1+newpos;
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_linked(codegen_scope *s, uint16_t pos)
|
||||
dispatch_linked(codegen_scope *s, uint32_t pos)
|
||||
{
|
||||
if (pos==0) return;
|
||||
for (;;) {
|
||||
@@ -1464,7 +1491,8 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
|
||||
case NODE_RESCUE:
|
||||
{
|
||||
int noexc, exend, pos1, pos2, tmp;
|
||||
int noexc;
|
||||
uint32_t exend, pos1, pos2, tmp;
|
||||
struct loopinfo *lp;
|
||||
int catch_entry, begin, end;
|
||||
|
||||
@@ -1739,7 +1767,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
case NODE_CASE:
|
||||
{
|
||||
int head = 0;
|
||||
int pos1, pos2, pos3, tmp;
|
||||
uint32_t pos1, pos2, pos3, tmp;
|
||||
node *n;
|
||||
|
||||
pos3 = 0;
|
||||
@@ -1782,7 +1810,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
tree = tree->cdr;
|
||||
}
|
||||
if (val) {
|
||||
int pos = cursp();
|
||||
uint32_t pos = cursp();
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
if (pos3) dispatch_linked(s, pos3);
|
||||
if (head) pop();
|
||||
|
||||
+10
-5
@@ -271,21 +271,26 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_JMP, S);
|
||||
printf("OP_JMP\t\t%03d\n", a);
|
||||
i = pc - irep->iseq;
|
||||
printf("OP_JMP\t\t%03d\n", (int)i+(int16_t)a);
|
||||
break;
|
||||
CASE(OP_JMPUW, S);
|
||||
printf("OP_JMPUW\t\t%03d\n", a);
|
||||
i = pc - irep->iseq;
|
||||
printf("OP_JMPUW\t\t%03d\n", (int)i+(int16_t)a);
|
||||
break;
|
||||
CASE(OP_JMPIF, BS);
|
||||
printf("OP_JMPIF\tR%d\t%03d\t", a, b);
|
||||
i = pc - irep->iseq;
|
||||
printf("OP_JMPIF\tR%d\t%03d\t", a, (int)i+(int16_t)b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_JMPNOT, BS);
|
||||
printf("OP_JMPNOT\tR%d\t%03d\t", a, b);
|
||||
i = pc - irep->iseq;
|
||||
printf("OP_JMPNOT\tR%d\t%03d\t", a, (int)i+(int16_t)b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_JMPNIL, BS);
|
||||
printf("OP_JMPNIL\tR%d\t%03d\t", a, b);
|
||||
i = pc - irep->iseq;
|
||||
printf("OP_JMPNIL\tR%d\t%03d\t", a, (int)i+(int16_t)b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_SENDV, BB);
|
||||
|
||||
@@ -1274,26 +1274,26 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_JMP, S) {
|
||||
pc = irep->iseq+a;
|
||||
pc += (int16_t)a;
|
||||
JUMP;
|
||||
}
|
||||
CASE(OP_JMPIF, BS) {
|
||||
if (mrb_test(regs[a])) {
|
||||
pc = irep->iseq+b;
|
||||
pc += (int16_t)b;
|
||||
JUMP;
|
||||
}
|
||||
NEXT;
|
||||
}
|
||||
CASE(OP_JMPNOT, BS) {
|
||||
if (!mrb_test(regs[a])) {
|
||||
pc = irep->iseq+b;
|
||||
pc += (int16_t)b;
|
||||
JUMP;
|
||||
}
|
||||
NEXT;
|
||||
}
|
||||
CASE(OP_JMPNIL, BS) {
|
||||
if (mrb_nil_p(regs[a])) {
|
||||
pc = irep->iseq+b;
|
||||
pc += (int16_t)b;
|
||||
JUMP;
|
||||
}
|
||||
NEXT;
|
||||
@@ -1306,6 +1306,7 @@ RETRY_TRY_BLOCK:
|
||||
mrb_assert(mrb_integer_p(target));
|
||||
a = (uint32_t)mrb_integer(target);
|
||||
mrb_assert(a >= 0 && a < irep->ilen);
|
||||
a = a - (pc - irep->iseq);
|
||||
}
|
||||
CHECKPOINT_MAIN(RBREAK_TAG_JUMP) {
|
||||
ch = catch_handler_find(mrb, mrb->c->ci, pc, MRB_CATCH_FILTER_ENSURE);
|
||||
@@ -1319,7 +1320,7 @@ RETRY_TRY_BLOCK:
|
||||
CHECKPOINT_END(RBREAK_TAG_JUMP);
|
||||
|
||||
mrb->exc = NULL; /* clear break object */
|
||||
pc = irep->iseq + a;
|
||||
pc += (int16_t)a;
|
||||
JUMP;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user