Explorar o código

Add missing StSlot for non-temp registers for JITLoopBody

Tom Tan %!s(int64=9) %!d(string=hai) anos
pai
achega
a72b7471aa

+ 31 - 17
lib/Backend/IRBuilder.cpp

@@ -670,6 +670,7 @@ IRBuilder::Build()
     JsUtil::BaseDictionary<IR::Instr*, int, JitArenaAllocator> ignoreExBranchInstrToOffsetMap(m_tempAlloc);
 
     Js::LayoutSize layoutSize;
+    IR::Instr* lastProcessedInstrForJITLoopBody = nullptr;
     for (Js::OpCode newOpcode = m_jnReader.ReadOp(layoutSize); (uint)m_jnReader.GetCurrentOffset() <= lastOffset; newOpcode = m_jnReader.ReadOp(layoutSize))
     {
         Assert(newOpcode != Js::OpCode::EndOfBlock);
@@ -750,28 +751,41 @@ IRBuilder::Build()
             }
         }
 #endif
-        if (IsLoopBodyInTry() && m_lastInstr->GetDst() && m_lastInstr->GetDst()->IsRegOpnd() && m_lastInstr->GetDst()->GetStackSym()->HasByteCodeRegSlot())
+
+        if (IsLoopBodyInTry() && lastProcessedInstrForJITLoopBody != m_lastInstr)
         {
-            StackSym * dstSym = m_lastInstr->GetDst()->GetStackSym();
-            Js::RegSlot dstRegSlot = dstSym->GetByteCodeRegSlot();
-            if (!this->RegIsTemp(dstRegSlot) && !this->RegIsConstant(dstRegSlot))
+            FOREACH_INSTR_BACKWARD_EDITING_IN_RANGE(
+                instr,
+                instrPrev,
+                m_lastInstr,
+                lastProcessedInstrForJITLoopBody ? lastProcessedInstrForJITLoopBody->m_next : m_lastInstr)
             {
-                SymID symId = dstSym->m_id;
-                if (this->m_stSlots->Test(symId))
+                if (instr->GetDst() && instr->GetDst()->IsRegOpnd() && instr->GetDst()->GetStackSym()->HasByteCodeRegSlot())
                 {
-                    // For jitted loop bodies that are in a try block, we consider any symbol that has a
-                    // non-temp bytecode reg slot, to be write-through. Hence, generating StSlots at all
-                    // defs for such symbols
-                    IR::Instr * stSlot = this->GenerateLoopBodyStSlot(dstRegSlot);
-                    AddInstr(stSlot, Js::Constants::NoByteCodeOffset);
+                    StackSym * dstSym = instr->GetDst()->GetStackSym();
+                    Js::RegSlot dstRegSlot = dstSym->GetByteCodeRegSlot();
+                    if (!this->RegIsTemp(dstRegSlot) && !this->RegIsConstant(dstRegSlot))
+                    {
+                        SymID symId = dstSym->m_id;
+                        if (this->m_stSlots->Test(symId))
+                        {
+                            // For jitted loop bodies that are in a try block, we consider any symbol that has a
+                            // non-temp bytecode reg slot, to be write-through. Hence, generating StSlots at all
+                            // defs for such symbols
+                            IR::Instr * stSlot = this->GenerateLoopBodyStSlot(dstRegSlot);
+                            AddInstr(stSlot, Js::Constants::NoByteCodeOffset);
 
-                    this->m_stSlots->Clear(symId);
-                }
-                else
-                {
-                    Assert(dstSym->m_isCatchObjectSym);
+                            this->m_stSlots->Clear(symId);
+                        }
+                        else
+                        {
+                            Assert(dstSym->m_isCatchObjectSym);
+                        }
+                    }
                 }
-            }
+            } NEXT_INSTR_BACKWARD_EDITING_IN_RANGE;
+
+            lastProcessedInstrForJITLoopBody = m_lastInstr;
         }
 
         offset = m_jnReader.GetCurrentOffset();

+ 20 - 0
test/Bugs/MissToGenerateStStSlotForJITLoopBody.js

@@ -0,0 +1,20 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+function test0(i)
+{
+    try{
+        for (var j = 0; j < 20010; j++) {
+            if (j > 20000)
+                return 'j ' + i + ' j in the loop ' + i;
+            else if (j > 30000)
+                return ' test0 ' + j;
+        }
+    } catch(e){}
+}
+
+var ret = test0() + ' test StSlot generation';
+
+print('pass');

+ 6 - 0
test/Bugs/rlexe.xml

@@ -380,4 +380,10 @@
       <compile-flags>-maxinterpretcount:1 -off:simplejit</compile-flags>
     </default>
   </test>
+  <test>
+    <default>
+      <files>MissToGenerateStStSlotForJITLoopBody.js</files>
+      <compile-flags>-mic:1 -off:simplejit -oopjit- -bgjit-</compile-flags>
+    </default>
+  </test>
 </regress-exe>