85#define __EXTENSIONS__ 1
98#include "insns_info.inc"
113#ifdef HAVE_SYS_PARAM_H
114# include <sys/param.h>
122# define MAXPATHLEN 1024
126#define dlopen(name,flag) ((void*)LoadLibrary(name))
127#define dlerror() strerror(rb_w32_map_errno(GetLastError()))
128#define dlsym(handle,name) ((void*)GetProcAddress((handle),(name)))
129#define dlclose(handle) (!FreeLibrary(handle))
132#define waitpid(pid,stat_loc,options) (WaitForSingleObject((HANDLE)(pid), INFINITE), GetExitCodeProcess((HANDLE)(pid), (LPDWORD)(stat_loc)), CloseHandle((HANDLE)pid), (pid))
133#define WIFEXITED(S) ((S) != STILL_ACTIVE)
134#define WEXITSTATUS(S) (S)
135#define WIFSIGNALED(S) (0)
140#define MJIT_ATOMIC_SET(var, val) (void)ATOMIC_PTR_EXCHANGE(var, val)
142#define MJIT_TMP_PREFIX "_ruby_mjit_"
148# define USE_JIT_COMPACTION 0
150# define USE_JIT_COMPACTION 1
217static int current_unit_num;
219static rb_nativethread_lock_t mjit_engine_mutex;
233static bool in_jit =
false;
235static bool pending_stale_p =
false;
237static int unload_requests = 0;
239static int total_unloads = 0;
241static bool stop_worker_p;
243static bool worker_stopped;
249static VALUE valid_class_serials;
252static const char *cc_path;
254static const char **cc_common_args;
256static char **cc_added_args;
258static char *pch_file;
260static rb_pid_t pch_owner_pid;
267static char *header_file;
272static char *libruby_pathflag;
277#if defined(__GNUC__) && \
278 (!defined(__clang__) || \
279 (defined(__clang__) && (defined(__FreeBSD__) || defined(__GLIBC__))))
280# define GCC_PIC_FLAGS "-Wfatal-errors", "-fPIC", "-shared", "-w", "-pipe",
281# define MJIT_CFLAGS_PIPE 1
283# define GCC_PIC_FLAGS
284# define MJIT_CFLAGS_PIPE 0
289#if defined __GNUC__ && !defined __clang__ && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(_AIX) && !defined(__OpenBSD__)
290# define GCC_NOSTDLIB_FLAGS "-nodefaultlibs", "-nostdlib",
292# define GCC_NOSTDLIB_FLAGS
295static const char *
const CC_COMMON_ARGS[] = {
306static const char *
const CC_LINKER_ARGS[] = {
307#if defined __GNUC__ && !defined __clang__ && !defined(__OpenBSD__)
313static const char *
const CC_LIBS[] = {
314#if defined(_WIN32) || defined(__CYGWIN__)
317#if defined __GNUC__ && !defined __clang__
323#if defined __ANDROID__
329#define CC_CODEFLAG_ARGS (mjit_opts.debug ? CC_DEBUG_ARGS : CC_OPTIMIZE_ARGS)
334verbose(
int level,
const char *format, ...)
339 char *full_format =
alloca(
sizeof(
char) * (
len + 2));
343 full_format[
len] =
'\n';
344 full_format[
len+1] =
'\0';
346 va_start(args, format);
347 vfprintf(stderr, full_format, args);
353mjit_warning(
const char *format, ...)
358 fprintf(stderr,
"MJIT warning: ");
359 va_start(args, format);
360 vfprintf(stderr, format, args);
362 fprintf(stderr,
"\n");
376 list_add_tail(&list->
head, &unit->
unode);
384 rb_debug_counter_add(RB_DEBUG_COUNTER_mjit_length_unit_queue, -1, list == &unit_queue);
385 rb_debug_counter_add(RB_DEBUG_COUNTER_mjit_length_active_units, -1, list == &active_units);
386 rb_debug_counter_add(RB_DEBUG_COUNTER_mjit_length_compact_units, -1, list == &compact_units);
387 rb_debug_counter_add(RB_DEBUG_COUNTER_mjit_length_stale_units, -1, list == &stale_units);
390 list_del(&unit->
unode);
408 char *so_file = unit->so_file;
410 unit->so_file =
NULL;
412 remove_file(so_file);
430 unit->
iseq->
body->jit_func = (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
438 mjit_warning(
"failed to close handle for u%d: %s", unit->
id, dlerror());
440 clean_temp_files(unit);
446CRITICAL_SECTION_START(
int level,
const char *msg)
448 verbose(level,
"Locking %s", msg);
450 verbose(level,
"Locked %s", msg);
456CRITICAL_SECTION_FINISH(
int level,
const char *msg)
458 verbose(level,
"Unlocked %s", msg);
463sprint_uniq_filename(
char *
str,
size_t size,
unsigned long id,
const char *
prefix,
const char *
suffix)
470double ruby_real_ms_time(
void);
471# define real_ms_time() ruby_real_ms_time()
476# ifdef HAVE_CLOCK_GETTIME
478# ifdef CLOCK_MONOTONIC
485 return tv.tv_nsec / 1000000.0 + tv.tv_sec * 1000.0;
490 return tv.tv_usec / 1000.0 + tv.tv_sec * 1000.0;
499 CRITICAL_SECTION_START(3,
"in valid_class_serial_p");
501 CRITICAL_SECTION_FINISH(3,
"in valid_class_serial_p");
512 verbose(3,
"Waiting wakeup from GC");
519 list_for_each_safe(&list->
head, unit, next,
unode) {
521 remove_from_list(unit, list);
526 if (best ==
NULL || best->iseq->body->total_calls < unit->
iseq->
body->total_calls) {
532 verbose(3,
"Sending wakeup signal to client in a mjit-worker for GC");
536 remove_from_list(best, list);
543args_len(
char *
const *args)
547 for (i = 0; (args[i]) !=
NULL;i++)
555form_args(
int num, ...)
560 char **args, **res, **tmp;
564 for (i =
len = 0; i <
num; i++) {
565 args = va_arg(argp,
char **);
567 if ((tmp = (
char **)
realloc(res,
sizeof(
char *) * (
len + n + 1))) ==
NULL) {
581#if __has_warning("-Wdeprecated-declarations") || RBIMPL_COMPILER_IS(GCC)
587start_process(
const char *abspath,
char *
const *
argv)
593 verbose(1,
"MJIT: Failed to open a null device: %s",
strerror(errno));
598 fprintf(stderr,
"Starting process: %s", abspath);
599 for (
int i = 0; (arg =
argv[i]) !=
NULL; i++)
600 fprintf(stderr,
" %s", arg);
601 fprintf(stderr,
"\n");
617 verbose(1,
"MJIT: Failed to create process: %s", dlerror());
621 if ((pid = vfork()) == 0) {
627 dup2(dev_null, STDERR_FILENO);
628 dup2(dev_null, STDOUT_FILENO);
630 (void)close(dev_null);
631 pid = execv(abspath,
argv);
635 verbose(1,
"MJIT: Error in execv: %s", abspath);
639 (void)close(dev_null);
648exec_process(
const char *path,
char *
const argv[])
650 int stat, exit_code = -2;
659 pid_t pid = start_process(path,
argv);
664 if (errno == EINTR)
continue;
665 fprintf(stderr,
"[%"PRI_PIDT_PREFIX
"d] waitpid(%lu): %s (SIGCHLD=%d,%u)\n",
666 getpid(), (
unsigned long)pid,
strerror(errno),
690remove_so_file(
const char *so_file,
struct rb_mjit_unit *unit)
694 unit->so_file =
strdup(so_file);
695 if (unit->so_file ==
NULL)
696 mjit_warning(
"failed to allocate memory to lazily remove '%s': %s", so_file,
strerror(errno));
698 remove_file(so_file);
704sprint_funcname(
char *funcname,
const struct rb_mjit_unit *unit)
708 sprintf(funcname,
"_mjit%d", unit->
id);
714 const char *lib =
"/lib/";
718 while (
strstr(path, version))
723 if (!strcmp(method,
"[]")) method =
"AREF";
724 if (!strcmp(method,
"[]=")) method =
"ASET";
727 sprintf(funcname,
"_mjit%d_%s_%s", unit->
id, path, method);
728 for (
size_t i = 0; i <
strlen(funcname); i++) {
729 char c = funcname[i];
730 if (!((
'a' <= c && c <=
'z') || (
'A' <= c && c <=
'Z') || (
'0' <= c && c <=
'9') || c ==
'_')) {
742 if (compiling_iseqs ==
NULL)
745 compiling_iseqs[0] =
iseq;
748 unsigned int pos = 0;
749 while (pos < iseq->body->iseq_size) {
750#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
755 if (insn == BIN(opt_send_without_block)) {
760 compiling_iseqs[i] =
iseq;
764 pos += insn_len(insn);
774 while (compiling_iseqs[i]) {
775 if (compiling_iseqs[i] ==
iseq)
return true;
781static const int c_file_access_mode =
785 O_WRONLY|O_EXCL|O_CREAT;
787#define append_str2(p, str, len) ((char *)memcpy((p), str, (len))+(len))
788#define append_str(p, str) append_str2(p, str, sizeof(str)-1)
789#define append_lit(p, str) append_str2(p, str, rb_strlen_lit(str))
794compile_c_to_so(
const char *c_file,
const char *so_file)
820 files[3] = p =
alloca(
sizeof(
char) * (
strlen(pch_file) + 1));
839 files, CC_LIBS, CC_DLDFLAGS_ARGS);
843 int exit_code = exec_process(cc_path, args);
846 if (exit_code == 0) {
850 remove_file(obj_file);
853 append_lit(before_dot,
".lib"); remove_file(obj_file);
854 append_lit(before_dot,
".exp"); remove_file(obj_file);
855 append_lit(before_dot,
".pdb"); remove_file(obj_file);
859 verbose(2,
"compile_c_to_so: compile error: %d", exit_code);
861 return exit_code == 0;
869 const char *rest_args[] = {
877 "-o", pch_file, header_file,
881 verbose(2,
"Creating precompiled header");
882 char **args = form_args(4, cc_common_args,
CC_CODEFLAG_ARGS, cc_added_args, rest_args);
884 mjit_warning(
"making precompiled header failed on forming args");
885 CRITICAL_SECTION_START(3,
"in make_pch");
887 CRITICAL_SECTION_FINISH(3,
"in make_pch");
891 int exit_code = exec_process(cc_path, args);
894 CRITICAL_SECTION_START(3,
"in make_pch");
895 if (exit_code == 0) {
899 mjit_warning(
"Making precompiled header failed on compilation. Stopping MJIT worker...");
904 CRITICAL_SECTION_FINISH(3,
"in make_pch");
911compile_c_to_so(
const char *c_file,
const char *so_file)
914 strcpy(o_file, c_file);
915 o_file[
strlen(c_file) - 1] =
'o';
917 const char *o_args[] = {
918 "-o", o_file, c_file,
920 "-include-pch", pch_file,
924 char **args = form_args(5, cc_common_args,
CC_CODEFLAG_ARGS, cc_added_args, o_args, CC_LINKER_ARGS);
925 if (args ==
NULL)
return false;
926 int exit_code = exec_process(cc_path, args);
928 if (exit_code != 0) {
929 verbose(2,
"compile_c_to_so: failed to compile .c to .o: %d", exit_code);
933 const char *so_args[] = {
940# if defined(__MACH__)
941 extern VALUE rb_libruby_selfpath;
942 const char *loader_args[] = {
"-bundle_loader",
StringValuePtr(rb_libruby_selfpath),
NULL};
944 const char *loader_args[] = {
NULL};
946 args = form_args(7, CC_LDSHARED_ARGS,
CC_CODEFLAG_ARGS, so_args, loader_args, CC_LIBS, CC_DLDFLAGS_ARGS, CC_LINKER_ARGS);
947 if (args ==
NULL)
return false;
948 exit_code = exec_process(cc_path, args);
950 if (!
mjit_opts.save_temps) remove_file(o_file);
951 if (exit_code != 0) {
952 verbose(2,
"compile_c_to_so: failed to link .o to .so: %d", exit_code);
954 return exit_code == 0;
958#if USE_JIT_COMPACTION
959static void compile_prelude(
FILE *
f);
962compile_compact_jit_code(
char* c_file)
968 if (fd >= 0) (void)close(fd);
969 verbose(1,
"Failed to fopen '%s', giving up JIT for it (%s)", c_file,
strerror(e));
976 CRITICAL_SECTION_START(3,
"before mjit_compile to wait GC finish");
978 verbose(3,
"Waiting wakeup from GC");
982 bool iseq_gced =
false;
984 list_for_each_safe(&active_units.
head, child_unit, next,
unode) {
987 verbose(1,
"JIT compaction: A method for JIT code u%d is obsoleted. Compaction will be skipped.", child_unit->
id);
988 remove_from_list(child_unit, &active_units);
989 free_unit(child_unit);
993 CRITICAL_SECTION_FINISH(3,
"before mjit_compile to wait GC finish");
1008 bool success =
true;
1009 list_for_each(&active_units.
head, child_unit,
unode) {
1010 CRITICAL_SECTION_START(3,
"before set_compiling_iseqs");
1011 success &= set_compiling_iseqs(child_unit->
iseq);
1012 CRITICAL_SECTION_FINISH(3,
"after set_compiling_iseqs");
1013 if (!success)
continue;
1016 sprint_funcname(funcname, child_unit);
1018 long iseq_lineno = 0;
1022 const char *sep =
"@";
1025 if (!iseq_label) iseq_label = sep =
"";
1026 fprintf(
f,
"\n/* %s%s%s:%ld */\n", iseq_label, sep, iseq_path, iseq_lineno);
1027 success &= mjit_compile(
f, child_unit->
iseq, funcname, child_unit->
id);
1029 CRITICAL_SECTION_START(3,
"before compiling_iseqs free");
1030 free(compiling_iseqs);
1031 compiling_iseqs =
NULL;
1032 CRITICAL_SECTION_FINISH(3,
"after compiling_iseqs free");
1036 CRITICAL_SECTION_START(3,
"after mjit_compile to wakeup client for GC");
1038 verbose(3,
"Sending wakeup signal to client in a mjit-worker for GC");
1040 CRITICAL_SECTION_FINISH(3,
"in worker to wakeup client for GC");
1049compact_all_jit_code(
void)
1052 static const char c_ext[] =
".c";
1053 static const char so_ext[] = DLEXT;
1058 if (unit ==
NULL)
return;
1059 unit->
id = current_unit_num++;
1060 sprint_uniq_filename(c_file, (
int)
sizeof(c_file), unit->
id,
MJIT_TMP_PREFIX, c_ext);
1061 sprint_uniq_filename(so_file, (
int)
sizeof(so_file), unit->
id,
MJIT_TMP_PREFIX, so_ext);
1063 bool success = compile_compact_jit_code(c_file);
1064 double start_time = real_ms_time();
1066 success = compile_c_to_so(c_file, so_file);
1068 remove_file(c_file);
1070 double end_time = real_ms_time();
1073 void *
handle = dlopen(so_file, RTLD_NOW);
1075 mjit_warning(
"failure in loading code from compacted '%s': %s", so_file, dlerror());
1082 add_to_list(unit, &compact_units);
1085 remove_so_file(so_file, unit);
1087 CRITICAL_SECTION_START(3,
"in compact_all_jit_code to read list");
1088 list_for_each(&active_units.
head, cur,
unode) {
1091 sprint_funcname(funcname, cur);
1093 if ((func = dlsym(
handle, funcname)) ==
NULL) {
1094 mjit_warning(
"skipping to reload '%s' from '%s': %s", funcname, so_file, dlerror());
1103 CRITICAL_SECTION_FINISH(3,
"in compact_all_jit_code to read list");
1104 verbose(1,
"JIT compaction (%.1fms): Compacted %d methods %s -> %s", end_time - start_time, active_units.
length, c_file, so_file);
1108 verbose(1,
"JIT compaction failure (%.1fms): Failed to compact methods", end_time - start_time);
1114load_func_from_so(
const char *so_file,
const char *funcname,
struct rb_mjit_unit *unit)
1118 handle = dlopen(so_file, RTLD_NOW);
1120 mjit_warning(
"failure in loading code from '%s': %s", so_file, dlerror());
1121 return (
void *)NOT_ADDED_JIT_ISEQ_FUNC;
1124 func = dlsym(
handle, funcname);
1131header_name_end(
const char *s)
1133 const char *e = s +
strlen(s);
1135 static const char suffix[] =
".gch";
1148compile_prelude(
FILE *
f)
1151 const char *s = pch_file;
1152 const char *e = header_name_end(s);
1154 fprintf(
f,
"#include \"");
1156 for (; s < e; s++) {
1158 case '\\':
case '"':
1167 fprintf(
f,
"void _pei386_runtime_relocator(void){}\n");
1168 fprintf(
f,
"int __stdcall DllMainCRTStartup(void* hinstDLL, unsigned int fdwReason, void* lpvReserved) { return 1; }\n");
1177 static const char c_ext[] =
".c";
1178 static const char so_ext[] = DLEXT;
1181 sprint_uniq_filename(c_file, (
int)
sizeof(c_file), unit->
id,
MJIT_TMP_PREFIX, c_ext);
1182 sprint_uniq_filename(so_file, (
int)
sizeof(so_file), unit->
id,
MJIT_TMP_PREFIX, so_ext);
1183 sprint_funcname(funcname, unit);
1189 if (fd >= 0) (void)close(fd);
1190 verbose(1,
"Failed to fopen '%s', giving up JIT for it (%s)", c_file,
strerror(e));
1191 return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
1198 CRITICAL_SECTION_START(3,
"before mjit_compile to wait GC finish");
1200 verbose(3,
"Waiting wakeup from GC");
1206 in_jit &= set_compiling_iseqs(unit->
iseq);
1207 CRITICAL_SECTION_FINISH(3,
"before mjit_compile to wait GC finish");
1211 remove_file(c_file);
1212 return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
1216 long iseq_lineno = 0;
1225 verbose(2,
"start compilation: %s@%s:%ld -> %s", iseq_label, iseq_path, iseq_lineno, c_file);
1226 fprintf(
f,
"/* %s@%s:%ld */\n\n", iseq_label, iseq_path, iseq_lineno);
1227 bool success = mjit_compile(
f, unit->
iseq, funcname, unit->
id);
1230 CRITICAL_SECTION_START(3,
"after mjit_compile to wakeup client for GC");
1231 free(compiling_iseqs);
1232 compiling_iseqs =
NULL;
1234 verbose(3,
"Sending wakeup signal to client in a mjit-worker for GC");
1236 CRITICAL_SECTION_FINISH(3,
"in worker to wakeup client for GC");
1241 remove_file(c_file);
1242 verbose(1,
"JIT failure: %s@%s:%ld -> %s", iseq_label, iseq_path, iseq_lineno, c_file);
1243 return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
1246 double start_time = real_ms_time();
1247 success = compile_c_to_so(c_file, so_file);
1249 remove_file(c_file);
1250 double end_time = real_ms_time();
1253 verbose(2,
"Failed to generate so: %s", so_file);
1254 return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
1257 void *func = load_func_from_so(so_file, funcname, unit);
1259 remove_so_file(so_file, unit);
1262 verbose(1,
"JIT success (%.1fms): %s@%s:%ld -> %s",
1263 end_time - start_time, iseq_label, iseq_path, iseq_lineno, c_file);
1265 return (mjit_func_t)func;
1272 return body->jit_unit->cc_entries;
1295 if (cc_entries ==
NULL)
return -1;
1300 if (cc_entries ==
NULL)
return -1;
1302 cc_entries += cc_entries_index;
1307 for (
unsigned int i = 0; i < captured_iseq->
ci_size; i++) {
1311 return cc_entries_index;
1326 && (iseq->
body->jit_unit) !=
NULL) {
1327 iseq->
body->jit_unit->used_code_p =
true;
1352 int units_num = active_units.
length;
1356 list_for_each_safe(&active_units.
head, unit,
next, unode) {
1358 remove_from_list(unit, &active_units);
1364 list_for_each(&active_units.
head, unit, unode) {
1370 for (cont = first_cont; cont !=
NULL; cont = cont->
next) {
1371 mark_ec_units(cont->
ec);
1377 long unsigned prev_queue_calls = -1;
1380 long unsigned max_queue_calls = 0;
1381 list_for_each(&unit_queue.
head, unit, unode) {
1382 if (unit->
iseq !=
NULL && max_queue_calls < unit->iseq->
body->total_calls
1383 && unit->
iseq->
body->total_calls < prev_queue_calls) {
1384 max_queue_calls = unit->
iseq->
body->total_calls;
1387 prev_queue_calls = max_queue_calls;
1389 bool unloaded_p =
false;
1390 list_for_each_safe(&active_units.
head, unit,
next, unode) {
1394 if (max_queue_calls > unit->
iseq->
body->total_calls) {
1395 verbose(2,
"Unloading unit %d (calls=%lu, threshold=%lu)",
1396 unit->
id, unit->
iseq->
body->total_calls, max_queue_calls);
1398 remove_from_list(unit, &active_units);
1403 if (!unloaded_p)
break;
1406 if (units_num > active_units.
length) {
1407 verbose(1,
"Too many JIT code -- %d units unloaded", units_num - active_units.
length);
1408 total_unloads += units_num - active_units.
length;
1412static void mjit_add_iseq_to_process(
const rb_iseq_t *iseq,
const struct rb_mjit_compile_info *compile_info,
bool worker_p);
1422 int max_compact_size =
mjit_opts.max_cache_size / 10;
1423 if (max_compact_size < 10) max_compact_size = 10;
1427 int throttle_threshold =
mjit_opts.max_cache_size / 10;
1436 CRITICAL_SECTION_START(3,
"in worker to update worker_stopped");
1437 worker_stopped =
true;
1438 verbose(3,
"Sending wakeup signal to client in a mjit-worker");
1440 CRITICAL_SECTION_FINISH(3,
"in worker to update worker_stopped");
1445 while (!stop_worker_p) {
1449 CRITICAL_SECTION_START(3,
"in worker dequeue");
1450 while ((list_empty(&unit_queue.
head) || active_units.
length >=
mjit_opts.max_cache_size) && !stop_worker_p) {
1452 verbose(3,
"Getting wakeup from client");
1455 if (pending_stale_p) {
1456 pending_stale_p =
false;
1458 list_for_each_safe(&active_units.
head, unit, next,
unode) {
1461 remove_from_list(unit, &active_units);
1462 add_to_list(unit, &stale_units);
1464 mjit_add_iseq_to_process(unit->
iseq, &unit->
iseq->
body->jit_unit->compile_info,
true);
1470 if (unload_requests >= throttle_threshold) {
1472 verbose(3,
"Waiting wakeup from GC");
1479 unload_requests = 0;
1482 verbose(3,
"Sending wakeup signal to client in a mjit-worker for GC");
1487 verbose(1,
"No units can be unloaded -- incremented max-cache-size to %d for --jit-wait",
mjit_opts.max_cache_size);
1490 unit = get_from_list(&unit_queue);
1491 CRITICAL_SECTION_FINISH(3,
"in worker dequeue");
1495 mjit_func_t func = convert_unit_to_func(unit);
1498 CRITICAL_SECTION_START(3,
"in jit func replace");
1500 verbose(3,
"Waiting wakeup from GC");
1505 add_to_list(unit, &active_units);
1513 CRITICAL_SECTION_FINISH(3,
"in jit func replace");
1515#if USE_JIT_COMPACTION
1517 if (compact_units.
length < max_compact_size
1519 || (active_units.
length ==
mjit_opts.max_cache_size && compact_units.
length * throttle_threshold <= total_unloads))) {
1520 compact_all_jit_code();
1527 worker_stopped =
true;
#define PRINTF_ARGS(decl, string_index, first_to_check)
Internal header for the compiler.
int rb_vm_insn_addr2insn(const void *)
#define RB_DEBUG_COUNTER_INC_IF(type, cond)
#define RB_DEBUG_COUNTER_INC(type)
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
const char ruby_null_device[]
#define WEXITSTATUS(status)
#define WIFEXITED(status)
unsigned char suffix[65536]
unsigned short prefix[65536]
int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
Defines RBIMPL_HAS_BUILTIN.
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
#define rb_strlen_lit(str)
char * strstr(const char *, const char *)
#define RUBY_API_VERSION_TEENY
#define RUBY_API_VERSION_MAJOR
#define RUBY_API_VERSION_MINOR
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
VALUE rb_iseq_path(const rb_iseq_t *iseq)
#define MEMCPY(p1, p2, type, n)
rb_pid_t ruby_waitpid_locked(rb_vm_t *, rb_pid_t, int *status, int options, rb_nativethread_cond_t *cond)
int mjit_capture_cc_entries(const struct rb_iseq_constant_body *compiled_iseq, const struct rb_iseq_constant_body *captured_iseq)
bool mjit_valid_class_serial_p(rb_serial_t class_serial)
void rb_native_mutex_lock(rb_nativethread_lock_t *lock)
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)
struct mjit_options mjit_opts
const struct rb_callcache ** mjit_iseq_cc_entries(const struct rb_iseq_constant_body *const body)
void rb_native_mutex_initialize(rb_nativethread_lock_t *lock)
void rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
#define GCC_NOSTDLIB_FLAGS
bool rb_mjit_compiling_iseq_p(const rb_iseq_t *iseq)
void rb_native_mutex_destroy(rb_nativethread_lock_t *lock)
void rb_native_cond_destroy(rb_nativethread_cond_t *cond)
void rb_native_cond_signal(rb_nativethread_cond_t *cond)
#define MJIT_ATOMIC_SET(var, val)
void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
#define append_lit(p, str)
#define StringValuePtr(v)
unsigned LONG_LONG rb_serial_t
size_t strlen(const char *)
rb_execution_context_t * ec
const struct rb_callcache * cc
const struct rb_callinfo * ci
rb_iseq_location_t location
struct rb_call_data * call_data
struct rb_iseq_constant_body * body
const struct rb_callcache ** cc_entries
struct rb_mjit_compile_info compile_info
unsigned int cc_entries_size
rb_nativethread_lock_t waitpid_lock
#define WAITPID_USE_SIGCHLD
#define RUBY_VM_NEXT_CONTROL_FRAME(cfp)
struct rb_call_data * CALL_DATA
#define COMPILER_WARNING_PUSH
#define COMPILER_WARNING_POP
#define COMPILER_WARNING_IGNORED(flag)
HANDLE rb_w32_start_process(const char *abspath, char *const *argv, int out_fd)
int gettimeofday(struct timeval *, struct timezone *)
rb_pid_t waitpid(rb_pid_t, int *, int)
int clock_gettime(clockid_t, struct timespec *)
if((ID)(DISPID) nameid !=nameid)