summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2020-11-26 10:34:31 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2020-11-26 10:34:31 +0900
commit7150c6753933f12a2ba63769fb7b3a44cfcddd3d (patch)
treecddfd89197039d98cac827837e58bd3041d88a2a /src
parent6dedd6a940194881c3b66124ff277c4cb14d08bd (diff)
downloadmruby-7150c6753933f12a2ba63769fb7b3a44cfcddd3d.tar.gz
mruby-7150c6753933f12a2ba63769fb7b3a44cfcddd3d.zip
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).
Diffstat (limited to 'src')
-rw-r--r--src/codedump.c15
-rw-r--r--src/vm.c11
2 files changed, 16 insertions, 10 deletions
diff --git a/src/codedump.c b/src/codedump.c
index 4f793b753..94d4f24c0 100644
--- a/src/codedump.c
+++ b/src/codedump.c
@@ -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);
diff --git a/src/vm.c b/src/vm.c
index a0d4c967b..85835149a 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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;
}