Просмотр исходного кода

Bailouts on a MemOp should not keep the overwritten induction variable's value.

wyrichte 7 лет назад
Родитель
Сommit
9ce4e1656c

+ 13 - 4
lib/Backend/BackwardPass.cpp

@@ -8685,18 +8685,27 @@ BackwardPass::RestoreInductionVariableValuesAfterMemOp(Loop *loop)
         }
         Func *localFunc = loop->GetFunc();
         StackSym *sym = localFunc->m_symTable->FindStackSym(symId)->GetInt32EquivSym(localFunc);
-
+        
         IR::Opnd *inductionVariableOpnd = IR::RegOpnd::New(sym, IRType::TyInt32, localFunc);
+        IR::Opnd *tempInductionVariableOpnd = IR::RegOpnd::New(IRType::TyInt32, localFunc);
         IR::Opnd *sizeOpnd = globOpt->GenerateInductionVariableChangeForMemOp(loop, inductionVariableChangeInfo.unroll);
-        IR::Instr* restoreInductionVarInstr = IR::Instr::New(opCode, inductionVariableOpnd, inductionVariableOpnd, sizeOpnd, loop->GetFunc());
+
+        // The induction variable is restored to a temp register before the MemOp occurs. Once the MemOp is
+        // complete, the induction variable's register is set to the value of the temp register. This is done
+        // in order to avoid overwriting the induction variable's value after a bailout on the MemOp.
+        IR::Instr* restoreInductionVarToTemp = IR::Instr::New(opCode, tempInductionVariableOpnd, inductionVariableOpnd, sizeOpnd, loop->GetFunc());
+        IR::Instr* restoreInductionVar = IR::Instr::New(Js::OpCode::Ld_A, inductionVariableOpnd, tempInductionVariableOpnd, loop->GetFunc());
 
         // The IR that restores the induction variable's value is placed before the MemOp. Since this IR can
         // bailout to the loop's landing pad, placing this IR before the MemOp avoids performing the MemOp,
         // bailing out because of this IR, and then performing the effects of the loop again.
-        loop->landingPad->InsertInstrBefore(restoreInductionVarInstr, loop->memOpInfo->instr);
+        loop->landingPad->InsertInstrBefore(restoreInductionVarToTemp, loop->memOpInfo->instr);
 
         // If restoring an induction variable results in an overflow, bailout to the loop's landing pad.
-        restoreInductionVarInstr->ConvertToBailOutInstr(loop->bailOutInfo, IR::BailOutOnOverflow);
+        restoreInductionVarToTemp->ConvertToBailOutInstr(loop->bailOutInfo, IR::BailOutOnOverflow);
+
+        // Restore the induction variable's actual register once all bailouts have been passed.
+        loop->landingPad->InsertAfter(restoreInductionVar);
     };
 
     for (auto it = loop->memOpInfo->inductionVariableChangeInfoMap->GetIterator(); it.IsValid(); it.MoveNext())

+ 4 - 0
test/loop/bailOutOfMemOp.baseline

@@ -0,0 +1,4 @@
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+1,1,1,-1
+1,1,1,-1

+ 47 - 0
test/loop/bailOutOfMemOp.js

@@ -0,0 +1,47 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+function f0() {
+    var printArr = [];
+    Object.prototype.m = {};
+    Object.defineProperty(Array.prototype, "5", {});
+
+    for (var iterator = 0; iterator < 10; iterator++) {
+        var arr0 = [];
+        arr0[10] = "Should not see this";
+        arr0.shift();
+        for (var arr0Elem in arr0) {
+            if (arr0Elem.indexOf('m')) {
+                continue;
+            }
+            for (var i = 9.1 | 0; i < arr0.length; i++) {
+                arr0[i] = "";
+            }
+            printArr.push(arr0);
+        }
+    }
+    WScript.Echo(printArr);
+}
+f0();
+f0();
+
+function f1() {
+    var printArr = [];
+    var arr0 = new Array(1, 1);
+    var arr1 = [];
+    arr0[3] = 1;
+    arr0[2] = 1;
+    arr1[1] = 1;
+    arr1[3] = -1;
+    arr1[2] = 1;
+    for (var i = 0.1 ? 1 : -1; i < arr0.length; i++) {
+        arr0[i] = arr1[i];
+    }
+    printArr.push(arr0);
+    i | 0;
+    WScript.Echo(printArr);
+}
+f1();
+f1();

+ 7 - 0
test/loop/rlexe.xml

@@ -1,5 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <regress-exe>
+  <test>
+    <default>
+      <files>bailOutOfMemOp.js</files>
+      <compile-flags>-bgjit- -mic:1 -off:simplejit -minmemopcount:0</compile-flags>
+      <baseline>bailOutOfMemOp.baseline</baseline>
+    </default>
+  </test>
   <test>
     <default>
       <files>loop.js</files>