Skip to content

Commit bd817cd

Browse files
committed
[GR-20709] [GR-20837] [GR-19473] [GR-20976] Bug fixes for 20.0.
PullRequest: truffleruby/1334
2 parents c4ee0e2 + 19bbce1 commit bd817cd

File tree

22 files changed

+208
-65
lines changed

22 files changed

+208
-65
lines changed

.gitattributes

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Merge options
22

3-
/CHANGELOG.md merge=union
43

54
# Rules for GitHub's Linguist language-classification system. We're abusing the
65
# 'vendored' attribute to exclude files as a lot of this isn't really vendored,

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ New features:
55
* Enable and document `--coverage` option (#1840, @chrisseaton).
66
* Update the internal LLVM toolchain to LLVM 9 and reduce its download size.
77
* Updated to Ruby 2.6.5 (#1749).
8+
* Automatically set `PKG_CONFIG_PATH` as needed for compiling OpenSSL on macOS (#1830).
89

910
Bug fixes:
1011

@@ -76,6 +77,8 @@ Bug fixes:
7677
* Fixed `IO.try_convert` parameter conversion.
7778
* Fixed linking of always-inline C API functions with `-std=gnu90` (#1837, #1879).
7879
* Avoid race conditions during `gem install` by using a single download thread.
80+
* `RSTRING_PTR()` now always returns a native pointer, resolving two bugs `memcpy`ing to (#1822) and from (#1772) Ruby Strings.
81+
* Do not use gems precompiled for MRI on TruffleRuby (#1837).
7982

8083
Compatibility:
8184

ci.jsonnet

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ local part_definitions = {
7676
environment+: { path+:: ["$MAVEN_HOME/bin"] },
7777
},
7878

79-
build: {
79+
build_no_clean: {
8080
setup+: [["mx", "sversions"]] +
8181
# aot-build.log is used for the build-stats metrics, in other cases it does no harm
8282
jt(["build", "--env", self.mx_env] + self.jt_build_options + ["--"] + self.mx_build_options + ["|", "tee", "aot-build.log"]) +
@@ -86,6 +86,11 @@ local part_definitions = {
8686
],
8787
},
8888

89+
build: $.use.build_no_clean + {
90+
# Clean build results to make sure nothing refers to them while testing
91+
setup+: jt(["mx", "--env", self.mx_env, "clean"]),
92+
},
93+
8994
clone_enterprise: {
9095
setup+: [["mx", "sversions"]] + jt(["checkout_enterprise_revision"]),
9196
},
@@ -273,18 +278,19 @@ local part_definitions = {
273278

274279
run: {
275280
test_unit_tck_specs: {
276-
run+: jt(["test", "unit"]) +
277-
jt(["test", "tck"]) +
278-
jt(["test", "specs"]) +
279-
jt(["test", "specs", ":next"]),
281+
run+: jt(["test", "specs"]) +
282+
jt(["test", "specs", ":next"]) +
283+
jt(["build"]) + # We need mx distributions to run unit tests
284+
jt(["test", "unit"]) +
285+
jt(["test", "tck"]),
280286
},
281287

282288
test_fast: {
283289
run+: jt(["test", "fast"]),
284290
},
285291

286292
lint: {
287-
is_after:: ["$.use.build"],
293+
is_after:: ["$.use.build_no_clean"],
288294
downloads+: {
289295
JDT: { name: "ecj", version: "4.5.1", platformspecific: false },
290296
ECLIPSE: { version: "4.5.2", name: "eclipse", platformspecific: true },
@@ -427,7 +433,7 @@ local composition_environment = utils.add_inclusion_tracking(part_definitions, "
427433

428434
test_builds:
429435
{
430-
"ruby-lint": $.platform.linux + $.cap.gate + $.jdk.v8 + $.use.common + $.env.jvm + $.use.build + $.run.lint + { timelimit: "30:00" },
436+
"ruby-lint": $.platform.linux + $.cap.gate + $.jdk.v8 + $.use.common + $.env.jvm + $.use.build_no_clean + $.run.lint + { timelimit: "30:00" },
431437
} +
432438

433439
{

lib/cext/include/truffleruby/truffleruby.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ int rb_encdb_alias(const char *alias, const char *orig);
158158
VALUE rb_ivar_lookup(VALUE object, const char *name, VALUE default_value);
159159

160160
// Additional macro to make sure the RSTRING_PTR and the bytes are in native memory, for testing.
161-
#define NATIVE_RSTRING_PTR(str) ((char*) polyglot_as_i64(polyglot_invoke(RSTRING_PTR(str), "polyglot_address")))
161+
#define NATIVE_RSTRING_PTR(str) ((char*) polyglot_as_i64(RUBY_CEXT_INVOKE_NO_WRAP("NATIVE_RSTRING_PTR", str)))
162162

163163
// Inline implementations
164164

lib/truffle/rubygems/defaults/truffleruby.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@ module Gem
1616
def self.default_dir
1717
@default_dir ||= "#{Truffle::Boot.ruby_home or raise 'TruffleRuby home not found'}/lib/gems"
1818
end
19+
20+
# Only report the RUBY platform as supported to make sure gems precompiled for MRI are not used.
21+
# TruffleRuby has a different ABI and cannot reuse gems precompiled for MRI.
22+
# See https://github.com/rubygems/rubygems/issues/2945
23+
Gem.platforms = [Gem::Platform::RUBY]
1924
end

lib/truffle/truffle/cext.rb

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,31 +149,31 @@ def initialize(string)
149149
end
150150

151151
def size
152-
Truffle::CExt.string_pointer_size(@string)
152+
TrufflePrimitive.string_pointer_size(@string)
153153
end
154154

155155
def polyglot_pointer?
156156
true
157157
end
158158

159159
def polyglot_address
160-
@address ||= Truffle::CExt.string_pointer_to_native(@string)
160+
@address ||= TrufflePrimitive.string_pointer_to_native(@string)
161161
end
162162

163163
# Every IS_POINTER object should also have TO_NATIVE
164164
def polyglot_to_native
165165
end
166166

167167
def [](index)
168-
Truffle::CExt.string_pointer_read(@string, index)
168+
TrufflePrimitive.string_pointer_read(@string, index)
169169
end
170170

171171
def []=(index, value)
172-
Truffle::CExt.string_pointer_write(@string, index, value)
172+
TrufflePrimitive.string_pointer_write(@string, index, value)
173173
end
174174

175175
def native?
176-
Truffle::CExt.string_pointer_is_native?(@string)
176+
TrufflePrimitive.string_pointer_is_native?(@string)
177177
end
178178

179179
alias_method :to_str, :string
@@ -231,7 +231,7 @@ def polyglot_pointer?
231231
end
232232

233233
def polyglot_address
234-
@address ||= Truffle::CExt.string_pointer_to_native(@string) + @string.bytesize
234+
@address ||= TrufflePrimitive.string_pointer_to_native(@string) + @string.bytesize
235235
end
236236

237237
# Every IS_POINTER object should also have TO_NATIVE
@@ -1846,10 +1846,18 @@ def rb_enc_from_native_encoding(rb_encoding)
18461846
RbEncoding.get_encoding_from_native(rb_encoding)
18471847
end
18481848

1849+
def native_string?(string)
1850+
TrufflePrimitive.string_pointer_is_native?(string)
1851+
end
1852+
18491853
def RSTRING_PTR(string)
18501854
RStringPtr.new(string)
18511855
end
18521856

1857+
def NATIVE_RSTRING_PTR(string)
1858+
TrufflePrimitive.string_pointer_to_native(string)
1859+
end
1860+
18531861
def RSTRING_END(string)
18541862
RStringEndPtr.new(string)
18551863
end

lib/truffle/truffle/lazy-rubygems.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
# Otherwise, --disable-gems would degrade startup which is counter-intuitive.
1111
Truffle::Boot.delay do
1212
if Truffle::Boot.get_option 'rubygems'
13+
module Truffle::LazyRubyGems
14+
end
15+
1316
module Kernel
1417
# Take this alias name so RubyGems will reuse this copy
1518
# and skip the method below once RubyGems is loaded.
@@ -19,11 +22,19 @@ module Kernel
1922
begin
2023
gem_original_require(path)
2124
rescue LoadError
22-
require 'rubygems'
23-
require path
25+
gem_original_require 'rubygems'
26+
27+
# Check that #require was redefined by RubyGems, otherwise we would end up in infinite recursion
28+
new_require = ::Kernel.instance_method(:require)
29+
if new_require == Truffle::LazyRubyGems::LAZY_REQUIRE
30+
raise 'RubyGems did not redefine #require as expected, make sure $LOAD_PATH and home are set correctly'
31+
end
32+
new_require.bind(self).call(path)
2433
end
2534
end
2635

36+
Truffle::LazyRubyGems::LAZY_REQUIRE = instance_method(:require)
37+
2738
private def gem(*args)
2839
require 'rubygems'
2940
gem(*args)

lib/truffle/truffle/openssl-prefix.rb

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,26 @@
1313
macOS = RbConfig::CONFIG['host_os'].include?('darwin')
1414

1515
if macOS && !ENV['OPENSSL_PREFIX']
16-
homebrew_prefix = `brew --prefix openssl 2>/dev/null`.chomp
17-
if $?.success? and Dir.exist?(homebrew_prefix) # Homebrew
18-
ENV['OPENSSL_PREFIX'] = homebrew_prefix
16+
homebrew = `brew --prefix 2>/dev/null`.strip
17+
unless $?.success? and !homebrew.empty? and Dir.exist?(homebrew)
18+
homebrew = nil
19+
end
20+
21+
if homebrew and prefix = "#{homebrew}/opt/openssl@1.1" and Dir.exist?(prefix)
22+
ENV['OPENSSL_PREFIX'] = prefix
23+
elsif homebrew and prefix = "#{homebrew}/opt/openssl" and Dir.exist?(prefix)
24+
ENV['OPENSSL_PREFIX'] = prefix
1925
elsif Dir.exist?('/opt/local/include/openssl') # MacPorts
2026
ENV['OPENSSL_PREFIX'] = '/opt/local'
2127
else
2228
abort 'Could not find OpenSSL headers, install via Homebrew or MacPorts or set OPENSSL_PREFIX'
2329
end
2430
end
31+
32+
if openssl_prefix = ENV['OPENSSL_PREFIX']
33+
Truffle::Debug.log_config("Found OpenSSL in #{openssl_prefix}")
34+
35+
# We need to set PKG_CONFIG_PATH too, see https://github.com/oracle/truffleruby/issues/1830
36+
# OpenSSL's extconf.rb calls the pkg_config() helper.
37+
ENV['PKG_CONFIG_PATH'] = ["#{openssl_prefix}/lib/pkgconfig", *ENV['PKG_CONFIG_PATH']].join(':')
38+
end

spec/ruby/optional/capi/ext/string_spec.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,26 @@ VALUE string_spec_RSTRING_PTR_iterate(VALUE self, VALUE str) {
284284
return Qnil;
285285
}
286286

287+
VALUE string_spec_RSTRING_PTR_iterate_uint32(VALUE self, VALUE str) {
288+
int i;
289+
uint32_t* ptr;
290+
int l = RSTRING_LEN(str) / sizeof(uint32_t);
291+
292+
ptr = (uint32_t *)RSTRING_PTR(str);
293+
for(i = 0; i < l; i++) {
294+
rb_yield(UINT2NUM(ptr[i]));
295+
}
296+
return Qnil;
297+
}
298+
299+
VALUE string_spec_RSTRING_PTR_short_memcpy(VALUE self, VALUE str) {
300+
// Short memcpy operations may be optimised by the compiler to a single write.
301+
if (RSTRING_LEN(str) >= 8) {
302+
memcpy(RSTRING_PTR(str), "Infinity", 8);
303+
}
304+
return str;
305+
}
306+
287307
VALUE string_spec_RSTRING_PTR_assign(VALUE self, VALUE str, VALUE chr) {
288308
int i;
289309
char c;
@@ -477,6 +497,8 @@ void Init_string_spec(void) {
477497
rb_define_method(cls, "RSTRING_LEN", string_spec_RSTRING_LEN, 1);
478498
rb_define_method(cls, "RSTRING_LENINT", string_spec_RSTRING_LENINT, 1);
479499
rb_define_method(cls, "RSTRING_PTR_iterate", string_spec_RSTRING_PTR_iterate, 1);
500+
rb_define_method(cls, "RSTRING_PTR_iterate_uint32", string_spec_RSTRING_PTR_iterate_uint32, 1);
501+
rb_define_method(cls, "RSTRING_PTR_short_memcpy", string_spec_RSTRING_PTR_short_memcpy, 1);
480502
rb_define_method(cls, "RSTRING_PTR_assign", string_spec_RSTRING_PTR_assign, 2);
481503
rb_define_method(cls, "RSTRING_PTR_set", string_spec_RSTRING_PTR_set, 3);
482504
rb_define_method(cls, "RSTRING_PTR_after_funcall", string_spec_RSTRING_PTR_after_funcall, 2);

spec/ruby/optional/capi/string_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,24 @@ def inspect
513513
end
514514
chars.should == [55, 48, 227, 131, 145, 227, 130, 175]
515515
end
516+
517+
it "returns a pointer which can be cast and used as another type" do
518+
s = "70パク".
519+
encode(Encoding::UTF_16LE).
520+
force_encoding(Encoding::UTF_16LE).
521+
encode(Encoding::UTF_8)
522+
523+
ints = []
524+
@s.RSTRING_PTR_iterate_uint32(s) do |i|
525+
ints << i
526+
end
527+
ints.should == s.unpack('LL')
528+
end
529+
530+
it "allows a short memcpy to the string which may be converted to a single write operation by the compiler" do
531+
str = " "
532+
@s.RSTRING_PTR_short_memcpy(str).should == "Infinity"
533+
end
516534
end
517535

518536
describe "RSTRING_LEN" do

0 commit comments

Comments
 (0)