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"
25#include "internal/cont.h"
26#include "internal/jit.h"
27#include "ractor_core.h"
36STATIC_ASSERT(pointer_tagging_scheme,
USE_FLONUM);
38enum zjit_struct_offsets {
41 RUBY_OFFSET_THREAD_RACTOR = offsetof(
rb_thread_t, ractor),
53 int32_t ractor_newobj_cache;
54 int32_t ractor_objspace;
57 .ractor_newobj_cache = offsetof(
rb_ractor_t, newobj_cache),
67 .materialize_block_code =
false,
70#if !defined(_WIN32) && defined(MAP_ANONYMOUS)
71uint8_t *rb_jit_align_ptr(uint8_t *ptr, uint32_t multiple);
82rb_zjit_reserve_low_addr_space(
size_t size)
84 void *mem_block = MAP_FAILED;
89 mem_block = mmap(NULL, size, PROT_NONE,
90 MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
95 #if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
96 if (mem_block == MAP_FAILED) {
98 const uintptr_t probe_stride = 64 * 1024 * 1024;
99 const uint32_t page_size = (uint32_t)sysconf(_SC_PAGESIZE);
100 const uintptr_t limit = (uintptr_t)INT32_MAX - size;
101 for (uintptr_t addr = probe_stride; addr < limit; addr += probe_stride) {
103 void *req = rb_jit_align_ptr((uint8_t *)addr, page_size);
104 mem_block = mmap(req, size, PROT_NONE,
105 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE, -1, 0);
106 if (mem_block != MAP_FAILED)
break;
111 if (mem_block == MAP_FAILED)
return NULL;
115 if ((uintptr_t)mem_block + size > (uintptr_t)INT32_MAX) {
116 munmap(mem_block, size);
119 ruby_annotate_mmap(mem_block, size,
"Ruby:rb_zjit_reserve_low_addr_space");
126void *rb_zjit_reserve_low_addr_space(
size_t size) {
return NULL; }
133 return ULL2NUM(rb_zjit_total_compile_time_ns);
139 return ULL2NUM(rb_zjit_max_compile_time_ns);
142void rb_zjit_update_max_compile_time_ns(uint64_t max_compile_time_ns);
147 rb_zjit_update_max_compile_time_ns(
NUM2ULL(max_compile_time_ns));
148 return max_compile_time_ns;
151void rb_zjit_profile_disable(
const rb_iseq_t *iseq);
152int rb_zjit_insn_to_bare_insn(
int insn);
162 uintptr_t code_ptr = (uintptr_t)rb_zjit_iseq_gen_entry_point(iseq, ec, jit_exception);
165 ISEQ_BODY(iseq)->jit_exception = (rb_jit_func_t)code_ptr;
168 ISEQ_BODY(iseq)->jit_entry = (rb_jit_func_t)code_ptr;
175rb_zjit_iseq_set_jit_entry(
const rb_iseq_t *iseq,
void *code_ptr)
177 ISEQ_BODY(iseq)->jit_entry = (rb_jit_func_t)code_ptr;
184rb_zjit_profile_enable(
const rb_iseq_t *iseq)
187 const void *
const *insn_table = rb_vm_get_insns_address_table();
189 unsigned int insn_idx = 0;
190 while (insn_idx < ISEQ_BODY(iseq)->iseq_size) {
191 int insn = rb_vm_insn_addr2opcode((
void *)ISEQ_BODY(iseq)->iseq_encoded[insn_idx]);
192 int zjit_insn = vm_bare_insn_to_zjit_insn(insn);
193 if (insn != zjit_insn) {
194 ISEQ_BODY(iseq)->iseq_encoded[insn_idx] = (
VALUE)insn_table[zjit_insn];
196 insn_idx += insn_len(insn);
203rb_zjit_iseq_has_profiled_enough(
const rb_iseq_t *iseq)
207 if (body->jit_entry_calls < rb_zjit_profile_threshold) {
210 body->jit_entry_calls = rb_zjit_profile_threshold;
211 rb_zjit_profile_enable(iseq);
214 body->jit_entry_calls++;
217 return body->jit_entry_calls >= rb_zjit_call_threshold;
222rb_zjit_profile_disable(
const rb_iseq_t *iseq)
225 const void *
const *insn_table = rb_vm_get_insns_address_table();
227 unsigned int insn_idx = 0;
228 while (insn_idx < ISEQ_BODY(iseq)->iseq_size) {
229 int insn = rb_vm_insn_addr2opcode((
void *)ISEQ_BODY(iseq)->iseq_encoded[insn_idx]);
230 int bare_insn = vm_zjit_insn_to_bare_insn(insn);
231 if (insn != bare_insn) {
232 ISEQ_BODY(iseq)->iseq_encoded[insn_idx] = (
VALUE)insn_table[bare_insn];
234 insn_idx += insn_len(insn);
240rb_zjit_insn_to_bare_insn(
int insn)
242 return vm_zjit_insn_to_bare_insn(insn);
247rb_zjit_iseq_insn_set(
const rb_iseq_t *iseq,
unsigned int insn_idx,
enum ruby_vminsn_type bare_insn)
250 int insn = rb_vm_insn_addr2opcode((
void *)ISEQ_BODY(iseq)->iseq_encoded[insn_idx]);
251 RUBY_ASSERT(vm_zjit_insn_to_bare_insn(insn) == (
int)bare_insn);
253 const void *
const *insn_table = rb_vm_get_insns_address_table();
254 ISEQ_BODY(iseq)->iseq_encoded[insn_idx] = (
VALUE)insn_table[bare_insn];
258rb_zjit_print_exception(
void)
260 VALUE exception = rb_errinfo();
261 rb_set_errinfo(
Qnil);
262 assert(
RTEST(exception));
263 rb_warn(
"Ruby error: %"PRIsVALUE
"",
rb_funcall(exception, rb_intern(
"full_message"), 0));
267rb_zjit_singleton_class_p(
VALUE klass)
269 return RCLASS_SINGLETON_P(klass);
276rb_zjit_new_obj_shape(
VALUE flags,
size_t alloc_size)
281 shape_id = ROOT_SHAPE_ID;
284 shape_id = ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_EXTENDED;
287 shape_id = ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_RDATA;
290 shape_id = ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER;
295 shape_id = rb_shape_transition_frozen(shape_id);
298 shape_id = rb_shape_transition_slot_size(shape_id, rb_gc_size_slot_size(alloc_size));
300 return (flags & SHAPE_FLAG_MASK) | ((
VALUE)shape_id << SHAPE_FLAG_SHIFT);
307 return result ? pushval :
Qnil;
311rb_zjit_method_tracing_currently_enabled(
void)
314 if (rb_multi_ractor_p()) {
315 tracing_events = ruby_vm_event_enabled_global_flags;
321 tracing_events = rb_ec_ractor_hooks(GET_EC())->events;
333rb_zjit_iseq_tracing_currently_enabled(
void)
336 if (rb_multi_ractor_p()) {
337 tracing_events = ruby_vm_event_enabled_global_flags;
340 tracing_events = rb_ec_ractor_hooks(GET_EC())->events;
343 return tracing_events & ISEQ_TRACE_EVENTS;
347rb_zjit_insn_leaf(
int insn,
const VALUE *opes)
349 return insn_leaf(insn, opes);
353rb_zjit_local_id(
const rb_iseq_t *iseq,
unsigned idx)
355 return ISEQ_BODY(iseq)->local_table[idx];
366bool rb_zjit_class_has_struct_allocator(
VALUE klass);
369bool rb_zjit_struct_embedded_p(
rb_len_t num_members);
375rb_zjit_class_has_default_allocator(
VALUE klass)
377 assert(RCLASS_INITIALIZED_P(klass));
378 assert(!RCLASS_SINGLETON_P(klass));
380 return alloc == rb_class_allocate_instance;
385bool rb_vm_once_done_value(
ISE is,
VALUE *result);
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#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 T_MASK
Old name of RUBY_T_MASK.
#define T_STRUCT
Old name of RUBY_T_STRUCT.
#define T_DATA
Old name of RUBY_T_DATA.
#define ULL2NUM
Old name of RB_ULL2NUM.
#define Qnil
Old name of RUBY_Qnil.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define T_OBJECT
Old name of RUBY_T_OBJECT.
#define NUM2ULL
Old name of RB_NUM2ULL.
#define FL_FREEZE
Old name of RUBY_FL_FREEZE.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Defines RBIMPL_HAS_BUILTIN.
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.
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_AREF(a, i)
References an object in an array.
#define RTEST
This is an old name of RB_TEST.
long rb_len_t
A signed integer type for lengths and indices of objects such as String and Array.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.