summaryrefslogtreecommitdiff
path: root/mjit_compile.c
diff options
context:
space:
mode:
authork0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-05-03 03:08:21 (GMT)
committerk0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-05-03 03:08:21 (GMT)
commitcdef13d7034d365cb7a9bc6aa981bf0a0aa854d0 (patch)
tree1c2ce895c4fd5003021797d702a52210e32409f0 /mjit_compile.c
parent0e32c7c10abb1080c88af76574bcc2aa25c78cd5 (diff)
mjit_compile.c: verify stack size agreement
between branches. mjit_compile.inc.erb: move the compiled_for_pos reference to mjit_compile.c git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63331 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'mjit_compile.c')
-rw-r--r--mjit_compile.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/mjit_compile.c b/mjit_compile.c
index d3ca3ee..bc507a3 100644
--- a/mjit_compile.c
+++ b/mjit_compile.c
@@ -14,12 +14,16 @@
#include "insns_info.inc"
#include "vm_insnhelper.h"
+/* Macros to check if a position is already compiled using compile_status.stack_size_for_pos */
+#define NOT_COMPILED_STACK_SIZE -1
+#define ALREADY_COMPILED_P(status, pos) (status->stack_size_for_pos[pos] != NOT_COMPILED_STACK_SIZE)
+
/* Storage to keep compiler's status. This should have information
which is global during one `mjit_compile` call. Ones conditional
in each branch should be stored in `compile_branch`. */
struct compile_status {
int success; /* has TRUE if compilation has had no issue */
- int *compiled_for_pos; /* compiled_for_pos[pos] has TRUE if the pos is compiled */
+ int *stack_size_for_pos; /* stack_size_for_pos[pos] has stack size for the position (otherwise -1) */
/* If TRUE, JIT-ed code will use local variables to store pushed values instead of
using VM's stack and moving stack pointer. */
int local_stack_p;
@@ -118,6 +122,20 @@ compile_insn(FILE *f, const struct rb_iseq_constant_body *body, const int insn,
#include "mjit_compile.inc"
/*****************/
+ if (next_pos < body->iseq_size && ALREADY_COMPILED_P(status, next_pos)) {
+ /* Verify stack size assumption is the same among multiple branches */
+ if ((unsigned int)status->stack_size_for_pos[next_pos] != b->stack_size) {
+ if (mjit_opts.warnings || mjit_opts.verbose)
+ fprintf(stderr, "MJIT warning: JIT stack assumption is not the same between branches (%d != %u)\n",
+ status->stack_size_for_pos[next_pos], b->stack_size);
+ status->success = FALSE;
+ return next_pos;
+ }
+
+ /* If next_pos is already compiled, next instruction won't be compiled in C code and needs `goto`. */
+ fprintf(f, "goto label_%d;\n", next_pos);
+ }
+
return next_pos;
}
@@ -133,13 +151,13 @@ compile_insns(FILE *f, const struct rb_iseq_constant_body *body, unsigned int st
branch.stack_size = stack_size;
branch.finish_p = FALSE;
- while (pos < body->iseq_size && !status->compiled_for_pos[pos] && !branch.finish_p) {
+ while (pos < body->iseq_size && !ALREADY_COMPILED_P(status, pos) && !branch.finish_p) {
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
insn = rb_vm_insn_addr2insn((void *)body->iseq_encoded[pos]);
#else
insn = (int)body->iseq_encoded[pos];
#endif
- status->compiled_for_pos[pos] = TRUE;
+ status->stack_size_for_pos[pos] = (int)branch.stack_size;
fprintf(f, "\nlabel_%d: /* %s */\n", pos, insn_name(insn));
pos = compile_insn(f, body, insn, body->iseq_encoded + (pos+1), pos, status, &branch);
@@ -173,8 +191,9 @@ mjit_compile(FILE *f, const struct rb_iseq_constant_body *body, const char *func
{
struct compile_status status;
status.success = TRUE;
- status.compiled_for_pos = ZALLOC_N(int, body->iseq_size);
status.local_stack_p = !body->catch_except_p;
+ status.stack_size_for_pos = ALLOC_N(int, body->iseq_size);
+ memset(status.stack_size_for_pos, NOT_COMPILED_STACK_SIZE, sizeof(int) * body->iseq_size);
/* For performance, we verify stack size only on compilation time (mjit_compile.inc.erb) without --jit-debug */
if (!mjit_opts.debug) {
@@ -217,6 +236,6 @@ mjit_compile(FILE *f, const struct rb_iseq_constant_body *body, const char *func
compile_cancel_handler(f, body, &status);
fprintf(f, "\n} /* end of %s */\n", funcname);
- xfree(status.compiled_for_pos);
+ xfree(status.stack_size_for_pos);
return status.success;
}