25mjit_copy_job_handler(
void *data)
32 CRITICAL_SECTION_START(3,
"in mjit_copy_job_handler");
38 CRITICAL_SECTION_FINISH(3,
"in mjit_copy_job_handler");
43 CRITICAL_SECTION_FINISH(3,
"in mjit_copy_job_handler");
54 *sink++ = calls[
i].
cc;
57 *sink++ = kw_calls[
i].
cc;
66 CRITICAL_SECTION_FINISH(3,
"in mjit_copy_job_handler");
69extern int rb_thread_create_mjit_thread(
void (*worker_func)(
void));
75get_uniq_filename(
unsigned long id,
const char *prefix,
const char *suffix)
77 char buff[70], *
str = buff;
78 int size = sprint_uniq_filename(buff,
sizeof(buff),
id, prefix, suffix);
82 if (
size <= (
int)
sizeof(buff)) {
86 sprint_uniq_filename(
str,
size,
id, prefix, suffix);
98 CRITICAL_SECTION_START(4,
"mjit_gc_start_hook");
100 verbose(4,
"Waiting wakeup from a worker for GC");
102 verbose(4,
"Getting wakeup from a worker for GC");
105 CRITICAL_SECTION_FINISH(4,
"mjit_gc_start_hook");
115 CRITICAL_SECTION_START(4,
"mjit_gc_exit_hook");
117 verbose(4,
"Sending wakeup signal to workers after GC");
119 CRITICAL_SECTION_FINISH(4,
"mjit_gc_exit_hook");
129 CRITICAL_SECTION_START(4,
"mjit_update_references");
147 CRITICAL_SECTION_FINISH(4,
"mjit_update_references");
158 CRITICAL_SECTION_START(4,
"mjit_free_iseq");
159 if (mjit_copy_job.iseq ==
iseq) {
160 mjit_copy_job.iseq =
NULL;
176 CRITICAL_SECTION_FINISH(4,
"mjit_free_iseq");
191 if (
list == &stale_units) {
197 mjit_warning(
"failed to close handle for u%d: %s", unit->
id, dlerror());
199 clean_object_files(unit);
212 struct mjit_cont *prev, *next;
217static struct mjit_cont *first_cont;
224 struct mjit_cont *cont;
226 cont =
ZALLOC(
struct mjit_cont);
229 CRITICAL_SECTION_START(3,
"in mjit_cont_new");
230 if (first_cont ==
NULL) {
231 cont->next = cont->prev =
NULL;
235 cont->next = first_cont;
236 first_cont->prev = cont;
239 CRITICAL_SECTION_FINISH(3,
"in mjit_cont_new");
248 CRITICAL_SECTION_START(3,
"in mjit_cont_new");
249 if (cont == first_cont) {
250 first_cont = cont->next;
251 if (first_cont !=
NULL)
252 first_cont->prev =
NULL;
255 cont->prev->next = cont->next;
256 if (cont->next !=
NULL)
257 cont->next->prev = cont->prev;
259 CRITICAL_SECTION_FINISH(3,
"in mjit_cont_new");
268 struct mjit_cont *cont, *next;
270 for (cont = first_cont; cont !=
NULL; cont = next) {
286 unit->
id = current_unit_num++;
320 struct mjit_cont *cont;
321 int delete_num, units_num = active_units.length;
327 remove_from_list(unit, &active_units);
338 mark_ec_units(th->
ec);
340 for (cont = first_cont; cont !=
NULL; cont = cont->next) {
341 mark_ec_units(cont->ec);
348 delete_num = active_units.length / 10;
364 verbose(2,
"Unloading unit %d (calls=%lu)", worst->id, worst->iseq->body->total_calls);
366 remove_from_list(worst, &active_units);
375 verbose(1,
"Too many JIT code -- %d units unloaded", units_num - active_units.length);
390 if (compile_info !=
NULL)
393 CRITICAL_SECTION_START(3,
"in add_iseq_to_process");
398 verbose(3,
"Sending wakeup signal to workers in mjit_add_iseq_to_process");
400 CRITICAL_SECTION_FINISH(3,
"in add_iseq_to_process");
408 mjit_add_iseq_to_process(
iseq,
NULL);
412#define MJIT_WAIT_TIMEOUT_SECONDS 60
423 if (tries / 1000 > MJIT_WAIT_TIMEOUT_SECONDS || pch_status ==
PCH_FAILED) {
424 CRITICAL_SECTION_START(3,
"in rb_mjit_wait_call to set jit_func");
426 CRITICAL_SECTION_FINISH(3,
"in rb_mjit_wait_call to set jit_func");
431 CRITICAL_SECTION_START(3,
"in rb_mjit_wait_call for a client wakeup");
433 CRITICAL_SECTION_FINISH(3,
"in rb_mjit_wait_call for a client wakeup");
466 CRITICAL_SECTION_START(3,
"in rb_mjit_recompile_iseq");
470 CRITICAL_SECTION_FINISH(3,
"in rb_mjit_recompile_iseq");
482init_header_filename(
void)
489 const char *basedir =
"";
493 static const char libpathflag[] =
500 const size_t libpathflag_len =
sizeof(libpathflag) - 1;
508 if (
getenv(
"MJIT_SEARCH_BUILD_DIR")) {
518 else if (hdr[0] !=
'/') {
519 verbose(1,
"Non-absolute header file path: %s", hdr);
522 verbose(1,
"Non-file header file path: %s", hdr);
524 else if ((
st.st_uid !=
getuid()) || (
st.st_mode & 022) ||
526 verbose(1,
"Unsafe header file: uid=%ld mode=%#o %s",
527 (
long)
st.st_uid, (
unsigned)
st.st_mode, hdr);
536 verbose(3,
"MJIT_HEADER: %s", hdr);
538 if (!header_file)
return false;
547 const size_t header_name_len =
sizeof(header_name) - 1;
549 header_file =
xmalloc(baselen + header_name_len + 1);
551 p =
append_str2(p, header_name, header_name_len + 1);
554 verbose(1,
"Cannot access header file: %s", header_file);
566 const size_t pch_name_len =
sizeof(pch_name) - 1;
568 pch_file =
xmalloc(baselen + pch_name_len + 1);
572 verbose(1,
"Cannot access precompiled header file: %s", pch_file);
585 libruby_pathflag = p =
xmalloc(libpathflag_len + baselen + 1);
595valid_class_serials_add_i(
ID key,
VALUE v,
void *unused)
612system_default_tmpdir(
void)
616 WCHAR tmppath[_MAX_PATH];
619 int blen = WideCharToMultiByte(CP_UTF8, 0, tmppath,
len,
NULL, 0,
NULL,
NULL);
620 char *tmpdir =
xmalloc(blen + 1);
621 WideCharToMultiByte(CP_UTF8, 0, tmppath,
len, tmpdir, blen,
NULL,
NULL);
625#elif defined _CS_DARWIN_USER_TEMP_DIR
631 confstr(_CS_DARWIN_USER_TEMP_DIR, tmpdir,
len);
643check_tmpdir(
const char *dir)
647 if (!dir)
return FALSE;
650# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
673# define RETURN_ENV(name) \
674 if (check_tmpdir(tmpdir = getenv(name))) return ruby_strdup(tmpdir)
675 RETURN_ENV(
"TMPDIR");
677 tmpdir = system_default_tmpdir();
678 if (check_tmpdir(tmpdir))
return tmpdir;
684#define MIN_CACHE_SIZE 10
686#define DEFAULT_MAX_CACHE_SIZE 100
688#define DEFAULT_MIN_CALLS_TO_ADD 10000
694 stop_worker_p =
false;
695 worker_stopped =
false;
704 verbose(1,
"Failure in MJIT thread initialization\n");
712ruby_strndup(
const char *
str,
size_t n)
723split_flags(
const char *flags)
728 for (; flags !=
NULL; flags = next) {
729 next =
strchr(flags,
' ');
736 buf[
i++] = ruby_strndup(flags, next - flags);
741 char **ret =
xmalloc(
sizeof(
char *) * (
i + 1));
771 cc_path = CC_COMMON_ARGS[0];
772 verbose(2,
"MJIT: CC defaults to %s", cc_path);
773 cc_common_args =
xmalloc(
sizeof(CC_COMMON_ARGS));
774 memcpy((
void *)cc_common_args, CC_COMMON_ARGS,
sizeof(CC_COMMON_ARGS));
779 for (
size_t i = 0, j = 0;
i <
sizeof(CC_COMMON_ARGS) /
sizeof(
char *);
i++) {
780 if (CC_COMMON_ARGS[
i] &&
strncmp(
"-save-temps", CC_COMMON_ARGS[
i],
strlen(
"-save-temps")) == 0)
782 cc_common_args[j] = CC_COMMON_ARGS[
i];
787 tmp_dir = system_tmpdir();
788 verbose(2,
"MJIT: tmp_dir is %s", tmp_dir);
790 if (!init_header_filename()) {
792 verbose(1,
"Failure in MJIT header file name initialization\n");
826 while (!worker_stopped) {
827 verbose(3,
"Sending cancel signal to worker");
828 CRITICAL_SECTION_START(3,
"in stop_worker");
829 stop_worker_p =
true;
831 CRITICAL_SECTION_FINISH(3,
"in stop_worker");
843 if (worker_stopped) {
854 CRITICAL_SECTION_START(3,
"in mjit_pause for a worker wakeup");
856 CRITICAL_SECTION_FINISH(3,
"in mjit_pause for a worker wakeup");
872 if (!worker_stopped) {
876 if (!start_worker()) {
895 if (unit->so_file) unit->so_file =
NULL;
923 skip_cleaning_object_files(&active_units);
942 verbose(2,
"Stopping worker thread");
943 CRITICAL_SECTION_START(3,
"in mjit_finish to wakeup from pch");
950 verbose(3,
"Waiting wakeup from make_pch");
953 CRITICAL_SECTION_FINISH(3,
"in mjit_finish to wakeup from pch");
966 remove_file(pch_file);
970 xfree((
void *)cc_common_args); cc_common_args =
NULL;
971 for (
char **flag = cc_added_args; *flag !=
NULL; flag++)
973 xfree((
void *)cc_added_args); cc_added_args =
NULL;
978 free_list(&unit_queue, close_handle_p);
979 free_list(&active_units, close_handle_p);
980 free_list(&compact_units, close_handle_p);
981 free_list(&stale_units, close_handle_p);
985 verbose(1,
"Successful MJIT finish");
995 CRITICAL_SECTION_START(4,
"mjit_mark");
997 CRITICAL_SECTION_FINISH(4,
"mjit_mark");
1004 CRITICAL_SECTION_START(4,
"mjit_mark");
1008 CRITICAL_SECTION_FINISH(4,
"mjit_mark rb_gc_mark");
1014 CRITICAL_SECTION_START(4,
"mjit_mark rb_gc_mark");
1017 CRITICAL_SECTION_FINISH(4,
"mjit_mark");
1041 CRITICAL_SECTION_START(3,
"in mjit_remove_class_serial");
1043 CRITICAL_SECTION_FINISH(3,
"in mjit_remove_class_serial");
struct rb_encoding_entry * list
char str[HTML_ESCAPE_MAX_LEN+1]
VALUE rb_cObject
Object class.
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data)
rb_id_table_iterator_result
#define MJIT_HEADER_INSTALL_DIR
#define MJIT_MIN_HEADER_NAME
#define append_str(p, str)
verbose(int level, const char *format,...)
void rb_native_cond_initialize(rb_nativethread_cond_t *cond)
#define append_str2(p, str, len)
void rb_native_cond_broadcast(rb_nativethread_cond_t *cond)
mjit_warning(const char *format,...)
void rb_native_mutex_initialize(rb_nativethread_lock_t *lock)
void rb_native_cond_destroy(rb_nativethread_cond_t *cond)
void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
VALUE ruby_archlibdir_path
struct rb_call_cache * cc_entries
union iseq_inline_storage_entry * is_entries
union iseq_inline_storage_entry * is_entries
VALUE(* jit_func)(struct rb_execution_context_struct *, struct rb_control_frame_struct *)
rb_iseq_location_t location
struct rb_call_data * call_data
long unsigned total_calls
struct rb_mjit_unit * jit_unit
struct rb_iseq_constant_body * body
struct rb_mjit_compile_info compile_info
rb_execution_context_t * ec
struct list_head living_threads
int rb_is_const_id(ID id)
char * ruby_strdup(const char *)
VALUE rb_vm_top_self(void)
UINT rb_w32_system_tmpdir(WCHAR *path, UINT len)