--enable=zjit sets the zjit feature bit without parsing a --zjit option,
so OPTIONS is never initialized and rb_zjit_option_enable() returns
false.
ZJIT then stays disabled at boot. The same happens with --enable-zjit
and RUBYOPT=--enable=zjit, and with --jit, --enable=jit and --enable=all
on ZJIT-only builds.
In this commit we call rb_zjit_prepare_options() whenever the zjit
feature is set, regardless of where the bit came from. It's a no-op
when the --zjit option parser has already initialized OPTIONS, so
--zjit-disable and the other ZJIT options still apply.
[Bug #22427]
Ruby::Prism itself does not compile the program (prism_compile.c does,
and other implementations may not even compile an AST into bytecode).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Ruby part of prism moves from lib/prism to lib/ruby/prism and is
namespaced as Ruby::Prism by the sync tool (see the previous commit).
Wire the build for that layout:
- prism_init.c registers the statically linked extension as
"ruby/prism/prism.so".
- Ruby::Prism is autoloaded from "ruby/prism", so programs that do not
use it pay nothing. The autoload is set up after the command line
options are processed, and only when prism is the parser that parses
the program: with --parser=parse.y, Ruby::Prism is not defined (an
explicit `require "ruby/prism"` still works).
- prism/srcs.mk.in generates the templated Ruby files into
lib/ruby/prism/ (.gitignore follows).
[Bug #22379]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
These still held String and Array lengths and indices in long, or cast them to long. rb_len_t is still long everywhere, so the generated code does not change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The file, dir, load and ruby.c changes go together because rb_get_expanded_load_path() returns the maximum path length through a pointer. Lengths passed to the Windows string conversion helpers that take `long *` stay `long`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The disasm options and RubyVM::YJIT.disasm need a dev build, which win32/configure.bat cannot make. The warning for builds without YJIT also mentions --enable-yjit, since installing rustc alone does not enable it on mswin.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ruby_push_include was its last user. A path separator never appears inside a multibyte character, so walk RUBYLIB and -I by bytes everywhere. This also fixes the same skipped separator on Cygwin, where CharNext came from windows.h.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RUBYLIB and -I are UTF-8 on Windows, but ruby_push_include walked them with CharNext in the ANSI code page. With a DBCS code page such as 932, the last byte of a UTF-8 character was taken as a lead byte and swallowed the following `;`, so `C:/あ;C:/b` became a single load path.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It held the base pointer for `ruby_xfree(ptr)` while the loop advanced `argv`. The free became `RB_ALLOCV_END(ptr_obj)` in da4bd3b3df, and nothing has read it since.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A script read from stdin used the locale encoding, so on a non-UTF-8
console such as CP932 its source encoding differed from a script read
from a file, which already defaults to UTF-8. Match both the Prism and
legacy paths to magic_comment_spec.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
It generally end up frozen in `$LOADED_FEATURES` so it's preferable
to predict its size and only deal with an embedded string most of
the time.
It saves on having to allocate a `MAXPATHLEN + 2` (1026) bytes long
buffer and then realloc it later to shink it.
This change separates the master box from the root box, as the single
master copy of boxes.
Before this change, the root box is the source of copies, and also
it runs builtin classes' code. Builtin code makes changes by
requiring files, thus the source of copies is mutable, be different
from the past one. This causes different internal states of boxes,
depending on when it is created.
After this change, all boxes are created from the master box, and
the master box never runs code, so it realizes the immutable source
of copies.
This also makes is possible to separate RubyGems (and other default
gems) from each boxes. All boxes will have their own copies of RubyGems.
RubyGems has its internal state, but it'll be separated between boxes
after this change.
C23 has qualifier-preserving standard library functions, so calling
strchr with a `const char *` will return a `const char *`. We can change
the type of the local variables because we don't mutate the strings.
Prism changed structure quite a bit. Most of the previously-public
structs are now opaque. This requires quite a bit of changes
internally.
It also triggered some unrelated changes, which were necessary
because Prism's main header used to pull in standard headers. So
box.c and jit.c are now no longer transitively getting all the
headers they needed.
Split rb_zjit_init into rb_zjit_init_builtin_cmes (called before
ruby_init_prelude) and rb_zjit_init (called after). The prelude may
load bundler via BUNDLER_SETUP which can call Kernel.prepend, moving
core methods to an origin iclass. Registering method annotations
before the prelude ensures we capture CMEs while core classes are
pristine.
Split rb_yjit_init into rb_yjit_init_builtin_cmes (called before
ruby_init_prelude) and rb_yjit_init (called after). The prelude may
load bundler via BUNDLER_SETUP which can call Kernel.prepend, moving
core methods to an origin iclass. Registering method codegen before
the prelude ensures we capture CMEs while core classes are pristine.
In the C API, we want to use slices instead of locations in the
AST. In this case a "slice" is effectively the same thing as the
location, expect it is represented using a 32-bit offset and a
32-bit length. This will cut down on half of the space of all of
the locations in the AST.
Note that from the Ruby/Java/JavaScript side, this is effectively
an invisible change. This only impacts the C/Rust side.
This implements Shopify#854:
- Splits boot-time and enable-time initialization,
tracks progress with `InitializationState` enum
- Introduces `RubyVM::ZJIT.enable` Ruby method for
enabling the JIT lazily, if not already enabled
- Introduces `--zjit-disable` flag, which can be
used alongside the other `--zjit-*` flags but
prevents enabling the JIT at boot time
- Adds ZJIT infra to support JIT hooks, but this
is not currently exercised (Shopify/ruby#667)
Left for future enhancements:
- Support kwargs for overriding the CLI flags in
`RubyVM::ZJIT.enable`
Closes Shopify#854
When RUBYOPT is invalid, it raises an error which causes moreswitches
to leak memory. It can be seen when building with LSAN enabled:
$ RUBY_FREE_AT_EXIT=1 RUBYOPT=f ruby
ruby: invalid option -f (-h will show valid options) (RuntimeError)
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x618cef8efa23 in malloc (miniruby+0x64a23)
#1 0x618cefa0e8d8 in rb_gc_impl_malloc gc/default/default.c:8182:5
#2 0x618cef9f7f01 in ruby_xmalloc2_body gc.c:5182:12
#3 0x618cef9f7eac in ruby_xmalloc2 gc.c:5176:34
#4 0x618cefb547b2 in moreswitches ruby.c:919:18
#5 0x618cefb526fe in process_options ruby.c:2350:9
#6 0x618cefb524ac in ruby_process_options ruby.c:3202:12
#7 0x618cef9dc11f in ruby_options eval.c:119:16
#8 0x618cef8f2fb5 in rb_main main.c:42:26
#9 0x618cef8f2f59 in main main.c:62:12
to fix inconsistent and wrong current namespace detections.
This includes:
* Moving load_path and related things from rb_vm_t to rb_namespace_t to simplify
accessing those values via namespace (instead of accessing either vm or ns)
* Initializing root_namespace earlier and consolidate builtin_namespace into root_namespace
* Adding VM_FRAME_FLAG_NS_REQUIRE for checkpoints to detect a namespace to load/require files
* Removing implicit refinements in the root namespace which was used to determine
the namespace to be loaded (replaced by VM_FRAME_FLAG_NS_REQUIRE)
* Removing namespaces from rb_proc_t because its namespace can be identified by lexical context
* Starting to use ep[VM_ENV_DATA_INDEX_SPECVAL] to store the current namespace when
the frame type is MAGIC_TOP or MAGIC_CLASS (block handlers don't exist in this case)