Skip to content

Commit 645a65d

Browse files
committed
Merge pull request #2515 from stevengj/unsafe_immutable
RFC: extend unsafe_assign to work for any isbits type, add pointer_from_objref
2 parents 7123ad3 + 5cdbfcf commit 645a65d

File tree

5 files changed

+25
-6
lines changed

5 files changed

+25
-6
lines changed

base/exports.jl

+1
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,7 @@ export
11271127
unsafe_ref,
11281128
unsafe_assign,
11291129
unsafe_pointer_to_objref,
1130+
pointer_from_objref,
11301131

11311132
# Macros
11321133
@b_str,

base/pointer.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ unsafe_assign(p::Ptr{Any}, x::ANY, i::Integer) = pointerset(p, x, int(i))
3838
unsafe_assign{T}(p::Ptr{T}, x, i::Integer) = pointerset(p, convert(T, x), int(i))
3939
unsafe_assign{T}(p::Ptr{T}, x) = unsafe_assign(p, convert(T,x), 1)
4040

41-
# convert a raw Ptr to an object reference
41+
# convert a raw Ptr to an object reference, and vice-versa
4242
unsafe_pointer_to_objref(p::Ptr) = pointertoref(unbox(Ptr{Void},p))
43+
pointer_from_objref(x::Any) = ccall(:jl_value_ptr, Ptr{Void}, (Any,), x)
4344

4445
integer(x::Ptr) = convert(Uint, x)
4546
unsigned(x::Ptr) = convert(Uint, x)

doc/manual/calling-c-and-fortran-code.rst

+6-3
Original file line numberDiff line numberDiff line change
@@ -321,12 +321,15 @@ If T is Any, then the referenced memory is assumed to contain some
321321
that the object was always visible to the garbage collector (pointers do not
322322
count, but the new object does) to ensure the memory is not prematurely freed.
323323
Note that if the object was not originally allocated by Julia, the new object
324-
will never be finalized by Julia's garbage collector. If the `Ptr` itself
324+
will never be finalized by Julia's garbage collector. If the ``Ptr`` itself
325325
is actually a ``jl_value_t*``, it can be converted back to a Julia object
326-
reference by ``unsafe_pointer_to_objref(ptr)``.
326+
reference by ``unsafe_pointer_to_objref(ptr)``. [Julia values ``v``
327+
can be converted to ``jl_value_t*`` pointers (``Ptr{Void}``) by calling
328+
``pointer_from_objref(v)``.]
327329

328330
The reverse operation (writing data to a Ptr{T}), can be performed using
329-
``unsafe_assign(ptr, value, [index])``.
331+
``unsafe_assign(ptr, value, [index])``. Currently, this is only supported
332+
for bitstypes or other pointer-free (``isbits``) immutable types.
330333

331334
Any operation that throws an error is probably currently unimplemented
332335
and should be posted as a bug so that it can be resolved.

src/intrinsics.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ static Value *emit_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ctx)
404404
Value *thePtr = auto_unbox(e,ctx);
405405
Value *idx = emit_unbox(T_size, T_psize, emit_unboxed(i, ctx));
406406
Value *im1 = builder.CreateSub(idx, ConstantInt::get(T_size, 1));
407-
if (!jl_is_bitstype(ety)) {
407+
if (!jl_isbits(ety)) {
408408
if (ety == (jl_value_t*)jl_any_type)
409409
return builder.CreateLoad(builder.CreateGEP(
410410
builder.CreateBitCast(thePtr, jl_ppvalue_llvmt),
@@ -438,7 +438,7 @@ static Value *emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_co
438438
jl_value_t *xty = expr_type(x, ctx);
439439
if (!jl_subtype(xty, ety, 0))
440440
jl_error("pointerset: type mismatch in assign");
441-
if (!jl_is_bitstype(ety)) {
441+
if (!jl_isbits(ety)) {
442442
jl_error("pointerset: invalid pointer type"); //ety = (jl_value_t*)jl_any_type;
443443
}
444444
if ((jl_datatype_t*)expr_type(i, ctx) != jl_long_type) {

test/core.jl

+14
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,20 @@ end
475475

476476
@test unsafe_pointer_to_objref(ccall(:jl_call1, Ptr{Void}, (Any,Any),
477477
x -> x+1, 314158)) == 314159
478+
@test unsafe_pointer_to_objref(pointer_from_objref(e+pi)) == e+pi
479+
480+
immutable FooBar
481+
foo::Int
482+
bar::Int
483+
end
484+
begin
485+
local X, p
486+
X = FooBar[ FooBar(3,1), FooBar(4,4) ]
487+
p = convert(Ptr{FooBar}, X)
488+
@test unsafe_ref(p, 2) == FooBar(4,4)
489+
unsafe_assign(p, FooBar(7,3), 1)
490+
@test X[1] == FooBar(7,3)
491+
end
478492

479493
# issue #1287, combinations of try, catch, return
480494
begin

0 commit comments

Comments
 (0)