Skip to content

Commit 56ecb19

Browse files
committed
[GR-39230] Backports for 22.2
PullRequest: truffleruby/3431
2 parents e3f9cae + bef8d1a commit 56ecb19

File tree

17 files changed

+292
-64
lines changed

17 files changed

+292
-64
lines changed

CHANGELOG.md

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,3 @@
1-
# 22.3.0
2-
3-
New features:
4-
5-
6-
Bug fixes:
7-
8-
9-
Compatibility:
10-
11-
12-
Performance:
13-
14-
15-
Changes:
16-
17-
181
# 22.2.0
192

203
New features:
@@ -40,6 +23,8 @@ Bug fixes:
4023
* Fix `/#{...}/o` to evaluate only once per context when splitting happens (@eregon).
4124
* Fix `Kernel#sprintf` formatting of floats to be like CRuby (@aardvark179).
4225
* Fix `Process.egid=` to accept `String`s (#2615, @ngtban)
26+
* Fix optional assignment to only evaluate index arguments once (#2658, @aardvark179).
27+
* Fix `StringIO` to set position correctly after reading multi-byte characters (#2207, @aardvark179).
4328

4429
Compatibility:
4530

@@ -61,13 +46,15 @@ Compatibility:
6146
* Use `$PAGER` for `--help` and `--help*`, similar to CRuby (#2542, @Strech).
6247
* Ensure all headers are warnings-free (#2662, @eregon).
6348
* All `IO` instances should have `T_FILE` as their `rb_type()`, not only `File` instances (#2662, @eregon).
49+
* Make `rb_fd_select` retry on `EINTR` (#1584, @aardvark179).
6450

6551
Performance:
6652

6753
* Reimplement `Float#to_s` for better performance (#1584, @aardvark179).
6854
* Improve reference processing by making C object free functions and other finalizers more lightweight (@aardvark179).
6955
* Improve performance of `RSTRING_PTR` for interned strings (@aardvark179).
7056
* Cache constant argument formats used with `rb_scan_args_kw` (@aardvark179).
57+
* Report polymorphism inside `Hash#[]` to recover performance (@aardvark179).
7158

7259
Changes:
7360

ci.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ local part_definitions = {
271271
bench_machine: ["x52"] + self.normal_machine + ["no_frequency_scaling"],
272272
},
273273
docker: {
274-
image: "phx.ocir.io/oraclelabs2/c_graal/buildslave:buildslave_ol7",
274+
image: "buildslave_ol7",
275275
mount_modules: true,
276276
},
277277
},

common.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
"jdks": {
55
"openjdk11": {"name": "openjdk", "version": "11.0.11+9", "platformspecific": true },
66
"oraclejdk11": {"name": "oraclejdk", "version": "11.0.11+9", "platformspecific": true },
7-
"labsjdk-ce-11": {"name": "labsjdk", "version": "ce-11.0.16+5-jvmci-22.2-b03", "platformspecific": true },
8-
"labsjdk-ce-11-llvm": {"name": "labsjdk", "version": "ce-11.0.16+5-jvmci-22.2-b03-sulong", "platformspecific": true },
9-
"labsjdk-ee-11": {"name": "labsjdk", "version": "ee-11.0.16+9-jvmci-22.2-b03", "platformspecific": true },
10-
"labsjdk-ee-11-llvm": {"name": "labsjdk", "version": "ee-11.0.16+9-jvmci-22.2-b03-sulong", "platformspecific": true },
7+
"labsjdk-ce-11": {"name": "labsjdk", "version": "ce-11.0.16+7-jvmci-22.2-b04", "platformspecific": true },
8+
"labsjdk-ce-11-llvm": {"name": "labsjdk", "version": "ce-11.0.16+7-jvmci-22.2-b04-sulong", "platformspecific": true },
9+
"labsjdk-ee-11": {"name": "labsjdk", "version": "ee-11.0.16+11-jvmci-22.2-b05", "platformspecific": true },
10+
"labsjdk-ee-11-llvm": {"name": "labsjdk", "version": "ee-11.0.16+11-jvmci-22.2-b05-sulong", "platformspecific": true },
1111

1212
"oraclejdk17": {"name": "oraclejdk", "version": "17.0.1+12", "platformspecific": true },
13-
"labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.4+5-jvmci-22.2-b03", "platformspecific": true },
14-
"labsjdk-ce-17Debug": {"name": "labsjdk", "version": "ce-17.0.4+5-jvmci-22.2-b03-debug", "platformspecific": true },
15-
"labsjdk-ce-17-llvm": {"name": "labsjdk", "version": "ce-17.0.4+5-jvmci-22.2-b03-sulong", "platformspecific": true },
16-
"labsjdk-ee-17": {"name": "labsjdk", "version": "ee-17.0.4+9-jvmci-22.2-b03", "platformspecific": true },
17-
"labsjdk-ee-17Debug": {"name": "labsjdk", "version": "ee-17.0.4+9-jvmci-22.2-b03-debug", "platformspecific": true },
18-
"labsjdk-ee-17-llvm": {"name": "labsjdk", "version": "ee-17.0.4+9-jvmci-22.2-b03-sulong", "platformspecific": true }
13+
"labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.4+7-jvmci-22.2-b04", "platformspecific": true },
14+
"labsjdk-ce-17Debug": {"name": "labsjdk", "version": "ce-17.0.4+7-jvmci-22.2-b04-debug", "platformspecific": true },
15+
"labsjdk-ce-17-llvm": {"name": "labsjdk", "version": "ce-17.0.4+7-jvmci-22.2-b04-sulong", "platformspecific": true },
16+
"labsjdk-ee-17": {"name": "labsjdk", "version": "ee-17.0.4+11-jvmci-22.2-b05", "platformspecific": true },
17+
"labsjdk-ee-17Debug": {"name": "labsjdk", "version": "ee-17.0.4+11-jvmci-22.2-b05-debug", "platformspecific": true },
18+
"labsjdk-ee-17-llvm": {"name": "labsjdk", "version": "ee-17.0.4+11-jvmci-22.2-b05-sulong", "platformspecific": true }
1919
},
2020

2121
"COMMENT.devkits" : "The devkits versions reflect those used to build the JVMCI JDKs (e.g., see devkit_platform_revisions in <jdk>/make/conf/jib-profiles.js)",

lib/cext/ABI_check.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5
1+
6

lib/truffle/stringio.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def each_byte
211211
d = @__data__
212212
string = d.string
213213

214-
while d.pos < string.length
214+
while d.pos < string.bytesize
215215
check_readable
216216
byte = string.getbyte d.pos
217217
d.pos += 1
@@ -468,7 +468,7 @@ def read(length = nil, buffer = nil)
468468
buffer.replace str if buffer
469469
end
470470

471-
d.pos += str.length
471+
d.pos += str.bytesize
472472
str
473473
end
474474

lib/truffle/truffle/openssl-prefix.rb

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88

99
# Set OPENSSL_PREFIX in ENV to find the OpenSSL headers
1010

11-
module Truffle
12-
OPENSSL_PREFIX_WAS_SET = ENV.key?('OPENSSL_PREFIX')
13-
end
14-
1511
search_homebrew = -> homebrew {
1612
if prefix = "#{homebrew}/opt/[email protected]" and Dir.exist?(prefix)
1713
prefix
@@ -20,10 +16,9 @@ module Truffle
2016
end
2117
}
2218

23-
macOS = RUBY_PLATFORM.include?('darwin')
24-
25-
if macOS && !ENV['OPENSSL_PREFIX']
26-
if prefix = search_homebrew.call('/usr/local')
19+
if Truffle::Platform.darwin? && !ENV['OPENSSL_PREFIX']
20+
default_homebrew_prefix = Truffle::System.host_cpu == 'aarch64' ? '/opt/homebrew' : '/usr/local'
21+
if prefix = search_homebrew.call(default_homebrew_prefix)
2722
# found
2823
else
2924
homebrew = `brew --prefix 2>/dev/null`.strip

mx.truffleruby/suite.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{
88
"name": "regex",
99
"subdir": True,
10-
"version": "f33384d85f86bc5f4fd1a92d9d734309c64d381d",
10+
"version": "105d87b99fc5879433f9b1c54040200530f9c1aa",
1111
"urls": [
1212
{"url": "https://github.com/oracle/graal.git", "kind": "git"},
1313
{"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"},
@@ -16,7 +16,7 @@
1616
{
1717
"name": "sulong",
1818
"subdir": True,
19-
"version": "f33384d85f86bc5f4fd1a92d9d734309c64d381d",
19+
"version": "105d87b99fc5879433f9b1c54040200530f9c1aa",
2020
"urls": [
2121
{"url": "https://github.com/oracle/graal.git", "kind": "git"},
2222
{"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"},

spec/ruby/language/optional_assignments_spec.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,44 @@ def []=(k, v)
300300
(@b[:k] ||= 12).should == 12
301301
end
302302

303+
it 'correctly handles a splatted argument for the index' do
304+
(@b[*[:k]] ||= 12).should == 12
305+
end
306+
307+
it "evaluates the index precisely once" do
308+
ary = [:x, :y]
309+
@a[:x] = 15
310+
@a[ary.pop] ||= 25
311+
ary.should == [:x]
312+
@a.should == { x: 15, y: 25 }
313+
end
314+
315+
it "evaluates the index arguments in the correct order" do
316+
ary = Class.new(Array) do
317+
def [](x, y)
318+
super(x + 3 * y)
319+
end
320+
321+
def []=(x, y, value)
322+
super(x + 3 * y, value)
323+
end
324+
end.new
325+
ary[0, 0] = 1
326+
ary[1, 0] = 1
327+
ary[2, 0] = nil
328+
ary[3, 0] = 1
329+
ary[4, 0] = 1
330+
ary[5, 0] = 1
331+
ary[6, 0] = nil
332+
333+
foo = [0, 2]
334+
335+
ary[foo.pop, foo.pop] ||= 2
336+
337+
ary[2, 0].should == 2
338+
ary[6, 0].should == nil
339+
end
340+
303341
it 'returns the assigned value, not the result of the []= method with +=' do
304342
@b[:k] = 17
305343
(@b[:k] += 12).should == 29

spec/ruby/library/stringio/shared/read.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@
8989
@io.send(@method)
9090
@io.pos.should eql(7)
9191
end
92+
93+
it "correctly update the current position in bytes when multi-byte characters are used" do
94+
@io.print("example\u03A3") # Overwrite the original string with 8 characters containing 9 bytes.
95+
@io.send(@method)
96+
@io.pos.should eql(9)
97+
end
9298
end
9399

94100
describe :stringio_read_nil, shared: true do

src/main/c/cext/fd.c

Lines changed: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
*/
1010
#include <truffleruby-impl.h>
1111
#include <fcntl.h>
12+
#include <errno.h>
1213
#include <ruby/thread.h>
14+
#include <time.h>
1315

1416
// For howmany()
1517
#ifdef HAVE_SYS_PARAM_H
@@ -105,6 +107,65 @@ void rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src) {
105107
memcpy(dst->fdset, src->fdset, size);
106108
}
107109

110+
void rb_fd_init_copy(rb_fdset_t *dst, rb_fdset_t *src) {
111+
size_t size = howmany(rb_fd_max(src), NFDBITS) * sizeof(fd_mask);
112+
113+
if (size < sizeof(fd_set)) {
114+
size = sizeof(fd_set);
115+
}
116+
dst->maxfd = src->maxfd;
117+
dst->fdset = xmalloc(size);
118+
memcpy(dst->fdset, src->fdset, size);
119+
}
120+
121+
static bool timespec_subtract(struct timespec *result, struct timespec x, struct timespec y) {
122+
/* Perform the carry for the later subtraction by updating y. */
123+
if (x.tv_nsec < y.tv_nsec) {
124+
long nsec = (y.tv_nsec - x.tv_nsec) / 1000000000 + 1;
125+
y.tv_nsec -= 1000000000 * nsec;
126+
y.tv_sec += nsec;
127+
}
128+
if (x.tv_nsec - y.tv_nsec > 1000000000) {
129+
long nsec = (x.tv_nsec - y.tv_nsec) / 1000000000;
130+
y.tv_nsec += 1000000000 * nsec;
131+
y.tv_sec -= nsec;
132+
}
133+
134+
/* Compute the time remaining to wait.
135+
tv_nsec is certainly positive. */
136+
result->tv_sec = x.tv_sec - y.tv_sec;
137+
result->tv_nsec = x.tv_nsec - y.tv_nsec;
138+
139+
/* Return 1 if result is negative. */
140+
return x.tv_sec < y.tv_sec;
141+
}
142+
143+
static bool timeval_subtract(struct timeval *result, struct timeval x, struct timeval y) {
144+
/* Perform the carry for the later subtraction by updating y. */
145+
if (x.tv_usec < y.tv_usec) {
146+
long usec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
147+
y.tv_usec -= 1000000 * usec;
148+
y.tv_sec += usec;
149+
}
150+
if (x.tv_usec - y.tv_usec > 1000000) {
151+
long usec = (x.tv_usec - y.tv_usec) / 1000000;
152+
y.tv_usec += 1000000 * usec;
153+
y.tv_sec -= usec;
154+
}
155+
156+
/* Compute the time remaining to wait.
157+
tv_usec is certainly positive. */
158+
result->tv_sec = x.tv_sec - y.tv_sec;
159+
result->tv_usec = x.tv_usec - y.tv_usec;
160+
161+
/* Return 1 if result is negative. */
162+
return x.tv_sec < y.tv_sec;
163+
}
164+
165+
static int should_retry(int result) {
166+
return (result < 0) && (errno == EINTR);
167+
}
168+
108169
int rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout) {
109170
fd_set *r = NULL, *w = NULL, *e = NULL;
110171
if (readfds) {
@@ -122,21 +183,90 @@ int rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *e
122183
return select(n, r, w, e, timeout);
123184
}
124185

186+
125187
// NOTE: MRI's version has more fields
126188
struct select_set {
127189
int max;
128190
rb_fdset_t *rset;
129191
rb_fdset_t *wset;
130192
rb_fdset_t *eset;
193+
rb_fdset_t *orig_rset;
194+
rb_fdset_t *orig_wset;
195+
rb_fdset_t *orig_eset;
131196
struct timeval *timeout;
197+
struct timeval *orig_timeout;
132198
};
133199

200+
static inline void restore_fds(rb_fdset_t *dst, rb_fdset_t *src) {
201+
if (dst) {
202+
rb_fd_dup(dst, src);
203+
}
204+
}
205+
206+
static bool update_timeout(struct timeval *timeout, struct timeval *orig_timeout, struct timespec *starttime) {
207+
struct timespec currenttime;
208+
struct timespec difftime;
209+
struct timeval difftimeout;
210+
bool timeleft = true;
211+
if (timeout) {
212+
clock_gettime(CLOCK_MONOTONIC, &currenttime);
213+
timespec_subtract(&difftime, currenttime, *starttime);
214+
difftimeout.tv_sec = difftime.tv_sec;
215+
difftimeout.tv_usec = difftime.tv_nsec / 1000;
216+
timeleft = timeval_subtract(timeout, *orig_timeout, difftimeout);
217+
}
218+
219+
return timeleft;
220+
}
221+
134222
static void* rb_thread_fd_select_blocking(void *data) {
135223
struct select_set *set = (struct select_set*)data;
136-
int result = rb_fd_select(set->max, set->rset, set->wset, set->eset, set->timeout);
224+
struct timespec starttime;
225+
226+
if (set->timeout) {
227+
clock_gettime(CLOCK_MONOTONIC, &starttime);
228+
}
229+
230+
int result = 0;
231+
bool timeleft = true;
232+
do {
233+
restore_fds(set->rset, set->orig_rset);
234+
restore_fds(set->wset, set->orig_wset);
235+
restore_fds(set->eset, set->orig_eset);
236+
timeleft = update_timeout(set->timeout, set->orig_timeout, &starttime);
237+
if (!timeleft) {
238+
break;
239+
}
240+
result = rb_fd_select(set->max, set->rset, set->wset, set->eset, set->timeout);
241+
} while (should_retry(result));
137242
return (void*)(long)result;
138243
}
139244

245+
static void* rb_thread_fd_select_internal(void *sets) {
246+
return rb_thread_call_without_gvl(rb_thread_fd_select_blocking, sets, RUBY_UBF_IO, 0);
247+
}
248+
249+
static void rb_thread_fd_select_set_free(struct select_set *sets) {
250+
if (sets->orig_rset) {
251+
rb_fd_term(sets->orig_rset);
252+
}
253+
if (sets->orig_wset) {
254+
rb_fd_term(sets->orig_wset);
255+
}
256+
if (sets->orig_eset) {
257+
rb_fd_term(sets->orig_eset);
258+
}
259+
}
260+
261+
static void fd_init_copy(rb_fdset_t *dst, int max, rb_fdset_t *src) {
262+
if (src) {
263+
rb_fd_resize(max - 1, src);
264+
if (dst != src) {
265+
rb_fd_init_copy(dst, src);
266+
}
267+
}
268+
}
269+
140270
int rb_thread_fd_select(int max, rb_fdset_t *read, rb_fdset_t *write, rb_fdset_t *except, struct timeval *timeout) {
141271
// NOTE: MRI has more logic in here
142272
struct select_set set;
@@ -145,7 +275,12 @@ int rb_thread_fd_select(int max, rb_fdset_t *read, rb_fdset_t *write, rb_fdset_t
145275
set.wset = write;
146276
set.eset = except;
147277
set.timeout = timeout;
278+
fd_init_copy(set.orig_rset, set.max, set.rset);
279+
fd_init_copy(set.orig_wset, set.max, set.wset);
280+
fd_init_copy(set.orig_eset, set.max, set.eset);
281+
struct timeval orig_timeval = *timeout;
282+
set.orig_timeout = &orig_timeval;
148283

149-
void* result = rb_thread_call_without_gvl(rb_thread_fd_select_blocking, (void*)(&set), RUBY_UBF_IO, 0);
284+
void* result = rb_ensure(rb_thread_fd_select_internal, (VALUE)&set, rb_thread_fd_select_set_free, (VALUE)&set);
150285
return (int)(long)result;
151286
}

0 commit comments

Comments
 (0)