Reduce instruction size
MODIFY
include/mruby/ops.h
include/mruby/ops.h
@@ -70,17 +70,17 @@ OPCODE(RETURN, B) /* return R(a) (normal) */
OPCODE(RETURN_BLK, B) /* return R(a) (in-block return) */
OPCODE(BREAK, B) /* break R(a) */
OPCODE(BLKPUSH, BS) /* R(a) = block (16=m5:r1:m5:d1:lv4) */
-OPCODE(ADD, BB) /* R(a) = R(a)+R(a+1) (Syms[b]=:+) */
-OPCODE(ADDI, BBB) /* R(a) = R(a)+mrb_int(c) (Syms[b]=:+) */
-OPCODE(SUB, BB) /* R(a) = R(a)-R(a+1) (Syms[b]=:-) */
-OPCODE(SUBI, BBB) /* R(a) = R(a)-C (Syms[b]=:-) */
-OPCODE(MUL, BB) /* R(a) = R(a)*R(a+1) (Syms[b]=:*) */
-OPCODE(DIV, BB) /* R(a) = R(a)/R(a+1) (Syms[b]=:/) */
-OPCODE(EQ, BB) /* R(a) = R(a)==R(a+1) (Syms[b]=:==) */
-OPCODE(LT, BB) /* R(a) = R(a)<R(a+1) (Syms[b]=:<) */
-OPCODE(LE, BB) /* R(a) = R(a)<=R(a+1) (Syms[b]=:<=) */
-OPCODE(GT, BB) /* R(a) = R(a)>R(a+1) (Syms[b]=:>) */
-OPCODE(GE, BB) /* R(a) = R(a)>=R(a+1) (Syms[b]=:>=) */
+OPCODE(ADD, B) /* R(a) = R(a)+R(a+1) */
+OPCODE(ADDI, BB) /* R(a) = R(a)+mrb_int(c) */
+OPCODE(SUB, B) /* R(a) = R(a)-R(a+1) */
+OPCODE(SUBI, BB) /* R(a) = R(a)-C */
+OPCODE(MUL, B) /* R(a) = R(a)*R(a+1) */
+OPCODE(DIV, B) /* R(a) = R(a)/R(a+1) */
+OPCODE(EQ, B) /* R(a) = R(a)==R(a+1) */
+OPCODE(LT, B) /* R(a) = R(a)<R(a+1) */
+OPCODE(LE, B) /* R(a) = R(a)<=R(a+1) */
+OPCODE(GT, B) /* R(a) = R(a)>R(a+1) */
+OPCODE(GE, B) /* R(a) = R(a)>=R(a+1) */
OPCODE(ARRAY, BB) /* R(a) = ary_new(R(a),R(a+1)..R(a+b)) */
OPCODE(ARRAY2, BBB) /* R(a) = ary_new(R(b),R(b+1)..R(b+c)) */
OPCODE(ARYCAT, B) /* ary_cat(R(a),R(a+1)) */

ADD
include/mruby/symbol.h
+/*
+** mruby/symbol.h - symbol utilities
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_SYMBOL_H
+#define MRUBY_SYMBOL_H
+
+#include "common.h"
+
+/**
+ * Symbol utilities
+ */
+MRB_BEGIN_DECL
+
+typedef enum mrb_reserved_symbol {
+ mrb_sym_add = 1, // +
+ mrb_sym_sub = 2, // -
+ mrb_sym_mul = 3, // *
+ mrb_sym_div = 4, // /
+ mrb_sym_eq = 5, // ==
+ mrb_sym_lt = 6, // <
+ mrb_sym_le = 7, // <=
+ mrb_sym_gt = 8, // >
+ mrb_sym_ge = 9, // >=
+ mrb_sym_method_missing = 10, // method_missing
+} mrb_reserved_symbol;
+
+MRB_END_DECL
+
+#endif /* MRUBY_SYMBOL_H */

MODIFY
mrbgems/mruby-compiler/core/codegen.c
mrbgems/mruby-compiler/core/codegen.c
@@ -468,11 +468,11 @@ gen_return(codegen_scope *s, uint8_t op, uint16_t src)
}
static void
-gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx)
+gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
{
if (no_peephole(s)) {
normal:
- genop_2(s, op, dst, idx);
+ genop_1(s, op, dst);
return;
}
else {
@@ -493,10 +493,10 @@ gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx)
if (data.b >= 128) goto normal;
s->pc = s->lastpc;
if (op == OP_ADD) {
- genop_3(s, OP_ADDI, dst, idx, (uint8_t)data.b);
+ genop_2(s, OP_ADDI, dst, (uint8_t)data.b);
}
else {
- genop_3(s, OP_SUBI, dst, idx, (uint8_t)data.b);
+ genop_2(s, OP_SUBI, dst, (uint8_t)data.b);
}
break;
default:
@@ -982,6 +982,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
gen_move(s, cursp(), recv, 1);
skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
}
+ // TODO: don't new when unused
idx = new_sym(s, sym);
tree = tree->cdr->cdr->car;
if (tree) {
@@ -1017,31 +1018,31 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
- gen_addsub(s, OP_ADD, cursp(), idx);
+ gen_addsub(s, OP_ADD, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) {
- gen_addsub(s, OP_SUB, cursp(), idx);
+ gen_addsub(s, OP_SUB, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) {
- genop_2(s, OP_MUL, cursp(), idx);
+ genop_1(s, OP_MUL, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) {
- genop_2(s, OP_DIV, cursp(), idx);
+ genop_1(s, OP_DIV, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) {
- genop_2(s, OP_LT, cursp(), idx);
+ genop_1(s, OP_LT, cursp());
}
else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) {
- genop_2(s, OP_LE, cursp(), idx);
+ genop_1(s, OP_LE, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) {
- genop_2(s, OP_GT, cursp(), idx);
+ genop_1(s, OP_GT, cursp());
}
else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) {
- genop_2(s, OP_GE, cursp(), idx);
+ genop_1(s, OP_GE, cursp());
}
else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) {
- genop_2(s, OP_EQ, cursp(), idx);
+ genop_1(s, OP_EQ, cursp());
}
else {
if (sendv) {
@@ -2025,28 +2026,28 @@ codegen(codegen_scope *s, node *tree, int val)
idx = new_sym(s, sym);
if (len == 1 && name[0] == '+') {
- gen_addsub(s, OP_ADD, cursp(), idx);
+ gen_addsub(s, OP_ADD, cursp());
}
else if (len == 1 && name[0] == '-') {
- gen_addsub(s, OP_SUB, cursp(), idx);
+ gen_addsub(s, OP_SUB, cursp());
}
else if (len == 1 && name[0] == '*') {
- genop_2(s, OP_MUL, cursp(), idx);
+ genop_1(s, OP_MUL, cursp());
}
else if (len == 1 && name[0] == '/') {
- genop_2(s, OP_DIV, cursp(), idx);
+ genop_1(s, OP_DIV, cursp());
}
else if (len == 1 && name[0] == '<') {
- genop_2(s, OP_LT, cursp(), idx);
+ genop_1(s, OP_LT, cursp());
}
else if (len == 2 && name[0] == '<' && name[1] == '=') {
- genop_2(s, OP_LE, cursp(), idx);
+ genop_1(s, OP_LE, cursp());
}
else if (len == 1 && name[0] == '>') {
- genop_2(s, OP_GT, cursp(), idx);
+ genop_1(s, OP_GT, cursp());
}
else if (len == 2 && name[0] == '>' && name[1] == '=') {
- genop_2(s, OP_GE, cursp(), idx);
+ genop_1(s, OP_GE, cursp());
}
else {
genop_3(s, OP_SEND, cursp(), idx, 1);

MODIFY
src/symbol.c
src/symbol.c
#include <mruby/string.h>
#include <mruby/dump.h>
#include <mruby/class.h>
+#include <mruby/symbol.h>
/* ------------------------------------------------------ */
typedef struct symbol_name {
@@ -170,10 +171,35 @@ mrb_free_symtbl(mrb_state *mrb)
kh_destroy(n2s, mrb, mrb->name2sym);
}
+struct reserved_symbol_t {
+ mrb_reserved_symbol sym;
+ char const *str;
+};
+
+static struct reserved_symbol_t reserved_symbols[] = {
+ { mrb_sym_add, "+" },
+ { mrb_sym_sub, "-" },
+ { mrb_sym_mul, "*" },
+ { mrb_sym_div, "/" },
+ { mrb_sym_eq, "==" },
+ { mrb_sym_lt, "<" },
+ { mrb_sym_le, "<=" },
+ { mrb_sym_gt, ">" },
+ { mrb_sym_ge, ">=" },
+ { mrb_sym_method_missing, "method_missing" },
+ { 0, NULL },
+};
+
void
mrb_init_symtbl(mrb_state *mrb)
{
+ int i;
mrb->name2sym = kh_init(n2s, mrb);
+
+ for (i = 0; reserved_symbols[i].sym != 0; ++i) {
+ mrb_sym s = mrb_intern_static(mrb, reserved_symbols[i].str, strlen(reserved_symbols[i].str));
+ mrb_assert(s == reserved_symbols[i].sym);
+ }
}
/**********************************************************************

MODIFY
src/vm.c
src/vm.c
#include <mruby/opcode.h>
#include "value_array.h"
#include <mruby/throw.h>
+#include <mruby/symbol.h>
#ifdef MRB_DISABLE_STDIO
#if defined(__cplusplus)
@@ -1009,6 +1010,7 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
uint32_t a;
uint16_t b;
uint8_t c;
+ mrb_sym mid;
#ifdef DIRECT_THREADED
static void *optable[] = {
@@ -1386,9 +1388,18 @@ RETRY_TRY_BLOCK:
SET_NIL_VALUE(regs[bidx]);
goto L_SENDB;
};
+ L_SEND_CONSTSYM:
+ {
+ /* push nil after arguments */
+ int bidx = (c == CALL_MAXARGS) ? a+2 : a+c+1;
+ SET_NIL_VALUE(regs[bidx]);
+ goto L_SENDB_CONSTSYM;
+ };
CASE(OP_SENDB, BBB)
L_SENDB:
+ mid = syms[b];
+ L_SENDB_CONSTSYM:
{
int argc = (c == CALL_MAXARGS) ? -1 : c;
int bidx = (argc < 0) ? a+2 : a+c+1;
@@ -1396,7 +1407,6 @@ RETRY_TRY_BLOCK:
struct RClass *cls;
mrb_callinfo *ci = mrb->c->ci;
mrb_value recv, blk;
- mrb_sym mid = syms[b];
mrb_assert(bidx < irep->nregs);
@@ -2204,7 +2214,7 @@ RETRY_TRY_BLOCK:
v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\
} while(0)
- CASE(OP_ADD, BB) {
+ CASE(OP_ADD, B) {
/* need to check if op is overridden */
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
@@ -2259,13 +2269,14 @@ RETRY_TRY_BLOCK:
break;
default:
c = 1;
- goto L_SEND;
+ mid = mrb_sym_add;
+ goto L_SEND_CONSTSYM;
}
mrb_gc_arena_restore(mrb, ai);
NEXT;
}
- CASE(OP_SUB, BB) {
+ CASE(OP_SUB, B) {
/* need to check if op is overridden */
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
@@ -2316,12 +2327,13 @@ RETRY_TRY_BLOCK:
#endif
default:
c = 1;
- goto L_SEND;
+ mid = mrb_sym_sub;
+ goto L_SEND_CONSTSYM;
}
NEXT;
}
- CASE(OP_MUL, BB) {
+ CASE(OP_MUL, B) {
/* need to check if op is overridden */
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
@@ -2372,12 +2384,13 @@ RETRY_TRY_BLOCK:
#endif
default:
c = 1;
- goto L_SEND;
+ mid = mrb_sym_mul;
+ goto L_SEND_CONSTSYM;
}
NEXT;
}
- CASE(OP_DIV, BB) {
+ CASE(OP_DIV, B) {
#ifndef MRB_WITHOUT_FLOAT
double x, y, f;
#endif
@@ -2411,7 +2424,8 @@ RETRY_TRY_BLOCK:
#endif
default:
c = 1;
- goto L_SEND;
+ mid = mrb_sym_div;
+ goto L_SEND_CONSTSYM;
}
#ifndef MRB_WITHOUT_FLOAT
@@ -2509,7 +2523,7 @@ RETRY_TRY_BLOCK:
#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
#ifdef MRB_WITHOUT_FLOAT
-#define OP_CMP(op) do {\
+#define OP_CMP(op, sym) do {\
int result;\
/* need to check if - is overridden */\
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
@@ -2518,7 +2532,8 @@ RETRY_TRY_BLOCK:
break;\
default:\
c = 1;\
- goto L_SEND;\
+ mid = mrb_sym_ ## sym;\
+ goto L_SEND_CONSTSYM;\
}\
if (result) {\
SET_TRUE_VALUE(regs[a]);\
@@ -2528,7 +2543,7 @@ RETRY_TRY_BLOCK:
}\
} while(0)
#else
-#define OP_CMP(op) do {\
+#define OP_CMP(op, sym) do {\
int result;\
/* need to check if - is overridden */\
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
@@ -2546,7 +2561,8 @@ RETRY_TRY_BLOCK:
break;\
default:\
c = 1;\
- goto L_SEND;\
+ mid = mrb_sym_ ## sym;\
+ goto L_SEND_CONSTSYM;\
}\
if (result) {\
SET_TRUE_VALUE(regs[a]);\
@@ -2557,33 +2573,33 @@ RETRY_TRY_BLOCK:
} while(0)
#endif
- CASE(OP_EQ, BB) {
+ CASE(OP_EQ, B) {
if (mrb_obj_eq(mrb, regs[a], regs[a+1])) {
SET_TRUE_VALUE(regs[a]);
}
else {
- OP_CMP(==);
+ OP_CMP(==, eq);
}
NEXT;
}
- CASE(OP_LT, BB) {
- OP_CMP(<);
+ CASE(OP_LT, B) {
+ OP_CMP(<, gt);
NEXT;
}
- CASE(OP_LE, BB) {
- OP_CMP(<=);
+ CASE(OP_LE, B) {
+ OP_CMP(<=, ge);
NEXT;
}
- CASE(OP_GT, BB) {
- OP_CMP(>);
+ CASE(OP_GT, B) {
+ OP_CMP(>, lt);
NEXT;
}
- CASE(OP_GE, BB) {
- OP_CMP(>=);
+ CASE(OP_GE, B) {
+ OP_CMP(>=, le);
NEXT;
}

Reduce instruction size