Skip to content

Commit 26c2c65

Browse files
committed
Aggregate byteCodeUpwardExposedUsed for ByteCodeUses instrs across ToVar, Ld_A, and BailOnNotObject
1 parent afdc851 commit 26c2c65

File tree

4 files changed

+114
-18
lines changed

4 files changed

+114
-18
lines changed

lib/Backend/GlobOpt.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2643,6 +2643,16 @@ GlobOpt::OptInstr(IR::Instr *&instr, bool* isInstrRemoved)
26432643
this->InsertByteCodeUses(instr);
26442644
}
26452645

2646+
if (!IsLoopPrePass() && instr->HasBailOutInfo())
2647+
{
2648+
// Aggregate byteCodeUpwardExposedUsed of preceding ByteCodeUses instrs with the same bytecode offset.
2649+
// This is required as different ByteCodeUses instrs may be inserted for an instr in the loop pre-pass
2650+
// and the main pass (and there may be additional instructions inserted between the two sets of
2651+
// ByteCodeUses instructions), but the Backward Pass only processes immediately preceding consecutive
2652+
// ByteCodeUses instructions before processing a pre-op bailout.
2653+
instr->AggregateByteCodeUses();
2654+
}
2655+
26462656
if (!this->IsLoopPrePass() && !isHoisted && this->IsImplicitCallBailOutCurrentlyNeeded(instr, src1Val, src2Val))
26472657
{
26482658
IR::BailOutKind kind = IR::BailOutOnImplicitCalls;
@@ -9588,7 +9598,7 @@ GlobOpt::TypeSpecializeBinary(IR::Instr **pInstr, Value **pSrc1Val, Value **pSrc
95889598
// calculation, we want to insert the Conv_bool after the whole compare instruction
95899599
// block.
95909600
IR::Instr *putAfter = instr;
9591-
while (putAfter->m_next && putAfter->m_next->m_opcode == Js::OpCode::ByteCodeUses)
9601+
while (putAfter->m_next && putAfter->m_next->IsByteCodeUsesInstrFor(instr))
95929602
{
95939603
putAfter = putAfter->m_next;
95949604
}

lib/Backend/GlobOptBailOut.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ GlobOpt::ConvertToByteCodeUses(IR::Instr * instr)
10761076
instr->Remove();
10771077
if (byteCodeUsesInstr)
10781078
{
1079-
byteCodeUsesInstr->Aggregate();
1079+
byteCodeUsesInstr->AggregateFollowingByteCodeUses();
10801080
}
10811081
return byteCodeUsesInstr;
10821082
}

lib/Backend/IR.cpp

Lines changed: 93 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -984,28 +984,69 @@ void ByteCodeUsesInstr::SetBV(BVSparse<JitArenaAllocator>* newbv)
984984
// a compare, but still need to generate them for bailouts. Without this, we cause
985985
// problems because we end up with an instruction losing atomicity in terms of its
986986
// bytecode use and generation lifetimes.
987-
void ByteCodeUsesInstr::Aggregate()
987+
void ByteCodeUsesInstr::AggregateFollowingByteCodeUses()
988988
{
989989
IR::Instr* scanner = this->m_next;
990990
while (scanner && scanner->m_opcode == Js::OpCode::ByteCodeUses && scanner->GetByteCodeOffset() == this->GetByteCodeOffset() && scanner->GetDst() == nullptr)
991991
{
992992
IR::ByteCodeUsesInstr* target = scanner->AsByteCodeUsesInstr();
993-
Assert(this->m_func == target->m_func);
994-
if (target->byteCodeUpwardExposedUsed)
993+
this->Aggregate(target);
994+
scanner = scanner->m_next;
995+
}
996+
}
997+
998+
void ByteCodeUsesInstr::AggregatePrecedingByteCodeUses()
999+
{
1000+
IR::Instr * instr = this->m_prev;
1001+
while (instr && this->CanAggregateByteCodeUsesAcrossInstr(instr))
1002+
{
1003+
if (instr->IsByteCodeUsesInstr())
9951004
{
996-
if (this->byteCodeUpwardExposedUsed)
997-
{
998-
this->byteCodeUpwardExposedUsed->Or(target->byteCodeUpwardExposedUsed);
999-
JitAdelete(target->byteCodeUpwardExposedUsed->GetAllocator(), target->byteCodeUpwardExposedUsed);
1000-
target->byteCodeUpwardExposedUsed = nullptr;
1001-
}
1002-
else
1003-
{
1004-
this->byteCodeUpwardExposedUsed = target->byteCodeUpwardExposedUsed;
1005-
target->byteCodeUpwardExposedUsed = nullptr;
1006-
}
1005+
IR::ByteCodeUsesInstr* precedingByteCodeUsesInstr = instr->AsByteCodeUsesInstr();
1006+
this->Aggregate(precedingByteCodeUsesInstr);
1007+
}
1008+
instr = instr->m_prev;
1009+
}
1010+
}
1011+
1012+
void ByteCodeUsesInstr::Aggregate(ByteCodeUsesInstr * byteCodeUsesInstr)
1013+
{
1014+
Assert(this->m_func == byteCodeUsesInstr->m_func);
1015+
if (byteCodeUsesInstr->byteCodeUpwardExposedUsed)
1016+
{
1017+
if (this->byteCodeUpwardExposedUsed)
1018+
{
1019+
this->byteCodeUpwardExposedUsed->Or(byteCodeUsesInstr->byteCodeUpwardExposedUsed);
1020+
JitAdelete(byteCodeUsesInstr->byteCodeUpwardExposedUsed->GetAllocator(), byteCodeUsesInstr->byteCodeUpwardExposedUsed);
1021+
byteCodeUsesInstr->byteCodeUpwardExposedUsed = nullptr;
1022+
}
1023+
else
1024+
{
1025+
this->byteCodeUpwardExposedUsed = byteCodeUsesInstr->byteCodeUpwardExposedUsed;
1026+
byteCodeUsesInstr->byteCodeUpwardExposedUsed = nullptr;
1027+
}
1028+
}
1029+
}
1030+
1031+
bool Instr::CanAggregateByteCodeUsesAcrossInstr(Instr * instr)
1032+
{
1033+
if (instr->GetByteCodeOffset() != Js::Constants::NoByteCodeOffset)
1034+
{
1035+
return (instr->GetByteCodeOffset() == this->GetByteCodeOffset()) &&
1036+
(instr->IsByteCodeUsesInstr() ||
1037+
instr->m_opcode == Js::OpCode::ToVar);
1038+
}
1039+
else
1040+
{
1041+
if (instr->HasBailOutInfo())
1042+
{
1043+
return (instr->GetBailOutInfo()->bailOutOffset == this->GetByteCodeOffset()) &&
1044+
instr->m_opcode == Js::OpCode::BailOnNotObject;
1045+
}
1046+
else
1047+
{
1048+
return (instr->m_opcode == Js::OpCode::Ld_A || instr->m_opcode == Js::OpCode::Ld_I4) && instr->GetSrc1()->IsImmediateOpnd(); // could have been inserted by PreLowerCanonicalize
10071049
}
1008-
scanner = scanner->m_next;
10091050
}
10101051
}
10111052

@@ -2838,6 +2879,27 @@ IR::Instr *Instr::GetInsertBeforeByteCodeUsesInstr()
28382879
return insertBeforeInstr;
28392880
}
28402881

2882+
IR::ByteCodeUsesInstr *
2883+
Instr::GetFirstByteCodeUsesInstrBackward()
2884+
{
2885+
IR::Instr * prevInstr = this->m_prev;
2886+
while (prevInstr && this->CanAggregateByteCodeUsesAcrossInstr(prevInstr))
2887+
{
2888+
if (prevInstr->IsByteCodeUsesInstr())
2889+
{
2890+
return prevInstr->AsByteCodeUsesInstr();
2891+
}
2892+
prevInstr = prevInstr->m_prev;
2893+
}
2894+
return nullptr;
2895+
}
2896+
2897+
bool
2898+
Instr::IsByteCodeUsesInstrFor(IR::Instr * instr) const
2899+
{
2900+
return this->IsByteCodeUsesInstr() && this->GetByteCodeOffset() == instr->GetByteCodeOffset();
2901+
}
2902+
28412903
///----------------------------------------------------------------------------
28422904
///
28432905
/// Instr::GetOrCreateContinueLabel
@@ -3341,6 +3403,22 @@ void Instr::Move(IR::Instr* insertInstr)
33413403
insertInstr->InsertBefore(this);
33423404
}
33433405

3406+
void Instr::AggregateByteCodeUses()
3407+
{
3408+
// Currently, this only aggregates byteCodeUpwardExposedUsed of those ByteCodeUses instructions
3409+
// associated with this instr which have at most a ToVar, Ld_A, Ld_I4, or a BailOnNotObject between them.
3410+
IR::ByteCodeUsesInstr * primaryByteCodeUsesInstr = this->GetFirstByteCodeUsesInstrBackward();
3411+
if (primaryByteCodeUsesInstr)
3412+
{
3413+
primaryByteCodeUsesInstr->AggregatePrecedingByteCodeUses();
3414+
if (primaryByteCodeUsesInstr != this->m_prev)
3415+
{
3416+
primaryByteCodeUsesInstr->Unlink();
3417+
this->InsertBefore(primaryByteCodeUsesInstr);
3418+
}
3419+
}
3420+
}
3421+
33443422
IR::Instr* Instr::GetBytecodeArgOutCapture()
33453423
{
33463424
Assert(this->m_opcode == Js::OpCode::ArgOut_A_Inline ||

lib/Backend/IR.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,16 @@ class Instr
290290
IR::Instr * GetPrevRealInstr() const;
291291
IR::Instr * GetPrevRealInstrOrLabel() const;
292292
IR::Instr * GetInsertBeforeByteCodeUsesInstr();
293+
IR::ByteCodeUsesInstr * GetFirstByteCodeUsesInstrBackward();
294+
bool IsByteCodeUsesInstrFor(IR::Instr * instr) const;
293295
IR::LabelInstr *GetOrCreateContinueLabel(const bool isHelper = false);
294296
static bool HasSymUseSrc(StackSym *sym, IR::Opnd*);
295297
static bool HasSymUseDst(StackSym *sym, IR::Opnd*);
296298
bool HasSymUse(StackSym *sym);
297299
static bool HasSymUseInRange(StackSym *sym, Instr *instrBegin, Instr *instrEnd);
298300
RegOpnd * FindRegDef(StackSym *sym);
299301
static Instr* FindSingleDefInstr(Js::OpCode opCode, Opnd* src);
302+
bool CanAggregateByteCodeUsesAcrossInstr(IR::Instr * instr);
300303

301304
BranchInstr * ChangeCmCCToBranchInstr(LabelInstr *targetInstr);
302305
static void MoveRangeAfter(Instr * instrStart, Instr * instrLast, Instr * instrAfter);
@@ -466,6 +469,7 @@ class Instr
466469
bool UsesAllFields();
467470
void MoveArgs(bool generateByteCodeCapture = false);
468471
void Move(IR::Instr* insertInstr);
472+
void AggregateByteCodeUses();
469473
private:
470474
void ClearNumber() { this->m_number = 0; }
471475
void SetNumber(uint32 number);
@@ -571,7 +575,11 @@ class ByteCodeUsesInstr : public Instr
571575
// a compare, but still need to generate them for bailouts. Without this, we cause
572576
// problems because we end up with an instruction losing atomicity in terms of its
573577
// bytecode use and generation lifetimes.
574-
void Aggregate();
578+
void AggregateFollowingByteCodeUses();
579+
void AggregatePrecedingByteCodeUses();
580+
581+
private:
582+
void Aggregate(ByteCodeUsesInstr * byteCodeUsesInstr);
575583
};
576584

577585
class JitProfilingInstr : public Instr

0 commit comments

Comments
 (0)