Skip to content

Commit c84ba70

Browse files
LouisLafpleath
authored andcommitted
Recover perf regression from CVE-2019-0992. Recognize induction variable like patterns which are preserving number values
1 parent 53b75c5 commit c84ba70

File tree

4 files changed

+65
-2
lines changed

4 files changed

+65
-2
lines changed

lib/Backend/BackwardPass.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1645,6 +1645,8 @@ BackwardPass::ProcessLoop(BasicBlock * lastBlock)
16451645
{
16461646
Assert(loop->symsAssignedToInLoop == nullptr);
16471647
loop->symsAssignedToInLoop = JitAnew(this->globOpt->alloc, BVSparse<JitArenaAllocator>, this->globOpt->alloc);
1648+
Assert(loop->preservesNumberValue == nullptr);
1649+
loop->preservesNumberValue = JitAnew(this->globOpt->alloc, BVSparse<JitArenaAllocator>, this->globOpt->alloc);
16481650
}
16491651

16501652
FOREACH_BLOCK_BACKWARD_IN_RANGE_DEAD_OR_ALIVE(block, lastBlock, nullptr)
@@ -7418,6 +7420,41 @@ BackwardPass::TrackFloatSymEquivalence(IR::Instr *const instr)
74187420
}
74197421
}
74207422

7423+
bool
7424+
BackwardPass::SymIsIntconstOrSelf(Sym *sym, IR::Opnd *opnd)
7425+
{
7426+
Assert(sym->IsStackSym());
7427+
if (!opnd->IsRegOpnd())
7428+
{
7429+
return false;
7430+
}
7431+
StackSym *opndSym = opnd->AsRegOpnd()->m_sym;
7432+
7433+
if (sym == opndSym)
7434+
{
7435+
return true;
7436+
}
7437+
7438+
if (!opndSym->IsSingleDef())
7439+
{
7440+
return false;
7441+
}
7442+
7443+
if (opndSym->GetInstrDef()->m_opcode == Js::OpCode::LdC_A_I4)
7444+
{
7445+
return true;
7446+
}
7447+
7448+
return false;
7449+
}
7450+
7451+
bool
7452+
BackwardPass::InstrPreservesNumberValues(IR::Instr *instr, Sym *defSym)
7453+
{
7454+
return (OpCodeAttr::ProducesNumber(instr->m_opcode) ||
7455+
(instr->m_opcode == Js::OpCode::Add_A && this->SymIsIntconstOrSelf(defSym, instr->GetSrc1()) && this->SymIsIntconstOrSelf(defSym, instr->GetSrc2())));
7456+
}
7457+
74217458
bool
74227459
BackwardPass::ProcessDef(IR::Opnd * opnd)
74237460
{
@@ -7432,7 +7469,19 @@ BackwardPass::ProcessDef(IR::Opnd * opnd)
74327469
this->InvalidateCloneStrCandidate(opnd);
74337470
if ((tag == Js::BackwardPhase) && IsPrePass())
74347471
{
7435-
this->currentPrePassLoop->symsAssignedToInLoop->Set(sym->m_id);
7472+
bool firstDef = !this->currentPrePassLoop->symsAssignedToInLoop->TestAndSet(sym->m_id);
7473+
7474+
if (firstDef)
7475+
{
7476+
if (this->InstrPreservesNumberValues(this->currentInstr, sym))
7477+
{
7478+
this->currentPrePassLoop->preservesNumberValue->Set(sym->m_id);
7479+
}
7480+
}
7481+
else if (!this->InstrPreservesNumberValues(this->currentInstr, sym))
7482+
{
7483+
this->currentPrePassLoop->preservesNumberValue->Clear(sym->m_id);
7484+
}
74367485
}
74377486
}
74387487
}

lib/Backend/BackwardPass.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class BackwardPass
3636
bool ProcessDef(IR::Opnd * opnd);
3737
void ProcessTransfers(IR::Instr * instr);
3838
void ProcessFieldKills(IR::Instr * instr);
39+
bool SymIsIntconstOrSelf(Sym *sym, IR::Opnd *opnd);
40+
bool InstrPreservesNumberValues(IR::Instr *instr, Sym *defSym);
41+
3942
template<typename T> void ClearBucketsOnFieldKill(IR::Instr *instr, HashTable<T> *table);
4043
StackSym* ProcessByteCodeUsesDst(IR::ByteCodeUsesInstr * byteCodeUsesInstr);
4144
const BVSparse<JitArenaAllocator>* ProcessByteCodeUsesSrcs(IR::ByteCodeUsesInstr * byteCodeUsesInstr);

lib/Backend/FlowGraph.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ class Loop
588588
// cleanup in PreOptPeep in the pre-pass of a loop. For aggressively transferring
589589
// values in prepass, we need to know if a source sym was ever assigned to in a loop.
590590
BVSparse<JitArenaAllocator> *symsAssignedToInLoop;
591+
BVSparse<JitArenaAllocator> *preservesNumberValue;
591592

592593
BailOutInfo * bailOutInfo;
593594
IR::BailOutInstr * toPrimitiveSideEffectCheck;
@@ -733,6 +734,7 @@ class Loop
733734
symsAssignedToInLoop(nullptr),
734735
needImplicitCallBailoutChecksForJsArrayCheckHoist(false),
735736
inductionVariables(nullptr),
737+
preservesNumberValue(nullptr),
736738
dominatingLoopCountableBlock(nullptr),
737739
loopCount(nullptr),
738740
loopCountBasedBoundBaseSyms(nullptr),

lib/Backend/GlobOpt.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2721,7 +2721,16 @@ GlobOpt::IsNonNumericRegOpnd(IR::RegOpnd *opnd, bool inGlobOpt) const
27212721

27222722
Value * opndValue = this->currentBlock->globOptData.FindValue(opnd->m_sym);
27232723
ValueInfo * opndValueInfo = opndValue ? opndValue->GetValueInfo() : nullptr;
2724-
return !opndValueInfo || !this->IsSafeToTransferInPrepass(opnd->m_sym, opndValueInfo);
2724+
if (!opndValueInfo)
2725+
{
2726+
return true;
2727+
}
2728+
if (currentBlock->loop->preservesNumberValue->Test(opnd->m_sym->m_id))
2729+
{
2730+
return false;
2731+
}
2732+
2733+
return !this->IsSafeToTransferInPrepass(opnd->m_sym, opndValueInfo);
27252734
}
27262735

27272736
return true;

0 commit comments

Comments
 (0)