Skip to content

Commit

Permalink
Place LocalJumpError messages in ROM
Browse files Browse the repository at this point in the history
Note that the meaning of the operand `a` in `OP_ERR` has changed.
  • Loading branch information
dearblue committed Oct 31, 2022
1 parent 416f012 commit 6897eb5
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 52 deletions.
17 changes: 17 additions & 0 deletions include/mruby/internal.h
Expand Up @@ -45,6 +45,23 @@ mrb_value mrb_get_backtrace(mrb_state *mrb);
void mrb_exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg);
mrb_value mrb_exc_mesg_get(mrb_state *mrb, struct RException *exc);

#define MRB_LOCALJUMP_ERROR_FOREACH(def) \
def(MRB_LOCALJUMP_ERROR_BREAK, "unexpected break") \
def(MRB_LOCALJUMP_ERROR_NEXT, "unexpected next") \
def(MRB_LOCALJUMP_ERROR_REDO, "unexpected redo") \
def(MRB_LOCALJUMP_ERROR_RETRY, "unexpected retry") \
def(MRB_LOCALJUMP_ERROR_RETURN, "unexpected return") \
def(MRB_LOCALJUMP_ERROR_YIELD, "unexpected yield")

enum {
#define MRB_LOCALJUMP_ERROR_DEFINE(n, mesg) n,
MRB_LOCALJUMP_ERROR_FOREACH(MRB_LOCALJUMP_ERROR_DEFINE)
#undef MRB_LOCALJUMP_ERROR_DEFINE
MRB_LOCALJUMP_ERROR_LAST
};

extern const char *const mrb_localjump_error_messages[MRB_LOCALJUMP_ERROR_LAST];

/* gc */
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
Expand Down
2 changes: 1 addition & 1 deletion include/mruby/ops.h
Expand Up @@ -113,7 +113,7 @@ OPCODE(UNDEF, B) /* undef_method(target_class,Syms[a]) */
OPCODE(SCLASS, B) /* R[a] = R[a].singleton_class */
OPCODE(TCLASS, B) /* R[a] = target_class */
OPCODE(DEBUG, BBB) /* print a,b,c */
OPCODE(ERR, B) /* raise(LocalJumpError, Pool[a]) */
OPCODE(ERR, B) /* raise(LocalJumpError, mrb_localjump_error_messages[a]) */
OPCODE(EXT1, Z) /* make 1st operand (a) 16bit */
OPCODE(EXT2, Z) /* make 2nd operand (b) 16bit */
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
Expand Down
19 changes: 8 additions & 11 deletions mrbgems/mruby-compiler/core/codegen.c
Expand Up @@ -106,7 +106,7 @@ static void gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int
static void gen_massignment(codegen_scope *s, node *tree, int sp, int val);

static void codegen(codegen_scope *s, node *tree, int val);
static void raise_error(codegen_scope *s, const char *msg);
static void raise_error(codegen_scope *s, int msg);

static void
codegen_error(codegen_scope *s, const char *message)
Expand Down Expand Up @@ -2143,11 +2143,9 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
}

static void
raise_error(codegen_scope *s, const char *msg)
raise_error(codegen_scope *s, int msg)
{
int idx = new_lit_cstr(s, msg);

genop_1(s, OP_ERR, idx);
genop_1(s, OP_ERR, msg);
}

static mrb_int
Expand Down Expand Up @@ -3144,7 +3142,7 @@ codegen(codegen_scope *s, node *tree, int val)

case NODE_NEXT:
if (!s->loop) {
raise_error(s, "unexpected next");
raise_error(s, MRB_LOCALJUMP_ERROR_NEXT);
}
else if (s->loop->type == LOOP_NORMAL) {
codegen(s, tree, NOVAL);
Expand All @@ -3165,7 +3163,7 @@ codegen(codegen_scope *s, node *tree, int val)

case NODE_REDO:
if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
raise_error(s, "unexpected redo");
raise_error(s, MRB_LOCALJUMP_ERROR_REDO);
}
else {
genjmp(s, OP_JMPUW, s->loop->pc1);
Expand All @@ -3175,14 +3173,13 @@ codegen(codegen_scope *s, node *tree, int val)

case NODE_RETRY:
{
const char *msg = "unexpected retry";
const struct loopinfo *lp = s->loop;

while (lp && lp->type != LOOP_RESCUE) {
lp = lp->prev;
}
if (!lp) {
raise_error(s, msg);
raise_error(s, MRB_LOCALJUMP_ERROR_RETRY);
}
else {
genjmp(s, OP_JMPUW, lp->pc0);
Expand Down Expand Up @@ -3950,7 +3947,7 @@ loop_break(codegen_scope *s, node *tree)
{
if (!s->loop) {
codegen(s, tree, NOVAL);
raise_error(s, "unexpected break");
raise_error(s, MRB_LOCALJUMP_ERROR_BREAK);
}
else {
struct loopinfo *loop;
Expand All @@ -3977,7 +3974,7 @@ loop_break(codegen_scope *s, node *tree)
}
}
if (!loop) {
raise_error(s, "unexpected break");
raise_error(s, MRB_LOCALJUMP_ERROR_BREAK);
return;
}

Expand Down
7 changes: 4 additions & 3 deletions src/codedump.c
Expand Up @@ -548,11 +548,12 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
print_lv_a(mrb, irep, a);
break;
CASE(OP_ERR, B):
if ((irep->pool[a].tt & IREP_TT_NFLAG) == 0) {
printf("ERR\t\t%s\n", irep->pool[a].u.str);
printf("ERR\t\t%d", a);
if (a < MRB_LOCALJUMP_ERROR_LAST) {
printf("\t\t\t; %s\n", mrb_localjump_error_messages[a]);
}
else {
printf("ERR\tL(%d)\n", a);
printf("\n");
}
break;
CASE(OP_EXCEPT, B):
Expand Down
59 changes: 22 additions & 37 deletions src/vm.c
Expand Up @@ -1115,34 +1115,24 @@ catch_handler_find(mrb_state *mrb, mrb_callinfo *ci, const mrb_code *pc, uint32_
return NULL;
}

typedef enum {
LOCALJUMP_ERROR_RETURN = 0,
LOCALJUMP_ERROR_BREAK = 1,
LOCALJUMP_ERROR_YIELD = 2
} localjump_error_kind;

static void
localjump_error(mrb_state *mrb, localjump_error_kind kind)
{
char kind_str[3][7] = { "return", "break", "yield" };
char kind_str_len[] = { 6, 5, 5 };
static const char lead[] = "unexpected ";
mrb_value msg;
mrb_value exc;

msg = mrb_str_new_capa(mrb, sizeof(lead) + 7);
mrb_str_cat(mrb, msg, lead, sizeof(lead) - 1);
mrb_str_cat(mrb, msg, kind_str[kind], kind_str_len[kind]);
exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
mrb_exc_set(mrb, exc);
}
const char *const mrb_localjump_error_messages[MRB_LOCALJUMP_ERROR_LAST] = {
#define MRB_LOCALJUMP_ERROR_MESSAGE(n, mesg) mesg,
MRB_LOCALJUMP_ERROR_FOREACH(MRB_LOCALJUMP_ERROR_MESSAGE)
#undef MRB_LOCALJUMP_ERROR_MESSAGE
};

#define RAISE_EXC(mrb, exc) do { \
mrb_value exc_value = (exc); \
mrb_exc_set(mrb, exc_value); \
goto L_RAISE; \
} while (0)

#define RAISE_LOCALJUMP_ERROR(mrb, kind) do { \
const char *exc_cmesg = mrb_localjump_error_messages[kind]; \
mrb_value exc_mesg = mrb_str_new_static(mrb, exc_cmesg, strlen(exc_cmesg)); \
RAISE_EXC(mrb, mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, exc_mesg)); \
} while (0)

#define RAISE_LIT(mrb, c, str) RAISE_EXC(mrb, mrb_exc_new_lit(mrb, c, str))
#define RAISE_FORMAT(mrb, c, fmt, ...) RAISE_EXC(mrb, mrb_exc_new_str(mrb, c, mrb_format(mrb, fmt, __VA_ARGS__)))

Expand Down Expand Up @@ -2243,21 +2233,18 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
struct REnv *e = MRB_PROC_ENV(dst);

if (!MRB_ENV_ONSTACK_P(e) || (e->cxt && e->cxt != mrb->c)) {
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
RAISE_LOCALJUMP_ERROR(mrb, MRB_LOCALJUMP_ERROR_RETURN);
}
}
/* check jump destination */
while (cibase <= ci && ci->proc != dst) {
if (ci->cci > CINFO_NONE) { /* jump cross C boundary */
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
RAISE_LOCALJUMP_ERROR(mrb, MRB_LOCALJUMP_ERROR_RETURN);
}
ci--;
}
if (ci <= cibase) { /* no jump destination */
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
RAISE_LOCALJUMP_ERROR(mrb, MRB_LOCALJUMP_ERROR_RETURN);
}
ci = mrb->c->ci;
while (cibase <= ci && ci->proc != dst) {
Expand Down Expand Up @@ -2447,14 +2434,12 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
struct REnv *e = uvenv(mrb, lv-1);
if (!e || (!MRB_ENV_ONSTACK_P(e) && e->mid == 0) ||
MRB_ENV_LEN(e) <= m1+r+m2+1) {
localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
goto L_RAISE;
RAISE_LOCALJUMP_ERROR(mrb, MRB_LOCALJUMP_ERROR_YIELD);
}
stack = e->stack + 1;
}
if (mrb_nil_p(stack[m1+r+m2+kd])) {
localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
goto L_RAISE;
RAISE_LOCALJUMP_ERROR(mrb, MRB_LOCALJUMP_ERROR_YIELD);
}
regs[a] = stack[m1+r+m2+kd];
NEXT;
Expand Down Expand Up @@ -3035,12 +3020,12 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
}

CASE(OP_ERR, B) {
size_t len = pool[a].tt >> 2;
mrb_value exc;

mrb_assert((pool[a].tt&IREP_TT_NFLAG)==0);
exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, pool[a].u.str, len);
RAISE_EXC(mrb, exc);
if (a < MRB_LOCALJUMP_ERROR_LAST) {
RAISE_LOCALJUMP_ERROR(mrb, a);
}
else {
RAISE_LIT(mrb, E_INDEX_ERROR, "invalid `a` operand for OP_ERR");
}
}

CASE(OP_EXT1, Z) {
Expand Down

0 comments on commit 6897eb5

Please sign in to comment.