Allow more than 256 child `irep`; fix #5310

We have introduced following new instructions.

 * `OP_LAMBDA16`
 * `OP_BLOCK16`
 * `OP_METHOD16`
 * `OP_EXEC16`

Each instruction uses 16 bits operand for `reps` index. Since new
instructions are added, `mruby/c` VM should be updated.

Due to new instructions, dump format compatibility is lost, we have
increased `RITE_BINARY_MAJOR_VER`.

In addition, we have decreased the size of `refcnt` in `mrb_irep` from
`uint32_t` to `uint16_t`, which is reasonably big enough.
parent bd6b48fa
...@@ -51,7 +51,7 @@ MRB_API mrb_irep *mrb_read_irep_buf(mrb_state*, const void*, size_t); ...@@ -51,7 +51,7 @@ MRB_API mrb_irep *mrb_read_irep_buf(mrb_state*, const void*, size_t);
/* Binary Format Version Major:Minor */ /* Binary Format Version Major:Minor */
/* Major: Incompatible to prior versions */ /* Major: Incompatible to prior versions */
/* Minor: Upper-compatible to prior versions */ /* Minor: Upper-compatible to prior versions */
#define RITE_BINARY_MAJOR_VER "01" #define RITE_BINARY_MAJOR_VER "02"
#define RITE_BINARY_MINOR_VER "00" #define RITE_BINARY_MINOR_VER "00"
#define RITE_BINARY_FORMAT_VER RITE_BINARY_MAJOR_VER RITE_BINARY_MINOR_VER #define RITE_BINARY_FORMAT_VER RITE_BINARY_MAJOR_VER RITE_BINARY_MINOR_VER
#define RITE_COMPILER_NAME "MATZ" #define RITE_COMPILER_NAME "MATZ"
......
...@@ -75,8 +75,8 @@ typedef struct mrb_irep { ...@@ -75,8 +75,8 @@ typedef struct mrb_irep {
uint32_t ilen; uint32_t ilen;
uint16_t plen, slen; uint16_t plen, slen;
uint8_t rlen; uint16_t rlen;
uint32_t refcnt; uint16_t refcnt;
} mrb_irep; } mrb_irep;
#define MRB_ISEQ_NO_FREE 1 #define MRB_ISEQ_NO_FREE 1
......
...@@ -100,14 +100,18 @@ OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b*2-1)) */ ...@@ -100,14 +100,18 @@ OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b*2-1)) */
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b*2)) */ OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b*2)) */
OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */ OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */ OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
OPCODE(LAMBDA16, BS) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */ OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
OPCODE(BLOCK16, BS) /* R(a) = lambda(SEQ[b],L_BLOCK) */
OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */ OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */
OPCODE(METHOD16, BS) /* R(a) = lambda(SEQ[b],L_METHOD) */
OPCODE(RANGE_INC, B) /* R(a) = range_new(R(a),R(a+1),FALSE) */ OPCODE(RANGE_INC, B) /* R(a) = range_new(R(a),R(a+1),FALSE) */
OPCODE(RANGE_EXC, B) /* R(a) = range_new(R(a),R(a+1),TRUE) */ OPCODE(RANGE_EXC, B) /* R(a) = range_new(R(a),R(a+1),TRUE) */
OPCODE(OCLASS, B) /* R(a) = ::Object */ OPCODE(OCLASS, B) /* R(a) = ::Object */
OPCODE(CLASS, BB) /* R(a) = newclass(R(a),Syms(b),R(a+1)) */ OPCODE(CLASS, BB) /* R(a) = newclass(R(a),Syms(b),R(a+1)) */
OPCODE(MODULE, BB) /* R(a) = newmodule(R(a),Syms(b)) */ OPCODE(MODULE, BB) /* R(a) = newmodule(R(a),Syms(b)) */
OPCODE(EXEC, BB) /* R(a) = blockexec(R(a),SEQ[b]) */ OPCODE(EXEC, BB) /* R(a) = blockexec(R(a),SEQ[b]) */
OPCODE(EXEC16, BS) /* R(a) = blockexec(R(a),SEQ[b]) */
OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)) */ OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)) */
OPCODE(ALIAS, BB) /* alias_method(target_class,Syms(a),Syms(b)) */ OPCODE(ALIAS, BB) /* alias_method(target_class,Syms(a),Syms(b)) */
OPCODE(UNDEF, B) /* undef_method(target_class,Syms(a)) */ OPCODE(UNDEF, B) /* undef_method(target_class,Syms(a)) */
......
...@@ -464,6 +464,7 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) ...@@ -464,6 +464,7 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV: case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
case OP_GETCONST: case OP_STRING: case OP_STRING16: case OP_GETCONST: case OP_STRING: case OP_STRING16:
case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH: case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH:
case OP_LAMBDA16: case OP_BLOCK16: case OP_METHOD16:
if (nopeep || data.a != src || data.a < s->nlocals) goto normal; if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
s->pc = s->lastpc; s->pc = s->lastpc;
genop_2(s, data.insn, dst, data.b); genop_2(s, data.insn, dst, data.b);
...@@ -1630,7 +1631,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -1630,7 +1631,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) { if (val) {
int idx = lambda_body(s, tree, 1); int idx = lambda_body(s, tree, 1);
genop_2(s, OP_LAMBDA, cursp(), idx); genop_bs(s, OP_LAMBDA, cursp(), idx);
push(); push();
} }
break; break;
...@@ -1639,7 +1640,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -1639,7 +1640,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) { if (val) {
int idx = lambda_body(s, tree, 1); int idx = lambda_body(s, tree, 1);
genop_2(s, OP_BLOCK, cursp(), idx); genop_bs(s, OP_BLOCK, cursp(), idx);
push(); push();
} }
break; break;
...@@ -2910,7 +2911,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2910,7 +2911,7 @@ codegen(codegen_scope *s, node *tree, int val)
} }
else { else {
idx = scope_body(s, body, val); idx = scope_body(s, body, val);
genop_2(s, OP_EXEC, cursp(), idx); genop_bs(s, OP_EXEC, cursp(), idx);
} }
if (val) { if (val) {
push(); push();
...@@ -2942,7 +2943,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2942,7 +2943,7 @@ codegen(codegen_scope *s, node *tree, int val)
} }
else { else {
idx = scope_body(s, tree->cdr->car, val); idx = scope_body(s, tree->cdr->car, val);
genop_2(s, OP_EXEC, cursp(), idx); genop_bs(s, OP_EXEC, cursp(), idx);
} }
if (val) { if (val) {
push(); push();
...@@ -2963,7 +2964,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2963,7 +2964,7 @@ codegen(codegen_scope *s, node *tree, int val)
} }
else { else {
idx = scope_body(s, tree->cdr->car, val); idx = scope_body(s, tree->cdr->car, val);
genop_2(s, OP_EXEC, cursp(), idx); genop_bs(s, OP_EXEC, cursp(), idx);
} }
if (val) { if (val) {
push(); push();
...@@ -2978,7 +2979,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2978,7 +2979,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop_1(s, OP_TCLASS, cursp()); genop_1(s, OP_TCLASS, cursp());
push(); push();
genop_2(s, OP_METHOD, cursp(), idx); genop_bs(s, OP_METHOD, cursp(), idx);
push(); pop(); push(); pop();
pop(); pop();
genop_2(s, OP_DEF, cursp(), sym); genop_2(s, OP_DEF, cursp(), sym);
...@@ -2999,7 +3000,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2999,7 +3000,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop(); pop();
genop_1(s, OP_SCLASS, cursp()); genop_1(s, OP_SCLASS, cursp());
push(); push();
genop_2(s, OP_METHOD, cursp(), idx); genop_bs(s, OP_METHOD, cursp(), idx);
pop(); pop();
genop_2(s, OP_DEF, cursp(), sym); genop_2(s, OP_DEF, cursp(), sym);
if (val) { if (val) {
...@@ -3032,7 +3033,7 @@ scope_add_irep(codegen_scope *s) ...@@ -3032,7 +3033,7 @@ scope_add_irep(codegen_scope *s)
return; return;
} }
else { else {
if (prev->irep->rlen == UINT8_MAX) { if (prev->irep->rlen == UINT16_MAX) {
codegen_error(s, "too many nested blocks/methods"); codegen_error(s, "too many nested blocks/methods");
} }
s->irep = irep = mrb_add_irep(s->mrb); s->irep = irep = mrb_add_irep(s->mrb);
......
...@@ -371,6 +371,15 @@ codedump(mrb_state *mrb, const mrb_irep *irep) ...@@ -371,6 +371,15 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
CASE(OP_METHOD, BB); CASE(OP_METHOD, BB);
printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, (void*)irep->reps[b]); printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, (void*)irep->reps[b]);
break; break;
CASE(OP_LAMBDA16, BS);
printf("OP_LAMBDA\tR%d\tI(%d:%p)\n", a, b, (void*)irep->reps[b]);
break;
CASE(OP_BLOCK16, BS);
printf("OP_BLOCK\tR%d\tI(%d:%p)\n", a, b, (void*)irep->reps[b]);
break;
CASE(OP_METHOD16, BS);
printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, (void*)irep->reps[b]);
break;
CASE(OP_RANGE_INC, B); CASE(OP_RANGE_INC, B);
printf("OP_RANGE_INC\tR%d\n", a); printf("OP_RANGE_INC\tR%d\n", a);
break; break;
......
...@@ -2644,6 +2644,18 @@ RETRY_TRY_BLOCK: ...@@ -2644,6 +2644,18 @@ RETRY_TRY_BLOCK:
c = OP_L_METHOD; c = OP_L_METHOD;
goto L_MAKE_LAMBDA; goto L_MAKE_LAMBDA;
} }
CASE(OP_LAMBDA16, BS) {
c = OP_L_LAMBDA;
goto L_MAKE_LAMBDA;
}
CASE(OP_BLOCK16, BS) {
c = OP_L_BLOCK;
goto L_MAKE_LAMBDA;
}
CASE(OP_METHOD16, BS) {
c = OP_L_METHOD;
goto L_MAKE_LAMBDA;
}
CASE(OP_RANGE_INC, B) { CASE(OP_RANGE_INC, B) {
mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], FALSE); mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], FALSE);
...@@ -2699,7 +2711,11 @@ RETRY_TRY_BLOCK: ...@@ -2699,7 +2711,11 @@ RETRY_TRY_BLOCK:
NEXT; NEXT;
} }
CASE(OP_EXEC, BB) { CASE(OP_EXEC16, BS)
goto L_EXEC;
CASE(OP_EXEC, BB)
L_EXEC:
{
mrb_value recv = regs[a]; mrb_value recv = regs[a];
struct RProc *p; struct RProc *p;
const mrb_irep *nirep = irep->reps[b]; const mrb_irep *nirep = irep->reps[b];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment