Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/jit/zjit.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<p align="center">
<img src="https://github.com/user-attachments/assets/27abfe03-3e96-4220-b6f1-278bb0c87684" width="400">
</p>

# ZJIT: ADVANCED RUBY JIT PROTOTYPE

ZJIT is a method-based just-in-time (JIT) compiler for Ruby. It uses profile
Expand Down
28 changes: 20 additions & 8 deletions ext/coverage/coverage.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,29 @@ rb_coverage_supported(VALUE self, VALUE _mode)

/*
* call-seq:
* Coverage.setup => nil
* Coverage.setup(:all) => nil
* Coverage.setup(lines: bool, branches: bool, methods: bool, eval: bool) => nil
* Coverage.setup(oneshot_lines: true) => nil
* Coverage.setup -> nil
* Coverage.setup(type) -> nil
* Coverage.setup(lines: false, branches: false, methods: false, eval: false, oneshot_lines: false) -> nil
*
* Set up the coverage measurement.
* Performs setup for coverage measurement, but does not start coverage measurement.
* To start coverage measurement, use Coverage.resume.
*
* Note that this method does not start the measurement itself.
* Use Coverage.resume to start the measurement.
* To perform both setup and start coverage measurement, Coverage.start can be used.
*
* You may want to use Coverage.start to setup and then start the measurement.
* With argument +type+ given and +type+ is symbol +:all+, enables all types of coverage
* (lines, branches, methods, and eval).
*
* Keyword arguments or hash +type+ can be given with each of the following keys:
*
* - +lines+: Enables line coverage that records the number of times each line was executed.
* If +lines+ is enabled, +oneshot_lines+ cannot be enabled.
* See {Lines Coverage}[rdoc-ref:Coverage@Lines+Coverage].
* - +branches+: Enables branch coverage that records the number of times each
* branch in each conditional was executed. See {Branches Coverage}[rdoc-ref:Coverage@Branch+Coverage].
* - +methods+: Enables method coverage that records the number of times each method was exectued.
* See {Methods Coverage}[rdoc-ref:Coverage@Methods+Coverage].
* - +eval+: Enables coverage for evaluations (e.g. Kernel#eval, Module#class_eval).
* See {Eval Coverage}[rdoc-ref:Coverage@Eval+Coverage].
*/
static VALUE
rb_coverage_setup(int argc, VALUE *argv, VALUE klass)
Expand Down
9 changes: 9 additions & 0 deletions ext/json/lib/json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
#
# \JSON is a lightweight data-interchange format.
#
# \JSON is easy for us humans to read and write,
# and equally simple for machines to read (parse) and write (generate).
#
# \JSON is language-independent, making it an ideal interchange format
# for applications in differing programming languages
# and on differing operating systems.
#
# == \JSON Values
#
# A \JSON value is one of the following:
# - Double-quoted text: <tt>"foo"</tt>.
# - Number: +1+, +1.0+, +2.0e2+.
Expand Down
8 changes: 8 additions & 0 deletions lib/rubygems/specification_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ def validate_values
warning "deprecated autorequire specified" if @specification.autorequire

@specification.executables.each do |executable|
validate_executable(executable)
validate_shebang_line_in(executable)
end

Expand All @@ -449,6 +450,13 @@ def validate_attribute_present(attribute)
warning("no #{attribute} specified") if value.nil? || value.empty?
end

def validate_executable(executable)
separators = [File::SEPARATOR, File::ALT_SEPARATOR, File::PATH_SEPARATOR].compact.map {|sep| Regexp.escape(sep) }.join
return unless executable.match?(/[\s#{separators}]/)

error "executable \"#{executable}\" contains invalid characters"
end

def validate_shebang_line_in(executable)
executable_path = File.join(@specification.bindir, executable)
return if File.read(executable_path, 2) == "#!"
Expand Down
59 changes: 59 additions & 0 deletions test/rubygems/test_gem_specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3013,6 +3013,65 @@ def test_validate_executables
assert_match "#{w}: bin/exec is missing #! line\n", @ui.error, "error"
end

def test_validate_executables_with_space
util_setup_validate

FileUtils.mkdir_p File.join(@tempdir, "bin")
File.write File.join(@tempdir, "bin", "echo hax"), "#!/usr/bin/env ruby\n"

@a1.executables = ["echo hax"]

e = assert_raise Gem::InvalidSpecificationException do
use_ui @ui do
Dir.chdir @tempdir do
@a1.validate
end
end
end

assert_match "executable \"echo hax\" contains invalid characters", e.message
end

def test_validate_executables_with_path_separator
util_setup_validate

FileUtils.mkdir_p File.join(@tempdir, "bin")
File.write File.join(@tempdir, "exe"), "#!/usr/bin/env ruby\n"

@a1.executables = Gem.win_platform? ? ["..\\exe"] : ["../exe"]

e = assert_raise Gem::InvalidSpecificationException do
use_ui @ui do
Dir.chdir @tempdir do
@a1.validate
end
end
end

assert_match "executable \"#{Gem.win_platform? ? "..\\exe" : "../exe"}\" contains invalid characters", e.message
end

def test_validate_executables_with_path_list_separator
sep = Gem.win_platform? ? ";" : ":"

util_setup_validate

FileUtils.mkdir_p File.join(@tempdir, "bin")
File.write File.join(@tempdir, "bin", "foo#{sep}bar"), "#!/usr/bin/env ruby\n"

@a1.executables = ["foo#{sep}bar"]

e = assert_raise Gem::InvalidSpecificationException do
use_ui @ui do
Dir.chdir @tempdir do
@a1.validate
end
end
end

assert_match "executable \"foo#{sep}bar\" contains invalid characters", e.message
end

def test_validate_empty_require_paths
util_setup_validate

Expand Down
3 changes: 3 additions & 0 deletions zjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2276,6 +2276,9 @@ fn gen_guard_type_not(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, g

/// Compile an identity check with a side exit
fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, expected: crate::hir::Const, reason: SideExitReason, state: &FrameState) -> lir::Opnd {
if matches!(reason, SideExitReason::GuardShape(_) ) {
gen_incr_counter(asm, Counter::guard_shape_count);
}
let expected_opnd: Opnd = match expected {
crate::hir::Const::Value(v) => { Opnd::Value(v) }
crate::hir::Const::CInt64(v) => { v.into() }
Expand Down