Skip to content

Commit

Permalink
Merge pull request #23562 from JuliaLang/kf/gcuse
Browse files Browse the repository at this point in the history
Add gc use intrinisic
  • Loading branch information
Keno authored Sep 3, 2017
2 parents 9cdec25 + 797e87b commit 7e2e6c9
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 17 deletions.
2 changes: 2 additions & 0 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -438,4 +438,6 @@ show(@nospecialize a) = show(STDOUT, a)
print(@nospecialize a...) = print(STDOUT, a...)
println(@nospecialize a...) = println(STDOUT, a...)

gcuse(@nospecialize a) = ccall(:jl_gc_use, Void, (Any,), a)

ccall(:jl_set_istopmod, Void, (Any, Bool), Core, true)
33 changes: 18 additions & 15 deletions base/strings/string.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ String(s::Symbol) = unsafe_string(Cstring(s))
pointer(s::String) = unsafe_convert(Ptr{UInt8}, s)
pointer(s::String, i::Integer) = pointer(s)+(i-1)

function unsafe_load(s::String, i::Integer=1)
ptr = pointer(s, i)
r = unsafe_load(ptr)
Core.gcuse(s)
r
end

sizeof(s::String) = Core.sizeof(s)

"""
Expand All @@ -73,7 +80,7 @@ codeunit(s::AbstractString, i::Integer)
@boundscheck if (i < 1) | (i > sizeof(s))
throw(BoundsError(s,i))
end
unsafe_load(pointer(s),i)
unsafe_load(s, i)
end

write(io::IO, s::String) = unsafe_write(io, pointer(s), reinterpret(UInt, sizeof(s)))
Expand Down Expand Up @@ -160,26 +167,24 @@ const utf8_trailing = [
## required core functionality ##

function endof(s::String)
p = pointer(s)
i = sizeof(s)
while i > 0 && is_valid_continuation(unsafe_load(p,i))
while i > 0 && is_valid_continuation(unsafe_load(s, i))
i -= 1
end
i
end

function length(s::String)
p = pointer(s)
cnum = 0
for i = 1:sizeof(s)
cnum += !is_valid_continuation(unsafe_load(p,i))
cnum += !is_valid_continuation(unsafe_load(s, i))
end
cnum
end

@noinline function slow_utf8_next(p::Ptr{UInt8}, b::UInt8, i::Int, l::Int)
@noinline function slow_utf8_next(s::String, b::UInt8, i::Int, l::Int)
if is_valid_continuation(b)
throw(UnicodeError(UTF_ERR_INVALID_INDEX, i, unsafe_load(p,i)))
throw(UnicodeError(UTF_ERR_INVALID_INDEX, i, unsafe_load(s, i)))
end
trailing = utf8_trailing[b + 1]
if l < i + trailing
Expand All @@ -188,7 +193,7 @@ end
c::UInt32 = 0
for j = 1:(trailing + 1)
c <<= 6
c += unsafe_load(p,i)
c += unsafe_load(s, i)
i += 1
end
c -= utf8_offset[trailing + 1]
Expand All @@ -206,12 +211,11 @@ done(s::String, state) = state > sizeof(s)
@boundscheck if (i < 1) | (i > sizeof(s))
throw(BoundsError(s,i))
end
p = pointer(s)
b = unsafe_load(p, i)
b = unsafe_load(s, i)
if b < 0x80
return Char(b), i + 1
end
return slow_utf8_next(p, b, i, sizeof(s))
return slow_utf8_next(s, b, i, sizeof(s))
end

function first_utf8_byte(ch::Char)
Expand All @@ -225,8 +229,7 @@ end

function reverseind(s::String, i::Integer)
j = sizeof(s) + 1 - i
p = pointer(s)
while is_valid_continuation(unsafe_load(p,j))
while is_valid_continuation(unsafe_load(s, j))
j -= 1
end
return j
Expand All @@ -235,7 +238,7 @@ end
## overload methods for efficiency ##

isvalid(s::String, i::Integer) =
(1 <= i <= sizeof(s)) && !is_valid_continuation(unsafe_load(pointer(s),i))
(1 <= i <= sizeof(s)) && !is_valid_continuation(unsafe_load(s, i))

function getindex(s::String, r::UnitRange{Int})
isempty(r) && return ""
Expand Down Expand Up @@ -438,7 +441,7 @@ function repeat(s::String, r::Integer)
n = sizeof(s)
out = _string_n(n*r)
if n == 1 # common case: repeating a single ASCII char
ccall(:memset, Ptr{Void}, (Ptr{UInt8}, Cint, Csize_t), out, unsafe_load(pointer(s)), r)
ccall(:memset, Ptr{Void}, (Ptr{UInt8}, Cint, Csize_t), out, unsafe_load(s), r)
else
for i=1:r
unsafe_copy!(pointer(out, 1+(i-1)*n), pointer(s), n)
Expand Down
7 changes: 7 additions & 0 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1687,6 +1687,13 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
emit_signal_fence(ctx);
return ghostValue(jl_void_type);
}
else if (is_libjulia_func(jl_gc_use)) {
assert(lrt == T_void);
assert(!isVa && !llvmcall && nargt == 1);
ctx.builder.CreateCall(prepare_call(gc_use_func), {decay_derived(boxed(ctx, argv[0]))});
JL_GC_POP();
return ghostValue(jl_void_type);
}
else if (_is_libjulia_func((uintptr_t)ptls_getter, "jl_get_ptls_states")) {
assert(lrt == T_pint8);
assert(!isVa && !llvmcall && nargt == 0);
Expand Down
7 changes: 7 additions & 0 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ static GlobalVariable *jlgetworld_global;

// placeholder functions
static Function *gcroot_flush_func;
static Function *gc_use_func;
static Function *except_enter_func;
static Function *pointer_from_objref_func;

Expand Down Expand Up @@ -6488,6 +6489,12 @@ static void init_julia_llvm_env(Module *m)
"julia.gcroot_flush");
add_named_global(gcroot_flush_func, (void*)NULL, /*dllimport*/false);

gc_use_func = Function::Create(FunctionType::get(T_void,
ArrayRef<Type*>(PointerType::get(T_jlvalue, AddressSpace::Derived)), false),
Function::ExternalLinkage,
"julia.gc_use");
add_named_global(gc_use_func, (void*)NULL, /*dllimport*/false);

pointer_from_objref_func = Function::Create(FunctionType::get(T_pjlvalue,
ArrayRef<Type*>(PointerType::get(T_jlvalue, AddressSpace::Derived)), false),
Function::ExternalLinkage,
Expand Down
1 change: 1 addition & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ JL_DLLEXPORT jl_value_t *jl_gc_alloc_1w(void);
JL_DLLEXPORT jl_value_t *jl_gc_alloc_2w(void);
JL_DLLEXPORT jl_value_t *jl_gc_alloc_3w(void);
JL_DLLEXPORT jl_value_t *jl_gc_allocobj(size_t sz);
JL_DLLEXPORT void jl_gc_use(jl_value_t *a);

JL_DLLEXPORT void jl_clear_malloc_data(void);

Expand Down
8 changes: 6 additions & 2 deletions src/llvm-late-gc-lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ struct LateLowerGCFrame: public FunctionPass {
MDNode *tbaa_tag;
Function *ptls_getter;
Function *gc_flush_func;
Function *gc_use_func;
Function *pointer_from_objref_func;
Function *alloc_obj_func;
Function *pool_alloc_func;
Expand Down Expand Up @@ -758,7 +759,8 @@ State LateLowerGCFrame::LocalScan(Function &F) {
}
if (auto callee = CI->getCalledFunction()) {
// Known functions emitted in codegen that are not safepoints
if (callee == pointer_from_objref_func || callee->getName() == "memcmp") {
if (callee == pointer_from_objref_func || callee == gc_use_func ||
callee->getName() == "memcmp") {
continue;
}
}
Expand Down Expand Up @@ -1150,7 +1152,8 @@ bool LateLowerGCFrame::CleanupIR(Function &F) {
}
CallingConv::ID CC = CI->getCallingConv();
auto callee = CI->getCalledValue();
if (gc_flush_func != nullptr && callee == gc_flush_func) {
if ((gc_flush_func != nullptr && callee == gc_flush_func) ||
(gc_use_func != nullptr && callee == gc_use_func)) {
/* No replacement */
} else if (pointer_from_objref_func != nullptr && callee == pointer_from_objref_func) {
auto *ASCI = new AddrSpaceCastInst(CI->getOperand(0),
Expand Down Expand Up @@ -1418,6 +1421,7 @@ static void addRetNoAlias(Function *F)
bool LateLowerGCFrame::doInitialization(Module &M) {
ptls_getter = M.getFunction("jl_get_ptls_states");
gc_flush_func = M.getFunction("julia.gcroot_flush");
gc_use_func = M.getFunction("julia.gc_use");
pointer_from_objref_func = M.getFunction("julia.pointer_from_objref");
auto &ctx = M.getContext();
T_size = M.getDataLayout().getIntPtrType(ctx);
Expand Down
4 changes: 4 additions & 0 deletions src/rtutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ JL_DLLEXPORT jl_value_t *jl_value_ptr(jl_value_t *a)
{
return a;
}
JL_DLLEXPORT void jl_gc_use(jl_value_t *a)
{
(void)a;
}

// parsing --------------------------------------------------------------------

Expand Down

0 comments on commit 7e2e6c9

Please sign in to comment.