Ruby
2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
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
JIT_ISEQ_SIZE_THRESHOLD
#define JIT_ISEQ_SIZE_THRESHOLD
Definition:
rb_mjit_min_header-2.7.1.h:11769
mjit_child_after_fork
void mjit_child_after_fork(void)
mjit_cont_new
struct mjit_cont * mjit_cont_new(rb_execution_context_t *ec)
rb_iseq_struct
Definition:
vm_core.h:456
mjit_free_iseq
void mjit_free_iseq(const rb_iseq_t *iseq)
mjit_func_t
VALUE(* mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *)
Definition:
rb_mjit_min_header-2.7.1.h:11745
NOT_COMPILED_JIT_ISEQ_FUNC
@ NOT_COMPILED_JIT_ISEQ_FUNC
Definition:
rb_mjit_min_header-2.7.1.h:11726
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.1.h:9597
iseq
const rb_iseq_t * iseq
Definition:
rb_mjit_min_header-2.7.1.h:13509
Qundef
#define Qundef
Definition:
ruby.h:470
rb_mjit_compile_info::disable_inlining
_Bool disable_inlining
Definition:
rb_mjit_min_header-2.7.1.h:11743
rb_mjit_recompile_iseq
void rb_mjit_recompile_iseq(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.1.h:11732
NULL
#define NULL
Definition:
_sdbm.c:101
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_cont_free
void mjit_cont_free(struct mjit_cont *cont)
mjit_options::wait
unsigned int wait
Definition:
rb_mjit_min_header-2.7.1.h:11735
LAST_JIT_ISEQ_FUNC
@ LAST_JIT_ISEQ_FUNC
Definition:
rb_mjit_min_header-2.7.1.h:11727
rb_serial_t
unsigned long rb_serial_t
Definition:
internal.h:1014
rb_mjit_iseq_compile_info
struct rb_mjit_compile_info * rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body)
mjit_options::debug_flags
char * debug_flags
Definition:
rb_mjit_min_header-2.7.1.h:11734
rb_mjit_compile_info
Definition:
rb_mjit_min_header-2.7.1.h:11740
mjit_options::save_temps
char save_temps
Definition:
rb_mjit_min_header-2.7.1.h:11731
ruby.h
rb_iseq_constant_body::type
enum rb_iseq_constant_body::iseq_type type
rb_control_frame_struct
Definition:
vm_core.h:760
rb_mjit_wait_call
VALUE rb_mjit_wait_call(rb_execution_context_t *ec, struct rb_iseq_constant_body *body)
mjit_add_class_serial
void mjit_add_class_serial(rb_serial_t class_serial)
mjit_init
void mjit_init(const struct mjit_options *opts)
mjit_update_references
void mjit_update_references(const rb_iseq_t *iseq)
mjit_options::on
char on
Definition:
rb_mjit_min_header-2.7.1.h:11730
rb_mjit_compile_info::disable_send_cache
_Bool disable_send_cache
Definition:
rb_mjit_min_header-2.7.1.h:11742
rb_mjit_compile_info::disable_ivar_cache
_Bool disable_ivar_cache
Definition:
rb_mjit_min_header-2.7.1.h:11741
mjit_options::verbose
int verbose
Definition:
rb_mjit_min_header-2.7.1.h:11737
rb_mjit_iseq_func
rb_mjit_iseq_func
Definition:
rb_mjit_min_header-2.7.1.h:11723
mjit_remove_class_serial
void mjit_remove_class_serial(rb_serial_t class_serial)
f
#define f
RUBY_SYMBOL_EXPORT_BEGIN
#define RUBY_SYMBOL_EXPORT_BEGIN
Definition:
missing.h:48
NOT_ADDED_JIT_ISEQ_FUNC
@ NOT_ADDED_JIT_ISEQ_FUNC
Definition:
rb_mjit_min_header-2.7.1.h:11724
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.1.h:9599
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.1.h:11738
debug_counter.h
NOT_READY_JIT_ISEQ_FUNC
@ NOT_READY_JIT_ISEQ_FUNC
Definition:
rb_mjit_min_header-2.7.1.h:11725
RUBY_EXTERN
#define RUBY_EXTERN
Definition:
missing.h:77
mjit_options
Definition:
rb_mjit_min_header-2.7.1.h:11729
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
mjit_compile
_Bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname)
rb_iseq_constant_body::iseq_size
unsigned int iseq_size
Definition:
vm_core.h:324
mjit_gc_exit_hook
void mjit_gc_exit_hook(void)
mjit_gc_start_hook
void mjit_gc_start_hook(void)
rb_mjit_add_iseq_to_process
void rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq)
mjit_mark
void mjit_mark(void)
__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.1.h:11733
rb_execution_context_struct
Definition:
vm_core.h:843
mjit_options::min_calls
unsigned int min_calls
Definition:
rb_mjit_min_header-2.7.1.h:11736
Generated by
1.8.17