25 mjit_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");
69 extern int rb_thread_create_mjit_thread(
void (*worker_func)(
void));
75 get_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;
217 static 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);
369 verbose(1,
"Too many JIT code -- %d units unloaded", units_num - active_units.length);
383 if (compile_info !=
NULL)
386 CRITICAL_SECTION_START(3,
"in add_iseq_to_process");
391 verbose(3,
"Sending wakeup signal to workers in mjit_add_iseq_to_process");
393 CRITICAL_SECTION_FINISH(3,
"in add_iseq_to_process");
401 mjit_add_iseq_to_process(
iseq,
NULL);
405 #define MJIT_WAIT_TIMEOUT_SECONDS 60
416 if (tries / 1000 > MJIT_WAIT_TIMEOUT_SECONDS || pch_status ==
PCH_FAILED) {
417 CRITICAL_SECTION_START(3,
"in rb_mjit_wait_call to set jit_func");
419 CRITICAL_SECTION_FINISH(3,
"in rb_mjit_wait_call to set jit_func");
424 CRITICAL_SECTION_START(3,
"in rb_mjit_wait_call for a client wakeup");
426 CRITICAL_SECTION_FINISH(3,
"in rb_mjit_wait_call for a client wakeup");
459 CRITICAL_SECTION_START(3,
"in rb_mjit_recompile_iseq");
463 CRITICAL_SECTION_FINISH(3,
"in rb_mjit_recompile_iseq");
475 init_header_filename(
void)
482 const char *basedir =
"";
486 static const char libpathflag[] =
493 const size_t libpathflag_len =
sizeof(libpathflag) - 1;
501 if (
getenv(
"MJIT_SEARCH_BUILD_DIR")) {
511 else if (hdr[0] !=
'/') {
512 verbose(1,
"Non-absolute header file path: %s", hdr);
515 verbose(1,
"Non-file header file path: %s", hdr);
517 else if ((
st.st_uid !=
getuid()) || (
st.st_mode & 022) ||
519 verbose(1,
"Unsafe header file: uid=%ld mode=%#o %s",
520 (
long)
st.st_uid, (
unsigned)
st.st_mode, hdr);
529 verbose(3,
"MJIT_HEADER: %s", hdr);
531 if (!header_file)
return false;
540 const size_t header_name_len =
sizeof(header_name) - 1;
542 header_file =
xmalloc(baselen + header_name_len + 1);
544 p =
append_str2(p, header_name, header_name_len + 1);
547 verbose(1,
"Cannot access header file: %s", header_file);
559 const size_t pch_name_len =
sizeof(pch_name) - 1;
561 pch_file =
xmalloc(baselen + pch_name_len + 1);
565 verbose(1,
"Cannot access precompiled header file: %s", pch_file);
578 libruby_pathflag = p =
xmalloc(libpathflag_len + baselen + 1);
588 valid_class_serials_add_i(
ID key,
VALUE v,
void *unused)
605 system_default_tmpdir(
void)
609 WCHAR tmppath[_MAX_PATH];
612 int blen = WideCharToMultiByte(CP_UTF8, 0, tmppath,
len,
NULL, 0,
NULL,
NULL);
613 char *tmpdir =
xmalloc(blen + 1);
614 WideCharToMultiByte(CP_UTF8, 0, tmppath,
len, tmpdir, blen,
NULL,
NULL);
618 #elif defined _CS_DARWIN_USER_TEMP_DIR
624 confstr(_CS_DARWIN_USER_TEMP_DIR, tmpdir,
len);
636 check_tmpdir(
const char *dir)
640 if (!dir)
return FALSE;
643 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
666 # define RETURN_ENV(name) \
667 if (check_tmpdir(tmpdir = getenv(name))) return ruby_strdup(tmpdir)
668 RETURN_ENV(
"TMPDIR");
670 tmpdir = system_default_tmpdir();
671 if (check_tmpdir(tmpdir))
return tmpdir;
677 #define MIN_CACHE_SIZE 10
679 #define DEFAULT_MAX_CACHE_SIZE 100
681 #define DEFAULT_MIN_CALLS_TO_ADD 10000
687 stop_worker_p =
false;
688 worker_stopped =
false;
697 verbose(1,
"Failure in MJIT thread initialization\n");
705 ruby_strndup(
const char *
str,
size_t n)
716 split_flags(
const char *flags)
721 for (; flags !=
NULL; flags = next) {
722 next =
strchr(flags,
' ');
729 buf[
i++] = ruby_strndup(flags, next - flags);
734 char **ret =
xmalloc(
sizeof(
char *) * (
i + 1));
764 cc_path = CC_COMMON_ARGS[0];
765 verbose(2,
"MJIT: CC defaults to %s", cc_path);
766 cc_common_args =
xmalloc(
sizeof(CC_COMMON_ARGS));
767 memcpy((
void *)cc_common_args, CC_COMMON_ARGS,
sizeof(CC_COMMON_ARGS));
772 for (
size_t i = 0, j = 0;
i <
sizeof(CC_COMMON_ARGS) /
sizeof(
char *);
i++) {
773 if (CC_COMMON_ARGS[
i] &&
strncmp(
"-save-temps", CC_COMMON_ARGS[
i],
strlen(
"-save-temps")) == 0)
775 cc_common_args[j] = CC_COMMON_ARGS[
i];
780 tmp_dir = system_tmpdir();
781 verbose(2,
"MJIT: tmp_dir is %s", tmp_dir);
783 if (!init_header_filename()) {
785 verbose(1,
"Failure in MJIT header file name initialization\n");
816 while (!worker_stopped) {
817 verbose(3,
"Sending cancel signal to worker");
818 CRITICAL_SECTION_START(3,
"in stop_worker");
819 stop_worker_p =
true;
821 CRITICAL_SECTION_FINISH(3,
"in stop_worker");
833 if (worker_stopped) {
844 CRITICAL_SECTION_START(3,
"in mjit_pause for a worker wakeup");
846 CRITICAL_SECTION_FINISH(3,
"in mjit_pause for a worker wakeup");
862 if (!worker_stopped) {
866 if (!start_worker()) {
880 #ifndef _MSC_VER // Actually mswin does not reach here since it doesn't have fork
884 #if defined(_WIN32) // mswin doesn't reach here either. This is for MinGW.
885 if (unit->so_file) unit->so_file =
NULL;
913 skip_cleaning_object_files(&active_units);
932 verbose(2,
"Stopping worker thread");
933 CRITICAL_SECTION_START(3,
"in mjit_finish to wakeup from pch");
940 verbose(3,
"Waiting wakeup from make_pch");
943 CRITICAL_SECTION_FINISH(3,
"in mjit_finish to wakeup from pch");
954 #ifndef _MSC_VER // mswin has prebuilt precompiled header
956 remove_file(pch_file);
960 xfree((
void *)cc_common_args); cc_common_args =
NULL;
961 for (
char **flag = cc_added_args; *flag !=
NULL; flag++)
963 xfree((
void *)cc_added_args); cc_added_args =
NULL;
968 free_list(&unit_queue, close_handle_p);
969 free_list(&active_units, close_handle_p);
970 free_list(&compact_units, close_handle_p);
971 free_list(&stale_units, close_handle_p);
975 verbose(1,
"Successful MJIT finish");
985 CRITICAL_SECTION_START(4,
"mjit_mark");
987 CRITICAL_SECTION_FINISH(4,
"mjit_mark");
994 CRITICAL_SECTION_START(4,
"mjit_mark");
998 CRITICAL_SECTION_FINISH(4,
"mjit_mark rb_gc_mark");
1004 CRITICAL_SECTION_START(4,
"mjit_mark rb_gc_mark");
1007 CRITICAL_SECTION_FINISH(4,
"mjit_mark");
1031 CRITICAL_SECTION_START(3,
"in mjit_remove_class_serial");
1033 CRITICAL_SECTION_FINISH(3,
"in mjit_remove_class_serial");