Skip to content

Commit bb2f294

Browse files
committed
fix
1 parent b6bda05 commit bb2f294

9 files changed

Lines changed: 6570 additions & 729 deletions

src/compiler.ts

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8230,39 +8230,55 @@ export class Compiler extends DiagnosticEmitter {
82308230
let arrayInstance = assert(this.resolver.resolveClass(this.program.staticArrayPrototype, [ stringType ]));
82318231
let segment = this.addStaticBuffer(stringType, values, arrayInstance.id);
82328232
this.program.OBJECTInstance.writeField("gcInfo", 3, segment.buffer, 0); // use transparent gcinfo
8233-
let offset = i64_add(segment.offset, i64_new(this.program.totalOverhead));
8233+
let arrayOffset = i64_add(segment.offset, i64_new(this.program.totalOverhead));
82348234
let joinInstance = assert(arrayInstance.getMethod("join"));
82358235
let indexedSetInstance = assert(arrayInstance.lookupOverload(OperatorKind.IndexedSet, true));
8236-
let stmts = new Array<ExpressionRef>(2 * numExpressions + 1);
8237-
// Use one local per toString'ed subexpression, since otherwise recursion on the same
8238-
// static array would overwrite already prepared parts. Avoids a temporary array.
8239-
let temps = new Array<Local>(numExpressions);
82408236
let flow = this.currentFlow;
8237+
8238+
// Store the static array address in a tmp local so the shadow stack
8239+
// keeps it reachable. GC will visit it and all dynamic children.
8240+
let arrayLocal = flow.getTempLocal(arrayInstance.type);
8241+
let stmts = new Array<ExpressionRef>();
8242+
stmts.push(module.local_set(arrayLocal.index, module.usize(arrayOffset), true));
8243+
8244+
// Evaluate each expression into a temp local.
8245+
// One local per expression prevents recursion on the same static array
8246+
// from overwriting already prepared parts.
8247+
let temps = new Array<Local>(numExpressions);
82418248
for (let i = 0; i < numExpressions; ++i) {
8242-
let expression = expressions[i];
8249+
let subExpression = expressions[i];
82438250
let temp = flow.getTempLocal(stringType);
82448251
temps[i] = temp;
8245-
stmts[i] = module.local_set(temp.index,
8246-
this.makeToString(
8247-
this.compileExpression(expression, stringType),
8248-
this.currentType, expression
8249-
),
8250-
true
8252+
stmts.push(
8253+
module.local_set(
8254+
temp.index,
8255+
this.makeToString(this.compileExpression(subExpression, stringType), this.currentType, subExpression),
8256+
true
8257+
)
82518258
);
82528259
}
8253-
// Populate the static array with the toString'ed subexpressions and call .join("")
8260+
8261+
// Populate the static array slots with the temp locals
82548262
for (let i = 0; i < numExpressions; ++i) {
8255-
stmts[numExpressions + i] = this.makeCallDirect(indexedSetInstance, [
8256-
module.usize(offset),
8257-
module.i32(expressionPositions[i]),
8258-
module.local_get(temps[i].index, stringType.toRef())
8259-
], expression);
8260-
}
8261-
stmts[2 * numExpressions] = this.makeCallDirect(joinInstance, [
8262-
module.usize(offset),
8263-
this.ensureStaticString("")
8264-
], expression);
8265-
return module.flatten(stmts, stringType.toRef());
8263+
stmts.push(
8264+
this.makeCallDirect(
8265+
indexedSetInstance,
8266+
[
8267+
module.local_get(arrayLocal.index, stringType.toRef()),
8268+
module.i32(expressionPositions[i]),
8269+
module.local_get(temps[i].index, stringType.toRef()),
8270+
],
8271+
expression
8272+
));
8273+
}
8274+
// Call join("") and return the result
8275+
stmts.push(
8276+
this.makeCallDirect(
8277+
joinInstance,
8278+
[module.local_get(arrayLocal.index, stringType.toRef()), this.ensureStaticString("")],
8279+
expression
8280+
));
8281+
return module.block(null, stmts, stringType.toRef());
82668282
}
82678283

82688284
// Try to find out whether the template function takes a full-blown TemplateStringsArray or if

0 commit comments

Comments
 (0)