summaryrefslogtreecommitdiff
path: root/rjit.h
blob: 20dc31db50e4f2663dbb3f11240e306564567e03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#ifndef RUBY_RJIT_H
#define RUBY_RJIT_H 1
/**********************************************************************

  rjit.h - Interface to RJIT

  Copyright (C) 2023 Takashi Kokubun <k0kubun@ruby-lang.org>.

**********************************************************************/

#include "ruby/internal/config.h" // defines USE_RJIT
#include "ruby/internal/stdbool.h"
#include "vm_core.h"

# if USE_RJIT

#ifndef RJIT_STATS
# define RJIT_STATS RUBY_DEBUG
#endif

#include "ruby.h"
#include "vm_core.h"

// Special address values of a function generated from the
// corresponding iseq by RJIT:
enum rb_rjit_func_state {
    // ISEQ has not been compiled yet
    RJIT_FUNC_NOT_COMPILED = 0,
    // ISEQ is already queued for the machine code generation but the
    // code is not ready yet for the execution
    RJIT_FUNC_COMPILING = 1,
    // ISEQ included not compilable insn, some internal assertion failed
    // or the unit is unloaded
    RJIT_FUNC_FAILED = 2,
};
// Return true if jit_func is part of enum rb_rjit_func_state
#define RJIT_FUNC_STATE_P(jit_func) ((uintptr_t)(jit_func) <= (uintptr_t)RJIT_FUNC_FAILED)

// RJIT options which can be defined on the MRI command line.
struct rjit_options {
    // Converted from "jit" feature flag to tell the enablement
    // information to ruby_show_version().
    bool on;
    // Save temporary files after MRI finish.  The temporary files
    // include the pre-compiled header, C code file generated for ISEQ,
    // and the corresponding object file.
    bool save_temps;
    // Print RJIT warnings to stderr.
    bool warnings;
    // Disable compiler optimization and add debug symbols. It can be
    // very slow.
    bool debug;
    // Add arbitrary cflags.
    char* debug_flags;
    // If true, all ISeqs are synchronously compiled. For testing.
    bool wait;
    // Number of calls to trigger JIT compilation. For testing.
    unsigned int call_threshold;
    // Collect RJIT statistics
    bool stats;
    // Force printing info about RJIT work of level VERBOSE or
    // less. 0=silence, 1=medium, 2=verbose.
    int verbose;
    // Maximal permitted number of iseq JIT codes in a RJIT memory
    // cache.
    int max_cache_size;
    // [experimental] Do not start RJIT until RJIT.resume is called.
    bool pause;
    // [experimental] Call custom RubyVM::RJIT.compile instead of RJIT.
    bool custom;
    // Enable disasm of all JIT code
    bool dump_disasm;
};

// State of optimization switches
struct rb_rjit_compile_info {
    // Disable getinstancevariable/setinstancevariable optimizations based on inline cache (T_OBJECT)
    bool disable_ivar_cache;
    // Disable getinstancevariable/setinstancevariable optimizations based on inline cache (FL_EXIVAR)
    bool disable_exivar_cache;
    // Disable send/opt_send_without_block optimizations based on inline cache
    bool disable_send_cache;
    // Disable method inlining
    bool disable_inlining;
    // Disable opt_getinlinecache inlining
    bool disable_const_cache;
};

RUBY_SYMBOL_EXPORT_BEGIN
RUBY_EXTERN struct rjit_options rb_rjit_opts;
RUBY_EXTERN bool rb_rjit_call_p;

#define rb_rjit_call_threshold() rb_rjit_opts.call_threshold

extern void rb_rjit_compile(const rb_iseq_t *iseq);
RUBY_SYMBOL_EXPORT_END

extern void rb_rjit_cancel_all(const char *reason);
extern void rb_rjit_init(const struct rjit_options *opts);
extern void rb_rjit_free_iseq(const rb_iseq_t *iseq);
extern void rb_rjit_iseq_update_references(struct rb_iseq_constant_body *const body);
extern void rb_rjit_mark(void);
extern void rb_rjit_iseq_mark(VALUE rjit_blocks);
extern void rjit_notify_waitpid(int exit_code);

extern void rb_rjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
extern void rb_rjit_cme_invalidate(rb_callable_method_entry_t *cme);
extern void rb_rjit_before_ractor_spawn(void);
extern void rb_rjit_constant_state_changed(ID id);
extern void rb_rjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx);
extern void rb_rjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events);

extern void rb_rjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
extern void rb_rjit_before_ractor_spawn(void);
extern void rb_rjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events);
extern void rb_rjit_collect_vm_usage_insn(int insn);

extern bool rb_rjit_enabled;
extern bool rb_rjit_stats_enabled;

# else // USE_RJIT

static inline void rb_rjit_compile(const rb_iseq_t *iseq){}

static inline void rb_rjit_cancel_all(const char *reason){}
static inline void rb_rjit_free_iseq(const rb_iseq_t *iseq){}
static inline void rb_rjit_mark(void){}

static inline void rb_rjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop) {}
static inline void rb_rjit_cme_invalidate(rb_callable_method_entry_t *cme) {}
static inline void rb_rjit_before_ractor_spawn(void) {}
static inline void rb_rjit_constant_state_changed(ID id) {}
static inline void rb_rjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx) {}
static inline void rb_rjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events) {}

#define rb_rjit_enabled false
#define rb_rjit_call_p false
#define rb_rjit_stats_enabled false

#define rb_rjit_call_threshold() UINT_MAX

static inline void rb_rjit_collect_vm_usage_insn(int insn) {}

# endif // USE_RJIT
#endif // RUBY_RJIT_H