Ruby  3.3.0dev (2023-03-07 revision 09b4236f17dfad945e85edb5c57ab4cd81065915)
mjit.h (09b4236f17dfad945e85edb5c57ab4cd81065915)
1 #ifndef RUBY_MJIT_H
2 #define RUBY_MJIT_H 1
3 /**********************************************************************
4 
5  mjit.h - Interface to MRI method JIT compiler
6 
7  Copyright (C) 2017 Vladimir Makarov <vmakarov@redhat.com>.
8  Copyright (C) 2017 Takashi Kokubun <k0kubun@ruby-lang.org>.
9 
10 **********************************************************************/
11 
12 #include "ruby/internal/config.h" // defines USE_MJIT
13 #include "ruby/internal/stdbool.h"
14 #include "vm_core.h"
15 
16 # if USE_MJIT
17 
18 #ifndef MJIT_STATS
19 # define MJIT_STATS RUBY_DEBUG
20 #endif
21 
22 #include "ruby.h"
23 #include "vm_core.h"
24 
25 // Special address values of a function generated from the
26 // corresponding iseq by MJIT:
27 enum rb_mjit_func_state {
28  // ISEQ has not been compiled yet
29  MJIT_FUNC_NOT_COMPILED = 0,
30  // ISEQ is already queued for the machine code generation but the
31  // code is not ready yet for the execution
32  MJIT_FUNC_COMPILING = 1,
33  // ISEQ included not compilable insn, some internal assertion failed
34  // or the unit is unloaded
35  MJIT_FUNC_FAILED = 2,
36 };
37 // Return true if jit_func is part of enum rb_mjit_func_state
38 #define MJIT_FUNC_STATE_P(jit_func) ((uintptr_t)(jit_func) <= (uintptr_t)MJIT_FUNC_FAILED)
39 
40 // MJIT options which can be defined on the MRI command line.
41 struct mjit_options {
42  // Converted from "jit" feature flag to tell the enablement
43  // information to ruby_show_version().
44  bool on;
45  // Save temporary files after MRI finish. The temporary files
46  // include the pre-compiled header, C code file generated for ISEQ,
47  // and the corresponding object file.
48  bool save_temps;
49  // Print MJIT warnings to stderr.
50  bool warnings;
51  // Disable compiler optimization and add debug symbols. It can be
52  // very slow.
53  bool debug;
54  // Add arbitrary cflags.
55  char* debug_flags;
56  // If true, all ISeqs are synchronously compiled. For testing.
57  bool wait;
58  // Number of calls to trigger JIT compilation. For testing.
59  unsigned int call_threshold;
60  // Collect MJIT statistics
61  bool stats;
62  // Force printing info about MJIT work of level VERBOSE or
63  // less. 0=silence, 1=medium, 2=verbose.
64  int verbose;
65  // Maximal permitted number of iseq JIT codes in a MJIT memory
66  // cache.
67  int max_cache_size;
68  // [experimental] Do not start MJIT until MJIT.resume is called.
69  bool pause;
70  // [experimental] Call custom RubyVM::MJIT.compile instead of MJIT.
71  bool custom;
72  // Enable disasm of all JIT code
73  bool dump_disasm;
74 };
75 
76 // State of optimization switches
77 struct rb_mjit_compile_info {
78  // Disable getinstancevariable/setinstancevariable optimizations based on inline cache (T_OBJECT)
79  bool disable_ivar_cache;
80  // Disable getinstancevariable/setinstancevariable optimizations based on inline cache (FL_EXIVAR)
81  bool disable_exivar_cache;
82  // Disable send/opt_send_without_block optimizations based on inline cache
83  bool disable_send_cache;
84  // Disable method inlining
85  bool disable_inlining;
86  // Disable opt_getinlinecache inlining
87  bool disable_const_cache;
88 };
89 
90 typedef VALUE (*jit_func_t)(rb_execution_context_t *, rb_control_frame_t *);
91 
92 RUBY_SYMBOL_EXPORT_BEGIN
93 RUBY_EXTERN struct mjit_options mjit_opts;
94 RUBY_EXTERN bool mjit_call_p;
95 
96 extern void rb_mjit_compile(const rb_iseq_t *iseq);
97 extern struct rb_mjit_compile_info* rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body);
98 extern void rb_mjit_recompile_send(const rb_iseq_t *iseq);
99 extern void rb_mjit_recompile_ivar(const rb_iseq_t *iseq);
100 extern void rb_mjit_recompile_exivar(const rb_iseq_t *iseq);
101 extern void rb_mjit_recompile_inlining(const rb_iseq_t *iseq);
102 extern void rb_mjit_recompile_const(const rb_iseq_t *iseq);
103 RUBY_SYMBOL_EXPORT_END
104 
105 extern void mjit_cancel_all(const char *reason);
106 extern bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname, int id);
107 extern void mjit_init(const struct mjit_options *opts);
108 extern void mjit_free_iseq(const rb_iseq_t *iseq);
109 extern void rb_mjit_iseq_update_references(struct rb_iseq_constant_body *const body);
110 extern void mjit_mark(void);
111 extern void rb_mjit_iseq_mark(VALUE mjit_blocks);
112 extern void mjit_notify_waitpid(int exit_code);
113 
114 extern void rb_mjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
115 extern void rb_mjit_cme_invalidate(rb_callable_method_entry_t *cme);
116 extern void rb_mjit_before_ractor_spawn(void);
117 extern void rb_mjit_constant_state_changed(ID id);
118 extern void rb_mjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx);
119 extern void rb_mjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events);
120 
121 void mjit_child_after_fork(void);
122 
123 extern void rb_mjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
124 extern void rb_mjit_before_ractor_spawn(void);
125 extern void rb_mjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events);
126 extern void rb_mjit_collect_vm_usage_insn(int insn);
127 
128 extern bool mjit_enabled;
129 extern bool mjit_stats_enabled;
130 VALUE mjit_pause(bool wait_p);
131 VALUE mjit_resume(void);
132 void mjit_finish(bool close_handle_p);
133 
134 # else // USE_MJIT
135 
136 static inline void mjit_cancel_all(const char *reason){}
137 static inline void mjit_free_iseq(const rb_iseq_t *iseq){}
138 static inline void mjit_mark(void){}
139 static inline VALUE jit_exec(rb_execution_context_t *ec) { return Qundef; /* unreachable */ }
140 static inline void mjit_child_after_fork(void){}
141 
142 static inline void rb_mjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop) {}
143 static inline void rb_mjit_cme_invalidate(rb_callable_method_entry_t *cme) {}
144 static inline void rb_mjit_before_ractor_spawn(void) {}
145 static inline void rb_mjit_constant_state_changed(ID id) {}
146 static inline void rb_mjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx) {}
147 static inline void rb_mjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events) {}
148 
149 #define mjit_enabled false
150 #define mjit_stats_enabled false
151 static inline VALUE mjit_pause(bool wait_p){ return Qnil; } // unreachable
152 static inline VALUE mjit_resume(void){ return Qnil; } // unreachable
153 static inline void mjit_finish(bool close_handle_p){}
154 
155 static inline void rb_mjit_collect_vm_usage_insn(int insn) {}
156 
157 # endif // USE_MJIT
158 #endif // RUBY_MJIT_H
#define RUBY_EXTERN
Declaration of externally visible global variables.
Definition: dllexport.h:47
uint32_t rb_event_flag_t
Represents event(s).
Definition: event.h:103
#define Qundef
Old name of RUBY_Qundef.
#define Qnil
Old name of RUBY_Qnil.
C99 shim for <stdbool.h>
Definition: method.h:62
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition: value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40