mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
mjit.c: make some variables static again
and remove redundant mjit_ prefixes. mjit_worker.c: ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64290 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a48d1d7991
commit
3c442229d6
2 changed files with 138 additions and 161 deletions
136
mjit.c
136
mjit.c
|
@ -1,6 +1,6 @@
|
|||
/**********************************************************************
|
||||
|
||||
mjit.c - Interface to MRI method JIT compiler for Ruby's main thread
|
||||
mjit.c - MRI method JIT compiler functions for Ruby's main thread
|
||||
|
||||
Copyright (C) 2017 Vladimir Makarov <vmakarov@redhat.com>.
|
||||
|
||||
|
@ -17,52 +17,6 @@
|
|||
|
||||
extern int rb_thread_create_mjit_thread(void (*worker_func)(void));
|
||||
|
||||
/* A copy of MJIT portion of MRI options since MJIT initialization. We
|
||||
need them as MJIT threads still can work when the most MRI data were
|
||||
freed. */
|
||||
struct mjit_options mjit_opts;
|
||||
|
||||
/* TRUE if MJIT is enabled. */
|
||||
int mjit_enabled = FALSE;
|
||||
/* TRUE if JIT-ed code should be called. When `ruby_vm_event_enabled_flags & ISEQ_TRACE_EVENTS`
|
||||
and `mjit_call_p == FALSE`, any JIT-ed code execution is cancelled as soon as possible. */
|
||||
int mjit_call_p = FALSE;
|
||||
|
||||
/* Priority queue of iseqs waiting for JIT compilation.
|
||||
This variable is a pointer to head unit of the queue. */
|
||||
struct rb_mjit_unit_list mjit_unit_queue;
|
||||
/* List of units which are successfully compiled. */
|
||||
struct rb_mjit_unit_list mjit_active_units;
|
||||
/* List of compacted so files which will be deleted in `mjit_finish()`. */
|
||||
struct rb_mjit_unit_list mjit_compact_units;
|
||||
/* The number of so far processed ISEQs, used to generate unique id. */
|
||||
int mjit_current_unit_num;
|
||||
/* A mutex for conitionals and critical sections. */
|
||||
rb_nativethread_lock_t mjit_engine_mutex;
|
||||
/* A thread conditional to wake up `mjit_finish` at the end of PCH thread. */
|
||||
rb_nativethread_cond_t mjit_pch_wakeup;
|
||||
/* A thread conditional to wake up the client if there is a change in
|
||||
executed unit status. */
|
||||
rb_nativethread_cond_t mjit_client_wakeup;
|
||||
/* A thread conditional to wake up a worker if there we have something
|
||||
to add or we need to stop MJIT engine. */
|
||||
rb_nativethread_cond_t mjit_worker_wakeup;
|
||||
/* A thread conditional to wake up workers if at the end of GC. */
|
||||
rb_nativethread_cond_t mjit_gc_wakeup;
|
||||
/* True when GC is working. */
|
||||
int mjit_in_gc;
|
||||
/* True when JIT is working. */
|
||||
int mjit_in_jit;
|
||||
|
||||
/* Path of "/tmp", which can be changed to $TMP in MinGW. */
|
||||
char *mjit_tmp_dir;
|
||||
/* Hash like { 1 => true, 2 => true, ... } whose keys are valid `class_serial`s.
|
||||
This is used to invalidate obsoleted CALL_CACHE. */
|
||||
VALUE mjit_valid_class_serials;
|
||||
|
||||
extern const char *mjit_cc_path;
|
||||
extern char *mjit_pch_file;
|
||||
|
||||
#ifndef _MSC_VER
|
||||
/* Name of the header file. */
|
||||
extern char *mjit_header_file;
|
||||
|
@ -152,7 +106,7 @@ init_list(struct rb_mjit_unit_list *list)
|
|||
}
|
||||
|
||||
/* Free unit list. This should be called only when worker is finished
|
||||
because node of mjit_unit_queue and one of mjit_active_units may have the same unit
|
||||
because node of unit_queue and one of active_units may have the same unit
|
||||
during proceeding unit. */
|
||||
static void
|
||||
free_list(struct rb_mjit_unit_list *list)
|
||||
|
@ -246,7 +200,7 @@ create_unit(const rb_iseq_t *iseq)
|
|||
if (unit == NULL)
|
||||
return;
|
||||
|
||||
unit->id = mjit_current_unit_num++;
|
||||
unit->id = current_unit_num++;
|
||||
unit->iseq = iseq;
|
||||
iseq->body->jit_unit = unit;
|
||||
}
|
||||
|
@ -283,20 +237,20 @@ unload_units(void)
|
|||
rb_thread_t *th = NULL;
|
||||
struct rb_mjit_unit_node *node, *next, *worst_node;
|
||||
struct mjit_cont *cont;
|
||||
int delete_num, units_num = mjit_active_units.length;
|
||||
int delete_num, units_num = active_units.length;
|
||||
|
||||
/* For now, we don't unload units when ISeq is GCed. We should
|
||||
unload such ISeqs first here. */
|
||||
for (node = mjit_active_units.head; node != NULL; node = next) {
|
||||
for (node = active_units.head; node != NULL; node = next) {
|
||||
next = node->next;
|
||||
if (node->unit->iseq == NULL) { /* ISeq is GCed. */
|
||||
free_unit(node->unit);
|
||||
remove_from_list(node, &mjit_active_units);
|
||||
remove_from_list(node, &active_units);
|
||||
}
|
||||
}
|
||||
|
||||
/* Detect units which are in use and can't be unloaded. */
|
||||
for (node = mjit_active_units.head; node != NULL; node = node->next) {
|
||||
for (node = active_units.head; node != NULL; node = node->next) {
|
||||
assert(node->unit != NULL && node->unit->iseq != NULL && node->unit->handle != NULL);
|
||||
node->unit->used_code_p = FALSE;
|
||||
}
|
||||
|
@ -308,13 +262,13 @@ unload_units(void)
|
|||
}
|
||||
|
||||
/* Remove 1/10 units more to decrease unloading calls. */
|
||||
/* TODO: Calculate max total_calls in mjit_unit_queue and don't unload units
|
||||
/* TODO: Calculate max total_calls in unit_queue and don't unload units
|
||||
whose total_calls are larger than the max. */
|
||||
delete_num = mjit_active_units.length / 10;
|
||||
for (; mjit_active_units.length > mjit_opts.max_cache_size - delete_num;) {
|
||||
delete_num = active_units.length / 10;
|
||||
for (; active_units.length > mjit_opts.max_cache_size - delete_num;) {
|
||||
/* Find one unit that has the minimum total_calls. */
|
||||
worst_node = NULL;
|
||||
for (node = mjit_active_units.head; node != NULL; node = node->next) {
|
||||
for (node = active_units.head; node != NULL; node = node->next) {
|
||||
if (node->unit->used_code_p) /* We can't unload code on stack. */
|
||||
continue;
|
||||
|
||||
|
@ -329,9 +283,9 @@ unload_units(void)
|
|||
verbose(2, "Unloading unit %d (calls=%lu)", worst_node->unit->id, worst_node->unit->iseq->body->total_calls);
|
||||
assert(worst_node->unit->handle != NULL);
|
||||
free_unit(worst_node->unit);
|
||||
remove_from_list(worst_node, &mjit_active_units);
|
||||
remove_from_list(worst_node, &active_units);
|
||||
}
|
||||
verbose(1, "Too many JIT code -- %d units unloaded", units_num - mjit_active_units.length);
|
||||
verbose(1, "Too many JIT code -- %d units unloaded", units_num - active_units.length);
|
||||
}
|
||||
|
||||
/* Add ISEQ to be JITed in parallel with the current thread.
|
||||
|
@ -352,8 +306,8 @@ mjit_add_iseq_to_process(const rb_iseq_t *iseq)
|
|||
|
||||
node = create_list_node(iseq->body->jit_unit);
|
||||
CRITICAL_SECTION_START(3, "in add_iseq_to_process");
|
||||
add_to_list(node, &mjit_unit_queue);
|
||||
if (mjit_active_units.length >= mjit_opts.max_cache_size) {
|
||||
add_to_list(node, &unit_queue);
|
||||
if (active_units.length >= mjit_opts.max_cache_size) {
|
||||
unload_units();
|
||||
}
|
||||
verbose(3, "Sending wakeup signal to workers in mjit_add_iseq_to_process");
|
||||
|
@ -394,7 +348,7 @@ mjit_get_iseq_func(struct rb_iseq_constant_body *body)
|
|||
|
||||
extern VALUE ruby_archlibdir_path, ruby_prefix_path;
|
||||
|
||||
/* Initialize mjit_header_file, mjit_pch_file, mjit_libruby_pathflag. Return TRUE on success. */
|
||||
/* Initialize mjit_header_file, pch_file, mjit_libruby_pathflag. Return TRUE on success. */
|
||||
static int
|
||||
init_header_filename(void)
|
||||
{
|
||||
|
@ -447,21 +401,21 @@ init_header_filename(void)
|
|||
(void)close(fd);
|
||||
}
|
||||
|
||||
mjit_pch_file = get_uniq_filename(0, MJIT_TMP_PREFIX "h", ".h.gch");
|
||||
if (mjit_pch_file == NULL)
|
||||
pch_file = get_uniq_filename(0, MJIT_TMP_PREFIX "h", ".h.gch");
|
||||
if (pch_file == NULL)
|
||||
return FALSE;
|
||||
#else
|
||||
{
|
||||
static const char pch_name[] = MJIT_PRECOMPILED_HEADER_NAME;
|
||||
const size_t pch_name_len = sizeof(pch_name) - 1;
|
||||
|
||||
mjit_pch_file = xmalloc(baselen + pch_name_len + 1);
|
||||
p = append_str2(mjit_pch_file, basedir, baselen);
|
||||
pch_file = xmalloc(baselen + pch_name_len + 1);
|
||||
p = append_str2(pch_file, basedir, baselen);
|
||||
p = append_str2(p, pch_name, pch_name_len + 1);
|
||||
if ((fd = rb_cloexec_open(mjit_pch_file, O_RDONLY, 0)) < 0) {
|
||||
verbose(1, "Cannot access precompiled header file: %s", mjit_pch_file);
|
||||
xfree(mjit_pch_file);
|
||||
mjit_pch_file = NULL;
|
||||
if ((fd = rb_cloexec_open(pch_file, O_RDONLY, 0)) < 0) {
|
||||
verbose(1, "Cannot access precompiled header file: %s", pch_file);
|
||||
xfree(pch_file);
|
||||
pch_file = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
(void)close(fd);
|
||||
|
@ -638,10 +592,10 @@ mjit_init(struct mjit_options *opts)
|
|||
#else
|
||||
mjit_pch_status = PCH_NOT_READY;
|
||||
#endif
|
||||
mjit_cc_path = CC_PATH;
|
||||
cc_path = CC_PATH;
|
||||
|
||||
mjit_tmp_dir = system_tmpdir();
|
||||
verbose(2, "MJIT: mjit_tmp_dir is %s", mjit_tmp_dir);
|
||||
tmp_dir = system_tmpdir();
|
||||
verbose(2, "MJIT: tmp_dir is %s", tmp_dir);
|
||||
|
||||
if (!init_header_filename()) {
|
||||
mjit_enabled = FALSE;
|
||||
|
@ -649,9 +603,9 @@ mjit_init(struct mjit_options *opts)
|
|||
return;
|
||||
}
|
||||
|
||||
init_list(&mjit_unit_queue);
|
||||
init_list(&mjit_active_units);
|
||||
init_list(&mjit_compact_units);
|
||||
init_list(&unit_queue);
|
||||
init_list(&active_units);
|
||||
init_list(&compact_units);
|
||||
|
||||
/* Initialize mutex */
|
||||
rb_native_mutex_initialize(&mjit_engine_mutex);
|
||||
|
@ -661,9 +615,9 @@ mjit_init(struct mjit_options *opts)
|
|||
rb_native_cond_initialize(&mjit_gc_wakeup);
|
||||
|
||||
/* Initialize class_serials cache for compilation */
|
||||
mjit_valid_class_serials = rb_hash_new();
|
||||
rb_obj_hide(mjit_valid_class_serials);
|
||||
rb_gc_register_mark_object(mjit_valid_class_serials);
|
||||
valid_class_serials = rb_hash_new();
|
||||
rb_obj_hide(valid_class_serials);
|
||||
rb_gc_register_mark_object(valid_class_serials);
|
||||
mjit_add_class_serial(RCLASS_SERIAL(rb_cObject));
|
||||
mjit_add_class_serial(RCLASS_SERIAL(CLASS_OF(rb_vm_top_self())));
|
||||
if (RCLASS_CONST_TBL(rb_cObject)) {
|
||||
|
@ -706,7 +660,7 @@ mjit_pause(int wait_p)
|
|||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1000;
|
||||
|
||||
while (mjit_unit_queue.length > 0) {
|
||||
while (unit_queue.length > 0) {
|
||||
CRITICAL_SECTION_START(3, "in mjit_pause for a worker wakeup");
|
||||
rb_native_cond_broadcast(&mjit_worker_wakeup);
|
||||
CRITICAL_SECTION_FINISH(3, "in mjit_pause for a worker wakeup");
|
||||
|
@ -769,17 +723,17 @@ mjit_finish(void)
|
|||
|
||||
#ifndef _MSC_VER /* mswin has prebuilt precompiled header */
|
||||
if (!mjit_opts.save_temps)
|
||||
remove_file(mjit_pch_file);
|
||||
remove_file(pch_file);
|
||||
|
||||
xfree(mjit_header_file); mjit_header_file = NULL;
|
||||
#endif
|
||||
xfree(mjit_tmp_dir); mjit_tmp_dir = NULL;
|
||||
xfree(mjit_pch_file); mjit_pch_file = NULL;
|
||||
xfree(tmp_dir); tmp_dir = NULL;
|
||||
xfree(pch_file); pch_file = NULL;
|
||||
|
||||
mjit_call_p = FALSE;
|
||||
free_list(&mjit_unit_queue);
|
||||
free_list(&mjit_active_units);
|
||||
free_list(&mjit_compact_units);
|
||||
free_list(&unit_queue);
|
||||
free_list(&active_units);
|
||||
free_list(&compact_units);
|
||||
finish_conts();
|
||||
|
||||
mjit_enabled = FALSE;
|
||||
|
@ -794,7 +748,7 @@ mjit_mark(void)
|
|||
return;
|
||||
RUBY_MARK_ENTER("mjit");
|
||||
CRITICAL_SECTION_START(4, "mjit_mark");
|
||||
for (node = mjit_unit_queue.head; node != NULL; node = node->next) {
|
||||
for (node = unit_queue.head; node != NULL; node = node->next) {
|
||||
if (node->unit->iseq) { /* ISeq is still not GCed */
|
||||
VALUE iseq = (VALUE)node->unit->iseq;
|
||||
CRITICAL_SECTION_FINISH(4, "mjit_mark rb_gc_mark");
|
||||
|
@ -810,7 +764,7 @@ mjit_mark(void)
|
|||
RUBY_MARK_LEAVE("mjit");
|
||||
}
|
||||
|
||||
/* A hook to update mjit_valid_class_serials. */
|
||||
/* A hook to update valid_class_serials. */
|
||||
void
|
||||
mjit_add_class_serial(rb_serial_t class_serial)
|
||||
{
|
||||
|
@ -819,10 +773,10 @@ mjit_add_class_serial(rb_serial_t class_serial)
|
|||
|
||||
/* Do not wrap CRITICAL_SECTION here. This function is only called in main thread
|
||||
and guarded by GVL, and `rb_hash_aset` may cause GC and deadlock in it. */
|
||||
rb_hash_aset(mjit_valid_class_serials, LONG2FIX(class_serial), Qtrue);
|
||||
rb_hash_aset(valid_class_serials, LONG2FIX(class_serial), Qtrue);
|
||||
}
|
||||
|
||||
/* A hook to update mjit_valid_class_serials. */
|
||||
/* A hook to update valid_class_serials. */
|
||||
void
|
||||
mjit_remove_class_serial(rb_serial_t class_serial)
|
||||
{
|
||||
|
@ -830,6 +784,6 @@ mjit_remove_class_serial(rb_serial_t class_serial)
|
|||
return;
|
||||
|
||||
CRITICAL_SECTION_START(3, "in mjit_remove_class_serial");
|
||||
rb_hash_delete_entry(mjit_valid_class_serials, LONG2FIX(class_serial));
|
||||
rb_hash_delete_entry(valid_class_serials, LONG2FIX(class_serial));
|
||||
CRITICAL_SECTION_FINISH(3, "in mjit_remove_class_serial");
|
||||
}
|
||||
|
|
163
mjit_worker.c
163
mjit_worker.c
|
@ -157,14 +157,6 @@ extern void rb_native_cond_signal(rb_nativethread_cond_t *cond);
|
|||
extern void rb_native_cond_broadcast(rb_nativethread_cond_t *cond);
|
||||
extern void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex);
|
||||
|
||||
extern char *mjit_tmp_dir;
|
||||
|
||||
static int
|
||||
sprint_uniq_filename(char *str, size_t size, unsigned long id, const char *prefix, const char *suffix)
|
||||
{
|
||||
return snprintf(str, size, "%s/%sp%"PRI_PIDT_PREFIX"uu%lu%s", mjit_tmp_dir, prefix, getpid(), id, suffix);
|
||||
}
|
||||
|
||||
/* Print the arguments according to FORMAT to stderr only if MJIT
|
||||
verbose option value is more or equal to LEVEL. */
|
||||
PRINTF_ARGS(static void, 2, 3)
|
||||
|
@ -180,27 +172,6 @@ verbose(int level, const char *format, ...)
|
|||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
extern rb_nativethread_lock_t mjit_engine_mutex;
|
||||
|
||||
/* Start a critical section. Use message MSG to print debug info at
|
||||
LEVEL. */
|
||||
static inline void
|
||||
CRITICAL_SECTION_START(int level, const char *msg)
|
||||
{
|
||||
verbose(level, "Locking %s", msg);
|
||||
rb_native_mutex_lock(&mjit_engine_mutex);
|
||||
verbose(level, "Locked %s", msg);
|
||||
}
|
||||
|
||||
/* Finish the current critical section. Use message MSG to print
|
||||
debug info at LEVEL. */
|
||||
static inline void
|
||||
CRITICAL_SECTION_FINISH(int level, const char *msg)
|
||||
{
|
||||
verbose(level, "Unlocked %s", msg);
|
||||
rb_native_mutex_unlock(&mjit_engine_mutex);
|
||||
}
|
||||
|
||||
/* Allocate struct rb_mjit_unit_node and return it. This MUST NOT be
|
||||
called inside critical section because that causes deadlock. ZALLOC
|
||||
may fire GC and GC hooks mjit_gc_start_hook that starts critical section. */
|
||||
|
@ -351,26 +322,54 @@ rb_pid_t ruby_waitpid_locked(rb_vm_t *, rb_pid_t, int *status, int options,
|
|||
/* Atomically set function pointer if possible. */
|
||||
#define MJIT_ATOMIC_SET(var, val) (void)ATOMIC_PTR_EXCHANGE(var, val)
|
||||
|
||||
extern struct mjit_options mjit_opts;
|
||||
extern int mjit_enabled;
|
||||
/* A copy of MJIT portion of MRI options since MJIT initialization. We
|
||||
need them as MJIT threads still can work when the most MRI data were
|
||||
freed. */
|
||||
struct mjit_options mjit_opts;
|
||||
|
||||
extern struct rb_mjit_unit_list mjit_unit_queue;
|
||||
extern struct rb_mjit_unit_list mjit_active_units;
|
||||
extern struct rb_mjit_unit_list mjit_compact_units;
|
||||
extern int mjit_current_unit_num;
|
||||
extern rb_nativethread_cond_t mjit_pch_wakeup;
|
||||
extern rb_nativethread_cond_t mjit_client_wakeup;
|
||||
extern rb_nativethread_cond_t mjit_worker_wakeup;
|
||||
extern rb_nativethread_cond_t mjit_gc_wakeup;
|
||||
/* TRUE if MJIT is enabled. */
|
||||
int mjit_enabled = FALSE;
|
||||
/* TRUE if JIT-ed code should be called. When `ruby_vm_event_enabled_flags & ISEQ_TRACE_EVENTS`
|
||||
and `mjit_call_p == FALSE`, any JIT-ed code execution is cancelled as soon as possible. */
|
||||
int mjit_call_p = FALSE;
|
||||
|
||||
extern int mjit_in_gc;
|
||||
extern int mjit_in_jit;
|
||||
/* Priority queue of iseqs waiting for JIT compilation.
|
||||
This variable is a pointer to head unit of the queue. */
|
||||
static struct rb_mjit_unit_list unit_queue;
|
||||
/* List of units which are successfully compiled. */
|
||||
static struct rb_mjit_unit_list active_units;
|
||||
/* List of compacted so files which will be deleted in `mjit_finish()`. */
|
||||
static struct rb_mjit_unit_list compact_units;
|
||||
/* The number of so far processed ISEQs, used to generate unique id. */
|
||||
static int current_unit_num;
|
||||
/* A mutex for conitionals and critical sections. */
|
||||
static rb_nativethread_lock_t mjit_engine_mutex;
|
||||
/* A thread conditional to wake up `mjit_finish` at the end of PCH thread. */
|
||||
static rb_nativethread_cond_t mjit_pch_wakeup;
|
||||
/* A thread conditional to wake up the client if there is a change in
|
||||
executed unit status. */
|
||||
static rb_nativethread_cond_t mjit_client_wakeup;
|
||||
/* A thread conditional to wake up a worker if there we have something
|
||||
to add or we need to stop MJIT engine. */
|
||||
static rb_nativethread_cond_t mjit_worker_wakeup;
|
||||
/* A thread conditional to wake up workers if at the end of GC. */
|
||||
static rb_nativethread_cond_t mjit_gc_wakeup;
|
||||
/* True when GC is working. */
|
||||
static int mjit_in_gc;
|
||||
/* True when JIT is working. */
|
||||
static int mjit_in_jit;
|
||||
|
||||
/* Path of "/tmp", which can be changed to $TMP in MinGW. */
|
||||
static char *tmp_dir;
|
||||
/* Hash like { 1 => true, 2 => true, ... } whose keys are valid `class_serial`s.
|
||||
This is used to invalidate obsoleted CALL_CACHE. */
|
||||
static VALUE valid_class_serials;
|
||||
|
||||
/* --- Defined in the client thread before starting MJIT threads: --- */
|
||||
/* Used C compiler path. */
|
||||
const char *mjit_cc_path;
|
||||
const char *cc_path;
|
||||
/* Name of the precompiled header file. */
|
||||
char *mjit_pch_file;
|
||||
char *pch_file;
|
||||
|
||||
#ifndef _MSC_VER
|
||||
/* Name of the header file. */
|
||||
|
@ -382,6 +381,31 @@ char *mjit_header_file;
|
|||
char *mjit_libruby_pathflag;
|
||||
#endif
|
||||
|
||||
/* Start a critical section. Use message MSG to print debug info at
|
||||
LEVEL. */
|
||||
static inline void
|
||||
CRITICAL_SECTION_START(int level, const char *msg)
|
||||
{
|
||||
verbose(level, "Locking %s", msg);
|
||||
rb_native_mutex_lock(&mjit_engine_mutex);
|
||||
verbose(level, "Locked %s", msg);
|
||||
}
|
||||
|
||||
/* Finish the current critical section. Use message MSG to print
|
||||
debug info at LEVEL. */
|
||||
static inline void
|
||||
CRITICAL_SECTION_FINISH(int level, const char *msg)
|
||||
{
|
||||
verbose(level, "Unlocked %s", msg);
|
||||
rb_native_mutex_unlock(&mjit_engine_mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
sprint_uniq_filename(char *str, size_t size, unsigned long id, const char *prefix, const char *suffix)
|
||||
{
|
||||
return snprintf(str, size, "%s/%sp%"PRI_PIDT_PREFIX"uu%lu%s", tmp_dir, prefix, getpid(), id, suffix);
|
||||
}
|
||||
|
||||
/* Return time in milliseconds as a double. */
|
||||
#ifdef __APPLE__
|
||||
double ruby_real_ms_time(void);
|
||||
|
@ -447,11 +471,10 @@ enum pch_status_t mjit_pch_status;
|
|||
int
|
||||
mjit_valid_class_serial_p(rb_serial_t class_serial)
|
||||
{
|
||||
extern VALUE mjit_valid_class_serials;
|
||||
int found_p;
|
||||
|
||||
CRITICAL_SECTION_START(3, "in valid_class_serial_p");
|
||||
found_p = st_lookup(RHASH_TBL_RAW(mjit_valid_class_serials), LONG2FIX(class_serial), NULL);
|
||||
found_p = st_lookup(RHASH_TBL_RAW(valid_class_serials), LONG2FIX(class_serial), NULL);
|
||||
CRITICAL_SECTION_FINISH(3, "in valid_class_serial_p");
|
||||
return found_p;
|
||||
}
|
||||
|
@ -648,14 +671,14 @@ compile_c_to_so(const char *c_file, const char *so_file)
|
|||
*p = '\0';
|
||||
|
||||
/* files[1] = "-Yu*.pch" */
|
||||
files[1] = p = (char *)alloca(sizeof(char) * (rb_strlen_lit("-Yu") + strlen(mjit_pch_file) + 1));
|
||||
files[1] = p = (char *)alloca(sizeof(char) * (rb_strlen_lit("-Yu") + strlen(pch_file) + 1));
|
||||
p = append_lit(p, "-Yu");
|
||||
p = append_str2(p, mjit_pch_file, strlen(mjit_pch_file));
|
||||
p = append_str2(p, pch_file, strlen(pch_file));
|
||||
*p = '\0';
|
||||
|
||||
/* files[2] = "C:/.../rb_mjit_header-*.obj" */
|
||||
files[2] = p = (char *)alloca(sizeof(char) * (strlen(mjit_pch_file) + 1));
|
||||
p = append_str2(p, mjit_pch_file, strlen(mjit_pch_file) - strlen(".pch"));
|
||||
files[2] = p = (char *)alloca(sizeof(char) * (strlen(pch_file) + 1));
|
||||
p = append_str2(p, pch_file, strlen(pch_file) - strlen(".pch"));
|
||||
p = append_lit(p, ".obj");
|
||||
*p = '\0';
|
||||
|
||||
|
@ -680,7 +703,7 @@ compile_c_to_so(const char *c_file, const char *so_file)
|
|||
Creating library C:.../_ruby_mjit_p12u3.lib and object C:.../_ruby_mjit_p12u3.exp
|
||||
TODO: Don't discard them on --jit-verbose=2+ */
|
||||
dup2(dev_null, stdout_fileno);
|
||||
exit_code = exec_process(mjit_cc_path, args);
|
||||
exit_code = exec_process(cc_path, args);
|
||||
dup2(orig_fd, stdout_fileno);
|
||||
|
||||
close(orig_fd);
|
||||
|
@ -710,7 +733,7 @@ make_pch(void)
|
|||
int len = sizeof(rest_args) / sizeof(const char *);
|
||||
|
||||
rest_args[len - 2] = mjit_header_file;
|
||||
rest_args[len - 3] = mjit_pch_file;
|
||||
rest_args[len - 3] = pch_file;
|
||||
verbose(2, "Creating precompiled header");
|
||||
args = form_args(3, CC_COMMON_ARGS, CC_CODEFLAG_ARGS, rest_args);
|
||||
if (args == NULL) {
|
||||
|
@ -722,7 +745,7 @@ make_pch(void)
|
|||
return;
|
||||
}
|
||||
|
||||
exit_code = exec_process(mjit_cc_path, args);
|
||||
exit_code = exec_process(cc_path, args);
|
||||
free(args);
|
||||
|
||||
CRITICAL_SECTION_START(3, "in make_pch");
|
||||
|
@ -755,13 +778,13 @@ compile_c_to_o(const char *c_file, const char *o_file)
|
|||
files[1] = o_file;
|
||||
files[2] = c_file;
|
||||
# ifdef __clang__
|
||||
files[4] = mjit_pch_file;
|
||||
files[4] = pch_file;
|
||||
# endif
|
||||
args = form_args(5, CC_COMMON_ARGS, CC_CODEFLAG_ARGS, files, CC_LIBS, CC_DLDFLAGS_ARGS);
|
||||
if (args == NULL)
|
||||
return FALSE;
|
||||
|
||||
exit_code = exec_process(mjit_cc_path, args);
|
||||
exit_code = exec_process(cc_path, args);
|
||||
free(args);
|
||||
|
||||
if (exit_code != 0)
|
||||
|
@ -789,7 +812,7 @@ link_o_to_so(const char **o_files, const char *so_file)
|
|||
if (args == NULL)
|
||||
return FALSE;
|
||||
|
||||
exit_code = exec_process(mjit_cc_path, args);
|
||||
exit_code = exec_process(cc_path, args);
|
||||
free(args);
|
||||
|
||||
if (exit_code != 0)
|
||||
|
@ -814,14 +837,14 @@ compact_all_jit_code(void)
|
|||
/* Abnormal use case of rb_mjit_unit that doesn't have ISeq */
|
||||
unit = (struct rb_mjit_unit *)calloc(1, sizeof(struct rb_mjit_unit)); /* To prevent GC, don't use ZALLOC */
|
||||
if (unit == NULL) return;
|
||||
unit->id = mjit_current_unit_num++;
|
||||
unit->id = current_unit_num++;
|
||||
sprint_uniq_filename(so_file, (int)sizeof(so_file), unit->id, MJIT_TMP_PREFIX, so_ext);
|
||||
|
||||
/* NULL-ending for form_args */
|
||||
o_files = (const char **)alloca(sizeof(char *) * (mjit_active_units.length + 1));
|
||||
o_files[mjit_active_units.length] = NULL;
|
||||
o_files = (const char **)alloca(sizeof(char *) * (active_units.length + 1));
|
||||
o_files[active_units.length] = NULL;
|
||||
CRITICAL_SECTION_START(3, "in compact_all_jit_code to keep .o files");
|
||||
for (node = mjit_active_units.head; node != NULL; node = node->next) {
|
||||
for (node = active_units.head; node != NULL; node = node->next) {
|
||||
o_files[i] = node->unit->o_file;
|
||||
i++;
|
||||
}
|
||||
|
@ -849,7 +872,7 @@ compact_all_jit_code(void)
|
|||
/* lazily dlclose handle (and .so file for win32) on `mjit_finish()`. */
|
||||
node = (struct rb_mjit_unit_node *)calloc(1, sizeof(struct rb_mjit_unit_node)); /* To prevent GC, don't use ZALLOC */
|
||||
node->unit = unit;
|
||||
add_to_list(node, &mjit_compact_units);
|
||||
add_to_list(node, &compact_units);
|
||||
|
||||
if (!mjit_opts.save_temps) {
|
||||
# ifdef _WIN32
|
||||
|
@ -860,7 +883,7 @@ compact_all_jit_code(void)
|
|||
}
|
||||
|
||||
CRITICAL_SECTION_START(3, "in compact_all_jit_code to read list");
|
||||
for (node = mjit_active_units.head; node != NULL; node = node->next) {
|
||||
for (node = active_units.head; node != NULL; node = node->next) {
|
||||
void *func;
|
||||
char funcname[35]; /* TODO: reconsider `35` */
|
||||
sprintf(funcname, "_mjit%d", node->unit->id);
|
||||
|
@ -877,7 +900,7 @@ compact_all_jit_code(void)
|
|||
}
|
||||
}
|
||||
CRITICAL_SECTION_FINISH(3, "in compact_all_jit_code to read list");
|
||||
verbose(1, "JIT compaction (%.1fms): Compacted %d methods -> %s", end_time - start_time, mjit_active_units.length, so_file);
|
||||
verbose(1, "JIT compaction (%.1fms): Compacted %d methods -> %s", end_time - start_time, active_units.length, so_file);
|
||||
}
|
||||
else {
|
||||
free(unit);
|
||||
|
@ -935,11 +958,11 @@ static void
|
|||
compile_prelude(FILE *f)
|
||||
{
|
||||
#ifndef __clang__ /* -include-pch is used for Clang */
|
||||
const char *s = mjit_pch_file;
|
||||
const char *s = pch_file;
|
||||
const char *e = header_name_end(s);
|
||||
|
||||
fprintf(f, "#include \"");
|
||||
/* print mjit_pch_file except .gch for gcc, but keep .pch for mswin */
|
||||
/* print pch_file except .gch for gcc, but keep .pch for mswin */
|
||||
for (; s < e; s++) {
|
||||
switch(*s) {
|
||||
case '\\': case '"':
|
||||
|
@ -1079,7 +1102,7 @@ convert_unit_to_func(struct rb_mjit_unit *unit)
|
|||
if ((uintptr_t)func > (uintptr_t)LAST_JIT_ISEQ_FUNC) {
|
||||
struct rb_mjit_unit_node *node = create_list_node(unit);
|
||||
CRITICAL_SECTION_START(3, "end of jit");
|
||||
add_to_list(node, &mjit_active_units);
|
||||
add_to_list(node, &active_units);
|
||||
if (unit->iseq)
|
||||
print_jit_result("success", unit, end_time - start_time, c_file);
|
||||
CRITICAL_SECTION_FINISH(3, "end of jit");
|
||||
|
@ -1119,11 +1142,11 @@ mjit_worker(void)
|
|||
|
||||
/* wait until unit is available */
|
||||
CRITICAL_SECTION_START(3, "in worker dequeue");
|
||||
while ((mjit_unit_queue.head == NULL || mjit_active_units.length > mjit_opts.max_cache_size) && !mjit_stop_worker_p) {
|
||||
while ((unit_queue.head == NULL || active_units.length > mjit_opts.max_cache_size) && !mjit_stop_worker_p) {
|
||||
rb_native_cond_wait(&mjit_worker_wakeup, &mjit_engine_mutex);
|
||||
verbose(3, "Getting wakeup from client");
|
||||
}
|
||||
node = get_from_list(&mjit_unit_queue);
|
||||
node = get_from_list(&unit_queue);
|
||||
CRITICAL_SECTION_FINISH(3, "in worker dequeue");
|
||||
|
||||
if (node) {
|
||||
|
@ -1134,13 +1157,13 @@ mjit_worker(void)
|
|||
/* Usage of jit_code might be not in a critical section. */
|
||||
MJIT_ATOMIC_SET(node->unit->iseq->body->jit_func, func);
|
||||
}
|
||||
remove_from_list(node, &mjit_unit_queue);
|
||||
remove_from_list(node, &unit_queue);
|
||||
CRITICAL_SECTION_FINISH(3, "in jit func replace");
|
||||
|
||||
#ifndef _MSC_VER
|
||||
/* Combine .o files to one .so and reload all jit_func to improve memory locality */
|
||||
if ((!mjit_opts.wait && mjit_unit_queue.length == 0 && mjit_active_units.length > 1)
|
||||
|| mjit_active_units.length == mjit_opts.max_cache_size) {
|
||||
if ((!mjit_opts.wait && unit_queue.length == 0 && active_units.length > 1)
|
||||
|| active_units.length == mjit_opts.max_cache_size) {
|
||||
compact_all_jit_code();
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue