-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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: change lowering of ccall cconvert arguments and add Ref{T} type #9986
Conversation
Overall this is really good. I think we can rename |
yeah, it may make more sense to just use SubArray instead. part of the intent of this PR is that you can replace most usages of there is one meaningful cconvert call, which is |
Yes, the fact that I'm not sure it's worth trying to replace Ptr with Ref. A Ref is not a pointer, and is not as efficient as a pointer, so nobody will be fooled. |
but a |
@@ -6,6 +6,17 @@ typealias AbstractVecOrMat{T} Union(AbstractVector{T}, AbstractMatrix{T}) | |||
|
|||
## Basic functions ## | |||
|
|||
# convert Arrays to pointer arrays for ccall | |||
cconvert_gcroot{P<:Ptr}(::Type{Ptr{P}}, a::Array{P}) = a | |||
function cconvert_gcroot{P<:Ptr}(::Type{Ptr{P}}, a::Array) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should go in array.jl as it is Array-specific.
actually, there might be a few more useful calls for the method currently named |
i'm more concerned about whether it remains valid under all code transforms. for example, in the following somewhat-contrived example, the string has become unrooted by the time it reached function f() = g("hello world")
g(x) = i(h(x))
@noinline h(x) = pointer(x)
@noinline i(x) = ccall(:write, Cint, (Ptr{Uint8},), x) |
But if you can still call |
true, but i would suggest most usages of |
do you want me to merge this separately, or is it acceptable if I continue this under #7906 and interleave these two changes when it gets merge |
@@ -100,6 +101,7 @@ end | |||
function study(regex::Ptr{Void}, options::Integer) | |||
# NOTE: options should always be zero in current PCRE | |||
errstr = Array(Ptr{UInt8},1) | |||
errstr[1] = C_NULL | |||
extra = ccall((:pcre_study, :libpcre), Ptr{Void}, | |||
(Ptr{Void}, Int32, Ptr{Ptr{UInt8}}), | |||
regex, options, errstr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like bug fixes in this file? Could you apply these to master?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not exactly a bug. Pcre should zero this field, but I had errors in the way I lowered ccall and this helped me get further
52ce45a
to
0904f36
Compare
i think this is ready to merge once CI checks pass |
hm, i'm not really sure why travis linux is the only place this PR seems to fail |
Looks like one of those mysterious hangs. Heck, if it even works on windows, it must be right, right? :) |
|
return Any | ||
end | ||
t = rt.parameters[1] | ||
if isa(t,DataType) && is((t::DataType).name,Ref.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does it mean if a ccall returns a Ref
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See gist or doc updates on the jn/ccall3 PR. Some of these updates are primarily only meaningful in that context
that sounds great, but it seemed to happen on every commit build, so i don't know what to make of it or how to repeat it edit: restarted again and it still failed. note that the missing tests appear to be |
b667509
to
4cd0665
Compare
now that I found the bug (affecting travis, but not source builds) and fixed it in fdad916, i should be able to merge this now, pending a green-light from travis
perhaps, but that was sort of the point of deleting them
it's written, and will merged as part of #7906
do you want me to change the names of any of these methods ( |
@@ -3244,21 +3244,26 @@ void jl_init_types(void) | |||
jl_any_type, jl_null, 32); | |||
|
|||
tv = jl_tuple1(tvar("T")); | |||
jl_ref_type = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JeffBezanson should we explicitly disable gc in this jl_init_types
function? it would be bad if it somehow ran, even though it shouldn't have managed to allocate that much memory by here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GC is already disabled at this point in the init process. I guess we could assert at the top of the function that GC is disabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nah, just wanted to make sure i wasn't missing something
I don't think we can just sneak in removing all these conversions to Ptr. cc @StefanKarpinski @ViralBShah Also, |
Part of the problem with the name is that in reality, |
But As it stands, this has ccall depend on four functions plus |
But you are proposing making more garbage Ref objects to avoid defining one functio no? (Also, I don't count the ptr_arg functions since this will also deprecate all that machinery) |
Not necessarily. For objects like |
But what would convert(::String) return? Plus that means I need to add another variable to hold your new proposed gc root |
Converting a string could return a Ref to the Vector{UInt8} inside a ByteString. Wouldn't this be the same variable currently used for |
that is true for ByteString, but it doesn't generalize particularly well. for example, what would you do for |
a7acb50
to
dad34a7
Compare
Base.getindex(b::RefArray) = b.x[b.i] | ||
|
||
Base.setindex!(b::RefValue, x) = (b.x = x; b) | ||
Base.setindex!(b::RefArray, x) = (b.x[b.i] = x; b) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should i undefine the setindex!
operation for a RefArray with roots? thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes definitely. Arguably getindex is not needed either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, there does need to be some way of turning a Ref
back into a value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i was thinking more along the lines of adding:
Base.setindex!{T}(b::RefArray{T,Void}, x) = (b.x[b.i] = x; b)
Base.setindex!{T}(b::RefArray{T}, x) = error("this Ref has associated GC-roots and does not know how to do setindex! for them")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1
I don't know why you'd need to setindex through a ref, and if you did that error message is pretty scary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to set an initial value, or populate an output of a function call, if used as an output argument
ccall(:a, B, (C,), d) is now lowered as: d#1 = cconvert_gcroot(C, d) Expr(:call, :ccall, :a, B, (C,), cconvert(C, d#1), d#1) This allows implementation of the special-case ccall lowering logic in Julia and still create a gcroot for it as needed the Ref{T} type is the new supertype of Ptr{T}. the ccall emission turns a Ref{T} into a Ptr{T}, as if the &addressOf operator had been applied. the specific rules for this will be moved from the current gist to the documentation at a later point.
… required references
dad34a7
to
3659629
Compare
this is mostly just waiting for CI to turn green to merge now |
3659629
to
721f3e2
Compare
this also makes changes such that cconvert is mostly unchanged from its functionality before this change. cconvert is expected to typically call convert. in some cases (such as when intending to create a Ptr for C-compatiblity), it should defer the actual unsafe step of making the Ptr to unsafe_convert. any code intending to allow conversion of an object to a Ptr should define the operation as a method of unsafe_convert after this commit, rather than the current behavior of making them a method of convert
change lowering of ccall cconvert arguments to provide user flexibility in the final convert step in ccall, and add Ref{T} type for general-purpose output argument usage
Maybe we should remove the |
This seems to make the system image significantly larger (more than 1MB, about 6%). Probably due to the lowering of ccall I'd guess. |
that's probably true. i removed the |
i'm on board with that, although it would need to be deprecated for a time first |
I wouldn't have thought the increase was due to |
perhaps not then. the lowering of |
continuation of #9913, but targeted for merging into master
(note: this is part of the implementation of Julep https://gist.github.com/vtjnash/7296634)