Skip to content

Commit 2a922d9

Browse files
committed
this reverts giving alloca it's own stack, and simply reuses the existing gc frame
1 parent cebf733 commit 2a922d9

File tree

6 files changed

+58
-86
lines changed

6 files changed

+58
-86
lines changed

src/builtins.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ void jl_enter_handler(jl_handler_t *eh)
120120
#ifdef JL_GC_MARKSWEEP
121121
eh->gcstack = jl_pgcstack;
122122
#endif
123-
eh->alloca_stack = jl_alloca_stack;
124123
jl_current_task->eh = eh;
125124
// TODO: this should really go after setjmp(). see comment in
126125
// ctx_switch in task.c.

src/cgutils.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -618,10 +618,12 @@ static bool has_julia_type(Value *v)
618618
static jl_value_t *julia_type_of_without_metadata(Value *v, bool err=true)
619619
{
620620
Type *T = v->getType();
621-
if (dyn_cast<AllocaInst>(v) != NULL ||
622-
dyn_cast<GetElementPtrInst>(v) != NULL) {
623-
// an alloca always has llvm type pointer
624-
return llvm_type_to_julia(T->getContainedType(0), err);
621+
if (T != jl_pvalue_llvmt) {
622+
if (dyn_cast<AllocaInst>(v) != NULL ||
623+
dyn_cast<GetElementPtrInst>(v) != NULL) {
624+
// an alloca always has llvm type pointer
625+
return llvm_type_to_julia(T->getContainedType(0), err);
626+
}
625627
}
626628
return llvm_type_to_julia(T, err);
627629
}

src/codegen.cpp

Lines changed: 23 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ static GlobalVariable *jlfloattemp_var;
268268
#ifdef JL_GC_MARKSWEEP
269269
static GlobalVariable *jlpgcstack_var;
270270
#endif
271-
static GlobalVariable *jl_alloca_stack_var;
272271
static GlobalVariable *jlexc_var;
273272
static GlobalVariable *jldiverr_var;
274273
static GlobalVariable *jlundeferr_var;
@@ -480,16 +479,14 @@ typedef struct {
480479
std::string funcName;
481480
jl_sym_t *vaName; // name of vararg argument
482481
bool vaStack; // varargs stack-allocated
483-
bool uses_alloca; // uses alloca-based gc allocation
484482
int nReqArgs;
485483
int lineno;
486484
std::vector<bool> boundsCheck;
487485
#ifdef JL_GC_MARKSWEEP
488-
Instruction *gcframe;
486+
Instruction *gcframe ;
489487
Instruction *argSpaceInits;
490488
StoreInst *storeFrameSize;
491489
#endif
492-
Instruction *alloca_frame;
493490
BasicBlock::iterator first_gcframe_inst;
494491
BasicBlock::iterator last_gcframe_inst;
495492
llvm::DIBuilder *dbuilder;
@@ -1143,36 +1140,36 @@ static void simple_escape_analysis(jl_value_t *expr, bool varesc, bool envesc, j
11431140
simple_escape_analysis(f, true, false, ctx);
11441141
jl_value_t *fv = static_eval(f, ctx, false);
11451142
if (fv) {
1146-
if (jl_typeis(fv, jl_intrinsic_type)) {
1147-
JL_I::intrinsic fi = (JL_I::intrinsic)jl_unbox_int32(fv);
1148-
if (fi == JL_I::ccall) {
1143+
if (jl_typeis(fv, jl_intrinsic_type)) {
1144+
JL_I::intrinsic fi = (JL_I::intrinsic)jl_unbox_int32(fv);
1145+
if (fi == JL_I::ccall) {
11491146
varesc = true;
11501147
envesc = local_var_occurs(jl_exprarg(e,3),jl_any_type->name->name);
11511148
simple_escape_analysis(jl_exprarg(e,1), varesc, envesc, ctx);
1152-
// 2nd and 3d arguments are static
1149+
// 2nd and 3d arguments are static
11531150
i = 4;
1154-
}
1151+
}
11551152
else if (fi == JL_I::llvmcall) {
11561153
varesc = true;
11571154
envesc = false;
11581155
// 1st, 2nd and 3d arguments are static
11591156
i = 4;
1160-
}
1157+
}
11611158
else {
11621159
varesc = false;
11631160
envesc = false;
11641161
}
11651162
}
1166-
else if (jl_is_function(fv)) {
1167-
jl_function_t *ff = (jl_function_t*)fv;
1168-
if (ff->fptr == jl_f_tuplelen ||
1169-
ff->fptr == jl_f_tupleref ||
1163+
else if (jl_is_function(fv)) {
1164+
jl_function_t *ff = (jl_function_t*)fv;
1165+
if (ff->fptr == jl_f_tuplelen ||
1166+
ff->fptr == jl_f_tupleref ||
11701167
(ff->fptr == jl_f_apply && elen==3 &&
11711168
expr_type(jl_exprarg(e,1),ctx) == (jl_value_t*)jl_function_type &&
11721169
expr_type(jl_exprarg(e,2),ctx) == (jl_value_t*)jl_tuple_type)) {
11731170
varesc = false;
11741171
envesc = false;
1175-
}
1172+
}
11761173
else if (ff->fptr == jl_f_arrayref ||
11771174
ff->fptr == jl_f_arraylen ||
11781175
ff->fptr == jl_f_get_field ||
@@ -1188,21 +1185,21 @@ static void simple_escape_analysis(jl_value_t *expr, bool varesc, bool envesc, j
11881185
varesc = true;
11891186
envesc = true;
11901187
i = 2;
1191-
}
1188+
}
11921189
else if (ff->fptr == jl_f_typeassert) {
11931190
simple_escape_analysis(jl_exprarg(e,1), true, envesc, ctx);
11941191
simple_escape_analysis(jl_exprarg(e,2), true, false, ctx);
11951192
return;
1196-
}
1193+
}
11971194
else if ( ff->fptr == jl_f_convert_default) {
11981195
simple_escape_analysis(jl_exprarg(e,1), true, false, ctx);
11991196
simple_escape_analysis(jl_exprarg(e,2), true, envesc, ctx);
12001197
return;
1201-
}
1198+
}
12021199
else {
12031200
varesc = true;
12041201
envesc = true;
1205-
}
1202+
}
12061203
}
12071204
else {
12081205
varesc = true;
@@ -1223,13 +1220,13 @@ static void simple_escape_analysis(jl_value_t *expr, bool varesc, bool envesc, j
12231220
varesc = true;
12241221
envesc = true;
12251222
i = 1;
1226-
}
1223+
}
12271224
else if (e->head == amp_sym) {
12281225
i = 0;
12291226
}
12301227
else if (e->head == line_sym) {
1231-
return;
1232-
}
1228+
return;
1229+
}
12331230
else {
12341231
varesc = true;
12351232
envesc = true;
@@ -1949,12 +1946,8 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs,
19491946
tup = builder.CreateCall(prepare_call(jlallocobj_func),
19501947
ConstantInt::get(T_size, sz));
19511948
} else {
1952-
tup = builder.CreateAlloca(T_pint8, ConstantInt::get(T_int32, 1+nwords));
1953-
ctx->uses_alloca = true;
1954-
builder.CreateStore(builder.CreateLoad(prepare_global(jl_alloca_stack_var)), tup);
1955-
builder.CreateStore(builder.CreatePointerCast(tup,T_pint8), prepare_global(jl_alloca_stack_var));
1956-
tup = builder.CreatePointerCast(builder.CreateConstGEP1_32(tup, 1), jl_pvalue_llvmt);
1957-
((Instruction*)tup)->setMetadata("isAlloca", MDNode::get(jl_LLVMContext, ArrayRef<Value*>()));
1949+
tup = builder.CreateAlloca(jl_value_llvmt, ConstantInt::get(T_int32, nwords));
1950+
// assert( dyn_cast<AllocaInst>(tup) != NULL );
19581951
}
19591952
#ifdef OVERLAP_TUPLE_LEN
19601953
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,
21222115
emit_expr(args[2],ctx,false,false);
21232116
}
21242117
else {
2125-
//Instruction *I = dyn_cast<Instruction>(ary);
2126-
//escapes = escapes || !I || !I->getMetadata("isAlloca");
21272118
typed_store(emit_arrayptr(ary,args[1],ctx), idx,
21282119
ety == (jl_value_t*)jl_any_type ?
21292120
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,
22312222
Value *strct = emit_expr(args[1], ctx, false);
22322223
Value *rhs;
22332224
if (sty->fields[idx].isptr) {
2234-
//Instruction *I = dyn_cast<Instruction>(strct);
2235-
//escapes = escapes || !I || !I->getMetadata("isAlloca");
22362225
rhs = emit_expr(args[3], ctx, true);
22372226
}
22382227
else {
@@ -2919,12 +2908,8 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool escapes,
29192908
ConstantInt::get(T_size, sz));
29202909
}
29212910
else {
2922-
strct = builder.CreateAlloca(T_pint8, ConstantInt::get(T_int32, 1+sz/sizeof(void*)));
2923-
ctx->uses_alloca = true;
2924-
builder.CreateStore(builder.CreateLoad(prepare_global(jl_alloca_stack_var)), strct);
2925-
builder.CreateStore(builder.CreatePointerCast(strct,T_pint8), prepare_global(jl_alloca_stack_var));
2926-
strct = builder.CreatePointerCast(builder.CreateConstGEP1_32(strct, 1), jl_pvalue_llvmt);
2927-
((Instruction*)strct)->setMetadata("isAlloca", MDNode::get(jl_LLVMContext, ArrayRef<Value*>()));
2911+
strct = builder.CreateAlloca(jl_value_llvmt, ConstantInt::get(T_int32, sz/sizeof(void*)));
2912+
// assert( dyn_cast<AllocaInst>(strct) != NULL );
29282913
}
29292914
builder.CreateStore(literal_pointer_val((jl_value_t*)ty),
29302915
emit_nthptr_addr(strct, (size_t)0));
@@ -3176,7 +3161,6 @@ static void allocate_gc_frame(size_t n_roots, jl_codectx_t *ctx)
31763161
ctx->argTemp = builder.CreateAlloca(jl_pvalue_llvmt,
31773162
ConstantInt::get(T_int32, n_roots));
31783163
#endif
3179-
ctx->alloca_frame = builder.CreateLoad(prepare_global(jl_alloca_stack_var), false);
31803164

31813165
}
31823166

@@ -3210,8 +3194,6 @@ static void finalize_gc_frame(jl_codectx_t *ctx)
32103194
il.erase(ctx->first_gcframe_inst, ctx->last_gcframe_inst);
32113195
// erase() erases up *to* the end point; erase last inst too
32123196
il.erase(ctx->last_gcframe_inst);
3213-
//if (!ctx->uses_alloca)
3214-
// il.erase(ctx->alloca_frame);
32153197
for(size_t i=0; i < ctx->gc_frame_pops.size(); i++) {
32163198
Instruction *pop = ctx->gc_frame_pops[i];
32173199
BasicBlock::InstListType &il2 = pop->getParent()->getInstList();
@@ -3250,10 +3232,6 @@ static void finalize_gc_frame(jl_codectx_t *ctx)
32503232
after = new StoreInst(V_null, argTempi);
32513233
instList.insertAfter(argTempi, after);
32523234
}
3253-
//if (!ctx->uses_alloca) {
3254-
// BasicBlock::InstListType &il = ctx->gcframe->getParent()->getInstList();
3255-
// il.erase(ctx->alloca_frame);
3256-
//}
32573235
}
32583236
}
32593237

@@ -3330,7 +3308,6 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Funct
33303308
ctx.gc_frame_pops.push_back(gcpop);
33313309
builder.CreateStore(builder.CreateBitCast(builder.CreateLoad(gcpop, false), jl_ppvalue_llvmt),
33323310
prepare_global(jlpgcstack_var));
3333-
builder.CreateStore(ctx.alloca_frame, prepare_global(jl_alloca_stack_var)),
33343311

33353312
finalize_gc_frame(&ctx);
33363313
builder.CreateRet(r);
@@ -4004,7 +3981,6 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle)
40043981
builder.CreateStore(builder.CreateBitCast(builder.CreateLoad(gcpop, false), jl_ppvalue_llvmt),
40053982
prepare_global(jlpgcstack_var));
40063983
#endif
4007-
builder.CreateStore(ctx.alloca_frame, prepare_global(jl_alloca_stack_var));
40083984
if (do_malloc_log && lno != -1)
40093985
mallocVisitLine(filename, lno);
40103986
if (builder.GetInsertBlock()->getTerminator() == NULL) {
@@ -4215,12 +4191,6 @@ static void init_julia_llvm_env(Module *m)
42154191
NULL, "jl_pgcstack");
42164192
add_named_global(jlpgcstack_var, (void*)&jl_pgcstack);
42174193
#endif
4218-
4219-
jl_alloca_stack_var =
4220-
new GlobalVariable(*m, T_pint8,
4221-
false, GlobalVariable::ExternalLinkage,
4222-
NULL, "jl_alloca_stack");
4223-
add_named_global(jl_alloca_stack_var, (void*)&jl_alloca_stack);
42244194

42254195
global_to_llvm("__stack_chk_guard", (void*)&__stack_chk_guard, m);
42264196
Function *jl__stack_chk_fail =

src/gc.c

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ static size_t mark_stack_size = 0;
637637
static size_t mark_sp = 0;
638638

639639
static struct {
640-
void* *s;
640+
jl_gcframe_t *s;
641641
ptrint_t offset;
642642
} *marked_stacks;
643643
static size_t marked_stacks_size = 0;
@@ -656,18 +656,42 @@ static void gc_unmark_stacks()
656656
{
657657
size_t i;
658658
for (i = 0; i < marked_stacks_sp; i++) {
659-
void* *s = marked_stacks[i].s;
659+
jl_gcframe_t *s = marked_stacks[i].s;
660660
ptrint_t offset = marked_stacks[i].offset;
661661
while (s != NULL) {
662-
s = (void**)((char*)s + offset);
663-
gc_clrmark(s+1);
664-
s = (void**)(*s);
662+
s = (jl_gcframe_t*)((char*)s + offset);
663+
jl_value_t ***rts = (jl_value_t***)(((void**)s)+2);
664+
size_t nr = s->nroots>>1;
665+
if (s->nroots & 1) {
666+
for(size_t i=0; i < nr; i++) {
667+
jl_value_t **ptr = (jl_value_t**)((char*)rts[i] + offset);
668+
if (*ptr != NULL && gc_marked(*ptr))
669+
gc_clrmark(*ptr);
670+
}
671+
}
672+
else {
673+
for(size_t i=0; i < nr; i++) {
674+
if (rts[i] != NULL && gc_marked(rts[i]))
675+
gc_clrmark(rts[i]);
676+
}
677+
}
678+
s = s->prev;
665679
}
666680
}
667681
}
668682

669683
static void gc_mark_stack(jl_gcframe_t *s, ptrint_t offset, int d)
670684
{
685+
if (marked_stacks_sp >= marked_stacks_size) {
686+
size_t newsz = marked_stacks_size>0 ? marked_stacks_size*2 : 8;
687+
marked_stacks = (typeof(marked_stacks))realloc(marked_stacks,newsz*sizeof(*marked_stacks));
688+
if (marked_stacks == NULL) exit(1);
689+
marked_stacks_size = newsz;
690+
}
691+
marked_stacks[marked_stacks_sp].s = s;
692+
marked_stacks[marked_stacks_sp].offset = offset;
693+
marked_stacks_sp++;
694+
671695
while (s != NULL) {
672696
s = (jl_gcframe_t*)((char*)s + offset);
673697
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)
727751
if (ta->stkbuf != NULL || ta == jl_current_task) {
728752
if (ta->stkbuf != NULL)
729753
gc_setmark_buf(ta->stkbuf);
730-
if (marked_stacks_sp >= marked_stacks_size) {
731-
size_t newsz = marked_stacks_size>0 ? marked_stacks_size*2 : 8;
732-
marked_stacks = (typeof(marked_stacks))realloc(marked_stacks,newsz*sizeof(*marked_stacks));
733-
if (marked_stacks == NULL) exit(1);
734-
marked_stacks_size = newsz;
735-
}
736754
#ifdef COPY_STACKS
737755
ptrint_t offset;
738756
if (ta == jl_current_task) {
739757
offset = 0;
740-
marked_stacks[marked_stacks_sp].s = jl_alloca_stack;
741-
marked_stacks[marked_stacks_sp].offset = offset;
742-
marked_stacks_sp++;
743758
gc_mark_stack(jl_pgcstack, offset, d);
744759
}
745760
else {
746761
offset = (char *)ta->stkbuf - ((char *)ta->stackbase - ta->ssize);
747-
marked_stacks[marked_stacks_sp].s = ta->alloca_stack;
748-
marked_stacks[marked_stacks_sp].offset = offset;
749-
marked_stacks_sp++;
750762
gc_mark_stack(ta->gcstack, offset, d);
751763
}
752764
#else
753-
marked_stacks[marked_stacks_sp].s = ta->alloca_stack;
754-
marked_stacks[marked_stacks_sp].offset = offset;
755-
marked_stacks_sp++;
756765
gc_mark_stack(ta->gcstack, 0, d);
757766
#endif
758767
}

src/julia.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,7 +1022,6 @@ typedef struct _jl_gcframe_t {
10221022
// x = f(); y = g(); foo(x, y); JL_GC_POP();
10231023

10241024
extern DLLEXPORT jl_gcframe_t *jl_pgcstack;
1025-
extern DLLEXPORT void** jl_alloca_stack;
10261025

10271026
#define JL_GC_PUSH(...) \
10281027
void *__gc_stkf[] = {(void*)((VA_NARG(__VA_ARGS__)<<1)|1), jl_pgcstack, \
@@ -1129,7 +1128,6 @@ typedef struct _jl_handler_t {
11291128
#ifdef JL_GC_MARKSWEEP
11301129
jl_gcframe_t *gcstack;
11311130
#endif
1132-
void* *alloca_stack;
11331131
struct _jl_handler_t *prev;
11341132
} jl_handler_t;
11351133

@@ -1158,7 +1156,6 @@ typedef struct _jl_task_t {
11581156
jl_handler_t *eh;
11591157
// saved gc stack top for context switches
11601158
jl_gcframe_t *gcstack;
1161-
void* *alloca_stack;
11621159
// current module, or NULL if this task has not set one
11631160
jl_module_t *current_module;
11641161
} jl_task_t;
@@ -1181,7 +1178,6 @@ STATIC_INLINE void jl_eh_restore_state(jl_handler_t *eh)
11811178
#ifdef JL_GC_MARKSWEEP
11821179
jl_pgcstack = eh->gcstack;
11831180
#endif
1184-
jl_alloca_stack = eh->alloca_stack;
11851181
JL_SIGATOMIC_END();
11861182
}
11871183

src/task.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ jl_value_t *jl_exception_in_transit;
153153
#ifdef JL_GC_MARKSWEEP
154154
jl_gcframe_t *jl_pgcstack = NULL;
155155
#endif
156-
void* *jl_alloca_stack = NULL;
157156

158157
static void start_task(jl_task_t *t);
159158

@@ -247,8 +246,6 @@ static void ctx_switch(jl_task_t *t, jl_jmp_buf *where)
247246
jl_current_task->gcstack = jl_pgcstack;
248247
jl_pgcstack = t->gcstack;
249248
#endif
250-
jl_current_task->alloca_stack = jl_alloca_stack;
251-
jl_alloca_stack = t->alloca_stack;
252249

253250
// restore task's current module, looking at parent tasks
254251
// if it hasn't set one.
@@ -787,7 +784,6 @@ jl_task_t *jl_new_task(jl_function_t *start, size_t ssize)
787784
#ifdef JL_GC_MARKSWEEP
788785
t->gcstack = NULL;
789786
#endif
790-
t->alloca_stack = NULL;
791787
t->stkbuf = NULL;
792788

793789
#ifdef COPY_STACKS

0 commit comments

Comments
 (0)