2#include "internal/sanitizers.h"
3#include "internal/string.h"
4#include "internal/hash.h"
5#include "internal/variable.h"
6#include "internal/compile.h"
7#include "internal/class.h"
8#include "internal/fixnum.h"
9#include "internal/numeric.h"
10#include "internal/gc.h"
11#include "internal/vm.h"
14#include "vm_callinfo.h"
17#include "insns_info.inc"
19#include "vm_insnhelper.h"
21#include "probes_helper.h"
24#include "internal/cont.h"
28STATIC_ASSERT(pointer_tagging_scheme,
USE_FLONUM);
30enum zjit_struct_offsets {
39 VALUE frame_id = PTR2NUM(frame);
41 if (
RTEST(rb_hash_aref(hash, frame_id))) {
58 rb_hash_aset(frame_info,
ID2SYM(rb_intern(
"name")), name);
59 rb_hash_aset(frame_info,
ID2SYM(rb_intern(
"file")), file);
60 rb_hash_aset(frame_info,
ID2SYM(rb_intern(
"samples")),
INT2NUM(0));
61 rb_hash_aset(frame_info,
ID2SYM(rb_intern(
"total_samples")),
INT2NUM(0));
66 rb_hash_aset(frame_info,
ID2SYM(rb_intern(
"line")), line);
69 rb_hash_aset(hash, frame_id, frame_info);
79rb_zjit_exit_locations_dict(
VALUE *zjit_raw_samples,
int *zjit_line_samples,
int samples_len)
89 while (idx < samples_len) {
90 int num = (int)zjit_raw_samples[idx];
91 int line_num = (int)zjit_line_samples[idx];
101 for (
int o = 0; o < num; o++) {
102 rb_zjit_add_frame(frames, zjit_raw_samples[idx]);
119 rb_hash_aset(result,
ID2SYM(rb_intern(
"raw")), raw_samples);
120 rb_hash_aset(result,
ID2SYM(rb_intern(
"lines")), line_samples);
121 rb_hash_aset(result,
ID2SYM(rb_intern(
"frames")), frames);
126void rb_zjit_profile_disable(
const rb_iseq_t *iseq);
129rb_zjit_compile_iseq(
const rb_iseq_t *iseq,
bool jit_exception)
135 uint8_t *rb_zjit_iseq_gen_entry_point(
const rb_iseq_t *iseq,
bool jit_exception);
136 uintptr_t code_ptr = (uintptr_t)rb_zjit_iseq_gen_entry_point(iseq, jit_exception);
139 iseq->body->jit_exception = (rb_jit_func_t)code_ptr;
142 iseq->body->jit_entry = (rb_jit_func_t)code_ptr;
152 return (ice->flags & IMEMO_CONST_CACHE_SHAREABLE) != 0;
157rb_zjit_profile_enable(
const rb_iseq_t *iseq)
160 const void *
const *insn_table = rb_vm_get_insns_address_table();
162 unsigned int insn_idx = 0;
163 while (insn_idx < iseq->body->iseq_size) {
164 int insn = rb_vm_insn_addr2opcode((
void *)iseq->body->iseq_encoded[insn_idx]);
165 int zjit_insn = vm_bare_insn_to_zjit_insn(insn);
166 if (insn != zjit_insn) {
167 iseq->body->iseq_encoded[insn_idx] = (
VALUE)insn_table[zjit_insn];
169 insn_idx += insn_len(insn);
175rb_zjit_profile_disable(
const rb_iseq_t *iseq)
178 const void *
const *insn_table = rb_vm_get_insns_address_table();
180 unsigned int insn_idx = 0;
181 while (insn_idx < iseq->body->iseq_size) {
182 int insn = rb_vm_insn_addr2opcode((
void *)iseq->body->iseq_encoded[insn_idx]);
183 int bare_insn = vm_zjit_insn_to_bare_insn(insn);
184 if (insn != bare_insn) {
185 iseq->body->iseq_encoded[insn_idx] = (
VALUE)insn_table[bare_insn];
187 insn_idx += insn_len(insn);
193rb_zjit_iseq_insn_set(
const rb_iseq_t *iseq,
unsigned int insn_idx,
enum ruby_vminsn_type bare_insn)
196 int insn = rb_vm_insn_addr2opcode((
void *)iseq->body->iseq_encoded[insn_idx]);
197 RUBY_ASSERT(vm_zjit_insn_to_bare_insn(insn) == (
int)bare_insn);
199 const void *
const *insn_table = rb_vm_get_insns_address_table();
200 iseq->body->iseq_encoded[insn_idx] = (
VALUE)insn_table[bare_insn];
205rb_iseq_get_zjit_payload(
const rb_iseq_t *iseq)
209 return iseq->body->zjit_payload;
219rb_iseq_set_zjit_payload(
const rb_iseq_t *iseq,
void *payload)
224 iseq->body->zjit_payload = payload;
228rb_zjit_print_exception(
void)
231 rb_set_errinfo(
Qnil);
232 assert(
RTEST(exception));
233 rb_warn(
"Ruby error: %"PRIsVALUE
"",
rb_funcall(exception, rb_intern(
"full_message"), 0));
237rb_zjit_singleton_class_p(
VALUE klass)
239 return RCLASS_SINGLETON_P(klass);
246 return result ? pushval :
Qnil;
250rb_zjit_method_tracing_currently_enabled(
void)
253 if (rb_multi_ractor_p()) {
254 tracing_events = ruby_vm_event_enabled_global_flags;
260 tracing_events = rb_ec_ractor_hooks(GET_EC())->events;
267rb_zjit_insn_leaf(
int insn,
const VALUE *opes)
269 return insn_leaf(insn, opes);
273rb_zjit_local_id(
const rb_iseq_t *iseq,
unsigned idx)
275 return ISEQ_BODY(iseq)->local_table[idx];
278bool rb_zjit_cme_is_cfunc(
const rb_callable_method_entry_t *me,
const void *func);
284rb_zjit_class_initialized_p(
VALUE klass)
286 return RCLASS_INITIALIZED_P(klass);
294rb_zjit_class_has_default_allocator(
VALUE klass)
296 assert(RCLASS_INITIALIZED_P(klass));
297 assert(!RCLASS_SINGLETON_P(klass));
299 return alloc == rb_class_allocate_instance;
303VALUE rb_vm_get_untagged_block_handler(rb_control_frame_t *reg_cfp);
306rb_zjit_writebarrier_check_immediate(
VALUE recv,
VALUE val)
309 rb_gc_writebarrier(recv, val);
314VALUE rb_zjit_enable(rb_execution_context_t *ec,
VALUE self);
315VALUE rb_zjit_assert_compiles(rb_execution_context_t *ec,
VALUE self);
316VALUE rb_zjit_stats(rb_execution_context_t *ec,
VALUE self,
VALUE target_key);
317VALUE rb_zjit_reset_stats_bang(rb_execution_context_t *ec,
VALUE self);
318VALUE rb_zjit_stats_enabled_p(rb_execution_context_t *ec,
VALUE self);
319VALUE rb_zjit_print_stats_p(rb_execution_context_t *ec,
VALUE self);
320VALUE rb_zjit_get_stats_file_path_p(rb_execution_context_t *ec,
VALUE self);
321VALUE rb_zjit_trace_exit_locations_enabled_p(rb_execution_context_t *ec,
VALUE self);
322VALUE rb_zjit_get_exit_locations(rb_execution_context_t *ec,
VALUE self);
#define RUBY_ASSERT_ALWAYS(expr,...)
A variant of RUBY_ASSERT that does not interface with RUBY_DEBUG.
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
VALUE rb_profile_frame_full_label(VALUE frame)
Identical to rb_profile_frame_label(), except it returns a qualified result.
VALUE rb_profile_frame_absolute_path(VALUE frame)
Identical to rb_profile_frame_path(), except it tries to expand the returning path.
VALUE rb_profile_frame_path(VALUE frame)
Queries the path of the passed backtrace.
VALUE rb_profile_frame_first_lineno(VALUE frame)
Queries the first line of the method of the passed frame pointer.
#define RUBY_EVENT_C_CALL
A method, written in C, is called.
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
uint32_t rb_event_flag_t
Represents event(s).
#define INT2FIX
Old name of RB_INT2FIX.
#define ID2SYM
Old name of RB_ID2SYM.
#define SIZET2NUM
Old name of RB_SIZE2NUM.
#define INT2NUM
Old name of RB_INT2NUM.
#define Qnil
Old name of RUBY_Qnil.
#define NIL_P
Old name of RB_NIL_P.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
VALUE rb_errinfo(void)
This is the same as $! in Ruby.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_hash_new(void)
Creates a new, empty hash object.
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
VALUE(* rb_alloc_func_t)(VALUE klass)
This is the type of functions that ruby calls when trying to allocate an object.
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
#define RTEST
This is an old name of RB_TEST.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.