Skip to content

Commit a9afcef

Browse files
committed
[GR-48942] Run C extensions natively
PullRequest: truffleruby/4018
2 parents 100d068 + e76aefb commit a9afcef

File tree

156 files changed

+4841
-1850
lines changed

Some content is hidden

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

156 files changed

+4841
-1850
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ lib/gems/gems/debug-*/ext/debug/debug_version.h
4848
src/main/c/*/Makefile
4949
!src/main/c/spawn-helper/Makefile
5050
!src/main/c/truffleposix/Makefile
51+
src/main/c/cext-trampoline/trampoline.c
52+
src/main/c/cext/wrappers.c
5153
src/main/c/etc/constdefs.h
5254
src/main/c/spawn-helper/spawn-helper
5355

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
New features:
44

5+
* C/C++ extensions are now compiled using the system toolchain and executed natively instead of using GraalVM LLVM (Sulong). This leads to faster startup, no warmup, better compatibility and faster installation for C/C++ extensions (#3118, @eregon).
56

67
Bug fixes:
78

@@ -11,7 +12,6 @@ Bug fixes:
1112

1213
Compatibility:
1314

14-
* Fix problems with the LLVM toolchain wrappers with Xcode 15 on macOS.
1515
* Add `Exception#detailed_message` method (#3257, @andrykonchin).
1616
* Fix `rb_enc_vsprintf` and force String encoding instead of converting it (@andrykonchin).
1717
* Add `rb_gc_mark_movable` function (@andrykonchin).

ci.jsonnet

+28-20
Original file line numberDiff line numberDiff line change
@@ -232,14 +232,18 @@ local part_definitions = {
232232
},
233233

234234
platform: {
235-
local common_deps = common.deps.truffleruby + common.deps.sulong,
236-
local linux_amd64_extra_deps = {
237-
packages+: {
238-
binutils: ">=2.30",
239-
},
240-
},
241-
242-
linux: common.linux_amd64 + common_deps + linux_amd64_extra_deps + {
235+
local devtoolset = { # Until there is a proper object in common.jsonnet for it
236+
packages+: if self.os == "linux" then
237+
(if self.arch == "aarch64" then {
238+
"00:devtoolset": "==10",
239+
} else {
240+
"00:devtoolset": "==11",
241+
})
242+
else {},
243+
},
244+
local common_deps = common.deps.truffleruby + common.deps.sulong + devtoolset,
245+
246+
linux: common.linux_amd64 + common_deps + {
243247
platform_name:: "LinuxAMD64",
244248
"$.cap":: {
245249
normal_machine: [],
@@ -308,6 +312,7 @@ local part_definitions = {
308312
run+: jt(["test", "specs", ":all"]) +
309313
jt(["test", "specs", ":tracepoint"]) +
310314
jt(["test", "specs", ":next"]) +
315+
[["env", "SPEC_CAPI_CXX=true"] + jt(["test", "specs", "--timeout", "180", ":capi"])[0]] +
311316
jt(["test", "basictest"]),
312317
},
313318

@@ -371,6 +376,13 @@ local part_definitions = {
371376
jt(["test", "bundle"]),
372377
},
373378

379+
test_cexts_sulong: {
380+
environment+: {
381+
TRUFFLERUBYOPT: "--experimental-options --cexts-sulong",
382+
},
383+
run+: jt(["test", "specs", ":cext"]),
384+
},
385+
374386
testdownstream_aot: { run+: [["mx", "ruby_testdownstream_aot", "$RUBY_BIN"]] },
375387

376388
test_make_standalone_distribution: {
@@ -381,18 +393,12 @@ local part_definitions = {
381393

382394
generate_native_config: {
383395
setup+: [
384-
["mx", "sforceimports"], # clone the graal repo
385-
["mx", "-p", "../graal/sulong", "build"],
386-
["set-export", "TOOLCHAIN_PATH", ["mx", "-p", "../graal/sulong", "lli", "--print-toolchain-path"]],
396+
["ruby", "-e", "pp RbConfig::MAKEFILE_CONFIG"], # For convenience
387397
],
388398
run+: [
389-
["env",
390-
"LD_LIBRARY_PATH=$BUILD_DIR/graal/sulong/mxbuild/" + self.os + "-" + self.arch + "/SULONG_HOME/native/lib:$LD_LIBRARY_PATH", # for finding libc++
391-
"PATH=$TOOLCHAIN_PATH:$PATH",
392-
"ruby", "tool/generate-native-config.rb"],
399+
["ruby", "tool/generate-native-config.rb"],
393400
["cat", "src/main/java/org/truffleruby/platform/" + self.platform_name + "NativeConfiguration.java"],
394401

395-
# Uses the system compiler as using the toolchain for this does not work on macOS
396402
["tool/generate-config-header.sh"],
397403
["cat", "lib/cext/include/truffleruby/config_" + self.os + "_" + self.arch + ".h"],
398404
],
@@ -537,6 +543,7 @@ local composition_environment = utils.add_inclusion_tracking(part_definitions, "
537543
"ruby-test-cexts-linux-aarch64": $.platform.linux_aarch64 + $.jdk.stable + $.env.jvm + gate + $.use.gem_test_pack + $.use.sqlite331 + $.run.test_cexts,
538544
"ruby-test-cexts-darwin-amd64": $.platform.darwin_amd64 + $.jdk.stable + $.env.jvm + gate + $.use.gem_test_pack + $.run.test_cexts + { timelimit: "01:30:00" },
539545
"ruby-test-cexts-darwin-aarch64": $.platform.darwin_aarch64 + $.jdk.stable + $.env.jvm + gate + $.use.gem_test_pack + $.run.test_cexts + { timelimit: "00:40:00" },
546+
"ruby-test-cexts-sulong": $.platform.linux + $.jdk.stable + $.env.jvm + gate + $.run.test_cexts_sulong + { timelimit: "20:00" },
540547
"ruby-test-gems-linux-amd64": $.platform.linux + $.jdk.stable + $.env.jvm + gate + $.use.gem_test_pack + $.run.test_gems,
541548
"ruby-test-gems-darwin-amd64": $.platform.darwin_amd64 + $.jdk.stable + $.env.jvm + gate + $.use.gem_test_pack + $.run.test_gems,
542549
"ruby-test-gems-darwin-aarch64": $.platform.darwin_aarch64 + $.jdk.stable + $.env.jvm + gate + $.use.gem_test_pack + $.run.test_gems,
@@ -701,11 +708,12 @@ local composition_environment = utils.add_inclusion_tracking(part_definitions, "
701708

702709
manual_builds: {
703710
local shared = $.use.common + $.cap.manual + { timelimit: "15:00" },
711+
local native_config = $.run.generate_native_config + $.run.check_native_config,
704712

705-
"ruby-generate-native-config-linux-amd64": $.platform.linux + $.jdk.stable + shared + $.run.generate_native_config,
706-
"ruby-generate-native-config-linux-aarch64": $.platform.linux_aarch64 + $.jdk.stable + shared + $.run.generate_native_config,
707-
"ruby-generate-native-config-darwin-amd64": $.platform.darwin_amd64 + $.jdk.stable + shared + $.run.generate_native_config,
708-
"ruby-generate-native-config-darwin-aarch64": $.platform.darwin_aarch64 + $.jdk.stable + shared + $.run.generate_native_config,
713+
"ruby-generate-native-config-linux-amd64": $.platform.linux + $.jdk.stable + shared + native_config,
714+
"ruby-generate-native-config-linux-aarch64": $.platform.linux_aarch64 + $.jdk.stable + shared + native_config,
715+
"ruby-generate-native-config-darwin-amd64": $.platform.darwin_amd64 + $.jdk.stable + shared + native_config,
716+
"ruby-generate-native-config-darwin-aarch64": $.platform.darwin_aarch64 + $.jdk.stable + shared + native_config,
709717
},
710718

711719
builds:

doc/contributor/how-to-guide.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1292,15 +1292,15 @@ When you modify C-files (*.c, *.h) or compilation-related Ruby files
12921292
affect the ABI or increase the ABI *check* version explicitly by modifying one of
12931293
the files:
12941294
1295-
- lib/cext/ABI_version.txt
1295+
- lib/cext/include/truffleruby/truffleruby-abi-version.h
12961296
- lib/cext/ABI_check.txt
12971297
12981298
ABI change is:
12991299
- changing headers or compilation flags
13001300
- removing/adding a non-static function
13011301
- implementing already declared non-static functions
13021302
1303-
In case of doubt, bump `ABI_version.txt`.
1303+
In case of doubt, bump `truffleruby-abi-version.h`.
13041304
13051305
## How to choose where to add new specs - in TruffleRuby or in ruby/spec repository
13061306

doc/contributor/updating-ruby.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ Also update the list of `provided_executables` in `mx_truffleruby.py` if some la
142142
Update all of these:
143143

144144
* Update `.ruby-version`, `TruffleRuby.LANGUAGE_VERSION`
145-
* Reset `lib/cext/ABI_version.txt` and `lib/cext/ABI_check.txt` to `1` if `RUBY_VERSION` was updated.
145+
* Reset `truffleruby-abi-version.h` to `$RUBY_VERSION.1` and `lib/cext/ABI_check.txt` to `1` if `RUBY_VERSION` was updated.
146146
* Update `versions.json` (with gem versions provided by `cat ../ruby/gems/bundled_gems | sort`, `ls -l lib/gems/specifications/default` and `grep 'VERSION =' lib/mri/rubygems.rb`)
147147
* Also update version numbers for `debug` and `rbs` in `src/main/c/Makefile` and in `mx.truffleruby/suite.py`.
148148
* Copy and paste `-h` and `--help` output to `RubyLauncher` (instructions are in the end of the file `src/launcher/java/org/truffleruby/launcher/RubyLauncher.java`)

lib/cext/ABI_version.txt

-1
This file was deleted.

lib/cext/include/internal/bignum.h

+6
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,13 @@ static inline bool BIGNUM_POSITIVE_P(VALUE b);
136136
static inline bool BIGNUM_NEGATIVE_P(VALUE b);
137137
static inline void BIGNUM_SET_SIGN(VALUE b, bool sign);
138138
static inline void BIGNUM_NEGATE(VALUE b);
139+
#ifndef TRUFFLERUBY
139140
static inline size_t BIGNUM_LEN(VALUE b);
141+
#endif
140142
static inline BDIGIT *BIGNUM_DIGITS(VALUE b);
143+
#ifndef TRUFFLERUBY
141144
static inline int BIGNUM_LENINT(VALUE b);
145+
#endif
142146
static inline bool BIGNUM_EMBED_P(VALUE b);
143147

144148
RUBY_SYMBOL_EXPORT_BEGIN
@@ -205,6 +209,7 @@ BIGNUM_NEGATE(VALUE b)
205209
FL_REVERSE_RAW(b, BIGNUM_SIGN_BIT);
206210
}
207211

212+
#ifndef TRUFFLERUBY
208213
static inline size_t
209214
BIGNUM_LEN(VALUE b)
210215
{
@@ -224,6 +229,7 @@ BIGNUM_LENINT(VALUE b)
224229
{
225230
return rb_long2int(BIGNUM_LEN(b));
226231
}
232+
#endif
227233

228234
/* LSB:BIGNUM_DIGITS(b)[0], MSB:BIGNUM_DIGITS(b)[BIGNUM_LEN(b)-1] */
229235
static inline BDIGIT *

lib/cext/include/internal/compile.h

+5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ st_index_t rb_iseq_cdhash_hash(VALUE a);
2525
/* iseq.c */
2626
int rb_vm_insn_addr2insn(const void *);
2727
int rb_vm_insn_decode(const VALUE encoded);
28+
29+
#ifdef TRUFFLERUBY
30+
#define ruby_vm_keep_script_lines false
31+
#else
2832
extern bool ruby_vm_keep_script_lines;
33+
#endif
2934

3035
MJIT_SYMBOL_EXPORT_BEGIN
3136
/* iseq.c (export) */

lib/cext/include/internal/imemo.h

+4
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,10 @@ typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
131131
rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
132132
struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
133133
void rb_strterm_mark(VALUE obj);
134+
#ifndef TRUFFLERUBY
134135
static inline enum imemo_type imemo_type(VALUE imemo);
135136
static inline int imemo_type_p(VALUE imemo, enum imemo_type imemo_type);
137+
#endif
136138
static inline bool imemo_throw_data_p(VALUE imemo);
137139
static inline struct vm_ifunc *rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data);
138140
#ifdef TRUFFLERUBY
@@ -160,6 +162,7 @@ VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
160162
const char *rb_imemo_name(enum imemo_type type);
161163
RUBY_SYMBOL_EXPORT_END
162164

165+
#ifndef TRUFFLERUBY
163166
static inline enum imemo_type
164167
imemo_type(VALUE imemo)
165168
{
@@ -182,6 +185,7 @@ imemo_type_p(VALUE imemo, enum imemo_type imemo_type)
182185
}
183186

184187
#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)v, t)
188+
#endif
185189

186190
static inline bool
187191
imemo_throw_data_p(VALUE imemo)

lib/cext/include/ruby/internal/arithmetic/long.h

-13
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,8 @@ int rb_long2int(long value);
106106
#endif
107107
RBIMPL_SYMBOL_EXPORT_END()
108108

109-
#ifndef TRUFFLERUBY
110109
RBIMPL_ATTR_CONST_UNLESS_DEBUG()
111110
RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
112-
#endif
113111
RBIMPL_ATTR_ARTIFICIAL()
114112
/**
115113
* Converts a C's `long` into an instance of ::rb_cInteger.
@@ -231,10 +229,7 @@ rbimpl_right_shift_is_arithmetic_p(void)
231229
}
232230

233231
RBIMPL_ATTR_CONST_UNLESS_DEBUG()
234-
#ifndef TRUFFLERUBY
235232
RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
236-
#endif
237-
238233
/**
239234
* Converts a Fixnum into C's `long`.
240235
*
@@ -245,16 +240,12 @@ RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
245240
static inline long
246241
rb_fix2long(VALUE x)
247242
{
248-
#ifdef TRUFFLERUBY
249-
return ((long)polyglot_as_i64(rb_tr_unwrap(x)));
250-
#else
251243
if /* constexpr */ (rbimpl_right_shift_is_arithmetic_p()) {
252244
return rbimpl_fix2long_by_shift(x);
253245
}
254246
else {
255247
return rbimpl_fix2long_by_idiv(x);
256248
}
257-
#endif
258249
}
259250

260251
RBIMPL_ATTR_CONST_UNLESS_DEBUG()
@@ -344,11 +335,7 @@ rb_ulong2num_inline(unsigned long v)
344335
if (RB_POSFIXABLE(v))
345336
return RB_LONG2FIX(v);
346337
else
347-
#ifdef TRUFFLERUBY
348-
return rb_tr_wrap(polyglot_invoke(RUBY_CEXT, "rb_ulong2num", (long) v));
349-
#else
350338
return rb_uint2big(v);
351-
#endif
352339
}
353340

354341
/**

lib/cext/include/ruby/internal/config.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@
5656
# define HAVE_VA_ARGS_MACRO
5757
# else
5858
# /* NG, not known. */
59+
// Always define HAVE_VA_ARGS_MACRO on TruffleRuby, as it leads to cleaner macros and more optimizations:
60+
// clang++ on macOS Ventura has __cplusplus defined as 199711 but it supports newer standards like c++11
61+
#ifdef TRUFFLERUBY
62+
#define HAVE_VA_ARGS_MACRO
63+
#endif
5964
# endif
6065
#endif
6166

@@ -155,7 +160,7 @@
155160
#endif
156161

157162
#define TRUFFLERUBY
158-
// Loaded at the end of config.h, included from defines.h. Needs STRINGIZE().
163+
// Loaded at the end of config.h, included from defines.h.
159164
#include <truffleruby/truffleruby-pre.h>
160165

161166
#endif /* RBIMPL_CONFIG_H */

lib/cext/include/ruby/internal/core/rarray.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ VALUE rb_tr_rarray_aref(VALUE array, long index);
283283
#endif
284284
RBIMPL_SYMBOL_EXPORT_END()
285285

286+
#ifndef TRUFFLERUBY
286287
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
287288
RBIMPL_ATTR_ARTIFICIAL()
288289
/**
@@ -312,7 +313,6 @@ RARRAY_EMBED_LEN(VALUE ary)
312313
return RBIMPL_CAST((long)f);
313314
}
314315

315-
#ifndef TRUFFLERUBY
316316
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
317317
/**
318318
* Queries the length of the array.

lib/cext/include/ruby/internal/core/rbasic.h

+4-12
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@
3737
* @param obj Arbitrary Ruby object.
3838
* @return The passed object casted to ::RBasic.
3939
*/
40-
#ifdef TRUFFLERUBY
41-
#define RBASIC(obj) (polyglot_as_RBasic(polyglot_invoke(RUBY_CEXT, "RBASIC", rb_tr_unwrap(obj))))
42-
#else
40+
#ifndef TRUFFLERUBY
4341
#define RBASIC(obj) RBIMPL_CAST((struct RBasic *)(obj))
4442
#endif
4543

@@ -75,7 +73,8 @@ enum ruby_rvalue_flags {
7573
struct
7674
RUBY_ALIGNAS(SIZEOF_VALUE)
7775
RBasic {
78-
76+
#ifndef TRUFFLERUBY
77+
// TruffleRuby: we cannot support writing to the flags field, so don't expose the field
7978
/**
8079
* Per-object flags. Each ruby objects have their own characteristics
8180
* apart from their classes. For instance whether an object is frozen or
@@ -98,11 +97,7 @@ RBasic {
9897
* Also note the `const` qualifier. In ruby an object cannot "change" its
9998
* class.
10099
*/
101-
#ifdef TRUFFLERUBY
102-
VALUE klass;
103-
#else
104100
const VALUE klass;
105-
#endif
106101

107102
#ifdef __cplusplus
108103
public:
@@ -122,12 +117,9 @@ RBasic {
122117
{
123118
}
124119
#endif
120+
#endif // TRUFFLERUBY
125121
};
126122

127-
#ifdef TRUFFLERUBY
128-
POLYGLOT_DECLARE_STRUCT(RBasic)
129-
#endif
130-
131123
RBIMPL_SYMBOL_EXPORT_BEGIN()
132124
/**
133125
* Make the object invisible from Ruby code.

0 commit comments

Comments
 (0)