Skip to content

Commit

Permalink
better marking and usage of isimmutable
Browse files Browse the repository at this point in the history
mark_julia_slot now assumes that the slot is immutable (or at least SA)
isimmutable is now assumed to mean "cannot change before an assignment",
so only assignment (to a GenSym) needs to consider whether to make a copy
  • Loading branch information
vtjnash authored and dfdx committed Mar 19, 2016
1 parent 6b74e9c commit 56711bc
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 19 deletions.
15 changes: 7 additions & 8 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1573,8 +1573,7 @@ static bool emit_getfield_unknownidx(jl_cgval_t *ret, const jl_cgval_t &strct, V
builder.CreateGEP(data_pointer(strct, ctx), idx)));
if ((unsigned)stt->ninitialized != nfields)
null_pointer_check(fld, ctx);
bool needsgcroot = true; // !strct.isimmutable; // jwn: probably want this as a llvm pass
*ret = mark_julia_type(fld, true, jl_any_type, ctx, needsgcroot);
*ret = mark_julia_type(fld, true, jl_any_type, ctx, true);
return true;
}
else if (is_tupletype_homogeneous(stt->types)) {
Expand All @@ -1586,9 +1585,9 @@ static bool emit_getfield_unknownidx(jl_cgval_t *ret, const jl_cgval_t &strct, V
// just compute the pointer and let user load it when necessary
Type *fty = julia_type_to_llvm(jt);
Value *addr = builder.CreateGEP(builder.CreatePointerCast(ptr, PointerType::get(fty,0)), idx);
jl_cgval_t fieldval = mark_julia_slot(addr, jt);
fieldval.gcroot = strct.gcroot;
*ret = fieldval;
*ret = mark_julia_slot(addr, jt);
ret->gcroot = strct.gcroot;
ret->isimmutable = strct.isimmutable;
return true;
}
*ret = typed_load(ptr, idx, jt, ctx, stt->mutabl ? tbaa_user : tbaa_immut);
Expand Down Expand Up @@ -1653,13 +1652,12 @@ static jl_cgval_t emit_getfield_knownidx(const jl_cgval_t &strct, unsigned idx,
Value *addr =
builder.CreateGEP(builder.CreateBitCast(boxed(strct, ctx), T_pint8),
ConstantInt::get(T_size, jl_field_offset(jt,idx)));
MDNode *tbaa = strct.isimmutable ? tbaa_immut : tbaa_user;
MDNode *tbaa = jt->mutabl ? tbaa_user : tbaa_immut;
if (jl_field_isptr(jt, idx)) {
Value *fldv = tbaa_decorate(tbaa, builder.CreateLoad(builder.CreateBitCast(addr, T_ppjlvalue)));
if (idx >= (unsigned)jt->ninitialized)
null_pointer_check(fldv, ctx);
bool needsgcroot = true; // !strct.isimmutable; // jwn: probably want this as a llvm pass
jl_cgval_t ret = mark_julia_type(fldv, true, jfty, ctx, needsgcroot);
jl_cgval_t ret = mark_julia_type(fldv, true, jfty, ctx, true);
return ret;
}
else {
Expand All @@ -1678,6 +1676,7 @@ static jl_cgval_t emit_getfield_knownidx(const jl_cgval_t &strct, unsigned idx,
strct.V, 0, idx);
assert(!jt->mutabl);
jl_cgval_t fieldval = mark_julia_slot(addr, jfty);
fieldval.isimmutable = strct.isimmutable;
fieldval.gcroot = strct.gcroot;
return fieldval;
}
Expand Down
13 changes: 8 additions & 5 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ static inline jl_cgval_t mark_julia_slot(Value *v, jl_value_t *typ)
assert(v->getType() != T_pjlvalue);
jl_cgval_t tagval(v, NULL, false, typ);
tagval.ispointer = true;
tagval.isimmutable = true;
return tagval;
}

Expand Down Expand Up @@ -782,7 +783,7 @@ static Value *alloc_local(jl_sym_t *s, jl_codectx_t *ctx)
// CreateAlloca is OK here because alloc_local is only called during prologue setup
Value *lv = builder.CreateAlloca(vtype, 0, jl_symbol_name(s));
vi.value = mark_julia_slot(lv, jt);
vi.value.isimmutable &= vi.isSA; // slot is not immutable if there are multiple assignments
vi.value.isimmutable = false; // slots are not immutable
assert(vi.value.isboxed == false);
return lv;
}
Expand Down Expand Up @@ -2977,10 +2978,10 @@ static jl_cgval_t emit_call_function_object(jl_lambda_info_t *li, const jl_cgval
else if (et->isAggregateType()) {
assert(at == PointerType::get(et, 0));
jl_cgval_t arg = i==0 ? theF : emit_expr(args[i], ctx);
if (arg.isimmutable && arg.ispointer) {
if (arg.ispointer) {
// can lazy load on demand, no copy needed
argvals[idx] = data_pointer(arg, ctx, at);
mark_gc_use(arg); // jwn must be after the jlcall
mark_gc_use(arg); // TODO: must be after the jlcall
}
else {
Value *v = emit_unbox(et, arg, jt);
Expand Down Expand Up @@ -3220,8 +3221,10 @@ static jl_cgval_t emit_var(jl_sym_t *sym, jl_codectx_t *ctx)
}

jl_varinfo_t &vi = ctx->vars[sym];
if (!vi.isArgument && !vi.isAssigned)
if (!vi.isArgument && !vi.isAssigned) {
undef_var_error_if_null(V_null, sym, ctx);
return jl_cgval_t();
}
if (vi.memloc) {
Value *bp = vi.memloc;
if (vi.isArgument || // arguments are always defined
Expand All @@ -3236,7 +3239,7 @@ static jl_cgval_t emit_var(jl_sym_t *sym, jl_codectx_t *ctx)
return v;
}
}
else if (vi.value.isboxed || vi.value.constant || !vi.value.ispointer || (vi.isSA && !vi.isVolatile)) {
else if (!vi.isVolatile || !vi.isAssigned) {
return vi.value;
}
else {
Expand Down
6 changes: 0 additions & 6 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,12 +529,6 @@ static jl_cgval_t generic_unbox(jl_value_t *targ, jl_value_t *x, jl_codectx_t *c

Value *vx;
if (v.ispointer) {
// TODO: validate the size and type of the pointer contents
if (v.isimmutable && !v.constant) { // wrong type, but can lazy load this later as needed
v.typ = bt;
v.isboxed = false;
return v;
}
vx = builder.CreateLoad(data_pointer(v, ctx, llvmt->getPointerTo()));
}
else {
Expand Down

0 comments on commit 56711bc

Please sign in to comment.