Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

September 2018 Security Update #5688

Merged
merged 10 commits into from
Sep 11, 2018
Merged
14 changes: 12 additions & 2 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14500,13 +14500,23 @@ GlobOpt::OptHoistUpdateValueType(
// Replace above will free srcOpnd, so reassign it
*srcOpndPtr = srcOpnd = reinterpret_cast<IR::Opnd *>(strOpnd);

if (loop->bailOutInfo->bailOutInstr)
if (IsImplicitCallBailOutCurrentlyNeeded(convPrimStrInstr, opndValueInLandingPad, nullptr, landingPad, landingPad->globOptData.liveFields->IsEmpty(), true, true))
{
EnsureBailTarget(loop);
loop->bailOutInfo->bailOutInstr->InsertBefore(convPrimStrInstr);
convPrimStrInstr = convPrimStrInstr->ConvertToBailOutInstr(convPrimStrInstr, IR::BailOutOnImplicitCallsPreOp, loop->bailOutInfo->bailOutOffset);
convPrimStrInstr->ReplaceBailOutInfo(loop->bailOutInfo);
}
else
{
landingPad->InsertAfter(convPrimStrInstr);
if (loop->bailOutInfo->bailOutInstr)
{
loop->bailOutInfo->bailOutInstr->InsertBefore(convPrimStrInstr);
}
else
{
landingPad->InsertAfter(convPrimStrInstr);
}
}

// If we came here opndSym can't be PropertySym
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/GlobOpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ class GlobOpt
void DetermineLoopCount(Loop *const loop);
void GenerateLoopCount(Loop *const loop, LoopCount *const loopCount);
void GenerateLoopCountPlusOne(Loop *const loop, LoopCount *const loopCount);
void GenerateSecondaryInductionVariableBound(Loop *const loop, StackSym *const inductionVariableSym, const LoopCount *const loopCount, const int maxMagnitudeChange, StackSym *const boundSym);
void GenerateSecondaryInductionVariableBound(Loop *const loop, StackSym *const inductionVariableSym, LoopCount *const loopCount, const int maxMagnitudeChange, const bool needsMagnitudeAdjustment, StackSym *const boundSym);

private:
void DetermineArrayBoundCheckHoistability(bool needLowerBoundCheck, bool needUpperBoundCheck, ArrayLowerBoundCheckHoistInfo &lowerHoistInfo, ArrayUpperBoundCheckHoistInfo &upperHoistInfo, const bool isJsArray, StackSym *const indexSym, Value *const indexValue, const IntConstantBounds &indexConstantBounds, StackSym *const headSegmentLengthSym, Value *const headSegmentLengthValue, const IntConstantBounds &headSegmentLengthConstantBounds, Loop *const headSegmentLengthInvariantLoop, bool &failedToUpdateCompatibleLowerBoundCheck, bool &failedToUpdateCompatibleUpperBoundCheck);
Expand Down
22 changes: 18 additions & 4 deletions lib/Backend/GlobOptArrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -902,30 +902,37 @@ void GlobOpt::ArraySrcOpt::DoLowerBoundCheck()
Assert(hoistInfo.Loop()->bailOutInfo);
globOpt->EnsureBailTarget(hoistInfo.Loop());

bool needsMagnitudeAdjustment = false;
if (hoistInfo.LoopCount())
{
// Generate the loop count and loop count based bound that will be used for the bound check
if (!hoistInfo.LoopCount()->HasBeenGenerated())
{
globOpt->GenerateLoopCount(hoistInfo.Loop(), hoistInfo.LoopCount());
}
needsMagnitudeAdjustment = (hoistInfo.MaxMagnitudeChange() > 0)
? (hoistInfo.IndexOffset() < hoistInfo.MaxMagnitudeChange())
: (hoistInfo.IndexOffset() > hoistInfo.MaxMagnitudeChange());

globOpt->GenerateSecondaryInductionVariableBound(
hoistInfo.Loop(),
indexVarSym->GetInt32EquivSym(nullptr),
hoistInfo.LoopCount(),
hoistInfo.MaxMagnitudeChange(),
needsMagnitudeAdjustment,
hoistInfo.IndexSym());
}

IR::Opnd* lowerBound = IR::IntConstOpnd::New(0, TyInt32, instr->m_func, true);
IR::Opnd* upperBound = IR::RegOpnd::New(indexIntSym, TyInt32, instr->m_func);
int offset = needsMagnitudeAdjustment ? (hoistInfo.IndexOffset() - hoistInfo.Offset()) : hoistInfo.Offset();
upperBound->SetIsJITOptimizedReg(true);

// 0 <= indexSym + offset (src1 <= src2 + dst)
IR::Instr *const boundCheck = globOpt->CreateBoundsCheckInstr(
lowerBound,
upperBound,
hoistInfo.Offset(),
offset,
hoistInfo.IsLoopCountBasedBound()
? IR::BailOutOnFailedHoistedLoopCountBasedBoundCheck
: IR::BailOutOnFailedHoistedBoundCheck,
Expand Down Expand Up @@ -1148,18 +1155,23 @@ void GlobOpt::ArraySrcOpt::DoUpperBoundCheck()
Assert(hoistInfo.Loop()->bailOutInfo);
globOpt->EnsureBailTarget(hoistInfo.Loop());

bool needsMagnitudeAdjustment = false;
if (hoistInfo.LoopCount())
{
// Generate the loop count and loop count based bound that will be used for the bound check
if (!hoistInfo.LoopCount()->HasBeenGenerated())
{
globOpt->GenerateLoopCount(hoistInfo.Loop(), hoistInfo.LoopCount());
}
needsMagnitudeAdjustment = (hoistInfo.MaxMagnitudeChange() > 0)
? (hoistInfo.IndexOffset() < hoistInfo.MaxMagnitudeChange())
: (hoistInfo.IndexOffset() > hoistInfo.MaxMagnitudeChange());
globOpt->GenerateSecondaryInductionVariableBound(
hoistInfo.Loop(),
indexVarSym->GetInt32EquivSym(nullptr),
hoistInfo.LoopCount(),
hoistInfo.MaxMagnitudeChange(),
needsMagnitudeAdjustment,
hoistInfo.IndexSym());
}

Expand All @@ -1174,11 +1186,13 @@ void GlobOpt::ArraySrcOpt::DoUpperBoundCheck()
IR::Opnd* upperBound = IR::RegOpnd::New(headSegmentLengthSym, headSegmentLengthSym->GetType(), instr->m_func);
upperBound->SetIsJITOptimizedReg(true);

int offset = needsMagnitudeAdjustment ? (hoistInfo.IndexOffset() + hoistInfo.Offset()) : hoistInfo.Offset();

// indexSym <= headSegmentLength + offset (src1 <= src2 + dst)
IR::Instr *const boundCheck = globOpt->CreateBoundsCheckInstr(
lowerBound,
upperBound,
hoistInfo.Offset(),
offset,
hoistInfo.IsLoopCountBasedBound()
? IR::BailOutOnFailedHoistedLoopCountBasedBoundCheck
: IR::BailOutOnFailedHoistedBoundCheck,
Expand All @@ -1197,7 +1211,7 @@ void GlobOpt::ArraySrcOpt::DoUpperBoundCheck()
landingPad->GetBlockNum(),
hoistInfo.IndexSym()->m_id,
headSegmentLengthSym->m_id,
hoistInfo.Offset());
offset);
}
else
{
Expand All @@ -1209,7 +1223,7 @@ void GlobOpt::ArraySrcOpt::DoUpperBoundCheck()
landingPad->GetBlockNum(),
hoistInfo.IndexConstantBounds().LowerBound(),
headSegmentLengthSym->m_id,
hoistInfo.Offset());
offset);
}

TESTTRACE_PHASE_INSTR(
Expand Down
4 changes: 4 additions & 0 deletions lib/Backend/GlobOptFields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,10 @@ GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr)
}
}
break;
case Js::TypeIds_NativeIntArray:
case Js::TypeIds_NativeFloatArray:
// Do not mark these values as definite to protect against array conversion
break;
case Js::TypeIds_Array:
// Because array can change type id, we can only make it definite if we are doing array check hoist
// so that implicit call will be installed between the array checks.
Expand Down
35 changes: 31 additions & 4 deletions lib/Backend/GlobOptIntBounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ void GlobOpt::ArrayLowerBoundCheckHoistInfo::SetLoop(
void GlobOpt::ArrayLowerBoundCheckHoistInfo::SetLoop(
::Loop *const loop,
StackSym *const indexSym,
const int indexOffset,
const int offset,
Value *const indexValue,
const IntConstantBounds &indexConstantBounds,
Expand All @@ -91,6 +92,7 @@ void GlobOpt::ArrayLowerBoundCheckHoistInfo::SetLoop(

this->loop = loop;
this->indexSym = indexSym;
this->indexOffset = indexOffset;
this->offset = offset;
this->indexValueNumber = indexValue->GetValueNumber();
this->indexValue = indexValue;
Expand Down Expand Up @@ -142,6 +144,7 @@ void GlobOpt::ArrayUpperBoundCheckHoistInfo::SetLoop(
void GlobOpt::ArrayUpperBoundCheckHoistInfo::SetLoop(
::Loop *const loop,
StackSym *const indexSym,
const int indexOffset,
const int offset,
Value *const indexValue,
const IntConstantBounds &indexConstantBounds,
Expand All @@ -151,7 +154,7 @@ void GlobOpt::ArrayUpperBoundCheckHoistInfo::SetLoop(
{
Assert(headSegmentLengthValue);

SetLoop(loop, indexSym, offset, indexValue, indexConstantBounds, isLoopCountBasedBound);
SetLoop(loop, indexSym, indexOffset, offset, indexValue, indexConstantBounds, isLoopCountBasedBound);
this->headSegmentLengthValue = headSegmentLengthValue;
this->headSegmentLengthConstantBounds = headSegmentLengthConstantBounds;
}
Expand Down Expand Up @@ -1831,8 +1834,9 @@ void GlobOpt::GenerateLoopCountPlusOne(Loop *const loop, LoopCount *const loopCo
void GlobOpt::GenerateSecondaryInductionVariableBound(
Loop *const loop,
StackSym *const inductionVariableSym,
const LoopCount *const loopCount,
LoopCount *const loopCount,
const int maxMagnitudeChange,
const bool needsMagnitudeAdjustment,
StackSym *const boundSym)
{
Assert(loop);
Expand All @@ -1857,18 +1861,33 @@ void GlobOpt::GenerateSecondaryInductionVariableBound(
Assert(insertBeforeInstr);
Func *const func = bailOutInfo->bailOutFunc;

StackSym* loopCountSym = nullptr;

// If indexOffset < maxMagnitudeChange, we need to account for the difference between them in the bound check
// i.e. BoundCheck: inductionVariable + loopCountMinusOne * maxMagnitudeChange + maxMagnitudeChange - indexOffset <= length - offset
// Since the BoundCheck instruction already deals with offset, we can simplify this to
// BoundCheck: inductionVariable + loopCount * maxMagnitudeChange <= length + indexOffset - offset
if (needsMagnitudeAdjustment)
{
GenerateLoopCountPlusOne(loop, loopCount);
loopCountSym = loopCount->LoopCountSym();
}
else
{
loopCountSym = loopCount->LoopCountMinusOneSym();
}
// intermediateValue = loopCount * maxMagnitudeChange
StackSym *intermediateValueSym;
if(maxMagnitudeChange == 1 || maxMagnitudeChange == -1)
{
intermediateValueSym = loopCount->LoopCountMinusOneSym();
intermediateValueSym = loopCountSym;
}
else
{
IR::BailOutInstr *const instr = IR::BailOutInstr::New(Js::OpCode::Mul_I4, bailOutKind, bailOutInfo, func);

instr->SetSrc1(
IR::RegOpnd::New(loopCount->LoopCountMinusOneSym(), loopCount->LoopCountMinusOneSym()->GetType(), func));
IR::RegOpnd::New(loopCountSym, loopCountSym->GetType(), func));
instr->GetSrc1()->SetIsJITOptimizedReg(true);

instr->SetSrc2(IR::IntConstOpnd::New(maxMagnitudeChange, TyInt32, func, true));
Expand Down Expand Up @@ -2418,6 +2437,7 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
loop,
indexSym,
lowerOffset,
lowerOffset,
landingPadIndexValue,
landingPadIndexConstantBounds);
}
Expand Down Expand Up @@ -2469,11 +2489,13 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
// Normalize the offset such that:
// boundBase <= headSegmentLength + offset
// Where (offset = -1 - boundOffset), and -1 is to simulate < instead of <=.
int indexOffset = upperOffset;
upperOffset = -1 - upperOffset;

upperHoistInfo.SetLoop(
loop,
indexSym,
indexOffset,
upperOffset,
landingPadIndexValue,
landingPadIndexConstantBounds,
Expand Down Expand Up @@ -2619,6 +2641,7 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
loop,
indexBoundBaseSym,
offset,
offset,
landingPadIndexBoundBaseValue,
landingPadIndexBoundBaseConstantBounds);
break;
Expand All @@ -2643,11 +2666,13 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
// Normalize the offset such that:
// boundBase <= headSegmentLength + offset
// Where (offset = -1 - boundOffset), and -1 is to simulate < instead of <=.
int indexOffset = offset;
offset = -1 - offset;

upperHoistInfo.SetLoop(
loop,
indexBoundBaseSym,
indexOffset,
offset,
landingPadIndexBoundBaseValue,
landingPadIndexBoundBaseConstantBounds,
Expand Down Expand Up @@ -3139,6 +3164,7 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
lowerHoistInfo.SetLoop(
currentLoop,
indexLoopCountBasedBoundBaseSym,
indexOffset,
offset,
indexLoopCountBasedBoundBaseValue,
indexLoopCountBasedBoundBaseConstantBounds,
Expand All @@ -3153,6 +3179,7 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
upperHoistInfo.SetLoop(
currentLoop,
indexLoopCountBasedBoundBaseSym,
indexOffset,
offset,
indexLoopCountBasedBoundBaseValue,
indexLoopCountBasedBoundBaseConstantBounds,
Expand Down
12 changes: 10 additions & 2 deletions lib/Backend/GlobOptIntBounds.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ class GlobOpt::ArrayLowerBoundCheckHoistInfo

// Info populated for a compatible bound check and for hoisting out of loop
StackSym *indexSym;
int indexOffset;
int offset;
ValueNumber indexValueNumber;

Expand Down Expand Up @@ -287,6 +288,12 @@ class GlobOpt::ArrayLowerBoundCheckHoistInfo
return offset;
}

int32 IndexOffset() const
{
Assert(HasAnyInfo());
return indexOffset;
}

void UpdateOffset(int newOffset)
{
Assert(HasAnyInfo());
Expand Down Expand Up @@ -334,7 +341,7 @@ class GlobOpt::ArrayLowerBoundCheckHoistInfo
public:
void SetCompatibleBoundCheck(BasicBlock *const compatibleBoundCheckBlock, StackSym *const indexSym, const int offset, const ValueNumber indexValueNumber);
void SetLoop(::Loop *const loop, const int indexConstantValue, const bool isLoopCountBasedBound = false);
void SetLoop(::Loop *const loop, StackSym *const indexSym, const int offset, Value *const indexValue, const IntConstantBounds &indexConstantBounds, const bool isLoopCountBasedBound = false);
void SetLoop(::Loop *const loop, StackSym *const indexSym, const int indexOffset, const int offset, Value *const indexValue, const IntConstantBounds &indexConstantBounds, const bool isLoopCountBasedBound = false);
void SetLoopCount(::LoopCount *const loopCount, const int maxMagnitudeChange);
};

Expand All @@ -353,6 +360,7 @@ class GlobOpt::ArrayUpperBoundCheckHoistInfo : protected ArrayLowerBoundCheckHoi
using Base::CompatibleBoundCheckBlock;
using Base::Loop;
using Base::IndexSym;
using Base::IndexOffset;
using Base::Offset;
using Base::UpdateOffset;
using Base::IndexValueNumber;
Expand Down Expand Up @@ -385,5 +393,5 @@ class GlobOpt::ArrayUpperBoundCheckHoistInfo : protected ArrayLowerBoundCheckHoi
public:
void SetCompatibleBoundCheck(BasicBlock *const compatibleBoundCheckBlock, const int indexConstantValue);
void SetLoop(::Loop *const loop, const int indexConstantValue, Value *const headSegmentLengthValue, const IntConstantBounds &headSegmentLengthConstantBounds, const bool isLoopCountBasedBound = false);
void SetLoop(::Loop *const loop, StackSym *const indexSym, const int offset, Value *const indexValue, const IntConstantBounds &indexConstantBounds, Value *const headSegmentLengthValue, const IntConstantBounds &headSegmentLengthConstantBounds, const bool isLoopCountBasedBound = false);
void SetLoop(::Loop *const loop, StackSym *const indexSym, const int indexOffset, const int offset, Value *const indexValue, const IntConstantBounds &indexConstantBounds, Value *const headSegmentLengthValue, const IntConstantBounds &headSegmentLengthConstantBounds, const bool isLoopCountBasedBound = false);
};
Loading