diff --git a/src/ccall.cpp b/src/ccall.cpp index a19d54c78d562..b23a8179e4288 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -603,7 +603,6 @@ static Value *julia_to_address(Type *to, jl_value_t *jlto, jl_unionall_t *jlto_e data_pointer(jvinfo, ctx, slot->getType()), (uint64_t)jl_datatype_size(ety), (uint64_t)jl_datatype_align(ety)); - mark_gc_use(jvinfo); } if (slot->getType() != to) slot = emit_bitcast(slot, to); @@ -642,7 +641,6 @@ static Value *julia_to_native(Type *to, bool toboxed, jl_value_t *jlto, jl_union data_pointer(jvinfo, ctx, slot->getType()), (uint64_t)jl_datatype_size(jlto), (uint64_t)jl_datatype_align(jlto)); - mark_gc_use(jvinfo); } return slot; } @@ -1021,7 +1019,6 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c Value *v = julia_to_native(t, toboxed, tti, NULL, arg, false, i, ctx, NULL); bool issigned = jl_signed_type && jl_subtype(tti, (jl_value_t*)jl_signed_type); - // make sure args are rooted argvals[i] = llvm_type_rewrite(v, t, issigned, ctx); } @@ -1134,22 +1131,9 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c f->setLinkage(GlobalValue::LinkOnceODRLinkage); } - // the actual call - builder.CreateCall(prepare_call(gcroot_flush_func)); - SmallVector gc_uses; - for (size_t i = 0; i < nargt; ++i) { - const jl_cgval_t &arg = argv[i]; - push_gc_use(gc_uses, arg); - } - // Mark GC use before **and** after the llvmcall to make sure the arguments - // are alive during the llvmcall even if the llvmcall has `unreachable`. - // If the llvmcall generates GC safepoint, it might need to emit its own - // gckill. - mark_gc_uses(gc_uses); CallInst *inst = builder.CreateCall(f, ArrayRef(&argvals[0], nargt)); if (isString) f->addFnAttr(Attribute::AlwaysInline); - mark_gc_uses(gc_uses); JL_GC_POP(); @@ -1859,14 +1843,15 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) jl_cgval_t &arg = argv[ai]; arg = emit_expr((jl_value_t*)argi, ctx); - push_gc_use(gc_uses, arg); // Julia (expression) value of current parameter gcroot jl_value_t *argi_root = args[i + 1]; if (jl_is_long(argi_root)) continue; jl_cgval_t arg_root = emit_expr(argi_root, ctx); - push_gc_use(gc_uses, arg_root); + Value *gcuse = arg_root.gcroot ? builder.CreateLoad(arg_root.gcroot) : arg_root.V; + if (gcuse) + gc_uses.push_back(gcuse); } function_sig_t sig(lrt, rt, retboxed, (jl_svec_t*)at, unionall, (nargs - 3) / 2, isVa, cc, llvmcall); @@ -2079,9 +2064,6 @@ jl_cgval_t function_sig_t::emit_a_ccall( } } - // Mark GC use before **and** after the ccall to make sure the arguments - // are alive during the ccall even if the function called is `noreturn`. - mark_gc_uses(gc_uses); OperandBundleDef OpBundle("jl_roots", gc_uses); // the actual call Value *ret = builder.CreateCall(prepare_call(llvmf), @@ -2101,9 +2083,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( ctx->f->addFnAttr(Attribute::StackProtectReq); } - mark_gc_uses(gc_uses); if (rt == jl_bottom_type) { - // Do this after we marked all the GC uses. CreateTrap(builder); return jl_cgval_t(); } diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 9ca01c96ddfe2..2e67daabf9fff 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -2099,10 +2099,6 @@ static Value *box_union(const jl_cgval_t &vinfo, jl_codectx_t *ctx, const SmallB builder.CreateUnreachable(); } else { - if (vinfo.gcroot && vinfo.V != vinfo.gcroot) { - // if this is a derived pointer, make sure the root usage itself is also visible to the delete-root pass - mark_gc_use(vinfo); - } // We're guaranteed here that Load(.gcroot) == .V, because we have determined // that this union is a boxed value, rather than an interior pointer of some sort box_merge->addIncoming(builder.CreateLoad(vinfo.gcroot), defaultBB); @@ -2216,10 +2212,6 @@ static void emit_unionmove(Value *dest, const jl_cgval_t &src, Value *skip, bool builder.CreateBr(postBB); } builder.SetInsertPoint(postBB); - if (src.gcroot && src.V != src.gcroot) { - // if this is a derived pointer, make sure the root usage itself is also visible to the delete-root pass - mark_gc_use(src); - } } else { Value *datatype = emit_typeof_boxed(src, ctx); @@ -2331,11 +2323,10 @@ static void emit_setfield(jl_datatype_t *sty, const jl_cgval_t &strct, size_t id ConstantInt::get(T_size, jl_field_offset(sty, idx0))); jl_value_t *jfty = jl_svecref(sty->types, idx0); if (jl_field_isptr(sty, idx0)) { - Value *r = maybe_decay_untracked(boxed(rhs, ctx, false)); // don't need a temporary gcroot since it'll be rooted by strct (but should ensure strct is rooted via mark_gc_use) + Value *r = maybe_decay_untracked(boxed(rhs, ctx, false)); // don't need a temporary gcroot since it'll be rooted by strct tbaa_decorate(strct.tbaa, builder.CreateStore(r, emit_bitcast(addr, T_pprjlvalue))); if (wb && strct.isboxed) emit_checked_write_barrier(ctx, boxed(strct, ctx), r); - mark_gc_use(strct); } else { int align = jl_field_offset(sty, idx0); diff --git a/src/codegen.cpp b/src/codegen.cpp index 35a83ed90d33b..5a2f61cbc528e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -354,9 +354,6 @@ static Function *jlarray_data_owner_func; static GlobalVariable *jlgetworld_global; // placeholder functions -static Function *gcroot_func; -static Function *gckill_func; -static Function *jlcall_frame_func; static Function *gcroot_flush_func; static Function *except_enter_func; static Function *pointer_from_objref_func; @@ -573,7 +570,6 @@ class jl_codectx_t { static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx); static Value *emit_local_root(jl_codectx_t *ctx, jl_varinfo_t *vi = NULL); -static void mark_gc_use(const jl_cgval_t &v); static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, jl_binding_t **pbnd, bool assign, jl_codectx_t *ctx); static jl_cgval_t emit_checked_var(Value *bp, jl_sym_t *name, jl_codectx_t *ctx, bool isvol, MDNode *tbaa); @@ -589,21 +585,6 @@ static Value *emit_jlcall(Value *theFptr, Value *theF, jl_cgval_t *args, static Value *emit_jlcall(Value *theFptr, Value *theF, jl_value_t **args, size_t nargs, jl_codectx_t *ctx); -template static void push_gc_use(T &&vec, const jl_cgval_t &v) -{ - if (v.gcroot) { - vec.push_back(v.gcroot); - } -} - -template static void mark_gc_uses(T &&vec) -{ - auto f = prepare_call(gckill_func); - for (auto &v: vec) { - builder.CreateCall(f, v); - } -} - // --- convenience functions for tagging llvm values with julia types --- static GlobalVariable *get_pointer_to_constant(Constant *val, StringRef name, Module &M) @@ -987,9 +968,6 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co } builder.CreateStore(newroot, froot); } - else { - mark_gc_use(v); - } if (v.V == NULL) { // v.V might be NULL if it was all ghost objects before return jl_cgval_t(boxv, froot, false, typ, new_tindex); @@ -2212,17 +2190,6 @@ static Value *emit_local_root(jl_codectx_t *ctx, jl_varinfo_t *vi) return newroot; } - -// Marks a use (and thus a potential kill) of a gcroot -// Note that if the operation that needs the root has terminating control flow -// (e.g. `unreachable`, `noreturn` functions) the use needs to be marked before -// the operation as well as after it. -static void mark_gc_use(const jl_cgval_t &v) -{ - if (v.gcroot) - builder.CreateCall(prepare_call(gckill_func), v.gcroot); -} - static void jl_add_method_root(jl_codectx_t *ctx, jl_value_t *val) { if (jl_is_leaf_type(val) || jl_is_bool(val) || jl_is_symbol(val) || @@ -2470,8 +2437,6 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, v2 = update_julia_type(v2, expr_type(args[2], ctx), ctx); // patch up typ if necessary // emit comparison test Value *ans = emit_f_is(v1, v2, ctx); - mark_gc_use(v1); - mark_gc_use(v2); *ret = mark_julia_type(builder.CreateZExt(ans, T_int8), false, jl_bool_type, ctx); JL_GC_POP(); return true; @@ -3097,7 +3062,6 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c break; } - SmallVector gc_uses; for (size_t i = 0; i < nargs + 1; i++) { jl_value_t *jt = jl_nth_slot_type(li->specTypes, i); bool isboxed; @@ -3121,7 +3085,6 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c jl_cgval_t arg = i == 0 ? theF : emit_expr(args[i], ctx); assert(arg.ispointer()); argvals[idx] = decay_derived(data_pointer(arg, ctx, at)); - push_gc_use(gc_uses, arg); } else { assert(at == et); @@ -3133,10 +3096,8 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c idx++; } assert(idx == nfargs); - mark_gc_uses(gc_uses); CallInst *call = builder.CreateCall(returninfo.decl, ArrayRef(&argvals[0], nfargs)); call->setAttributes(returninfo.decl->getAttributes()); - mark_gc_uses(gc_uses); jl_cgval_t retval; switch (returninfo.cc) { @@ -6739,24 +6700,6 @@ static void init_julia_llvm_env(Module *m) #endif add_named_global(jlarray_data_owner_func, jl_array_data_owner); - gcroot_func = - Function::Create(FunctionType::get(T_pprjlvalue, false), - Function::ExternalLinkage, - "julia.gc_root_decl"); - add_named_global(gcroot_func, (void*)NULL, /*dllimport*/false); - - gckill_func = - Function::Create(FunctionType::get(T_void, ArrayRef(T_pprjlvalue), false), - Function::ExternalLinkage, - "julia.gc_root_kill"); - add_named_global(gckill_func, (void*)NULL, /*dllimport*/false); - - jlcall_frame_func = - Function::Create(FunctionType::get(T_pprjlvalue, ArrayRef(T_int32), false), - Function::ExternalLinkage, - "julia.jlcall_frame_decl"); - add_named_global(jlcall_frame_func, (void*)NULL, /*dllimport*/false); - gcroot_flush_func = Function::Create(FunctionType::get(T_void, false), Function::ExternalLinkage, "julia.gcroot_flush"); diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 7211038633620..e6706c850a899 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -307,10 +307,6 @@ static Value *emit_unbox(Type *to, const jl_cgval_t &x, jl_value_t *jt, Value *d return NULL; } - // if this is a derived pointer, make sure the root usage itself is also visible to the delete-root pass - if (x.gcroot && x.V != x.gcroot) - mark_gc_use(x); - // bools stored as int8, so an extra Trunc is needed to get an int1 Value *p = x.constant ? literal_pointer_val(x.constant) : x.V; Type *ptype = (to == T_int1 ? T_pint8 : to->getPointerTo()); @@ -839,8 +835,6 @@ static jl_cgval_t emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, boxed(x, ctx)); } jl_value_t *jt = (t1 == t2 ? t1 : (jl_value_t*)jl_any_type); - mark_gc_use(x); - mark_gc_use(y); return mark_julia_type(ifelse_result, isboxed, jt, ctx); } diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index 72b258ab90d48..cd44a7c196a1d 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -297,7 +297,6 @@ struct LateLowerGCFrame: public FunctionPass { Type *T_size; Type *T_int32; MDNode *tbaa_gcframe; - Function *gc_kill_func; Function *ptls_getter; Function *gc_flush_func; Function *pointer_from_objref_func; @@ -1023,8 +1022,7 @@ bool LateLowerGCFrame::CleanupIR(Function &F) { continue; } CallingConv::ID CC = CI->getCallingConv(); - if ((gc_kill_func != nullptr && CI->getCalledFunction() == gc_kill_func) || - (gc_flush_func != nullptr && CI->getCalledFunction() == gc_flush_func)) { + if (gc_flush_func != nullptr && CI->getCalledFunction() == gc_flush_func) { /* No replacement */ } else if (pointer_from_objref_func != nullptr && CI->getCalledFunction() == pointer_from_objref_func) { @@ -1201,7 +1199,6 @@ void LateLowerGCFrame::PlaceRootsAndUpdateCalls(Function &F, std::vector &C bool LateLowerGCFrame::doInitialization(Module &M) { ptls_getter = M.getFunction("jl_get_ptls_states"); - gc_kill_func = M.getFunction("julia.gc_root_kill"); gc_flush_func = M.getFunction("julia.gcroot_flush"); pointer_from_objref_func = M.getFunction("julia.pointer_from_objref"); return false;