зеркало из https://github.com/github/ruby.git
Aesthetic changes and add missing counter
This commit is contained in:
Родитель
8106a95efb
Коммит
3e80104024
133
yjit_codegen.c
133
yjit_codegen.c
|
@ -27,8 +27,8 @@ codeblock_t* cb = NULL;
|
||||||
static codeblock_t outline_block;
|
static codeblock_t outline_block;
|
||||||
codeblock_t* ocb = NULL;
|
codeblock_t* ocb = NULL;
|
||||||
|
|
||||||
// Code for exiting back to the interpreter
|
// Code for exiting back to the interpreter from the leave insn
|
||||||
static void *interp_exit;
|
static void *leave_exit_code;
|
||||||
|
|
||||||
// Print the current source location for debugging purposes
|
// Print the current source location for debugging purposes
|
||||||
RBIMPL_ATTR_MAYBE_UNUSED()
|
RBIMPL_ATTR_MAYBE_UNUSED()
|
||||||
|
@ -116,6 +116,61 @@ jit_peek_at_self(jitstate_t *jit, ctx_t *ctx)
|
||||||
|
|
||||||
static bool jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_t insn_opnd, const int max_chain_depth, uint8_t *side_exit);
|
static bool jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_t insn_opnd, const int max_chain_depth, uint8_t *side_exit);
|
||||||
|
|
||||||
|
#if RUBY_DEBUG
|
||||||
|
|
||||||
|
// Increment a profiling counter with counter_name
|
||||||
|
#define GEN_COUNTER_INC(cb, counter_name) _gen_counter_inc(cb, &(yjit_runtime_counters . counter_name))
|
||||||
|
static void
|
||||||
|
_gen_counter_inc(codeblock_t *cb, int64_t *counter)
|
||||||
|
{
|
||||||
|
if (!rb_yjit_opts.gen_stats) return;
|
||||||
|
mov(cb, REG0, const_ptr_opnd(counter));
|
||||||
|
cb_write_lock_prefix(cb); // for ractors.
|
||||||
|
add(cb, mem_opnd(64, REG0, 0), imm_opnd(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment a counter then take an existing side exit.
|
||||||
|
#define COUNTED_EXIT(side_exit, counter_name) _counted_side_exit(side_exit, &(yjit_runtime_counters . counter_name))
|
||||||
|
static uint8_t *
|
||||||
|
_counted_side_exit(uint8_t *existing_side_exit, int64_t *counter)
|
||||||
|
{
|
||||||
|
if (!rb_yjit_opts.gen_stats) return existing_side_exit;
|
||||||
|
|
||||||
|
uint8_t *start = cb_get_ptr(ocb, ocb->write_pos);
|
||||||
|
_gen_counter_inc(ocb, counter);
|
||||||
|
jmp_ptr(ocb, existing_side_exit);
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a comment at the current position in the code block
|
||||||
|
static void
|
||||||
|
_add_comment(codeblock_t* cb, const char* comment_str)
|
||||||
|
{
|
||||||
|
// Avoid adding duplicate comment strings (can happen due to deferred codegen)
|
||||||
|
size_t num_comments = rb_darray_size(yjit_code_comments);
|
||||||
|
if (num_comments > 0) {
|
||||||
|
struct yjit_comment last_comment = rb_darray_get(yjit_code_comments, num_comments - 1);
|
||||||
|
if (last_comment.offset == cb->write_pos && strcmp(last_comment.comment, comment_str) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct yjit_comment new_comment = (struct yjit_comment){ cb->write_pos, comment_str };
|
||||||
|
rb_darray_append(&yjit_code_comments, new_comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comments for generated machine code
|
||||||
|
#define ADD_COMMENT(cb, comment) _add_comment((cb), (comment))
|
||||||
|
yjit_comment_array_t yjit_code_comments;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define GEN_COUNTER_INC(cb, counter_name) ((void)0)
|
||||||
|
#define COUNTED_EXIT(side_exit, counter_name) side_exit
|
||||||
|
#define ADD_COMMENT(cb, comment) ((void)0)
|
||||||
|
|
||||||
|
#endif // if RUBY_DEBUG
|
||||||
|
|
||||||
// Save YJIT registers prior to a C call
|
// Save YJIT registers prior to a C call
|
||||||
static void
|
static void
|
||||||
yjit_save_regs(codeblock_t* cb)
|
yjit_save_regs(codeblock_t* cb)
|
||||||
|
@ -189,25 +244,24 @@ yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
|
||||||
|
|
||||||
// Generate an interpreter to REG_CFP->pc.
|
// Generate an interpreter to REG_CFP->pc.
|
||||||
static uint8_t *
|
static uint8_t *
|
||||||
yjit_gen_context_free_exit(codeblock_t *cb)
|
yjit_gen_leave_exit(codeblock_t *cb)
|
||||||
{
|
{
|
||||||
uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
|
uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
|
||||||
|
|
||||||
// Update the CFP on the EC
|
// Update the CFP on the EC
|
||||||
mov(cb, member_opnd(REG_EC, rb_execution_context_t, cfp), REG_CFP);
|
//mov(cb, member_opnd(REG_EC, rb_execution_context_t, cfp), REG_CFP);
|
||||||
|
|
||||||
|
// Every exit to the interpreter should be counted
|
||||||
|
GEN_COUNTER_INC(cb, leave_interp_return);
|
||||||
|
|
||||||
// Put PC into the return register, which the post call bytes dispatches to
|
// Put PC into the return register, which the post call bytes dispatches to
|
||||||
mov(cb, RAX, member_opnd(REG_CFP, rb_control_frame_t, pc));
|
mov(cb, RAX, member_opnd(REG_CFP, rb_control_frame_t, pc));
|
||||||
|
|
||||||
cb_write_post_call_bytes(cb);
|
cb_write_post_call_bytes(cb);
|
||||||
|
|
||||||
// Note, not incrementing stats here since this exit is the natural end to
|
|
||||||
// executing output code.
|
|
||||||
|
|
||||||
return code_ptr;
|
return code_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// A shorthand for generating an exit in the outline block
|
// A shorthand for generating an exit in the outline block
|
||||||
static uint8_t *
|
static uint8_t *
|
||||||
yjit_side_exit(jitstate_t *jit, ctx_t *ctx)
|
yjit_side_exit(jitstate_t *jit, ctx_t *ctx)
|
||||||
|
@ -215,61 +269,6 @@ yjit_side_exit(jitstate_t *jit, ctx_t *ctx)
|
||||||
return yjit_gen_exit(jit, ctx, ocb);
|
return yjit_gen_exit(jit, ctx, ocb);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RUBY_DEBUG
|
|
||||||
|
|
||||||
// Increment a profiling counter with counter_name
|
|
||||||
#define GEN_COUNTER_INC(cb, counter_name) _gen_counter_inc(cb, &(yjit_runtime_counters . counter_name))
|
|
||||||
static void
|
|
||||||
_gen_counter_inc(codeblock_t *cb, int64_t *counter)
|
|
||||||
{
|
|
||||||
if (!rb_yjit_opts.gen_stats) return;
|
|
||||||
mov(cb, REG0, const_ptr_opnd(counter));
|
|
||||||
cb_write_lock_prefix(cb); // for ractors.
|
|
||||||
add(cb, mem_opnd(64, REG0, 0), imm_opnd(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment a counter then take an existing side exit.
|
|
||||||
#define COUNTED_EXIT(side_exit, counter_name) _counted_side_exit(side_exit, &(yjit_runtime_counters . counter_name))
|
|
||||||
static uint8_t *
|
|
||||||
_counted_side_exit(uint8_t *existing_side_exit, int64_t *counter)
|
|
||||||
{
|
|
||||||
if (!rb_yjit_opts.gen_stats) return existing_side_exit;
|
|
||||||
|
|
||||||
uint8_t *start = cb_get_ptr(ocb, ocb->write_pos);
|
|
||||||
_gen_counter_inc(ocb, counter);
|
|
||||||
jmp_ptr(ocb, existing_side_exit);
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a comment at the current position in the code block
|
|
||||||
static void
|
|
||||||
_add_comment(codeblock_t* cb, const char* comment_str)
|
|
||||||
{
|
|
||||||
// Avoid adding duplicate comment strings (can happen due to deferred codegen)
|
|
||||||
size_t num_comments = rb_darray_size(yjit_code_comments);
|
|
||||||
if (num_comments > 0) {
|
|
||||||
struct yjit_comment last_comment = rb_darray_get(yjit_code_comments, num_comments - 1);
|
|
||||||
if (last_comment.offset == cb->write_pos && strcmp(last_comment.comment, comment_str) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct yjit_comment new_comment = (struct yjit_comment){ cb->write_pos, comment_str };
|
|
||||||
rb_darray_append(&yjit_code_comments, new_comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comments for generated machine code
|
|
||||||
#define ADD_COMMENT(cb, comment) _add_comment((cb), (comment))
|
|
||||||
yjit_comment_array_t yjit_code_comments;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define GEN_COUNTER_INC(cb, counter_name) ((void)0)
|
|
||||||
#define COUNTED_EXIT(side_exit, counter_name) side_exit
|
|
||||||
#define ADD_COMMENT(cb, comment) ((void)0)
|
|
||||||
|
|
||||||
#endif // if RUBY_DEBUG
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Compile an interpreter entry block to be inserted into an iseq
|
Compile an interpreter entry block to be inserted into an iseq
|
||||||
Returns `NULL` if compilation fails.
|
Returns `NULL` if compilation fails.
|
||||||
|
@ -296,7 +295,7 @@ yjit_entry_prologue(void)
|
||||||
|
|
||||||
// Setup cfp->jit_return
|
// Setup cfp->jit_return
|
||||||
// TODO: this could use an IP relative LEA instead of an 8 byte immediate
|
// TODO: this could use an IP relative LEA instead of an 8 byte immediate
|
||||||
mov(cb, REG0, const_ptr_opnd(interp_exit));
|
mov(cb, REG0, const_ptr_opnd(leave_exit_code));
|
||||||
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, jit_return), REG0);
|
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, jit_return), REG0);
|
||||||
|
|
||||||
return code_ptr;
|
return code_ptr;
|
||||||
|
@ -2101,7 +2100,7 @@ gen_leave(jitstate_t* jit, ctx_t* ctx)
|
||||||
mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
|
mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
|
||||||
mov(cb, mem_opnd(64, REG_SP, -SIZEOF_VALUE), REG0);
|
mov(cb, mem_opnd(64, REG_SP, -SIZEOF_VALUE), REG0);
|
||||||
|
|
||||||
// Jump to the JIT return address in the frame that was popped
|
// Jump to the JIT return address on the frame that was just popped
|
||||||
const int32_t offset_to_jit_return = -((int32_t)sizeof(rb_control_frame_t)) + (int32_t)offsetof(rb_control_frame_t, jit_return);
|
const int32_t offset_to_jit_return = -((int32_t)sizeof(rb_control_frame_t)) + (int32_t)offsetof(rb_control_frame_t, jit_return);
|
||||||
jmp_rm(cb, mem_opnd(64, REG_CFP, offset_to_jit_return));
|
jmp_rm(cb, mem_opnd(64, REG_CFP, offset_to_jit_return));
|
||||||
|
|
||||||
|
@ -2173,8 +2172,8 @@ yjit_init_codegen(void)
|
||||||
ocb = &outline_block;
|
ocb = &outline_block;
|
||||||
cb_init(ocb, mem_block + mem_size/2, mem_size/2);
|
cb_init(ocb, mem_block + mem_size/2, mem_size/2);
|
||||||
|
|
||||||
// Generate interp_exit
|
// Generate the interpreter exit code for leave
|
||||||
interp_exit = yjit_gen_context_free_exit(cb);
|
leave_exit_code = yjit_gen_leave_exit(cb);
|
||||||
|
|
||||||
// Map YARV opcodes to the corresponding codegen functions
|
// Map YARV opcodes to the corresponding codegen functions
|
||||||
yjit_reg_op(BIN(dup), gen_dup);
|
yjit_reg_op(BIN(dup), gen_dup);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче