diff --git a/base/boot.jl b/base/boot.jl index dd5a425add0a9..fe360e128d31a 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -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) diff --git a/base/strings/string.jl b/base/strings/string.jl index 4b43c2a4d7b44..42296c4fa9ad1 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -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) """ @@ -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))) @@ -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 @@ -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] @@ -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) @@ -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 @@ -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 "" @@ -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) diff --git a/src/ccall.cpp b/src/ccall.cpp index 01f622623db34..046827aff214e 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -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); diff --git a/src/codegen.cpp b/src/codegen.cpp index 24f62d52f04e4..2f03581ecbfd1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -357,6 +357,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; @@ -6489,6 +6490,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(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(PointerType::get(T_jlvalue, AddressSpace::Derived)), false), Function::ExternalLinkage, diff --git a/src/julia.h b/src/julia.h index 5fda2e5415f25..c56d28b5f4f8a 100644 --- a/src/julia.h +++ b/src/julia.h @@ -648,6 +648,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); diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index dc77551d192c3..431c1a27550ec 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -320,6 +320,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; @@ -745,7 +746,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; } } @@ -1137,7 +1139,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), @@ -1405,6 +1408,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); diff --git a/src/rtutils.c b/src/rtutils.c index a2385e24dd364..748c308d9d0a4 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -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 --------------------------------------------------------------------