Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: extend unsafe_assign to work for any isbits type, add pointer_from_objref #2515

Merged
merged 3 commits into from
Mar 8, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
@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