Skip to content

Commit

Permalink
Merge pull request #2515 from stevengj/unsafe_immutable
Browse files Browse the repository at this point in the history
RFC: extend unsafe_assign to work for any isbits type, add pointer_from_objref
  • Loading branch information
JeffBezanson committed Mar 8, 2013
2 parents 7123ad3 + 5cdbfcf commit 645a65d
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 6 deletions.
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,7 @@ export
unsafe_ref,
unsafe_assign,
unsafe_pointer_to_objref,
pointer_from_objref,

# Macros
@b_str,
Expand Down
3 changes: 2 additions & 1 deletion base/pointer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ unsafe_assign(p::Ptr{Any}, x::ANY, i::Integer) = pointerset(p, x, int(i))
unsafe_assign{T}(p::Ptr{T}, x, i::Integer) = pointerset(p, convert(T, x), int(i))
unsafe_assign{T}(p::Ptr{T}, x) = unsafe_assign(p, convert(T,x), 1)

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

integer(x::Ptr) = convert(Uint, x)
unsigned(x::Ptr) = convert(Uint, x)
Expand Down
9 changes: 6 additions & 3 deletions doc/manual/calling-c-and-fortran-code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,15 @@ If T is Any, then the referenced memory is assumed to contain some
that the object was always visible to the garbage collector (pointers do not
count, but the new object does) to ensure the memory is not prematurely freed.
Note that if the object was not originally allocated by Julia, the new object
will never be finalized by Julia's garbage collector. If the `Ptr` itself
will never be finalized by Julia's garbage collector. If the ``Ptr`` itself
is actually a ``jl_value_t*``, it can be converted back to a Julia object
reference by ``unsafe_pointer_to_objref(ptr)``.
reference by ``unsafe_pointer_to_objref(ptr)``. [Julia values ``v``
can be converted to ``jl_value_t*`` pointers (``Ptr{Void}``) by calling
``pointer_from_objref(v)``.]

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

Any operation that throws an error is probably currently unimplemented
and should be posted as a bug so that it can be resolved.
Expand Down
4 changes: 2 additions & 2 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ static Value *emit_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ctx)
Value *thePtr = auto_unbox(e,ctx);
Value *idx = emit_unbox(T_size, T_psize, emit_unboxed(i, ctx));
Value *im1 = builder.CreateSub(idx, ConstantInt::get(T_size, 1));
if (!jl_is_bitstype(ety)) {
if (!jl_isbits(ety)) {
if (ety == (jl_value_t*)jl_any_type)
return builder.CreateLoad(builder.CreateGEP(
builder.CreateBitCast(thePtr, jl_ppvalue_llvmt),
Expand Down Expand Up @@ -438,7 +438,7 @@ static Value *emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_co
jl_value_t *xty = expr_type(x, ctx);
if (!jl_subtype(xty, ety, 0))
jl_error("pointerset: type mismatch in assign");
if (!jl_is_bitstype(ety)) {
if (!jl_isbits(ety)) {
jl_error("pointerset: invalid pointer type"); //ety = (jl_value_t*)jl_any_type;
}
if ((jl_datatype_t*)expr_type(i, ctx) != jl_long_type) {
Expand Down
14 changes: 14 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,20 @@ end

@test unsafe_pointer_to_objref(ccall(:jl_call1, Ptr{Void}, (Any,Any),
x -> x+1, 314158)) == 314159
@test unsafe_pointer_to_objref(pointer_from_objref(e+pi)) == e+pi

immutable FooBar
foo::Int
bar::Int
end
begin
local X, p
X = FooBar[ FooBar(3,1), FooBar(4,4) ]
p = convert(Ptr{FooBar}, X)
@test unsafe_ref(p, 2) == FooBar(4,4)
unsafe_assign(p, FooBar(7,3), 1)
@test X[1] == FooBar(7,3)
end

# issue #1287, combinations of try, catch, return
begin
Expand Down

0 comments on commit 645a65d

Please sign in to comment.