Ruby
2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
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
debug_counter.h
NULL
#define NULL
Definition:
rb_mjit_min_header-2.7.7.h:17333
mjit_call_p
_Bool mjit_call_p
Definition:
mjit_worker.c:180
mjit_gc_exit_hook
void mjit_gc_exit_hook(void)
Qundef
#define Qundef
Definition:
rb_mjit_min_header-2.7.7.h:15745
mjit_update_references
void mjit_update_references(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.7.h:7682
mjit_compile
_Bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname)
RUBY_SYMBOL_EXPORT_BEGIN
#define RUBY_SYMBOL_EXPORT_BEGIN
Definition:
rb_mjit_min_header-2.7.7.h:13332
VALUE
const char const char *typedef unsigned long VALUE
Definition:
rb_mjit_min_header-2.7.7.h:1875
JIT_ISEQ_SIZE_THRESHOLD
#define JIT_ISEQ_SIZE_THRESHOLD
Definition:
rb_mjit_min_header-2.7.7.h:17453
mjit_child_after_fork
void mjit_child_after_fork(void)
mjit_init
void mjit_init(const struct mjit_options *opts)
RUBY_SYMBOL_EXPORT_END
#define RUBY_SYMBOL_EXPORT_END
Definition:
rb_mjit_min_header-2.7.7.h:13333
rb_serial_t
unsigned long long rb_serial_t
Definition:
rb_mjit_min_header-2.7.7.h:3853
mjit_opts
struct mjit_options mjit_opts
Definition:
mjit_worker.c:174
rb_mjit_iseq_func
rb_mjit_iseq_func
Definition:
rb_mjit_min_header-2.7.7.h:7660
LAST_JIT_ISEQ_FUNC
@ LAST_JIT_ISEQ_FUNC
Definition:
rb_mjit_min_header-2.7.7.h:7664
NOT_COMPILED_JIT_ISEQ_FUNC
@ NOT_COMPILED_JIT_ISEQ_FUNC
Definition:
rb_mjit_min_header-2.7.7.h:7663
NOT_READY_JIT_ISEQ_FUNC
@ NOT_READY_JIT_ISEQ_FUNC
Definition:
rb_mjit_min_header-2.7.7.h:7662
NOT_ADDED_JIT_ISEQ_FUNC
@ NOT_ADDED_JIT_ISEQ_FUNC
Definition:
rb_mjit_min_header-2.7.7.h:7661
iseq
const rb_iseq_t * iseq
Definition:
rb_mjit_min_header-2.7.7.h:9316
UNLIKELY
#define UNLIKELY(x)
Definition:
rb_mjit_min_header-2.7.7.h:16362
uintptr_t
__uintptr_t uintptr_t
Definition:
rb_mjit_min_header-2.7.7.h:265
mjit_free_iseq
void mjit_free_iseq(const rb_iseq_t *iseq)
rb_mjit_add_iseq_to_process
void rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq)
rb_mjit_recompile_iseq
void rb_mjit_recompile_iseq(const rb_iseq_t *iseq)
mjit_remove_class_serial
void mjit_remove_class_serial(rb_serial_t class_serial)
rb_mjit_wait_call
VALUE rb_mjit_wait_call(rb_execution_context_t *ec, struct rb_iseq_constant_body *body)
RUBY_EXTERN
#define RUBY_EXTERN
Definition:
rb_mjit_min_header-2.7.7.h:15394
mjit_cont_free
void mjit_cont_free(struct mjit_cont *cont)
mjit_add_class_serial
void mjit_add_class_serial(rb_serial_t class_serial)
mjit_mark
void mjit_mark(void)
rb_mjit_iseq_compile_info
struct rb_mjit_compile_info * rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body)
mjit_cont_new
struct mjit_cont * mjit_cont_new(rb_execution_context_t *ec)
mjit_gc_start_hook
void mjit_gc_start_hook(void)
RB_DEBUG_COUNTER_INC
#define RB_DEBUG_COUNTER_INC(type)
Definition:
rb_mjit_min_header-2.7.7.h:17446
ruby.h
VALUE
unsigned long VALUE
Definition:
ruby.h:102
f
#define f
__sFILE64
Definition:
rb_mjit_min_header-2.7.7.h:151
mjit_options
Definition:
rb_mjit_min_header-2.7.7.h:7666
mjit_options::verbose
int verbose
Definition:
rb_mjit_min_header-2.7.7.h:7674
mjit_options::on
char on
Definition:
rb_mjit_min_header-2.7.7.h:7667
mjit_options::max_cache_size
int max_cache_size
Definition:
rb_mjit_min_header-2.7.7.h:7675
mjit_options::warnings
char warnings
Definition:
rb_mjit_min_header-2.7.7.h:7669
mjit_options::save_temps
char save_temps
Definition:
rb_mjit_min_header-2.7.7.h:7668
mjit_options::debug_flags
char * debug_flags
Definition:
rb_mjit_min_header-2.7.7.h:7671
mjit_options::debug
char debug
Definition:
rb_mjit_min_header-2.7.7.h:7670
mjit_options::min_calls
unsigned int min_calls
Definition:
rb_mjit_min_header-2.7.7.h:7673
mjit_options::wait
unsigned int wait
Definition:
rb_mjit_min_header-2.7.7.h:7672
rb_control_frame_struct
Definition:
rb_mjit_min_header-2.7.7.h:6087
rb_control_frame_struct::iseq
const rb_iseq_t * iseq
Definition:
rb_mjit_min_header-2.7.7.h:6090
rb_execution_context_struct
Definition:
rb_mjit_min_header-2.7.7.h:6141
rb_execution_context_struct::cfp
rb_control_frame_t * cfp
Definition:
rb_mjit_min_header-2.7.7.h:6144
rb_iseq_constant_body
Definition:
rb_mjit_min_header-2.7.7.h:5841
rb_iseq_constant_body::type
enum rb_iseq_constant_body::iseq_type type
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.7.h:5910
rb_iseq_constant_body::iseq_size
unsigned int iseq_size
Definition:
rb_mjit_min_header-2.7.7.h:5853
rb_iseq_constant_body::total_calls
long unsigned total_calls
Definition:
rb_mjit_min_header-2.7.7.h:5912
rb_iseq_struct
Definition:
rb_mjit_min_header-2.7.7.h:5916
rb_iseq_struct::body
struct rb_iseq_constant_body * body
Definition:
rb_mjit_min_header-2.7.7.h:5919
rb_mjit_compile_info
Definition:
rb_mjit_min_header-2.7.7.h:7677
rb_mjit_compile_info::disable_ivar_cache
_Bool disable_ivar_cache
Definition:
rb_mjit_min_header-2.7.7.h:7678
rb_mjit_compile_info::disable_send_cache
_Bool disable_send_cache
Definition:
rb_mjit_min_header-2.7.7.h:7679
rb_mjit_compile_info::disable_inlining
_Bool disable_inlining
Definition:
rb_mjit_min_header-2.7.7.h:7680
Generated by
1.9.2