Skip to content

Commit 9ce4e16

Browse files
committed
Bailouts on a MemOp should not keep the overwritten induction variable's value.
1 parent 757bd0d commit 9ce4e16

File tree

4 files changed

+71
-4
lines changed

4 files changed

+71
-4
lines changed

lib/Backend/BackwardPass.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8685,18 +8685,27 @@ BackwardPass::RestoreInductionVariableValuesAfterMemOp(Loop *loop)
86858685
}
86868686
Func *localFunc = loop->GetFunc();
86878687
StackSym *sym = localFunc->m_symTable->FindStackSym(symId)->GetInt32EquivSym(localFunc);
8688-
8688+
86898689
IR::Opnd *inductionVariableOpnd = IR::RegOpnd::New(sym, IRType::TyInt32, localFunc);
8690+
IR::Opnd *tempInductionVariableOpnd = IR::RegOpnd::New(IRType::TyInt32, localFunc);
86908691
IR::Opnd *sizeOpnd = globOpt->GenerateInductionVariableChangeForMemOp(loop, inductionVariableChangeInfo.unroll);
8691-
IR::Instr* restoreInductionVarInstr = IR::Instr::New(opCode, inductionVariableOpnd, inductionVariableOpnd, sizeOpnd, loop->GetFunc());
8692+
8693+
// The induction variable is restored to a temp register before the MemOp occurs. Once the MemOp is
8694+
// complete, the induction variable's register is set to the value of the temp register. This is done
8695+
// in order to avoid overwriting the induction variable's value after a bailout on the MemOp.
8696+
IR::Instr* restoreInductionVarToTemp = IR::Instr::New(opCode, tempInductionVariableOpnd, inductionVariableOpnd, sizeOpnd, loop->GetFunc());
8697+
IR::Instr* restoreInductionVar = IR::Instr::New(Js::OpCode::Ld_A, inductionVariableOpnd, tempInductionVariableOpnd, loop->GetFunc());
86928698

86938699
// The IR that restores the induction variable's value is placed before the MemOp. Since this IR can
86948700
// bailout to the loop's landing pad, placing this IR before the MemOp avoids performing the MemOp,
86958701
// bailing out because of this IR, and then performing the effects of the loop again.
8696-
loop->landingPad->InsertInstrBefore(restoreInductionVarInstr, loop->memOpInfo->instr);
8702+
loop->landingPad->InsertInstrBefore(restoreInductionVarToTemp, loop->memOpInfo->instr);
86978703

86988704
// If restoring an induction variable results in an overflow, bailout to the loop's landing pad.
8699-
restoreInductionVarInstr->ConvertToBailOutInstr(loop->bailOutInfo, IR::BailOutOnOverflow);
8705+
restoreInductionVarToTemp->ConvertToBailOutInstr(loop->bailOutInfo, IR::BailOutOnOverflow);
8706+
8707+
// Restore the induction variable's actual register once all bailouts have been passed.
8708+
loop->landingPad->InsertAfter(restoreInductionVar);
87008709
};
87018710

87028711
for (auto it = loop->memOpInfo->inductionVariableChangeInfoMap->GetIterator(); it.IsValid(); it.MoveNext())

test/loop/bailOutOfMemOp.baseline

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
2+
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
3+
1,1,1,-1
4+
1,1,1,-1

test/loop/bailOutOfMemOp.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
function f0() {
7+
var printArr = [];
8+
Object.prototype.m = {};
9+
Object.defineProperty(Array.prototype, "5", {});
10+
11+
for (var iterator = 0; iterator < 10; iterator++) {
12+
var arr0 = [];
13+
arr0[10] = "Should not see this";
14+
arr0.shift();
15+
for (var arr0Elem in arr0) {
16+
if (arr0Elem.indexOf('m')) {
17+
continue;
18+
}
19+
for (var i = 9.1 | 0; i < arr0.length; i++) {
20+
arr0[i] = "";
21+
}
22+
printArr.push(arr0);
23+
}
24+
}
25+
WScript.Echo(printArr);
26+
}
27+
f0();
28+
f0();
29+
30+
function f1() {
31+
var printArr = [];
32+
var arr0 = new Array(1, 1);
33+
var arr1 = [];
34+
arr0[3] = 1;
35+
arr0[2] = 1;
36+
arr1[1] = 1;
37+
arr1[3] = -1;
38+
arr1[2] = 1;
39+
for (var i = 0.1 ? 1 : -1; i < arr0.length; i++) {
40+
arr0[i] = arr1[i];
41+
}
42+
printArr.push(arr0);
43+
i | 0;
44+
WScript.Echo(printArr);
45+
}
46+
f1();
47+
f1();

test/loop/rlexe.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<regress-exe>
3+
<test>
4+
<default>
5+
<files>bailOutOfMemOp.js</files>
6+
<compile-flags>-bgjit- -mic:1 -off:simplejit -minmemopcount:0</compile-flags>
7+
<baseline>bailOutOfMemOp.baseline</baseline>
8+
</default>
9+
</test>
310
<test>
411
<default>
512
<files>loop.js</files>

0 commit comments

Comments
 (0)