diff --git a/CHANGELOG.md b/CHANGELOG.md index 95b59d87e56..be51681e5c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ Compatibility: Performance: +* Speedup some C extensions like `sqlite3`, `trilogy` and `json` by 2 to 3 times by using the Panama NFI backend for faster upcalls in JVM mode (@eregon). * Optimize encoding negotiation for ASCII-compatible encodings (@eregon, @andrykonchin). Changes: diff --git a/lib/truffle/truffle/cext.rb b/lib/truffle/truffle/cext.rb index 61fa786b680..9c19ade6d3a 100644 --- a/lib/truffle/truffle/cext.rb +++ b/lib/truffle/truffle/cext.rb @@ -190,7 +190,20 @@ def self.init_libtrufflerubytrampoline(libtrampoline) init_functions = libtrampoline[:rb_tr_trampoline_init_functions] init_functions = Primitive.interop_eval_nfi('(env,(string):pointer):void').bind(init_functions) - if Truffle::Boot.get_option 'cexts-panama' and Primitive.vm_java_version >= 22 and !TruffleRuby.native? + + panama = Truffle::Boot.get_option('cexts-panama') && Primitive.vm_java_version >= 22 && !TruffleRuby.native? + if panama + # Check if the Panama backend is available, it might not be when embedding TruffleRuby + rb_tr_invoke = LIBTRUFFLERUBY['rb_tr_invoke'] + begin + keep_alive << rb_tr_invoke.createNativeClosure('panama') + rescue Polyglot::ForeignException => e + warn "warning: the Panama Truffle NFI backend for running C extensions faster is not available (#{e.message}). Add 'org.graalvm.truffle:truffle-nfi-panama' to Maven dependencies to resolve or use '--ruby.cexts-panama=false' to ignore." + panama = false + end + end + + if panama init_functions.call(-> name { closure = LIBTRUFFLERUBY[name].createNativeClosure('panama') keep_alive << closure diff --git a/src/main/java/org/truffleruby/options/Options.java b/src/main/java/org/truffleruby/options/Options.java index c9454214d1b..03a71a2ee8c 100644 --- a/src/main/java/org/truffleruby/options/Options.java +++ b/src/main/java/org/truffleruby/options/Options.java @@ -107,7 +107,7 @@ public final class Options { public final boolean CEXTS; /** --cexts-lock=true */ public final boolean CEXT_LOCK; - /** --cexts-panama=false */ + /** --cexts-panama=true */ public final boolean CEXTS_PANAMA; /** --options-log=false */ public final boolean OPTIONS_LOG; diff --git a/src/options.yml b/src/options.yml index f9c2f78a0c2..82dbfb693d0 100644 --- a/src/options.yml +++ b/src/options.yml @@ -132,7 +132,7 @@ EXPERT: # C extension options CEXTS: [cexts, boolean, true, Enable use of C extensions] CEXT_LOCK: [cexts-lock, boolean, true, Use a Global Lock when running C extensions] - CEXTS_PANAMA: [cexts-panama, boolean, false, 'Use Panama for native to Ruby calls in C extensions. Only available in --jvm mode on JDK 22+.'] + CEXTS_PANAMA: [cexts-panama, boolean, true, 'Use Panama for native to Ruby calls in C extensions. Only available in --jvm mode on JDK 22+.'] # Debugging the values of options OPTIONS_LOG: [options-log, boolean, false, Log the final value of all options] diff --git a/src/shared/java/org/truffleruby/shared/options/OptionsCatalog.java b/src/shared/java/org/truffleruby/shared/options/OptionsCatalog.java index b30be90715c..adb40077bff 100644 --- a/src/shared/java/org/truffleruby/shared/options/OptionsCatalog.java +++ b/src/shared/java/org/truffleruby/shared/options/OptionsCatalog.java @@ -71,7 +71,7 @@ public final class OptionsCatalog { public static final OptionKey BACKTRACE_ON_NEW_FIBER_KEY = new OptionKey<>(false); public static final OptionKey CEXTS_KEY = new OptionKey<>(true); public static final OptionKey CEXT_LOCK_KEY = new OptionKey<>(true); - public static final OptionKey CEXTS_PANAMA_KEY = new OptionKey<>(false); + public static final OptionKey CEXTS_PANAMA_KEY = new OptionKey<>(true); public static final OptionKey OPTIONS_LOG_KEY = new OptionKey<>(false); public static final OptionKey LOG_LOAD_KEY = new OptionKey<>(false); public static final OptionKey LOG_AUTOLOAD_KEY = new OptionKey<>(false); diff --git a/src/test-embedding/java/org/truffleruby/test/embedding/ContextPermissionsTest.java b/src/test-embedding/java/org/truffleruby/test/embedding/ContextPermissionsTest.java index 645382ad033..ac445091b91 100644 --- a/src/test-embedding/java/org/truffleruby/test/embedding/ContextPermissionsTest.java +++ b/src/test-embedding/java/org/truffleruby/test/embedding/ContextPermissionsTest.java @@ -77,6 +77,13 @@ public void testRequireGem() { } } + @Test + public void testRequireCExtension() { + try (Context context = Context.newBuilder("ruby").allowIO(IOAccess.ALL).allowNativeAccess(true).build()) { + Assert.assertEquals("Etc", context.eval("ruby", "require 'etc'; Etc.to_s").asString()); + } + } + @Test public void testThreadsNoNative() throws Throwable { // The ruby.single_threaded option needs to be set because --single-threaded defaults to --embedded.