зеркало из https://github.com/github/ruby.git
Implement --ujit-stats and instructoin counting
VM and ujit instruction counting in debug builds. shopify/ruby#19
This commit is contained in:
Родитель
36232a48a6
Коммит
b7f93e81df
27
ruby.c
27
ruby.c
|
@ -189,6 +189,8 @@ struct ruby_cmdline_options {
|
|||
#if USE_MJIT
|
||||
struct mjit_options mjit;
|
||||
#endif
|
||||
struct rb_ujit_options ujit;
|
||||
|
||||
int sflag, xflag;
|
||||
unsigned int warning: 1;
|
||||
unsigned int verbose: 1;
|
||||
|
@ -1018,10 +1020,6 @@ set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen
|
|||
#define set_source_encoding_once(opt, e, elen) \
|
||||
set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
|
||||
|
||||
#if USE_MJIT
|
||||
static void
|
||||
setup_mjit_options(const char *s, struct mjit_options *mjit_opt)
|
||||
{
|
||||
#define opt_match(s, l, name) \
|
||||
((((l) > rb_strlen_lit(name)) ? (s)[rb_strlen_lit(name)] == '=' : \
|
||||
(l) == rb_strlen_lit(name)) && \
|
||||
|
@ -1031,6 +1029,24 @@ setup_mjit_options(const char *s, struct mjit_options *mjit_opt)
|
|||
opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --jit-" name " is ignored"), 1) : 1)
|
||||
#define opt_match_arg(s, l, name) \
|
||||
opt_match(s, l, name) && (*(s) ? 1 : (rb_raise(rb_eRuntimeError, "--jit-" name " needs an argument"), 0))
|
||||
|
||||
static void
|
||||
setup_ujit_options(const char *s, struct rb_ujit_options *ujit_opt)
|
||||
{
|
||||
*ujit_opt = (struct rb_ujit_options) { 0 };
|
||||
|
||||
if (*s != '-') return;
|
||||
const size_t l = strlen(++s);
|
||||
|
||||
if (opt_match_noarg(s, l, "stats")) {
|
||||
ujit_opt->gen_stats = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_MJIT
|
||||
static void
|
||||
setup_mjit_options(const char *s, struct mjit_options *mjit_opt)
|
||||
{
|
||||
if (*s != '-') return;
|
||||
const size_t l = strlen(++s);
|
||||
if (*s == 0) return;
|
||||
|
@ -1442,6 +1458,7 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
|
|||
}
|
||||
else if (strncmp("ujit", s, 4) == 0) {
|
||||
FEATURE_SET(opt->features, FEATURE_BIT(ujit));
|
||||
setup_ujit_options(s + 4, &opt->ujit);
|
||||
}
|
||||
else if (strcmp("yydebug", s) == 0) {
|
||||
if (envopt) goto noenvopt_long;
|
||||
|
@ -1804,7 +1821,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
|
|||
rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
|
||||
|
||||
if (opt->features.set & FEATURE_BIT(ujit))
|
||||
rb_ujit_init();
|
||||
rb_ujit_init(&opt->ujit);
|
||||
#if USE_MJIT
|
||||
if (opt->features.set & FEATURE_BIT(jit)) {
|
||||
opt->mjit.on = TRUE; /* set mjit.on for ruby_show_version() API and check to call mjit_init() */
|
||||
|
|
7
ujit.h
7
ujit.h
|
@ -31,6 +31,10 @@ typedef struct rb_iseq_struct rb_iseq_t;
|
|||
#define rb_iseq_t rb_iseq_t
|
||||
#endif
|
||||
|
||||
struct rb_ujit_options {
|
||||
bool gen_stats;
|
||||
};
|
||||
|
||||
RUBY_SYMBOL_EXPORT_BEGIN
|
||||
RUBY_EXTERN bool rb_ujit_enabled;
|
||||
RUBY_SYMBOL_EXPORT_END
|
||||
|
@ -44,8 +48,9 @@ bool rb_ujit_enabled_p(void)
|
|||
// Threshold==1 means compile on first execution
|
||||
#define UJIT_CALL_THRESHOLD (2u)
|
||||
|
||||
void rb_ujit_collect_vm_usage_insn(int insn);
|
||||
void rb_ujit_method_lookup_change(VALUE cme_or_cc);
|
||||
void rb_ujit_compile_iseq(const rb_iseq_t *iseq);
|
||||
void rb_ujit_init(void);
|
||||
void rb_ujit_init(struct rb_ujit_options *options);
|
||||
|
||||
#endif // #ifndef UJIT_H
|
||||
|
|
|
@ -179,6 +179,11 @@ ujit_gen_block(ctx_t* ctx, block_t* block)
|
|||
break;
|
||||
}
|
||||
|
||||
#if RUBY_DEBUG
|
||||
mov(cb, REG0, const_ptr_opnd((void *)&rb_ujit_exec_insns_count));
|
||||
add(cb, mem_opnd(64, REG0, 0), imm_opnd(1));
|
||||
#endif
|
||||
|
||||
//fprintf(stderr, "compiling %d: %s\n", insn_idx, insn_name(opcode));
|
||||
//print_str(cb, insn_name(opcode));
|
||||
|
||||
|
|
38
ujit_iface.c
38
ujit_iface.c
|
@ -23,8 +23,17 @@ VALUE cUjitBlock;
|
|||
VALUE cUjitDisasm;
|
||||
VALUE cUjitDisasmInsn;
|
||||
|
||||
bool rb_ujit_enabled;
|
||||
|
||||
static int64_t vm_insns_count = 0;
|
||||
int64_t rb_ujit_exec_insns_count = 0;
|
||||
|
||||
extern st_table * version_tbl;
|
||||
extern codeblock_t *cb;
|
||||
// Hash table of encoded instructions
|
||||
extern st_table *rb_encoded_insn_data;
|
||||
|
||||
struct rb_ujit_options rb_ujit_opts;
|
||||
|
||||
static const rb_data_type_t ujit_block_type = {
|
||||
"UJIT/Block",
|
||||
|
@ -32,11 +41,6 @@ static const rb_data_type_t ujit_block_type = {
|
|||
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
||||
};
|
||||
|
||||
bool rb_ujit_enabled;
|
||||
|
||||
// Hash table of encoded instructions
|
||||
extern st_table *rb_encoded_insn_data;
|
||||
|
||||
// Write the uJIT entry point pre-call bytes
|
||||
void
|
||||
cb_write_pre_call_bytes(codeblock_t* cb)
|
||||
|
@ -412,14 +416,36 @@ ujit_disasm(VALUE self, VALUE code, VALUE from)
|
|||
}
|
||||
#endif
|
||||
|
||||
__attribute__((destructor))
|
||||
static void
|
||||
print_ujit_stats(void)
|
||||
{
|
||||
if (rb_ujit_opts.gen_stats) {
|
||||
double double_ujit_exec_insns_count = rb_ujit_exec_insns_count;
|
||||
double total_insns_count = vm_insns_count + rb_ujit_exec_insns_count;
|
||||
double ratio = double_ujit_exec_insns_count / total_insns_count;
|
||||
|
||||
fprintf(stderr, "vm_insns_count: %10" PRId64 "\n", vm_insns_count);
|
||||
fprintf(stderr, "ujit_exec_insns_count: %10" PRId64 "\n", rb_ujit_exec_insns_count);
|
||||
fprintf(stderr, "ratio_in_ujit: %9.1f%%\n", ratio * 100);
|
||||
}
|
||||
}
|
||||
|
||||
void rb_ujit_collect_vm_usage_insn(int insn)
|
||||
{
|
||||
vm_insns_count++;
|
||||
}
|
||||
|
||||
void
|
||||
rb_ujit_init(void)
|
||||
rb_ujit_init(struct rb_ujit_options *options)
|
||||
{
|
||||
if (!ujit_scrape_successful || !PLATFORM_SUPPORTED_P)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rb_ujit_opts = *options;
|
||||
|
||||
rb_ujit_enabled = true;
|
||||
|
||||
ujit_init_core();
|
||||
|
|
|
@ -20,6 +20,9 @@ struct rb_callcache;
|
|||
#define rb_callcache rb_callcache
|
||||
#endif
|
||||
|
||||
RUBY_EXTERN struct rb_ujit_options rb_ujit_opts;
|
||||
RUBY_EXTERN int64_t rb_ujit_exec_insns_count;
|
||||
|
||||
void cb_write_pre_call_bytes(codeblock_t* cb);
|
||||
void cb_write_post_call_bytes(codeblock_t* cb);
|
||||
|
||||
|
|
13
vm.c
13
vm.c
|
@ -37,6 +37,7 @@
|
|||
#include "vm_insnhelper.h"
|
||||
#include "ractor_core.h"
|
||||
#include "vm_sync.h"
|
||||
#include "ujit.h"
|
||||
|
||||
#include "builtin.h"
|
||||
|
||||
|
@ -344,6 +345,10 @@ static void vm_collect_usage_insn(int insn);
|
|||
static void vm_collect_usage_register(int reg, int isset);
|
||||
#endif
|
||||
|
||||
#if RUBY_DEBUG
|
||||
static void vm_ujit_collect_usage_insn(int insn);
|
||||
#endif
|
||||
|
||||
static VALUE vm_make_env_object(const rb_execution_context_t *ec, rb_control_frame_t *cfp);
|
||||
extern VALUE rb_vm_invoke_bmethod(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self,
|
||||
int argc, const VALUE *argv, int kw_splat, VALUE block_handler,
|
||||
|
@ -4054,6 +4059,14 @@ MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_register)(int reg, int iss
|
|||
|
||||
#endif
|
||||
|
||||
#if RUBY_DEBUG
|
||||
static void
|
||||
vm_ujit_collect_usage_insn(int insn)
|
||||
{
|
||||
rb_ujit_collect_vm_usage_insn(insn);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if VM_COLLECT_USAGE_DETAILS
|
||||
/* @param insn instruction number */
|
||||
static void
|
||||
|
|
|
@ -25,6 +25,11 @@ MJIT_SYMBOL_EXPORT_END
|
|||
#define COLLECT_USAGE_OPERAND(insn, n, op) vm_collect_usage_operand((insn), (n), ((VALUE)(op)))
|
||||
|
||||
#define COLLECT_USAGE_REGISTER(reg, s) vm_collect_usage_register((reg), (s))
|
||||
#elif RUBY_DEBUG
|
||||
/* for --ujit-stats */
|
||||
#define COLLECT_USAGE_INSN(insn) vm_ujit_collect_usage_insn(insn)
|
||||
#define COLLECT_USAGE_OPERAND(insn, n, op) /* none */
|
||||
#define COLLECT_USAGE_REGISTER(reg, s) /* none */
|
||||
#else
|
||||
#define COLLECT_USAGE_INSN(insn) /* none */
|
||||
#define COLLECT_USAGE_OPERAND(insn, n, op) /* none */
|
||||
|
|
Загрузка…
Ссылка в новой задаче