diff --git a/src/builtins.c b/src/builtins.c index 7834df6ff78fe8..9218ab294490cb 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -120,7 +120,6 @@ void jl_enter_handler(jl_handler_t *eh) #ifdef JL_GC_MARKSWEEP eh->gcstack = jl_pgcstack; #endif - eh->alloca_stack = jl_alloca_stack; jl_current_task->eh = eh; // TODO: this should really go after setjmp(). see comment in // ctx_switch in task.c. diff --git a/src/cgutils.cpp b/src/cgutils.cpp index b1c9733777d569..a95c3aea48d5d7 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -618,10 +618,12 @@ static bool has_julia_type(Value *v) static jl_value_t *julia_type_of_without_metadata(Value *v, bool err=true) { Type *T = v->getType(); - if (dyn_cast(v) != NULL || - dyn_cast(v) != NULL) { - // an alloca always has llvm type pointer - return llvm_type_to_julia(T->getContainedType(0), err); + if (T != jl_pvalue_llvmt) { + if (dyn_cast(v) != NULL || + dyn_cast(v) != NULL) { + // an alloca always has llvm type pointer + return llvm_type_to_julia(T->getContainedType(0), err); + } } return llvm_type_to_julia(T, err); } diff --git a/src/codegen.cpp b/src/codegen.cpp index c37421c60a6b4b..948ad62a8c030e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -268,7 +268,6 @@ static GlobalVariable *jlfloattemp_var; #ifdef JL_GC_MARKSWEEP static GlobalVariable *jlpgcstack_var; #endif -static GlobalVariable *jl_alloca_stack_var; static GlobalVariable *jlexc_var; static GlobalVariable *jldiverr_var; static GlobalVariable *jlundeferr_var; @@ -480,16 +479,14 @@ typedef struct { std::string funcName; jl_sym_t *vaName; // name of vararg argument bool vaStack; // varargs stack-allocated - bool uses_alloca; // uses alloca-based gc allocation int nReqArgs; int lineno; std::vector boundsCheck; #ifdef JL_GC_MARKSWEEP - Instruction *gcframe; + Instruction *gcframe ; Instruction *argSpaceInits; StoreInst *storeFrameSize; #endif - Instruction *alloca_frame; BasicBlock::iterator first_gcframe_inst; BasicBlock::iterator last_gcframe_inst; llvm::DIBuilder *dbuilder; @@ -1143,36 +1140,36 @@ static void simple_escape_analysis(jl_value_t *expr, bool varesc, bool envesc, j simple_escape_analysis(f, true, false, ctx); jl_value_t *fv = static_eval(f, ctx, false); if (fv) { - if (jl_typeis(fv, jl_intrinsic_type)) { - JL_I::intrinsic fi = (JL_I::intrinsic)jl_unbox_int32(fv); - if (fi == JL_I::ccall) { + if (jl_typeis(fv, jl_intrinsic_type)) { + JL_I::intrinsic fi = (JL_I::intrinsic)jl_unbox_int32(fv); + if (fi == JL_I::ccall) { varesc = true; envesc = local_var_occurs(jl_exprarg(e,3),jl_any_type->name->name); simple_escape_analysis(jl_exprarg(e,1), varesc, envesc, ctx); - // 2nd and 3d arguments are static + // 2nd and 3d arguments are static i = 4; - } + } else if (fi == JL_I::llvmcall) { varesc = true; envesc = false; // 1st, 2nd and 3d arguments are static i = 4; - } + } else { varesc = false; envesc = false; } } - else if (jl_is_function(fv)) { - jl_function_t *ff = (jl_function_t*)fv; - if (ff->fptr == jl_f_tuplelen || - ff->fptr == jl_f_tupleref || + else if (jl_is_function(fv)) { + jl_function_t *ff = (jl_function_t*)fv; + if (ff->fptr == jl_f_tuplelen || + ff->fptr == jl_f_tupleref || (ff->fptr == jl_f_apply && elen==3 && expr_type(jl_exprarg(e,1),ctx) == (jl_value_t*)jl_function_type && expr_type(jl_exprarg(e,2),ctx) == (jl_value_t*)jl_tuple_type)) { varesc = false; envesc = false; - } + } else if (ff->fptr == jl_f_arrayref || ff->fptr == jl_f_arraylen || ff->fptr == jl_f_get_field || @@ -1188,21 +1185,21 @@ static void simple_escape_analysis(jl_value_t *expr, bool varesc, bool envesc, j varesc = true; envesc = true; i = 2; - } + } else if (ff->fptr == jl_f_typeassert) { simple_escape_analysis(jl_exprarg(e,1), true, envesc, ctx); simple_escape_analysis(jl_exprarg(e,2), true, false, ctx); return; - } + } else if ( ff->fptr == jl_f_convert_default) { simple_escape_analysis(jl_exprarg(e,1), true, false, ctx); simple_escape_analysis(jl_exprarg(e,2), true, envesc, ctx); return; - } + } else { varesc = true; envesc = true; - } + } } else { varesc = true; @@ -1223,13 +1220,13 @@ static void simple_escape_analysis(jl_value_t *expr, bool varesc, bool envesc, j varesc = true; envesc = true; i = 1; - } + } else if (e->head == amp_sym) { i = 0; } else if (e->head == line_sym) { - return; - } + return; + } else { varesc = true; envesc = true; @@ -1949,12 +1946,8 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, tup = builder.CreateCall(prepare_call(jlallocobj_func), ConstantInt::get(T_size, sz)); } else { - tup = builder.CreateAlloca(T_pint8, ConstantInt::get(T_int32, 1+nwords)); - ctx->uses_alloca = true; - builder.CreateStore(builder.CreateLoad(prepare_global(jl_alloca_stack_var)), tup); - builder.CreateStore(builder.CreatePointerCast(tup,T_pint8), prepare_global(jl_alloca_stack_var)); - tup = builder.CreatePointerCast(builder.CreateConstGEP1_32(tup, 1), jl_pvalue_llvmt); - ((Instruction*)tup)->setMetadata("isAlloca", MDNode::get(jl_LLVMContext, ArrayRef())); + tup = builder.CreateAlloca(jl_value_llvmt, ConstantInt::get(T_int32, nwords)); + // assert( dyn_cast(tup) != NULL ); } #ifdef OVERLAP_TUPLE_LEN builder.CreateStore(arg1, emit_nthptr_addr(tup, 1)); @@ -2122,8 +2115,6 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, emit_expr(args[2],ctx,false,false); } else { - //Instruction *I = dyn_cast(ary); - //escapes = escapes || !I || !I->getMetadata("isAlloca"); typed_store(emit_arrayptr(ary,args[1],ctx), idx, ety == (jl_value_t*)jl_any_type ? emit_expr(args[2],ctx,true) : @@ -2231,8 +2222,6 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, Value *strct = emit_expr(args[1], ctx, false); Value *rhs; if (sty->fields[idx].isptr) { - //Instruction *I = dyn_cast(strct); - //escapes = escapes || !I || !I->getMetadata("isAlloca"); rhs = emit_expr(args[3], ctx, true); } else { @@ -2919,12 +2908,8 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool escapes, ConstantInt::get(T_size, sz)); } else { - strct = builder.CreateAlloca(T_pint8, ConstantInt::get(T_int32, 1+sz/sizeof(void*))); - ctx->uses_alloca = true; - builder.CreateStore(builder.CreateLoad(prepare_global(jl_alloca_stack_var)), strct); - builder.CreateStore(builder.CreatePointerCast(strct,T_pint8), prepare_global(jl_alloca_stack_var)); - strct = builder.CreatePointerCast(builder.CreateConstGEP1_32(strct, 1), jl_pvalue_llvmt); - ((Instruction*)strct)->setMetadata("isAlloca", MDNode::get(jl_LLVMContext, ArrayRef())); + strct = builder.CreateAlloca(jl_value_llvmt, ConstantInt::get(T_int32, sz/sizeof(void*))); + // assert( dyn_cast(strct) != NULL ); } builder.CreateStore(literal_pointer_val((jl_value_t*)ty), emit_nthptr_addr(strct, (size_t)0)); @@ -3176,7 +3161,6 @@ static void allocate_gc_frame(size_t n_roots, jl_codectx_t *ctx) ctx->argTemp = builder.CreateAlloca(jl_pvalue_llvmt, ConstantInt::get(T_int32, n_roots)); #endif - ctx->alloca_frame = builder.CreateLoad(prepare_global(jl_alloca_stack_var), false); } @@ -3210,8 +3194,6 @@ static void finalize_gc_frame(jl_codectx_t *ctx) il.erase(ctx->first_gcframe_inst, ctx->last_gcframe_inst); // erase() erases up *to* the end point; erase last inst too il.erase(ctx->last_gcframe_inst); - //if (!ctx->uses_alloca) - // il.erase(ctx->alloca_frame); for(size_t i=0; i < ctx->gc_frame_pops.size(); i++) { Instruction *pop = ctx->gc_frame_pops[i]; BasicBlock::InstListType &il2 = pop->getParent()->getInstList(); @@ -3250,10 +3232,6 @@ static void finalize_gc_frame(jl_codectx_t *ctx) after = new StoreInst(V_null, argTempi); instList.insertAfter(argTempi, after); } - //if (!ctx->uses_alloca) { - // BasicBlock::InstListType &il = ctx->gcframe->getParent()->getInstList(); - // il.erase(ctx->alloca_frame); - //} } } @@ -3330,7 +3308,6 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Funct ctx.gc_frame_pops.push_back(gcpop); builder.CreateStore(builder.CreateBitCast(builder.CreateLoad(gcpop, false), jl_ppvalue_llvmt), prepare_global(jlpgcstack_var)); - builder.CreateStore(ctx.alloca_frame, prepare_global(jl_alloca_stack_var)), finalize_gc_frame(&ctx); builder.CreateRet(r); @@ -4004,7 +3981,6 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) builder.CreateStore(builder.CreateBitCast(builder.CreateLoad(gcpop, false), jl_ppvalue_llvmt), prepare_global(jlpgcstack_var)); #endif - builder.CreateStore(ctx.alloca_frame, prepare_global(jl_alloca_stack_var)); if (do_malloc_log && lno != -1) mallocVisitLine(filename, lno); if (builder.GetInsertBlock()->getTerminator() == NULL) { @@ -4215,12 +4191,6 @@ static void init_julia_llvm_env(Module *m) NULL, "jl_pgcstack"); add_named_global(jlpgcstack_var, (void*)&jl_pgcstack); #endif - - jl_alloca_stack_var = - new GlobalVariable(*m, T_pint8, - false, GlobalVariable::ExternalLinkage, - NULL, "jl_alloca_stack"); - add_named_global(jl_alloca_stack_var, (void*)&jl_alloca_stack); global_to_llvm("__stack_chk_guard", (void*)&__stack_chk_guard, m); Function *jl__stack_chk_fail = diff --git a/src/gc.c b/src/gc.c index 4d111d8749a61e..d489ef80a3e997 100644 --- a/src/gc.c +++ b/src/gc.c @@ -637,7 +637,7 @@ static size_t mark_stack_size = 0; static size_t mark_sp = 0; static struct { - void* *s; + jl_gcframe_t *s; ptrint_t offset; } *marked_stacks; static size_t marked_stacks_size = 0; @@ -656,18 +656,42 @@ static void gc_unmark_stacks() { size_t i; for (i = 0; i < marked_stacks_sp; i++) { - void* *s = marked_stacks[i].s; + jl_gcframe_t *s = marked_stacks[i].s; ptrint_t offset = marked_stacks[i].offset; while (s != NULL) { - s = (void**)((char*)s + offset); - gc_clrmark(s+1); - s = (void**)(*s); + s = (jl_gcframe_t*)((char*)s + offset); + jl_value_t ***rts = (jl_value_t***)(((void**)s)+2); + size_t nr = s->nroots>>1; + if (s->nroots & 1) { + for(size_t i=0; i < nr; i++) { + jl_value_t **ptr = (jl_value_t**)((char*)rts[i] + offset); + if (*ptr != NULL && gc_marked(*ptr)) + gc_clrmark(*ptr); + } + } + else { + for(size_t i=0; i < nr; i++) { + if (rts[i] != NULL && gc_marked(rts[i])) + gc_clrmark(rts[i]); + } + } + s = s->prev; } } } static void gc_mark_stack(jl_gcframe_t *s, ptrint_t offset, int d) { + if (marked_stacks_sp >= marked_stacks_size) { + size_t newsz = marked_stacks_size>0 ? marked_stacks_size*2 : 8; + marked_stacks = (typeof(marked_stacks))realloc(marked_stacks,newsz*sizeof(*marked_stacks)); + if (marked_stacks == NULL) exit(1); + marked_stacks_size = newsz; + } + marked_stacks[marked_stacks_sp].s = s; + marked_stacks[marked_stacks_sp].offset = offset; + marked_stacks_sp++; + while (s != NULL) { s = (jl_gcframe_t*)((char*)s + offset); jl_value_t ***rts = (jl_value_t***)(((void**)s)+2); @@ -727,32 +751,17 @@ static void gc_mark_task(jl_task_t *ta, int d) if (ta->stkbuf != NULL || ta == jl_current_task) { if (ta->stkbuf != NULL) gc_setmark_buf(ta->stkbuf); - if (marked_stacks_sp >= marked_stacks_size) { - size_t newsz = marked_stacks_size>0 ? marked_stacks_size*2 : 8; - marked_stacks = (typeof(marked_stacks))realloc(marked_stacks,newsz*sizeof(*marked_stacks)); - if (marked_stacks == NULL) exit(1); - marked_stacks_size = newsz; - } #ifdef COPY_STACKS ptrint_t offset; if (ta == jl_current_task) { offset = 0; - marked_stacks[marked_stacks_sp].s = jl_alloca_stack; - marked_stacks[marked_stacks_sp].offset = offset; - marked_stacks_sp++; gc_mark_stack(jl_pgcstack, offset, d); } else { offset = (char *)ta->stkbuf - ((char *)ta->stackbase - ta->ssize); - marked_stacks[marked_stacks_sp].s = ta->alloca_stack; - marked_stacks[marked_stacks_sp].offset = offset; - marked_stacks_sp++; gc_mark_stack(ta->gcstack, offset, d); } #else - marked_stacks[marked_stacks_sp].s = ta->alloca_stack; - marked_stacks[marked_stacks_sp].offset = offset; - marked_stacks_sp++; gc_mark_stack(ta->gcstack, 0, d); #endif } diff --git a/src/julia.h b/src/julia.h index 2d35708e5d6d32..ad198304759507 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1022,7 +1022,6 @@ typedef struct _jl_gcframe_t { // x = f(); y = g(); foo(x, y); JL_GC_POP(); extern DLLEXPORT jl_gcframe_t *jl_pgcstack; -extern DLLEXPORT void** jl_alloca_stack; #define JL_GC_PUSH(...) \ void *__gc_stkf[] = {(void*)((VA_NARG(__VA_ARGS__)<<1)|1), jl_pgcstack, \ @@ -1129,7 +1128,6 @@ typedef struct _jl_handler_t { #ifdef JL_GC_MARKSWEEP jl_gcframe_t *gcstack; #endif - void* *alloca_stack; struct _jl_handler_t *prev; } jl_handler_t; @@ -1158,7 +1156,6 @@ typedef struct _jl_task_t { jl_handler_t *eh; // saved gc stack top for context switches jl_gcframe_t *gcstack; - void* *alloca_stack; // current module, or NULL if this task has not set one jl_module_t *current_module; } jl_task_t; @@ -1181,7 +1178,6 @@ STATIC_INLINE void jl_eh_restore_state(jl_handler_t *eh) #ifdef JL_GC_MARKSWEEP jl_pgcstack = eh->gcstack; #endif - jl_alloca_stack = eh->alloca_stack; JL_SIGATOMIC_END(); } diff --git a/src/task.c b/src/task.c index 7dd436371bda02..627fb835156793 100644 --- a/src/task.c +++ b/src/task.c @@ -153,7 +153,6 @@ jl_value_t *jl_exception_in_transit; #ifdef JL_GC_MARKSWEEP jl_gcframe_t *jl_pgcstack = NULL; #endif -void* *jl_alloca_stack = NULL; static void start_task(jl_task_t *t); @@ -247,8 +246,6 @@ static void ctx_switch(jl_task_t *t, jl_jmp_buf *where) jl_current_task->gcstack = jl_pgcstack; jl_pgcstack = t->gcstack; #endif - jl_current_task->alloca_stack = jl_alloca_stack; - jl_alloca_stack = t->alloca_stack; // restore task's current module, looking at parent tasks // if it hasn't set one. @@ -787,7 +784,6 @@ jl_task_t *jl_new_task(jl_function_t *start, size_t ssize) #ifdef JL_GC_MARKSWEEP t->gcstack = NULL; #endif - t->alloca_stack = NULL; t->stkbuf = NULL; #ifdef COPY_STACKS