Skip to content

Commit a6d2e0b

Browse files
committed
[GR-17457] C tidy up
PullRequest: truffleruby/3241
2 parents 9bef946 + 3c18983 commit a6d2e0b

File tree

7 files changed

+103
-60
lines changed

7 files changed

+103
-60
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ Compatibility:
1818
* `Exception#full_message` now defaults the order to `:top` like CRuby 3+ (@eregon).
1919
* Fix `Process.wait2` to return `nil` when the `WNOHANG` flag is given and the child process is still running (@bjfish).
2020
* Disable most `nokogiri` C extension patches when system libraries are not being used (#2693, @aardvark179).
21+
* Implement `rb_gc_mark_maybe` and `rb_global_variable` to ensure `VALUE` stay live in C extensions (@aardvark179).
2122

2223
Performance:
2324

2425
* Reimplement `Float#to_s` for better performance (#1584, @aardvark179).
2526
* Improve reference processing by making C object free functions and other finalizers more lightweight (@aardvark179).
2627
* Improve performance of `RSTRING_PTR` for interned strings (@aardvark179).
28+
* Cache constant argument formats used with `rb_scan_args_kw` (@aardvark179).
2729

2830
Changes:
2931

lib/cext/ABI_version.txt

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

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,7 @@ void rb_gc_register_address(VALUE *valptr);
3636
/**
3737
* An alias for `rb_gc_register_address()`.
3838
*/
39-
#ifdef TRUFFLERUBY
40-
#define rb_global_variable(address) ;
41-
#else
4239
void rb_global_variable(VALUE *);
43-
#endif
4440

4541
/**
4642
* Inform the garbage collector that a pointer previously passed to

lib/cext/include/truffleruby/truffleruby.h

Lines changed: 37 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,24 @@ if (polyglot_as_boolean(polyglot_invoke(RUBY_CEXT, "warning?"))) { \
6161
} \
6262
})
6363

64+
#define rb_tr_scan_args_kw(kw_flag, argc, argv, format, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) \
65+
(RBIMPL_CONSTANT_P(format) ? \
66+
__extension__ ({ \
67+
static bool evaled; \
68+
static int pre; \
69+
static int optional; \
70+
static bool rest; \
71+
static int post; \
72+
static bool kwargs; \
73+
static bool block; \
74+
if (!evaled) { \
75+
rb_tr_scan_args_kw_parse(format, &pre, &optional, &rest, &post, &kwargs, &block); \
76+
evaled = true; \
77+
} \
78+
rb_tr_scan_args_kw_int(kw_flag, argc, argv, pre, optional, rest, post, kwargs, block, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); \
79+
}) : \
80+
rb_tr_scan_args_kw_non_const(kw_flag, argc, argv, format, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10))
81+
6482
#define rb_tr_scan_args_kw_1(KW_FLAG, ARGC, ARGV, FORMAT, V1) rb_tr_scan_args_kw(KW_FLAG, ARGC, ARGV, FORMAT, V1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
6583
#define rb_tr_scan_args_kw_2(KW_FLAG, ARGC, ARGV, FORMAT, V1, V2) rb_tr_scan_args_kw(KW_FLAG, ARGC, ARGV, FORMAT, V1, V2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
6684
#define rb_tr_scan_args_kw_3(KW_FLAG, ARGC, ARGV, FORMAT, V1, V2, V3) rb_tr_scan_args_kw(KW_FLAG, ARGC, ARGV, FORMAT, V1, V2, V3, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
@@ -196,20 +214,10 @@ static inline char *rb_tr_string_value_cstr(VALUE *value_pointer) {
196214
return RSTRING_PTR(string);
197215
}
198216

199-
ALWAYS_INLINE(static int rb_tr_scan_args_kw(int kw_flag, int argc, VALUE *argv, const char *format, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10));
200-
static inline int rb_tr_scan_args_kw(int kw_flag, int argc, VALUE *argv, const char *format, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10) {
201-
202-
// TODO CS 7-Feb-17 maybe we could inline cache this part?
203-
204-
const char *formatp = format;
205-
int pre = 0;
206-
int optional = 0;
207-
bool rest;
208-
int post = 0;
209-
bool kwargs;
210-
bool block;
217+
void rb_tr_scan_args_kw_parse(const char *format, int *pre, int *optional, bool *rest, int *post, bool *kwargs, bool *block);
211218

212-
// Interpret kw_flag
219+
ALWAYS_INLINE(static int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int pre, int optional, bool rest, int post, bool kwargs, bool block, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10));
220+
static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int pre, int optional, bool rest, int post, bool kwargs, bool block, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10) {
213221

214222
int keyword_given = 0;
215223
int last_hash_keyword = 0;
@@ -220,48 +228,6 @@ static inline int rb_tr_scan_args_kw(int kw_flag, int argc, VALUE *argv, const c
220228
case RB_SCAN_ARGS_LAST_HASH_KEYWORDS: last_hash_keyword = 1; break;
221229
}
222230

223-
// TODO CS 27-Feb-17 can LLVM constant-fold through isdigit?
224-
225-
if (isdigit(*formatp)) {
226-
pre = *formatp - '0';
227-
formatp++;
228-
229-
if (isdigit(*formatp)) {
230-
optional = *formatp - '0';
231-
formatp++;
232-
}
233-
}
234-
235-
if (*formatp == '*') {
236-
rest = true;
237-
formatp++;
238-
} else {
239-
rest = false;
240-
}
241-
242-
if (isdigit(*formatp)) {
243-
post = *formatp - '0';
244-
formatp++;
245-
}
246-
247-
if (*formatp == ':') {
248-
kwargs = true;
249-
formatp++;
250-
} else {
251-
kwargs = false;
252-
}
253-
254-
if (*formatp == '&') {
255-
block = true;
256-
formatp++;
257-
} else {
258-
block = false;
259-
}
260-
261-
if (*formatp != '\0') {
262-
rb_raise(rb_eArgError, "bad rb_scan_args format");
263-
}
264-
265231
// Check we have enough arguments
266232

267233
if (pre + post > argc) {
@@ -425,6 +391,22 @@ static inline int rb_tr_scan_args_kw(int kw_flag, int argc, VALUE *argv, const c
425391
return argc;
426392
}
427393

394+
ALWAYS_INLINE(static int rb_tr_scan_args_kw_non_const(int kw_flag, int argc, VALUE *argv, const char *format, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10));
395+
static inline int rb_tr_scan_args_kw_non_const(int kw_flag, int argc, VALUE *argv, const char *format, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10) {
396+
397+
const char *formatp = format;
398+
int pre = 0;
399+
int optional = 0;
400+
bool rest;
401+
int post = 0;
402+
bool kwargs;
403+
bool block;
404+
405+
rb_tr_scan_args_kw_parse(format, &pre, &optional, &rest, &post, &kwargs, &block);
406+
407+
return rb_tr_scan_args_kw_int(kw_flag, argc, argv, pre, optional, rest, post, kwargs, block, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10);
408+
}
409+
428410
#define rb_iv_get(obj, name) \
429411
(__builtin_constant_p(name) ? \
430412
rb_ivar_get(obj, rb_intern(name)) : \

lib/truffle/truffle/cext.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ module Truffle::CExt
106106
RUBY_ECONV_PARTIAL_INPUT = Encoding::Converter::PARTIAL_INPUT
107107
RUBY_ECONV_AFTER_OUTPUT = Encoding::Converter::AFTER_OUTPUT
108108

109+
GLOBALLY_PRESERVED_VALUES = []
110+
109111
SET_LIBTRUFFLERUBY = -> libtruffleruby do
110112
LIBTRUFFLERUBY = libtruffleruby
111113
end
@@ -1919,4 +1921,8 @@ def rb_tr_pointer(pointer)
19191921
def rb_exception_set_message(e, mesg)
19201922
Primitive.exception_set_message(e, mesg)
19211923
end
1924+
1925+
def rb_global_variable(obj)
1926+
GLOBALLY_PRESERVED_VALUES << obj
1927+
end
19221928
end

src/main/c/cext/args.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,47 @@ int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optiona
102102

103103
return extracted;
104104
}
105+
106+
void rb_tr_scan_args_kw_parse(const char *format, int *pre, int *optional, bool *rest, int *post, bool *kwargs, bool *block) {
107+
const char *formatp = format;
108+
109+
if (isdigit(*formatp)) {
110+
*pre = *formatp - '0';
111+
formatp++;
112+
113+
if (isdigit(*formatp)) {
114+
*optional = *formatp - '0';
115+
formatp++;
116+
}
117+
}
118+
119+
if (*formatp == '*') {
120+
*rest = true;
121+
formatp++;
122+
} else {
123+
*rest = false;
124+
}
125+
126+
if (isdigit(*formatp)) {
127+
*post = *formatp - '0';
128+
formatp++;
129+
}
130+
131+
if (*formatp == ':') {
132+
*kwargs = true;
133+
formatp++;
134+
} else {
135+
*kwargs = false;
136+
}
137+
138+
if (*formatp == '&') {
139+
*block = true;
140+
formatp++;
141+
} else {
142+
*block = false;
143+
}
144+
145+
if (*formatp != '\0') {
146+
rb_raise(rb_eArgError, "bad rb_scan_args format");
147+
}
148+
}

src/main/c/cext/gc.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ void rb_gc_mark(VALUE ptr) {
2323
polyglot_invoke(RUBY_CEXT, "rb_gc_mark", ptr);
2424
}
2525

26+
void rb_gc_mark_maybe(VALUE ptr) {
27+
if (!RB_TYPE_P(ptr, T_NONE)) {
28+
polyglot_invoke(RUBY_CEXT, "rb_gc_mark", ptr);
29+
}
30+
}
31+
2632
VALUE rb_gc_enable() {
2733
return RUBY_CEXT_INVOKE("rb_gc_enable");
2834
}
@@ -47,3 +53,10 @@ VALUE rb_gc_latest_gc_info(VALUE key) {
4753
void rb_gc_register_mark_object(VALUE obj) {
4854
RUBY_CEXT_INVOKE_NO_WRAP("rb_gc_register_mark_object", obj);
4955
}
56+
57+
void rb_global_variable(VALUE *obj) {
58+
/* TODO: This should guard the address of the pointer, not the
59+
object pointed to, but we haven't yet found a good way to implement
60+
that, or a real world use case where it is required. */
61+
RUBY_CEXT_INVOKE_NO_WRAP("rb_global_variable", *obj);
62+
}

0 commit comments

Comments
 (0)