summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2020-01-17 09:28:21 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2020-05-07 08:38:46 +0900
commitfa8668c77d181a5075dc56fb63d6fa087ab4b1d3 (patch)
tree6ff4773e5be236b2783f4dc47aaa2095bb4454d1
parent47f5f887e892ce46fecd12ad97193a501e09accb (diff)
downloadmruby-fa8668c77d181a5075dc56fb63d6fa087ab4b1d3.tar.gz
mruby-fa8668c77d181a5075dc56fb63d6fa087ab4b1d3.zip
Add a new instruction `OP_LOADI16`.
Which loads 16bit integer to the register. The instruction number should be reorder on massive instruction refactoring. The instruction is added for `mruby/c` which had performance issue with `OP_EXT`. With this instruction, `mruby/c` VM can just raise errors on `OP_EXT` extension instructions.
-rw-r--r--include/mruby/ops.h1
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c21
-rw-r--r--src/codedump.c4
-rw-r--r--src/vm.c5
4 files changed, 26 insertions, 5 deletions
diff --git a/include/mruby/ops.h b/include/mruby/ops.h
index 2327c33fd..c8990ae43 100644
--- a/include/mruby/ops.h
+++ b/include/mruby/ops.h
@@ -115,3 +115,4 @@ OPCODE(EXT1, Z) /* make 1st operand 16bit */
OPCODE(EXT2, Z) /* make 2nd operand 16bit */
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
OPCODE(STOP, Z) /* stop VM */
+OPCODE(LOADI16, BS) /* R(a) = mrb_int(b) */
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 717d9eb9a..162666eb9 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -2440,12 +2440,20 @@ codegen(codegen_scope *s, node *tree, int val)
else
#endif
{
- if (i == -1) genop_1(s, OP_LOADI__1, cursp());
- else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
+ if (i < 0) {
+ if (i == -1) genop_1(s, OP_LOADI__1, cursp());
+ else if (i >= -0xff) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
+ else if (i >= -0x8000) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
+ else goto lit_int;
+ }
else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
- else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
+ else if (i <= 0xff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
+ else if (i <= 0xffff) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
else {
- int off = new_lit(s, mrb_fixnum_value(i));
+ int off;
+
+ lit_int:
+ off = new_lit(s, mrb_fixnum_value(i));
genop_2(s, OP_LOADL, cursp(), off);
}
}
@@ -2501,9 +2509,12 @@ codegen(codegen_scope *s, node *tree, int val)
else {
#endif
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
- else if (i >= -0xffff) {
+ else if (i >= -0xff) {
genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
}
+ else if (i >= -0x8000) {
+ genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
+ }
else {
int off = new_lit(s, mrb_fixnum_value(i));
genop_2(s, OP_LOADL, cursp(), off);
diff --git a/src/codedump.c b/src/codedump.c
index 7faa39360..649be176b 100644
--- a/src/codedump.c
+++ b/src/codedump.c
@@ -130,6 +130,10 @@ codedump(mrb_state *mrb, mrb_irep *irep)
printf("OP_LOADI\tR%d\t-%d\t", a, b);
print_lv_a(mrb, irep, a);
break;
+ CASE(OP_LOADI16, BS):
+ printf("OP_LOADI16\tR%d\t%d\t", a, (int)(int16_t)b);
+ print_lv_a(mrb, irep, a);
+ break;
CASE(OP_LOADI__1, B):
printf("OP_LOADI__1\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
diff --git a/src/vm.c b/src/vm.c
index ea1bb5087..26da5831e 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1047,6 +1047,11 @@ RETRY_TRY_BLOCK:
NEXT;
}
+ CASE(OP_LOADI16, BS) {
+ SET_INT_VALUE(regs[a], (mrb_int)(int16_t)b);
+ NEXT;
+ }
+
CASE(OP_LOADSYM, BB) {
SET_SYM_VALUE(regs[a], syms[b]);
NEXT;