mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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.
This commit is contained in:
@@ -51,7 +51,7 @@ MRB_API mrb_irep *mrb_read_irep_buf(mrb_state*, const void*, size_t);
|
||||
/* Binary Format Version Major:Minor */
|
||||
/* Major: Incompatible 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_FORMAT_VER RITE_BINARY_MAJOR_VER RITE_BINARY_MINOR_VER
|
||||
#define RITE_COMPILER_NAME "MATZ"
|
||||
|
||||
@@ -75,8 +75,8 @@ typedef struct mrb_irep {
|
||||
|
||||
uint32_t ilen;
|
||||
uint16_t plen, slen;
|
||||
uint8_t rlen;
|
||||
uint32_t refcnt;
|
||||
uint16_t rlen;
|
||||
uint16_t refcnt;
|
||||
} mrb_irep;
|
||||
|
||||
#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)) */
|
||||
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(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(BLOCK16, BS) /* R(a) = lambda(SEQ[b],L_BLOCK) */
|
||||
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_EXC, B) /* R(a) = range_new(R(a),R(a+1),TRUE) */
|
||||
OPCODE(OCLASS, B) /* R(a) = ::Object */
|
||||
OPCODE(CLASS, BB) /* R(a) = newclass(R(a),Syms(b),R(a+1)) */
|
||||
OPCODE(MODULE, BB) /* R(a) = newmodule(R(a),Syms(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(ALIAS, BB) /* alias_method(target_class,Syms(a),Syms(b)) */
|
||||
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)
|
||||
case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
|
||||
case OP_GETCONST: case OP_STRING: case OP_STRING16:
|
||||
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;
|
||||
s->pc = s->lastpc;
|
||||
genop_2(s, data.insn, dst, data.b);
|
||||
@@ -1630,7 +1631,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
if (val) {
|
||||
int idx = lambda_body(s, tree, 1);
|
||||
|
||||
genop_2(s, OP_LAMBDA, cursp(), idx);
|
||||
genop_bs(s, OP_LAMBDA, cursp(), idx);
|
||||
push();
|
||||
}
|
||||
break;
|
||||
@@ -1639,7 +1640,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
if (val) {
|
||||
int idx = lambda_body(s, tree, 1);
|
||||
|
||||
genop_2(s, OP_BLOCK, cursp(), idx);
|
||||
genop_bs(s, OP_BLOCK, cursp(), idx);
|
||||
push();
|
||||
}
|
||||
break;
|
||||
@@ -2910,7 +2911,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
else {
|
||||
idx = scope_body(s, body, val);
|
||||
genop_2(s, OP_EXEC, cursp(), idx);
|
||||
genop_bs(s, OP_EXEC, cursp(), idx);
|
||||
}
|
||||
if (val) {
|
||||
push();
|
||||
@@ -2942,7 +2943,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
else {
|
||||
idx = scope_body(s, tree->cdr->car, val);
|
||||
genop_2(s, OP_EXEC, cursp(), idx);
|
||||
genop_bs(s, OP_EXEC, cursp(), idx);
|
||||
}
|
||||
if (val) {
|
||||
push();
|
||||
@@ -2963,7 +2964,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
else {
|
||||
idx = scope_body(s, tree->cdr->car, val);
|
||||
genop_2(s, OP_EXEC, cursp(), idx);
|
||||
genop_bs(s, OP_EXEC, cursp(), idx);
|
||||
}
|
||||
if (val) {
|
||||
push();
|
||||
@@ -2978,7 +2979,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
|
||||
genop_1(s, OP_TCLASS, cursp());
|
||||
push();
|
||||
genop_2(s, OP_METHOD, cursp(), idx);
|
||||
genop_bs(s, OP_METHOD, cursp(), idx);
|
||||
push(); pop();
|
||||
pop();
|
||||
genop_2(s, OP_DEF, cursp(), sym);
|
||||
@@ -2999,7 +3000,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
pop();
|
||||
genop_1(s, OP_SCLASS, cursp());
|
||||
push();
|
||||
genop_2(s, OP_METHOD, cursp(), idx);
|
||||
genop_bs(s, OP_METHOD, cursp(), idx);
|
||||
pop();
|
||||
genop_2(s, OP_DEF, cursp(), sym);
|
||||
if (val) {
|
||||
@@ -3032,7 +3033,7 @@ scope_add_irep(codegen_scope *s)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (prev->irep->rlen == UINT8_MAX) {
|
||||
if (prev->irep->rlen == UINT16_MAX) {
|
||||
codegen_error(s, "too many nested blocks/methods");
|
||||
}
|
||||
s->irep = irep = mrb_add_irep(s->mrb);
|
||||
|
||||
@@ -371,6 +371,15 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
|
||||
CASE(OP_METHOD, BB);
|
||||
printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, (void*)irep->reps[b]);
|
||||
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);
|
||||
printf("OP_RANGE_INC\tR%d\n", a);
|
||||
break;
|
||||
|
||||
@@ -2644,6 +2644,18 @@ RETRY_TRY_BLOCK:
|
||||
c = OP_L_METHOD;
|
||||
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) {
|
||||
mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], FALSE);
|
||||
@@ -2699,7 +2711,11 @@ RETRY_TRY_BLOCK:
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_EXEC, BB) {
|
||||
CASE(OP_EXEC16, BS)
|
||||
goto L_EXEC;
|
||||
CASE(OP_EXEC, BB)
|
||||
L_EXEC:
|
||||
{
|
||||
mrb_value recv = regs[a];
|
||||
struct RProc *p;
|
||||
const mrb_irep *nirep = irep->reps[b];
|
||||
|
||||
Reference in New Issue
Block a user