Skip to content

Commit

Permalink
fix Issue 14886 - std.parallelism.parallel with large static array se…
Browse files Browse the repository at this point in the history
…ems to hang compile

Add ArrayLiteralExp.basis for repeated array literal elements.
  • Loading branch information
9rnsr committed Sep 22, 2015
1 parent 5503154 commit 51ecaf8
Show file tree
Hide file tree
Showing 17 changed files with 274 additions and 75 deletions.
2 changes: 1 addition & 1 deletion src/apply.d
Expand Up @@ -108,7 +108,7 @@ public:

override void visit(ArrayLiteralExp e)
{
doCond(e.elements) || applyTo(e);
doCond(e.basis) || doCond(e.elements) || applyTo(e);
}

override void visit(AssocArrayLiteralExp e)
Expand Down
113 changes: 83 additions & 30 deletions src/constfold.d
Expand Up @@ -762,6 +762,10 @@ extern (C++) UnionExp Equal(TOK op, Loc loc, Type type, Expression e1, Expressio
{
Expression ee1 = (*es1.elements)[i];
Expression ee2 = (*es2.elements)[i];
if (!ee1)
ee1 = es1.basis;
if (!ee2)
ee2 = es2.basis;
ue = Equal(TOKequal, loc, Type.tint32, ee1, ee2);
if (CTFEExp.isCantExp(ue.exp()))
return ue;
Expand Down Expand Up @@ -795,6 +799,8 @@ extern (C++) UnionExp Equal(TOK op, Loc loc, Type type, Expression e1, Expressio
{
uinteger_t c = es1.charAt(i);
Expression ee2 = (*es2.elements)[i];
if (!ee2)
ee2 = es2.basis;
if (ee2.isConst() != 1)
{
emplaceExp!(CTFEExp)(&ue, TOKcantexp);
Expand Down Expand Up @@ -1431,6 +1437,8 @@ extern (C++) UnionExp Index(Type type, Expression e1, Expression e2)
{
ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
Expression e = (*ale.elements)[cast(size_t)i];
if (!e)
e = ale.basis;
e.type = type;
e.loc = loc;
if (hasSideEffect(e))
Expand All @@ -1455,6 +1463,8 @@ extern (C++) UnionExp Index(Type type, Expression e1, Expression e2)
else
{
Expression e = (*ale.elements)[cast(size_t)i];
if (!e)
e = ale.basis;
e.type = type;
e.loc = loc;
if (hasSideEffect(e))
Expand Down Expand Up @@ -1600,7 +1610,10 @@ extern (C++) void sliceAssignStringFromArrayLiteral(StringExp existingSE, ArrayL
void* s = existingSE.string;
for (size_t j = 0; j < newae.elements.dim; j++)
{
uint val = cast(uint)(*newae.elements)[j].toInteger();
auto el = (*newae.elements)[j];
if (!el)
el = newae.basis;
uint val = cast(uint)el.toInteger();
switch (existingSE.sz)
{
case 1:
Expand Down Expand Up @@ -1650,7 +1663,10 @@ extern (C++) int sliceCmpStringWithArray(StringExp se1, ArrayLiteralExp ae2, siz
size_t sz = se1.sz;
for (size_t j = 0; j < len; j++)
{
uint val2 = cast(uint)(*ae2.elements)[j + lo2].toInteger();
auto el = (*ae2.elements)[j + lo2];
if (!el)
el = ae2.basis;
uint val2 = cast(uint)el.toInteger();
uint val1;
switch (sz)
{
Expand Down Expand Up @@ -1797,7 +1813,10 @@ extern (C++) UnionExp Cat(Type type, Expression e1, Expression e2)
elems.setDim(len);
for (size_t i = 0; i < ea.elements.dim; ++i)
{
(*elems)[i] = (*ea.elements)[i];
auto el = (*ea.elements)[i];
if (!el)
el = ea.basis;
(*elems)[i] = el;
}
emplaceExp!(ArrayLiteralExp)(&ue, e1.loc, elems);
ArrayLiteralExp dest = cast(ArrayLiteralExp)ue.exp();
Expand All @@ -1816,7 +1835,10 @@ extern (C++) UnionExp Cat(Type type, Expression e1, Expression e2)
elems.setDim(len);
for (size_t i = 0; i < ea.elements.dim; ++i)
{
(*elems)[es.len + i] = (*ea.elements)[i];
auto el = (*ea.elements)[i];
if (!el)
el = ea.basis;
(*elems)[es.len + i] = el;
}
emplaceExp!(ArrayLiteralExp)(&ue, e1.loc, elems);
ArrayLiteralExp dest = cast(ArrayLiteralExp)ue.exp();
Expand Down Expand Up @@ -1878,13 +1900,26 @@ extern (C++) UnionExp Cat(Type type, Expression e1, Expression e2)
// Concatenate the arrays
ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
emplaceExp!(ArrayLiteralExp)(&ue, es1.loc, cast(Expressions*)es1.elements.copy());
es1 = cast(ArrayLiteralExp)ue.exp();
es1.elements.insert(es1.elements.dim, es2.elements);
e = es1;

auto elems = es1.elements.copy();
elems.append(es2.elements);
foreach (ref el; (*elems)[][0 .. es1.elements.dim])
{
if (!el)
el = es1.basis;
}
foreach (ref el; (*elems)[][es1.elements.dim .. elems.dim])
{
if (!el)
el = es2.basis;
}

emplaceExp!(ArrayLiteralExp)(&ue, es1.loc, elems);

e = ue.exp();
if (type.toBasetype().ty == Tsarray)
{
e.type = t1.nextOf().sarrayOf(es1.elements.dim);
e.type = t1.nextOf().sarrayOf(elems.dim);
}
else
e.type = type;
Expand All @@ -1902,12 +1937,20 @@ extern (C++) UnionExp Cat(Type type, Expression e1, Expression e2)
L3:
// Concatenate the array with null
ArrayLiteralExp es = cast(ArrayLiteralExp)e;
emplaceExp!(ArrayLiteralExp)(&ue, es.loc, cast(Expressions*)es.elements.copy());
es = cast(ArrayLiteralExp)ue.exp();
e = es;

auto elems = es.elements.copy();
foreach (ref el; *elems)
{
if (!el)
el = es.basis;
}

emplaceExp!(ArrayLiteralExp)(&ue, es.loc, elems);

e = ue.exp();
if (type.toBasetype().ty == Tsarray)
{
e.type = t1.nextOf().sarrayOf(es.elements.dim);
e.type = t1.nextOf().sarrayOf(elems.dim);
}
else
e.type = type;
Expand All @@ -1916,23 +1959,25 @@ extern (C++) UnionExp Cat(Type type, Expression e1, Expression e2)
}
else if ((e1.op == TOKarrayliteral || e1.op == TOKnull) && e1.type.toBasetype().nextOf() && e1.type.toBasetype().nextOf().equals(e2.type))
{
ArrayLiteralExp es1;
auto elems = new Expressions();
if (e1.op == TOKarrayliteral)
{
es1 = cast(ArrayLiteralExp)e1;
emplaceExp!(ArrayLiteralExp)(&ue, es1.loc, cast(Expressions*)es1.elements.copy());
es1 = cast(ArrayLiteralExp)ue.exp();
es1.elements.push(e2);
}
else
{
emplaceExp!(ArrayLiteralExp)(&ue, e1.loc, e2);
es1 = cast(ArrayLiteralExp)ue.exp();
auto es1 = cast(ArrayLiteralExp)e1;
elems.append(es1.elements);
foreach (ref el; *elems)
{
if (!el)
el = es1.basis;
}
}
e = es1;
elems.push(e2);

emplaceExp!(ArrayLiteralExp)(&ue, e1.loc, elems);

e = ue.exp();
if (type.toBasetype().ty == Tsarray)
{
e.type = e2.type.sarrayOf(es1.elements.dim);
e.type = e2.type.sarrayOf(elems.dim);
}
else
e.type = type;
Expand All @@ -1942,13 +1987,21 @@ extern (C++) UnionExp Cat(Type type, Expression e1, Expression e2)
else if (e2.op == TOKarrayliteral && e2.type.toBasetype().nextOf().equals(e1.type))
{
ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
emplaceExp!(ArrayLiteralExp)(&ue, es2.loc, cast(Expressions*)es2.elements.copy());
es2 = cast(ArrayLiteralExp)ue.exp();
es2.elements.shift(e1);
e = es2;
auto elems = new Expressions();
elems.push(e1);
elems.append(es2.elements);
foreach (ref el; (*elems)[][1 .. elems.dim])
{
if (!el)
el = es2.basis;
}

emplaceExp!(ArrayLiteralExp)(&ue, es2.loc, elems);

e = ue.exp();
if (type.toBasetype().ty == Tsarray)
{
e.type = e1.type.sarrayOf(es2.elements.dim);
e.type = e1.type.sarrayOf(elems.dim);
}
else
e.type = type;
Expand Down
17 changes: 13 additions & 4 deletions src/ctfeexpr.d
Expand Up @@ -306,15 +306,20 @@ extern (C++) bool needToCopyLiteral(Expression expr)
}
}

extern (C++) Expressions* copyLiteralArray(Expressions* oldelems)
extern (C++) Expressions* copyLiteralArray(Expressions* oldelems, Expression basis = null)
{
if (!oldelems)
return oldelems;
CtfeStatus.numArrayAllocs++;
auto newelems = new Expressions();
newelems.setDim(oldelems.dim);
for (size_t i = 0; i < oldelems.dim; i++)
(*newelems)[i] = copyLiteral((*oldelems)[i]).copy();
{
auto el = (*oldelems)[i];
if (!el)
el = basis;
(*newelems)[i] = copyLiteral(el).copy();
}
return newelems;
}

Expand All @@ -339,8 +344,12 @@ extern (C++) UnionExp copyLiteral(Expression e)
}
if (e.op == TOKarrayliteral)
{
ArrayLiteralExp ae = cast(ArrayLiteralExp)e;
emplaceExp!(ArrayLiteralExp)(&ue, e.loc, copyLiteralArray(ae.elements));
auto ale = cast(ArrayLiteralExp)e;
auto basis = ale.basis ? copyLiteral(ale.basis).copy() : null;
auto elements = copyLiteralArray(ale.elements, ale.basis);

emplaceExp!(ArrayLiteralExp)(&ue, e.loc, elements);

ArrayLiteralExp r = cast(ArrayLiteralExp)ue.exp();
r.type = e.type;
r.ownedByCtfe = OWNEDctfe;
Expand Down
20 changes: 18 additions & 2 deletions src/dcast.d
Expand Up @@ -676,12 +676,19 @@ extern (C++) MATCH implicitConvTo(Expression e, Type t)
}
else
{
if (e.basis)
{
MATCH m = e.basis.implicitConvTo(telement);
if (m < result)
result = m;
}
for (size_t i = 0; i < e.elements.dim; i++)
{
Expression el = (*e.elements)[i];
if (result == MATCHnomatch)
break;
// no need to check for worse
if (!el)
continue;
MATCH m = el.implicitConvTo(telement);
if (m < result)
result = m; // remember worst match
Expand Down Expand Up @@ -1946,10 +1953,14 @@ extern (C++) Expression castTo(Expression e, Scope* sc, Type t)
goto L1;
}
ae = cast(ArrayLiteralExp)e.copy();
if (e.basis)
ae.basis = e.basis.castTo(sc, tb.nextOf());
ae.elements = e.elements.copy();
for (size_t i = 0; i < e.elements.dim; i++)
{
Expression ex = (*e.elements)[i];
if (!ex)
continue;
ex = ex.castTo(sc, tb.nextOf());
(*ae.elements)[i] = ex;
}
Expand Down Expand Up @@ -2279,6 +2290,8 @@ extern (C++) Expression inferType(Expression e, Type t, int flag = 0)
if (tb.ty == Tarray || tb.ty == Tsarray)
{
Type tn = tb.nextOf();
if (ale.basis)
ale.basis = inferType(ale.basis, tn, flag);
for (size_t i = 0; i < ale.elements.dim; i++)
{
Expression e = (*ale.elements)[i];
Expand Down Expand Up @@ -2416,7 +2429,10 @@ extern (C++) bool isVoidArrayLiteral(Expression e, Type other)
{
while (e.op == TOKarrayliteral && e.type.ty == Tarray && ((cast(ArrayLiteralExp)e).elements.dim == 1))
{
e = (*(cast(ArrayLiteralExp)e).elements)[0];
auto ale = cast(ArrayLiteralExp)e;
e = (*ale.elements)[0];
if (!e)
e = ale.basis;
if (other.ty == Tsarray || other.ty == Tarray)
other = other.nextOf();
else
Expand Down
47 changes: 33 additions & 14 deletions src/dinterpret.d
Expand Up @@ -2559,38 +2559,57 @@ public:
}
Type tn = e.type.toBasetype().nextOf().toBasetype();
bool wantCopy = (tn.ty == Tsarray || tn.ty == Tstruct);

auto basis = interpret(e.basis, istate);
if (exceptionOrCant(basis))
return;

Expressions* expsx = null;
size_t dim = e.elements ? e.elements.dim : 0;
for (size_t i = 0; i < dim; i++)
{
Expression exp = (*e.elements)[i];
if (exp.op == TOKindex) // segfault bug 6250
assert((cast(IndexExp)exp).e1 != e);
Expression ex = interpret(exp, istate);
Expression ex;
if (!exp)
{
ex = copyLiteral(basis).copy();
goto Lcow;
}

// segfault bug 6250
assert(exp.op != TOKindex || (cast(IndexExp)exp).e1 != e);

ex = interpret(exp, istate);
if (exceptionOrCant(ex))
return;

/* Each elements should have distinct CFE memory.
* int[1] z = 7;
* int[1][] pieces = [z,z]; // here
*/
if (wantCopy || ex == exp && expsx)
ex = copyLiteral(ex).copy();

if (ex == exp && !expsx)
continue;

/* If any changes, do Copy On Write
*/
if (ex != exp)
Lcow:
if (!expsx)
{
if (!expsx)
expsx = new Expressions();
++CtfeStatus.numArrayAllocs;
expsx.setDim(dim);
for (size_t j = 0; j < i; j++)
{
expsx = new Expressions();
++CtfeStatus.numArrayAllocs;
expsx.setDim(dim);
for (size_t j = 0; j < i; j++)
{
(*expsx)[j] = copyLiteral((*e.elements)[j]).copy();
}
auto el = (*e.elements)[j];
if (!el)
el = e.basis;
(*expsx)[j] = copyLiteral(el).copy();
}
(*expsx)[i] = ex;
}
(*expsx)[i] = ex;
}
if (expsx)
{
Expand All @@ -2602,7 +2621,7 @@ public:
result = CTFEExp.cantexp;
return;
}
auto ae = new ArrayLiteralExp(e.loc, expsx);
auto ae = new ArrayLiteralExp(e.loc, basis, expsx);
ae.type = e.type;
ae.ownedByCtfe = OWNEDctfe;
result = ae;
Expand Down

0 comments on commit 51ecaf8

Please sign in to comment.