Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
mjit.h
Go to the documentation of this file.
1 /**********************************************************************
2 
3  mjit.h - Interface to MRI method JIT compiler for Ruby's main thread
4 
5  Copyright (C) 2017 Vladimir Makarov <vmakarov@redhat.com>.
6 
7 **********************************************************************/
8 
9 #ifndef RUBY_MJIT_H
10 #define RUBY_MJIT_H 1
11 
12 #include "ruby.h"
13 #include "debug_counter.h"
14 
15 #if USE_MJIT
16 
17 // Special address values of a function generated from the
18 // corresponding iseq by MJIT:
19 enum rb_mjit_iseq_func {
20  // ISEQ was not queued yet for the machine code generation
22  // ISEQ is already queued for the machine code generation but the
23  // code is not ready yet for the execution
25  // ISEQ included not compilable insn, some internal assertion failed
26  // or the unit is unloaded
28  // End mark
30 };
31 
32 // MJIT options which can be defined on the MRI command line.
33 struct mjit_options {
34  // Converted from "jit" feature flag to tell the enablement
35  // information to ruby_show_version().
36  char on;
37  // Save temporary files after MRI finish. The temporary files
38  // include the pre-compiled header, C code file generated for ISEQ,
39  // and the corresponding object file.
40  char save_temps;
41  // Print MJIT warnings to stderr.
42  char warnings;
43  // Disable compiler optimization and add debug symbols. It can be
44  // very slow.
45  char debug;
46  // Add arbitrary cflags.
47  char* debug_flags;
48  // If not 0, all ISeqs are synchronously compiled. For testing.
49  unsigned int wait;
50  // Number of calls to trigger JIT compilation. For testing.
51  unsigned int min_calls;
52  // Force printing info about MJIT work of level VERBOSE or
53  // less. 0=silence, 1=medium, 2=verbose.
54  int verbose;
55  // Maximal permitted number of iseq JIT codes in a MJIT memory
56  // cache.
57  int max_cache_size;
58 };
59 
60 // State of optimization switches
61 struct rb_mjit_compile_info {
62  // Disable getinstancevariable/setinstancevariable optimizations based on inline cache
63  bool disable_ivar_cache;
64  // Disable send/opt_send_without_block optimizations based on inline cache
65  bool disable_send_cache;
66  // Disable method inlining
67  bool disable_inlining;
68 };
69 
71 
75 
76 extern void rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq);
79 extern void rb_mjit_recompile_iseq(const rb_iseq_t *iseq);
81 
82 extern bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname);
83 extern void mjit_init(const struct mjit_options *opts);
84 extern void mjit_gc_start_hook(void);
85 extern void mjit_gc_exit_hook(void);
86 extern void mjit_free_iseq(const rb_iseq_t *iseq);
87 extern void mjit_update_references(const rb_iseq_t *iseq);
88 extern void mjit_mark(void);
89 extern struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec);
90 extern void mjit_cont_free(struct mjit_cont *cont);
91 extern void mjit_add_class_serial(rb_serial_t class_serial);
92 extern void mjit_remove_class_serial(rb_serial_t class_serial);
93 
94 // A threshold used to reject long iseqs from JITting as such iseqs
95 // takes too much time to be compiled.
96 #define JIT_ISEQ_SIZE_THRESHOLD 1000
97 
98 // Return TRUE if given ISeq body should be compiled by MJIT
99 static inline int
100 mjit_target_iseq_p(struct rb_iseq_constant_body *body)
101 {
102  return (body->type == ISEQ_TYPE_METHOD || body->type == ISEQ_TYPE_BLOCK)
104 }
105 
106 // Try to execute the current iseq in ec. Use JIT code if it is ready.
107 // If it is not, add ISEQ to the compilation queue and return Qundef.
108 static inline VALUE
109 mjit_exec(rb_execution_context_t *ec)
110 {
111  const rb_iseq_t *iseq;
112  struct rb_iseq_constant_body *body;
113  long unsigned total_calls;
114  mjit_func_t func;
115 
116  if (!mjit_call_p)
117  return Qundef;
118  RB_DEBUG_COUNTER_INC(mjit_exec);
119 
120  iseq = ec->cfp->iseq;
121  body = iseq->body;
122  total_calls = ++body->total_calls;
123 
124  func = body->jit_func;
126 # ifdef MJIT_HEADER
127  RB_DEBUG_COUNTER_INC(mjit_frame_JT2VM);
128 # else
129  RB_DEBUG_COUNTER_INC(mjit_frame_VM2VM);
130 # endif
131  switch ((enum rb_mjit_iseq_func)func) {
133  RB_DEBUG_COUNTER_INC(mjit_exec_not_added);
134  if (total_calls == mjit_opts.min_calls && mjit_target_iseq_p(body)) {
135  RB_DEBUG_COUNTER_INC(mjit_exec_not_added_add_iseq);
137  if (UNLIKELY(mjit_opts.wait)) {
138  return rb_mjit_wait_call(ec, body);
139  }
140  }
141  return Qundef;
143  RB_DEBUG_COUNTER_INC(mjit_exec_not_ready);
144  return Qundef;
146  RB_DEBUG_COUNTER_INC(mjit_exec_not_compiled);
147  return Qundef;
148  default: // to avoid warning with LAST_JIT_ISEQ_FUNC
149  break;
150  }
151  }
152 
153 # ifdef MJIT_HEADER
154  RB_DEBUG_COUNTER_INC(mjit_frame_JT2JT);
155 # else
156  RB_DEBUG_COUNTER_INC(mjit_frame_VM2JT);
157 # endif
158  RB_DEBUG_COUNTER_INC(mjit_exec_call_func);
159  return func(ec, ec->cfp);
160 }
161 
162 void mjit_child_after_fork(void);
163 
164 #else // USE_MJIT
165 static inline struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec){return NULL;}
166 static inline void mjit_cont_free(struct mjit_cont *cont){}
167 static inline void mjit_gc_start_hook(void){}
168 static inline void mjit_gc_exit_hook(void){}
169 static inline void mjit_free_iseq(const rb_iseq_t *iseq){}
170 static inline void mjit_mark(void){}
171 static inline void mjit_add_class_serial(rb_serial_t class_serial){}
172 static inline void mjit_remove_class_serial(rb_serial_t class_serial){}
173 static inline VALUE mjit_exec(rb_execution_context_t *ec) { return Qundef; /* unreachable */ }
174 static inline void mjit_child_after_fork(void){}
175 
176 #endif // USE_MJIT
177 #endif // RUBY_MJIT_H
UNLIKELY
#define UNLIKELY(x)
Definition: ffi_common.h:126
RUBY_SYMBOL_EXPORT_END
#define RUBY_SYMBOL_EXPORT_END
Definition: missing.h:49
rb_iseq_struct
Definition: vm_core.h:456
mjit_child_after_fork
void mjit_child_after_fork(void)
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_iseq_constant_body::jit_func
VALUE(* jit_func)(struct rb_execution_context_struct *, struct rb_control_frame_struct *)
Definition: rb_mjit_min_header-2.7.2.h:9560
Qundef
#define Qundef
Definition: ruby.h:470
NOT_READY_JIT_ISEQ_FUNC
@ NOT_READY_JIT_ISEQ_FUNC
Definition: rb_mjit_min_header-2.7.2.h:11688
rb_mjit_compile_info::disable_inlining
_Bool disable_inlining
Definition: rb_mjit_min_header-2.7.2.h:11706
uintptr_t
unsigned int uintptr_t
Definition: win32.h:106
mjit_options::warnings
char warnings
Definition: rb_mjit_min_header-2.7.2.h:11695
NULL
#define NULL
Definition: _sdbm.c:101
rb_mjit_iseq_func
rb_mjit_iseq_func
Definition: rb_mjit_min_header-2.7.2.h:11686
rb_iseq_constant_body
Definition: vm_core.h:311
rb_mjit_iseq_compile_info
struct rb_mjit_compile_info * rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body)
rb_execution_context_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:847
JIT_ISEQ_SIZE_THRESHOLD
#define JIT_ISEQ_SIZE_THRESHOLD
Definition: rb_mjit_min_header-2.7.2.h:11732
mjit_options::wait
unsigned int wait
Definition: rb_mjit_min_header-2.7.2.h:11698
mjit_remove_class_serial
void mjit_remove_class_serial(rb_serial_t class_serial)
mjit_func_t
VALUE(* mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *)
Definition: rb_mjit_min_header-2.7.2.h:11708
rb_serial_t
unsigned long rb_serial_t
Definition: internal.h:1014
NOT_ADDED_JIT_ISEQ_FUNC
@ NOT_ADDED_JIT_ISEQ_FUNC
Definition: rb_mjit_min_header-2.7.2.h:11687
mjit_options::debug_flags
char * debug_flags
Definition: rb_mjit_min_header-2.7.2.h:11697
rb_mjit_compile_info
Definition: rb_mjit_min_header-2.7.2.h:11703
mjit_options::save_temps
char save_temps
Definition: rb_mjit_min_header-2.7.2.h:11694
ruby.h
rb_iseq_constant_body::type
enum rb_iseq_constant_body::iseq_type type
rb_control_frame_struct
Definition: vm_core.h:760
mjit_options::on
char on
Definition: rb_mjit_min_header-2.7.2.h:11693
rb_mjit_compile_info::disable_send_cache
_Bool disable_send_cache
Definition: rb_mjit_min_header-2.7.2.h:11705
rb_mjit_compile_info::disable_ivar_cache
_Bool disable_ivar_cache
Definition: rb_mjit_min_header-2.7.2.h:11704
mjit_gc_start_hook
void mjit_gc_start_hook(void)
mjit_options::verbose
int verbose
Definition: rb_mjit_min_header-2.7.2.h:11700
f
#define f
RUBY_SYMBOL_EXPORT_BEGIN
#define RUBY_SYMBOL_EXPORT_BEGIN
Definition: missing.h:48
mjit_cont_new
struct mjit_cont * mjit_cont_new(rb_execution_context_t *ec)
mjit_add_class_serial
void mjit_add_class_serial(rb_serial_t class_serial)
mjit_opts
struct mjit_options mjit_opts
Definition: mjit_worker.c:174
rb_iseq_constant_body::total_calls
long unsigned total_calls
Definition: rb_mjit_min_header-2.7.2.h:9562
rb_control_frame_struct::iseq
const rb_iseq_t * iseq
Definition: vm_core.h:763
mjit_options::max_cache_size
int max_cache_size
Definition: rb_mjit_min_header-2.7.2.h:11701
mjit_update_references
void mjit_update_references(const rb_iseq_t *iseq)
debug_counter.h
mjit_cont_free
void mjit_cont_free(struct mjit_cont *cont)
LAST_JIT_ISEQ_FUNC
@ LAST_JIT_ISEQ_FUNC
Definition: rb_mjit_min_header-2.7.2.h:11690
RUBY_EXTERN
#define RUBY_EXTERN
Definition: missing.h:77
mjit_compile
_Bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname)
rb_mjit_wait_call
VALUE rb_mjit_wait_call(rb_execution_context_t *ec, struct rb_iseq_constant_body *body)
mjit_options
Definition: rb_mjit_min_header-2.7.2.h:11692
RB_DEBUG_COUNTER_INC
#define RB_DEBUG_COUNTER_INC(type)
Definition: debug_counter.h:375
mjit_free_iseq
void mjit_free_iseq(const rb_iseq_t *iseq)
rb_iseq_struct::body
struct rb_iseq_constant_body * body
Definition: vm_core.h:460
rb_iseq_constant_body::iseq_size
unsigned int iseq_size
Definition: vm_core.h:324
mjit_init
void mjit_init(const struct mjit_options *opts)
NOT_COMPILED_JIT_ISEQ_FUNC
@ NOT_COMPILED_JIT_ISEQ_FUNC
Definition: rb_mjit_min_header-2.7.2.h:11689
mjit_gc_exit_hook
void mjit_gc_exit_hook(void)
rb_mjit_recompile_iseq
void rb_mjit_recompile_iseq(const rb_iseq_t *iseq)
mjit_mark
void mjit_mark(void)
rb_mjit_add_iseq_to_process
void rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq)
__sFILE
Definition: vsnprintf.c:169
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.2.h:13469
mjit_call_p
bool mjit_call_p
Definition: mjit_worker.c:180
mjit_options::debug
char debug
Definition: rb_mjit_min_header-2.7.2.h:11696
rb_execution_context_struct
Definition: vm_core.h:843
mjit_options::min_calls
unsigned int min_calls
Definition: rb_mjit_min_header-2.7.2.h:11699