Skip to content

Commit a69cf90

Browse files
committed
[GR-37533] Backports for 24.0 batch 2
PullRequest: truffleruby/4178
2 parents e7103f0 + f9b982e commit a69cf90

File tree

86 files changed

+1715
-1873
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+1715
-1873
lines changed

3rd_party_licenses.txt

Lines changed: 36 additions & 385 deletions
Large diffs are not rendered by default.

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,17 @@ Compatibility:
5454
* Limit maximum encoding set size by 256 (#3039, @thomasmarshall, @goyox86).
5555
* Remove deprecated methods `Dir.exists?`, `File.exists?`, and `Kernel#=~` (#3039, @patricklinpl, @nirvdrum).
5656
* Remove deprecated `FileTest.exists?` method (#3039, @andrykonchin).
57+
* Fix {Method,Proc}#parameters and return `*`, `**` and `&` names for anonymous parameters (@andrykonchin).
58+
* Remove deprecated `Fixnum` and `Bignum` constants (#3039, @andrykonchin).
59+
* Add `rb_enc_interned_str_cstr` function (#3408, @goyox86, @thomasmarshall).
60+
* Add `rb_str_to_interned_str` function (#3408, @thomasmarshall).
5761

5862
Performance:
5963

6064
* Change the `Hash` representation from traditional buckets to a "compact hash table" for improved locality, performance and memory footprint (#3172, @moste00).
6165
* Optimize calls with `ruby2_keywords` forwarding by deciding it per call site instead of per callee thanks to [my fix in CRuby 3.2](https://bugs.ruby-lang.org/issues/18625) (@eregon).
6266
* Optimize feature loading when require is called with an absolute path to a .rb file (@rwstauner).
67+
* Avoid extra copies for Strings passed as `:string` arguments to a FFI call and used later for Regexp matching (#3293, @eregon).
6368

6469
Changes:
6570

bench/asciidoctor/asciidoctor/lib/asciidoctor/document.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ def initialize data = nil, options = {}
225225
# safely resolve the safe mode from const, int or string
226226
if !(safe_mode = options[:safe])
227227
@safe = SafeMode::SECURE
228-
elsif ::Fixnum === safe_mode
228+
elsif ::Integer === safe_mode # this is fixed in upstream in v1.5.5 (https://github.com/asciidoctor/asciidoctor/blob/main/CHANGELOG.adoc#155-2016-10-05---mojavelinux)
229229
# be permissive in case API user wants to define new levels
230230
@safe = safe_mode
231231
else

doc/legal/jruby-copying.txt

Lines changed: 23 additions & 1049 deletions
Large diffs are not rendered by default.

doc/legal/legal.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ MIT licence, see `mit.txt`.
5858

5959
## JRuby
6060

61-
TruffleRuby contains code from JRuby 9.2.19.0, including Java implementation
61+
TruffleRuby contains code from JRuby 9.4.4.0, including Java implementation
6262
code, build system, shell script launchers, standard library modified from MRI,
6363
and so on.
6464

lib/cext/ABI_check.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
10
1+
13

lib/truffle/ffi/autopointer.rb

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,21 +76,21 @@ class AutoPointer < Pointer
7676
# going to be useful if you subclass {AutoPointer}, and override
7777
# #release, which by default does nothing.
7878
def initialize(ptr, proc=nil, &block)
79+
raise TypeError, "Invalid pointer" if ptr.nil? || !ptr.kind_of?(Pointer) ||
80+
ptr.kind_of?(MemoryPointer) || ptr.kind_of?(AutoPointer)
7981
super(ptr.type_size, ptr)
80-
raise TypeError, "Invalid pointer" if ptr.nil? || !ptr.kind_of?(Pointer) \
81-
|| ptr.kind_of?(MemoryPointer) || ptr.kind_of?(AutoPointer)
8282

8383
@releaser = if proc
8484
if not proc.respond_to?(:call)
8585
raise RuntimeError.new("proc must be callable")
8686
end
87-
CallableReleaser.new(ptr, proc)
87+
Releaser.new(ptr, proc)
8888

8989
else
90-
if not self.class.respond_to?(:release)
90+
if not self.class.respond_to?(:release, true)
9191
raise RuntimeError.new("no release method defined")
9292
end
93-
DefaultReleaser.new(ptr, self.class)
93+
Releaser.new(ptr, self.class.method(:release))
9494
end
9595

9696
ObjectSpace.define_finalizer(self, @releaser)
@@ -107,6 +107,7 @@ def free
107107
# @return [Boolean] +autorelease+
108108
# Set +autorelease+ property. See {Pointer Autorelease section at Pointer}.
109109
def autorelease=(autorelease)
110+
raise FrozenError.new("can't modify frozen #{self.class}") if frozen?
110111
@releaser.autorelease=(autorelease)
111112
end
112113

@@ -149,23 +150,7 @@ def free
149150
def call(*args)
150151
release(@ptr) if @autorelease && @ptr
151152
end
152-
end
153-
154-
# DefaultReleaser is a {Releaser} used when an {AutoPointer} is defined
155-
# without Proc or Method. In this case, the pointer to release must be of
156-
# a class derived from AutoPointer with a {release} class method.
157-
class DefaultReleaser < Releaser
158-
# @param [Pointer] ptr
159-
# @return [nil]
160-
# Release +ptr+ using the {release} class method of its class.
161-
def release(ptr)
162-
@proc.release(ptr)
163-
end
164-
end
165153

166-
# CallableReleaser is a {Releaser} used when an {AutoPointer} is defined with a
167-
# Proc or a Method.
168-
class CallableReleaser < Releaser
169154
# Release +ptr+ by using Proc or Method defined at +ptr+
170155
# {AutoPointer#initialize initialization}.
171156
#
@@ -182,7 +167,7 @@ def release(ptr)
182167
# @return [Type::POINTER]
183168
# @raise {RuntimeError} if class does not implement a +#release+ method
184169
def self.native_type
185-
if not self.respond_to?(:release)
170+
if not self.respond_to?(:release, true)
186171
raise RuntimeError.new("no release method defined for #{self.inspect}")
187172
end
188173
Type::POINTER

lib/truffle/ffi/compat.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#
2+
# Copyright (C) 2023-2023 Lars Kanis
3+
#
4+
# This file is part of ruby-ffi.
5+
#
6+
# All rights reserved.
7+
#
8+
# Redistribution and use in source and binary forms, with or without
9+
# modification, are permitted provided that the following conditions are met:
10+
#
11+
# * Redistributions of source code must retain the above copyright notice, this
12+
# list of conditions and the following disclaimer.
13+
# * Redistributions in binary form must reproduce the above copyright notice
14+
# this list of conditions and the following disclaimer in the documentation
15+
# and/or other materials provided with the distribution.
16+
# * Neither the name of the Ruby FFI project nor the names of its contributors
17+
# may be used to endorse or promote products derived from this software
18+
# without specific prior written permission.
19+
#
20+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
#
31+
32+
module FFI
33+
if defined?(Ractor.make_shareable)
34+
# This is for FFI internal use only.
35+
def self.make_shareable(obj)
36+
Ractor.make_shareable(obj)
37+
end
38+
else
39+
def self.make_shareable(obj)
40+
obj.freeze
41+
end
42+
end
43+
end

lib/truffle/ffi/data_converter.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
module FFI
3232
# This module is used to extend somes classes and give then a common API.
3333
#
34-
# Most of methods defined here must be overriden.
34+
# Most of methods defined here must be overridden.
3535
module DataConverter
3636
# Get native type.
3737
#
@@ -41,7 +41,7 @@ module DataConverter
4141
# Get native type from +type+.
4242
#
4343
# @overload native_type
44-
# @raise {NotImplementedError} This method must be overriden.
44+
# @raise {NotImplementedError} This method must be overridden.
4545
def native_type(type = nil)
4646
if type
4747
@native_type = FFI.find_type(type)

lib/truffle/ffi/dynamic_library.rb

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#
2+
# Copyright (C) 2008-2010 Wayne Meissner
3+
#
4+
# This file is part of ruby-ffi.
5+
#
6+
# All rights reserved.
7+
#
8+
# Redistribution and use in source and binary forms, with or without
9+
# modification, are permitted provided that the following conditions are met:
10+
#
11+
# * Redistributions of source code must retain the above copyright notice, this
12+
# list of conditions and the following disclaimer.
13+
# * Redistributions in binary form must reproduce the above copyright notice
14+
# this list of conditions and the following disclaimer in the documentation
15+
# and/or other materials provided with the distribution.
16+
# * Neither the name of the Ruby FFI project nor the names of its contributors
17+
# may be used to endorse or promote products derived from this software
18+
# without specific prior written permission.
19+
#
20+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#
30+
31+
module FFI
32+
class DynamicLibrary
33+
SEARCH_PATH = %w[/usr/lib /usr/local/lib /opt/local/lib]
34+
if FFI::Platform::ARCH == 'aarch64' && FFI::Platform.mac?
35+
SEARCH_PATH << '/opt/homebrew/lib'
36+
end
37+
38+
SEARCH_PATH_MESSAGE = "Searched in <system library path>, #{SEARCH_PATH.join(', ')}".freeze
39+
40+
def self.load_library(name, flags)
41+
if name == FFI::CURRENT_PROCESS
42+
FFI::DynamicLibrary.open(nil, RTLD_LAZY | RTLD_LOCAL)
43+
else
44+
flags ||= RTLD_LAZY | RTLD_LOCAL
45+
46+
libnames = (name.is_a?(::Array) ? name : [name])
47+
libnames = libnames.map(&:to_s).map { |n| [n, FFI.map_library_name(n)].uniq }.flatten.compact
48+
errors = []
49+
50+
libnames.each do |libname|
51+
lib = try_load(libname, flags, errors)
52+
return lib if lib
53+
54+
unless libname.start_with?("/") || FFI::Platform.windows?
55+
SEARCH_PATH.each do |prefix|
56+
path = "#{prefix}/#{libname}"
57+
if File.exist?(path)
58+
lib = try_load(path, flags, errors)
59+
return lib if lib
60+
end
61+
end
62+
end
63+
end
64+
65+
raise LoadError, [*errors, SEARCH_PATH_MESSAGE].join(".\n")
66+
end
67+
end
68+
private_class_method :load_library
69+
70+
def self.try_load(libname, flags, errors)
71+
begin
72+
lib = FFI::DynamicLibrary.open(libname, flags)
73+
return lib if lib
74+
75+
# LoadError for C ext & JRuby, RuntimeError for TruffleRuby
76+
rescue LoadError, RuntimeError => ex
77+
if ex.message =~ /(([^ \t()])+\.so([^ \t:()])*):([ \t])*(invalid ELF header|file too short|invalid file format)/
78+
if File.binread($1) =~ /(?:GROUP|INPUT) *\( *([^ \)]+)/
79+
return try_load($1, flags, errors)
80+
end
81+
end
82+
83+
errors << ex
84+
nil
85+
end
86+
end
87+
private_class_method :try_load
88+
end
89+
end

lib/truffle/ffi/enum.rb

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ class Bitmask < Enum
192192
# @param [nil, Symbol] tag name of new Bitmask
193193
def initialize(*args)
194194
@native_type = args.first.kind_of?(FFI::Type) ? args.shift : Type::INT
195+
@signed = [Type::INT8, Type::INT16, Type::INT32, Type::INT64].include?(@native_type)
195196
info, @tag = *args
196197
@kv_map = Hash.new
197198
unless info.nil?
@@ -220,7 +221,7 @@ def initialize(*args)
220221
# @param [Symbol] query
221222
# @return [Integer]
222223
# @overload [](query)
223-
# Get bitmaks value from symbol array
224+
# Get bitmask value from symbol array
224225
# @param [Array<Symbol>] query
225226
# @return [Integer]
226227
# @overload [](*query)
@@ -240,7 +241,7 @@ def [](*query)
240241
when Symbol
241242
flat_query.inject(0) do |val, o|
242243
v = @kv_map[o]
243-
if v then val |= v else val end
244+
if v then val | v else val end
244245
end
245246
when Integer, ->(o) { o.respond_to?(:to_int) }
246247
val = flat_query.inject(0) { |mask, o| mask |= o.to_int }
@@ -260,35 +261,41 @@ def [](*query)
260261
def to_native(query, ctx)
261262
return 0 if query.nil?
262263
flat_query = [query].flatten
263-
flat_query.inject(0) do |val, o|
264+
res = flat_query.inject(0) do |val, o|
264265
case o
265266
when Symbol
266267
v = @kv_map[o]
267268
raise ArgumentError, "invalid bitmask value, #{o.inspect}" unless v
268-
val |= v
269+
val | v
269270
when Integer
270-
val |= o
271+
val | o
271272
when ->(obj) { obj.respond_to?(:to_int) }
272-
val |= o.to_int
273+
val | o.to_int
273274
else
274275
raise ArgumentError, "invalid bitmask value, #{o.inspect}"
275276
end
276277
end
278+
# Take two's complement of positive values bigger than the max value
279+
# for the type when native type is signed.
280+
if @signed && res >= (1 << (@native_type.size * 8 - 1))
281+
res = -(-res & ((1 << (@native_type.size * 8)) - 1))
282+
end
283+
res
277284
end
278285

279286
# @param [Integer] val
280287
# @param ctx unused
281288
# @return [Array<Symbol, Integer>] list of symbol names corresponding to val, plus an optional remainder if some bits don't match any constant
282289
def from_native(val, ctx)
283-
list = @kv_map.select { |_, v| v & val != 0 }.keys
290+
flags = @kv_map.select { |_, v| v & val != 0 }
291+
list = flags.keys
292+
# force an unsigned value of the correct size
293+
val &= (1 << (@native_type.size * 8)) - 1 if @signed
284294
# If there are unmatch flags,
285295
# return them in an integer,
286296
# else information can be lost.
287297
# Similar to Enum behavior.
288-
remainder = val ^ list.inject(0) do |tmp, o|
289-
v = @kv_map[o]
290-
if v then tmp |= v else tmp end
291-
end
298+
remainder = val ^ flags.values.reduce(0, :|)
292299
list.push remainder unless remainder == 0
293300
return list
294301
end

lib/truffle/ffi/ffi.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@
2828
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2929
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030

31+
require 'ffi/compat'
3132
require 'ffi/platform'
3233
require 'ffi/data_converter'
3334
require 'ffi/types'
35+
require 'ffi/library_path'
3436
require 'ffi/library'
3537
require 'ffi/errno'
3638
require 'ffi/abstract_memory'
@@ -45,3 +47,4 @@
4547
require 'ffi/variadic'
4648
require 'ffi/enum'
4749
require 'ffi/version'
50+
require 'ffi/function'

0 commit comments

Comments
 (0)