Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Place LocalJumpError messages in ROM #5750

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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