Skip to content

Commit be190ac

Browse files
committed
[GR-8654] Native array storage.
PullRequest: truffleruby/1003
2 parents c384538 + e23f00b commit be190ac

File tree

16 files changed

+469
-21
lines changed

16 files changed

+469
-21
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Compatibility:
3636
* Implemented the `unit` argument of `Time.at` (#1791, @XrXr).
3737
* Implemented `keyword_init: true` for `Struct.new` (#1789, @XrXr).
3838
* Implemented `MatchData#dup` (#1792, @XrXr).
39+
* Implemented a native storage strategy for arrays to allow better C extension compatibility.
3940

4041
Performance:
4142

lib/truffle/truffle/cext.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ def polyglot_pointer?
195195
end
196196

197197
def polyglot_address
198-
raise RuntimeError, 'RARRAY_PTRs cannot be converted to native pointers yet'
198+
TrufflePrimitive.array_store_to_native(@array)
199+
TrufflePrimitive.array_store_address(@array)
199200
end
200201

201202
# Every IS_POINTER object should also have TO_NATIVE

spec/ruby/optional/capi/array_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,14 @@
249249
@s.RARRAY_PTR_assign(a, :set)
250250
a.should == [:set, :set, :set]
251251
end
252+
253+
it "allows memcpying between arrays" do
254+
a = [1, 2, 3]
255+
b = [0, 0, 0]
256+
@s.RARRAY_PTR_memcpy(a, b)
257+
b.should == [1, 2, 3]
258+
a.should == [1, 2, 3] # check a was not modified
259+
end
252260
end
253261

254262
describe "RARRAY_LEN" do

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ static VALUE array_spec_RARRAY_PTR_assign(VALUE self, VALUE array, VALUE value)
3333
return Qnil;
3434
}
3535

36+
37+
static VALUE array_spec_RARRAY_PTR_memcpy(VALUE self, VALUE array1, VALUE array2) {
38+
VALUE *ptr1, *ptr2;
39+
int size;
40+
size = RARRAY_LEN(array1);
41+
ptr1 = RARRAY_PTR(array1);
42+
ptr2 = RARRAY_PTR(array2);
43+
if (ptr1 != NULL && ptr2 != NULL) {
44+
memcpy(ptr2, ptr1, size * sizeof(VALUE));
45+
}
46+
return Qnil;
47+
}
48+
3649
static VALUE array_spec_RARRAY_LEN(VALUE self, VALUE array) {
3750
return INT2FIX(RARRAY_LEN(array));
3851
}
@@ -229,6 +242,7 @@ void Init_array_spec(void) {
229242
rb_define_method(cls, "RARRAY_LEN", array_spec_RARRAY_LEN, 1);
230243
rb_define_method(cls, "RARRAY_PTR_iterate", array_spec_RARRAY_PTR_iterate, 1);
231244
rb_define_method(cls, "RARRAY_PTR_assign", array_spec_RARRAY_PTR_assign, 2);
245+
rb_define_method(cls, "RARRAY_PTR_memcpy", array_spec_RARRAY_PTR_memcpy, 2);
232246
rb_define_method(cls, "RARRAY_AREF", array_spec_RARRAY_AREF, 2);
233247
rb_define_method(cls, "rb_ary_aref", array_spec_rb_ary_aref, -1);
234248
rb_define_method(cls, "rb_ary_clear", array_spec_rb_ary_clear, 1);

src/main/c/cext/ruby.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1497,7 +1497,7 @@ VALUE rb_Array(VALUE array) {
14971497
}
14981498

14991499
VALUE *RARRAY_PTR_IMPL(VALUE array) {
1500-
return (VALUE *) RUBY_CEXT_INVOKE_NO_WRAP("RARRAY_PTR", array);
1500+
return (VALUE *) polyglot_as_i64_array(RUBY_CEXT_INVOKE_NO_WRAP("RARRAY_PTR", array));
15011501
}
15021502

15031503
VALUE rb_ary_new() {

src/main/c/zlib/zlib.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3032,8 +3032,6 @@ typedef struct {
30323032
VALUE klass;
30333033
} new_wrap_arg_t;
30343034

3035-
POLYGLOT_DECLARE_TYPE(new_wrap_arg_t)
3036-
30373035
static VALUE
30383036
new_wrap(VALUE tmp)
30393037
{
@@ -3060,11 +3058,11 @@ gzfile_wrap(int argc, VALUE *argv, VALUE klass, int close_io_on_error)
30603058

30613059
if (close_io_on_error) {
30623060
int state = 0;
3063-
new_wrap_arg_t *arg = rb_tr_new_managed_struct(new_wrap_arg_t);
3064-
arg->argc = argc;
3065-
arg->argv = argv;
3066-
arg->klass = klass;
3067-
obj = rb_protect(new_wrap, (VALUE)arg, &state);
3061+
new_wrap_arg_t arg;
3062+
arg.argc = argc;
3063+
arg.argv = argv;
3064+
arg.klass = klass;
3065+
obj = rb_protect(new_wrap, (VALUE)&arg, &state);
30683066
if (state) {
30693067
rb_io_close(argv[0]);
30703068
rb_jump_tag(state);

src/main/java/org/truffleruby/cext/UnwrapNode.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ protected ValueWrapper wrappedValueWrapper(ValueWrapper value) {
168168
return value;
169169
}
170170

171+
@Specialization
172+
protected ValueWrapper longToWrapper(long value,
173+
@Cached NativeToWrapperNode nativeToWrapperNode) {
174+
return nativeToWrapperNode.execute(value);
175+
}
176+
171177
@Specialization(
172178
guards = { "!isWrapper(value)", "values.isPointer(value)" },
173179
limit = "getCacheLimit()",
@@ -217,6 +223,12 @@ protected long unwrapValueTaggedLong(ValueWrapper value) {
217223
return value.getHandle() >> 1;
218224
}
219225

226+
@Specialization
227+
protected Object longToWrapper(long value,
228+
@Cached UnwrapNativeNode unwrapNode) {
229+
return unwrapNode.execute(value);
230+
}
231+
220232
@Specialization(
221233
guards = { "!isWrapper(value)", "values.isPointer(value)" },
222234
limit = "getCacheLimit()",

src/main/java/org/truffleruby/core/MarkerReference.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@
1111

1212
import java.lang.ref.ReferenceQueue;
1313

14-
import com.oracle.truffle.api.object.DynamicObject;
1514

16-
class MarkerReference extends ReferenceProcessingService.WeakProcessingReference<MarkerReference, DynamicObject> {
15+
class MarkerReference extends ReferenceProcessingService.WeakProcessingReference<MarkerReference, Object> {
1716

1817
final MarkingService.MarkerAction action;
1918

2019
MarkerReference(
21-
DynamicObject object,
20+
Object object,
2221
ReferenceQueue<? super Object> queue,
2322
MarkingService.MarkerAction action,
2423
MarkingService service) {

src/main/java/org/truffleruby/core/MarkingService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
public class MarkingService extends ReferenceProcessingService<MarkerReference> {
4343

4444
public static interface MarkerAction {
45-
public abstract void mark(DynamicObject owner);
45+
public abstract void mark(Object owner);
4646
}
4747

4848
public static class MarkRunnerReference extends WeakProcessingReference<MarkRunnerReference, Object> {
@@ -208,7 +208,7 @@ public void queueMarking() {
208208
queueForMarking(ValueWrapperManager.HandleBlock.DUMMY_BLOCK);
209209
}
210210

211-
public void addMarker(DynamicObject object, MarkerAction action) {
211+
public void addMarker(Object object, MarkerAction action) {
212212
add(new MarkerReference(object, referenceProcessor.processingQueue, action, this));
213213
}
214214

@@ -218,7 +218,7 @@ private void runMarker(MarkerReference markerReference) {
218218

219219
private void runMarkerInternal(MarkerReference markerReference) {
220220
if (!context.isFinalizing()) {
221-
DynamicObject owner = markerReference.get();
221+
Object owner = markerReference.get();
222222
if (owner != null) {
223223
final MarkerAction action = markerReference.action;
224224
action.mark(owner);

src/main/java/org/truffleruby/core/ReferenceProcessingService.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,7 @@ public WeakProcessingReference(
5555
private void check(R previous, R next) {
5656

5757
if (next != null && next == previous) {
58-
Error e = new Error();
59-
e.printStackTrace();
60-
throw e;
58+
throw new Error();
6159
}
6260

6361
}

0 commit comments

Comments
 (0)