diff --git a/lib/Backend/GlobOptBailOut.cpp b/lib/Backend/GlobOptBailOut.cpp index 804d9ae751b..b9c37173604 100644 --- a/lib/Backend/GlobOptBailOut.cpp +++ b/lib/Backend/GlobOptBailOut.cpp @@ -1085,6 +1085,43 @@ GlobOpt::ConvertToByteCodeUses(IR::Instr * instr) this->CaptureByteCodeSymUses(instr); IR::ByteCodeUsesInstr * byteCodeUsesInstr = this->InsertByteCodeUses(instr, true); instr->Remove(); + // If possible, we want to aggregate with subsequent ByteCodeUses Instructions, so + // that we can do some optimizations in other places where we can simplify args in + // a compare, but still need to generate them for bailouts. Without this, we cause + // problems because we end up with an instruction losing atomicity in terms of its + // bytecode use and generation lifetimes. + if (byteCodeUsesInstr && + byteCodeUsesInstr->m_next && + byteCodeUsesInstr->m_next->m_opcode == Js::OpCode::ByteCodeUses && + byteCodeUsesInstr->GetByteCodeOffset() == byteCodeUsesInstr->m_next->GetByteCodeOffset() + ) + { + IR::ByteCodeUsesInstr * nextinstr = byteCodeUsesInstr->m_next->AsByteCodeUsesInstr(); + if (nextinstr->GetDst() == nullptr) + { + // We move all of the uses of the next bytecodeuses instruction into this one. The + // instruction is notably not removed or repurposed; unfortunately, at this point, + // doing either would be somewhat complex. Removing the instruction breaks some of + // the assumptions made in other code (notably RemoveCodeAfterNoFallthroughInstr), + // and repurposing it by removing the newly-added byteCodeUsesInstr requires us to + // be able to handle transferring the Dst reg in a couple more cases (like if it's + // single-def). + if (nextinstr->byteCodeUpwardExposedUsed) + { + if (byteCodeUsesInstr->byteCodeUpwardExposedUsed) + { + byteCodeUsesInstr->byteCodeUpwardExposedUsed->Or(nextinstr->byteCodeUpwardExposedUsed); + JitAdelete(nextinstr->byteCodeUpwardExposedUsed->GetAllocator(), nextinstr->byteCodeUpwardExposedUsed); + nextinstr->byteCodeUpwardExposedUsed = nullptr; + } + else + { + byteCodeUsesInstr->byteCodeUpwardExposedUsed = nextinstr->byteCodeUpwardExposedUsed; + nextinstr->byteCodeUpwardExposedUsed = nullptr; + } + } + } + } return byteCodeUsesInstr; } diff --git a/test/Bugs/bug9080773_2.js b/test/Bugs/bug9080773_2.js new file mode 100644 index 00000000000..5cad9d61436 --- /dev/null +++ b/test/Bugs/bug9080773_2.js @@ -0,0 +1,15 @@ +//------------------------------------------------------------------------------------------------------- +// 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() { + var protoObj1 = {}; + for (var __loopSecondaryVar1000_0 = 10; protoObj1.length; protoObj1) { + var v4 = prop0 >>> 0 < 0; + } +} +test0(); +test0(); +test0(); + +WScript.Echo("PASSED"); diff --git a/test/Bugs/rlexe.xml b/test/Bugs/rlexe.xml index 266134bd921..f165c0cb8bb 100644 --- a/test/Bugs/rlexe.xml +++ b/test/Bugs/rlexe.xml @@ -290,6 +290,12 @@ -maxinterpretcount:1 -off:simplejit + + + bug9080773_2.js + -maxinterpretcount:1 -maxsimplejitruncount:1 + + b208_asmjs.js