Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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
21 NOT_ADDED_JIT_ISEQ_FUNC = 0,
22 // ISEQ is already queued for the machine code generation but the
23 // code is not ready yet for the execution
24 NOT_READY_JIT_ISEQ_FUNC = 1,
25 // ISEQ included not compilable insn, some internal assertion failed
26 // or the unit is unloaded
27 NOT_COMPILED_JIT_ISEQ_FUNC = 2,
28 // End mark
29 LAST_JIT_ISEQ_FUNC = 3
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
70 typedef VALUE (*mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *);
71
72 RUBY_SYMBOL_EXPORT_BEGIN
73 RUBY_EXTERN struct mjit_options mjit_opts;
74 RUBY_EXTERN bool mjit_call_p;
75
76 extern void rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq);
77 extern VALUE rb_mjit_wait_call(rb_execution_context_t *ec, struct rb_iseq_constant_body *body);
78 extern struct rb_mjit_compile_info* rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body);
79 extern void rb_mjit_recompile_iseq(const rb_iseq_t *iseq);
80 RUBY_SYMBOL_EXPORT_END
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)
103 && body->iseq_size < JIT_ISEQ_SIZE_THRESHOLD;
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;
125 if (UNLIKELY((uintptr_t)func <= (uintptr_t)LAST_JIT_ISEQ_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) {
132 case NOT_ADDED_JIT_ISEQ_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);
136 rb_mjit_add_iseq_to_process(iseq);
137 if (UNLIKELY(mjit_opts.wait)) {
138 return rb_mjit_wait_call(ec, body);
139 }
140 }
141 return Qundef;
142 case NOT_READY_JIT_ISEQ_FUNC:
143 RB_DEBUG_COUNTER_INC(mjit_exec_not_ready);
144 return Qundef;
145 case NOT_COMPILED_JIT_ISEQ_FUNC:
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_mjit_iseq_func
rb_mjit_iseq_func
Definition: rb_mjit_min_header-2.7.0.h:11718
mjit_add_class_serial
void mjit_add_class_serial(rb_serial_t class_serial)
rb_mjit_iseq_compile_info
struct rb_mjit_compile_info * rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body)
mjit_cont_free
void mjit_cont_free(struct mjit_cont *cont)
rb_iseq_struct
Definition: vm_core.h:456
mjit_remove_class_serial
void mjit_remove_class_serial(rb_serial_t class_serial)
mjit_init
void mjit_init(const struct mjit_options *opts)
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.0.h:9592
Qundef
#define Qundef
Definition: ruby.h:470
rb_mjit_compile_info::disable_inlining
_Bool disable_inlining
Definition: rb_mjit_min_header-2.7.0.h:11738
NOT_COMPILED_JIT_ISEQ_FUNC
@ NOT_COMPILED_JIT_ISEQ_FUNC
Definition: rb_mjit_min_header-2.7.0.h:11721
mjit_update_references
void mjit_update_references(const rb_iseq_t *iseq)
uintptr_t
unsigned int uintptr_t
Definition: win32.h:106
mjit_options::warnings
char warnings
Definition: rb_mjit_min_header-2.7.0.h:11727
NULL
#define NULL
Definition: _sdbm.c:101
mjit_compile
_Bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname)
rb_iseq_constant_body
Definition: vm_core.h:311
rb_execution_context_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:847
mjit_mark
void mjit_mark(void)
mjit_options::wait
unsigned int wait
Definition: rb_mjit_min_header-2.7.0.h:11730
mjit_cont_new
struct mjit_cont * mjit_cont_new(rb_execution_context_t *ec)
mjit_gc_exit_hook
void mjit_gc_exit_hook(void)
rb_mjit_add_iseq_to_process
void rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq)
rb_serial_t
unsigned long rb_serial_t
Definition: internal.h:1014
mjit_options::debug_flags
char * debug_flags
Definition: rb_mjit_min_header-2.7.0.h:11729
rb_mjit_compile_info
Definition: rb_mjit_min_header-2.7.0.h:11735
mjit_options::save_temps
char save_temps
Definition: rb_mjit_min_header-2.7.0.h:11726
ruby.h
rb_iseq_constant_body::type
enum rb_iseq_constant_body::iseq_type type
mjit_gc_start_hook
void mjit_gc_start_hook(void)
mjit_free_iseq
void mjit_free_iseq(const rb_iseq_t *iseq)
rb_control_frame_struct
Definition: vm_core.h:760
NOT_ADDED_JIT_ISEQ_FUNC
@ NOT_ADDED_JIT_ISEQ_FUNC
Definition: rb_mjit_min_header-2.7.0.h:11719
LAST_JIT_ISEQ_FUNC
@ LAST_JIT_ISEQ_FUNC
Definition: rb_mjit_min_header-2.7.0.h:11722
mjit_options::on
char on
Definition: rb_mjit_min_header-2.7.0.h:11725
rb_mjit_recompile_iseq
void rb_mjit_recompile_iseq(const rb_iseq_t *iseq)
NOT_READY_JIT_ISEQ_FUNC
@ NOT_READY_JIT_ISEQ_FUNC
Definition: rb_mjit_min_header-2.7.0.h:11720
rb_mjit_compile_info::disable_send_cache
_Bool disable_send_cache
Definition: rb_mjit_min_header-2.7.0.h:11737
rb_mjit_compile_info::disable_ivar_cache
_Bool disable_ivar_cache
Definition: rb_mjit_min_header-2.7.0.h:11736
mjit_options::verbose
int verbose
Definition: rb_mjit_min_header-2.7.0.h:11732
mjit_child_after_fork
void mjit_child_after_fork(void)
JIT_ISEQ_SIZE_THRESHOLD
#define JIT_ISEQ_SIZE_THRESHOLD
Definition: rb_mjit_min_header-2.7.0.h:11764
f
#define f
RUBY_SYMBOL_EXPORT_BEGIN
#define RUBY_SYMBOL_EXPORT_BEGIN
Definition: missing.h:48
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.0.h:9594
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.0.h:11733
debug_counter.h
mjit_func_t
VALUE(* mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *)
Definition: rb_mjit_min_header-2.7.0.h:11740
RUBY_EXTERN
#define RUBY_EXTERN
Definition: missing.h:77
mjit_options
Definition: rb_mjit_min_header-2.7.0.h:11724
RB_DEBUG_COUNTER_INC
#define RB_DEBUG_COUNTER_INC(type)
Definition: debug_counter.h:375
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
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.0.h:13504
rb_mjit_wait_call
VALUE rb_mjit_wait_call(rb_execution_context_t *ec, struct rb_iseq_constant_body *body)
__sFILE
Definition: vsnprintf.c:169
mjit_call_p
bool mjit_call_p
Definition: mjit_worker.c:180
mjit_options::debug
char debug
Definition: rb_mjit_min_header-2.7.0.h:11728
rb_execution_context_struct
Definition: vm_core.h:843
mjit_options::min_calls
unsigned int min_calls
Definition: rb_mjit_min_header-2.7.0.h:11731