@@ -1996,41 +1996,76 @@ BackwardPass::ProcessBailOutCopyProps(BailOutInfo * bailOutInfo, BVSparse<JitAre
1996
1996
NEXT_SLISTBASE_ENTRY_EDITING;
1997
1997
}
1998
1998
1999
- bool
2000
- BackwardPass::ProcessBailOutInfo (IR::Instr * instr)
1999
+
2000
+ StackSym*
2001
+ BackwardPass::ProcessByteCodeUsesDst (IR::ByteCodeUsesInstr * byteCodeUsesInstr)
2001
2002
{
2002
- if (this ->tag == Js::BackwardPhase)
2003
+ Assert (this ->DoByteCodeUpwardExposedUsed ());
2004
+ IR::Opnd * dst = byteCodeUsesInstr->GetDst ();
2005
+ if (dst)
2003
2006
{
2004
- // We don't need to fill in the bailout instruction in backward pass
2005
- Assert (this ->func ->hasBailout || !instr->HasBailOutInfo ());
2006
- Assert (!instr->HasBailOutInfo () || instr->GetBailOutInfo ()->byteCodeUpwardExposedUsed == nullptr || (this ->func ->HasTry () && this ->func ->DoOptimizeTry ()));
2007
+ IR::RegOpnd * dstRegOpnd = dst->AsRegOpnd ();
2008
+ StackSym * dstStackSym = dstRegOpnd->m_sym ->AsStackSym ();
2009
+ Assert (!dstRegOpnd->GetIsJITOptimizedReg ());
2010
+ Assert (dstStackSym->GetByteCodeRegSlot () != Js::Constants::NoRegister);
2011
+ if (dstStackSym->GetType () != TyVar)
2012
+ {
2013
+ dstStackSym = dstStackSym->GetVarEquivSym (nullptr );
2014
+ }
2007
2015
2008
- if (instr->IsByteCodeUsesInstr ())
2016
+ // If the current region is a Try, symbols in its write-through set shouldn't be cleared.
2017
+ // Otherwise, symbols in the write-through set of the first try ancestor shouldn't be cleared.
2018
+ if (!this ->currentRegion ||
2019
+ !this ->CheckWriteThroughSymInRegion (this ->currentRegion , dstStackSym))
2009
2020
{
2010
- // FGPeeps inserts bytecodeuses instrs with srcs. We need to look at them to set the proper
2011
- // UpwardExposedUsed info and keep the defs alive.
2012
- // The inliner inserts bytecodeuses instrs withs dsts, but we don't want to look at them for upwardExposedUsed
2013
- // as it would cause real defs to look dead. We use these for bytecodeUpwardExposedUsed info only, which is needed
2014
- // in the dead-store pass only.
2015
- //
2016
- // Handle the source side.
2017
- IR::ByteCodeUsesInstr *byteCodeUsesInstr = instr->AsByteCodeUsesInstr ();
2018
- const BVSparse<JitArenaAllocator> * byteCodeUpwardExposedUsed = byteCodeUsesInstr->GetByteCodeUpwardExposedUsed ();
2019
- if (byteCodeUpwardExposedUsed != nullptr )
2020
- {
2021
- this ->currentBlock ->upwardExposedUses ->Or (byteCodeUpwardExposedUsed);
2022
- if (this ->DoByteCodeUpwardExposedUsed ())
2023
- {
2024
- this ->currentBlock ->byteCodeUpwardExposedUsed ->Or (byteCodeUpwardExposedUsed);
2025
- }
2026
- }
2027
- return true ;
2021
+ this ->currentBlock ->byteCodeUpwardExposedUsed ->Clear (dstStackSym->m_id );
2022
+ return dstStackSym;
2023
+
2028
2024
}
2025
+ }
2026
+ return nullptr ;
2027
+ }
2028
+
2029
+ const BVSparse<JitArenaAllocator>*
2030
+ BackwardPass::ProcessByteCodeUsesSrcs (IR::ByteCodeUsesInstr * byteCodeUsesInstr)
2031
+ {
2032
+ Assert (this ->DoByteCodeUpwardExposedUsed () || tag == Js::BackwardPhase);
2033
+ const BVSparse<JitArenaAllocator>* byteCodeUpwardExposedUsed = byteCodeUsesInstr->GetByteCodeUpwardExposedUsed ();
2034
+ if (byteCodeUpwardExposedUsed && this ->DoByteCodeUpwardExposedUsed ())
2035
+ {
2036
+ this ->currentBlock ->byteCodeUpwardExposedUsed ->Or (byteCodeUpwardExposedUsed);
2037
+ }
2038
+ return byteCodeUpwardExposedUsed;
2039
+ }
2040
+
2041
+ bool
2042
+ BackwardPass::ProcessByteCodeUsesInstr (IR::Instr * instr)
2043
+ {
2044
+ if (!instr->IsByteCodeUsesInstr ())
2045
+ {
2029
2046
return false ;
2030
2047
}
2031
2048
2032
- if (instr->IsByteCodeUsesInstr ())
2049
+ IR::ByteCodeUsesInstr * byteCodeUsesInstr = instr->AsByteCodeUsesInstr ();
2050
+
2051
+ if (this ->tag == Js::BackwardPhase)
2033
2052
{
2053
+ // FGPeeps inserts bytecodeuses instrs with srcs. We need to look at them to set the proper
2054
+ // UpwardExposedUsed info and keep the defs alive.
2055
+ // The inliner inserts bytecodeuses instrs withs dsts, but we don't want to look at them for upwardExposedUsed
2056
+ // as it would cause real defs to look dead. We use these for bytecodeUpwardExposedUsed info only, which is needed
2057
+ // in the dead-store pass only.
2058
+ //
2059
+ // Handle the source side.
2060
+ const BVSparse<JitArenaAllocator>* byteCodeUpwardExposedUsed = ProcessByteCodeUsesSrcs (byteCodeUsesInstr);
2061
+ if (byteCodeUpwardExposedUsed != nullptr )
2062
+ {
2063
+ this ->currentBlock ->upwardExposedUses ->Or (byteCodeUpwardExposedUsed);
2064
+ }
2065
+ }
2066
+ else
2067
+ {
2068
+ Assert (tag == Js::DeadStorePhase);
2034
2069
Assert (instr->m_opcode == Js::OpCode::ByteCodeUses);
2035
2070
#if DBG
2036
2071
if (this ->DoMarkTempObjectVerify () && (this ->currentBlock ->isDead || !this ->func ->hasBailout ))
@@ -2053,44 +2088,22 @@ BackwardPass::ProcessBailOutInfo(IR::Instr * instr)
2053
2088
2054
2089
if (this ->func ->hasBailout )
2055
2090
{
2056
- Assert (this ->DoByteCodeUpwardExposedUsed ());
2057
-
2058
2091
// Just collect the byte code uses, and remove the instruction
2059
2092
// We are going backward, process the dst first and then the src
2060
- IR::Opnd * dst = instr->GetDst ();
2061
- if (dst)
2062
- {
2063
- IR::RegOpnd * dstRegOpnd = dst->AsRegOpnd ();
2064
- StackSym * dstStackSym = dstRegOpnd->m_sym ->AsStackSym ();
2065
- Assert (!dstRegOpnd->GetIsJITOptimizedReg ());
2066
- Assert (dstStackSym->GetByteCodeRegSlot () != Js::Constants::NoRegister);
2067
- if (dstStackSym->GetType () != TyVar)
2068
- {
2069
- dstStackSym = dstStackSym->GetVarEquivSym (nullptr );
2070
- }
2071
-
2072
- // If the current region is a Try, symbols in its write-through set shouldn't be cleared.
2073
- // Otherwise, symbols in the write-through set of the first try ancestor shouldn't be cleared.
2074
- if (!this ->currentRegion ||
2075
- !this ->CheckWriteThroughSymInRegion (this ->currentRegion , dstStackSym))
2076
- {
2077
- this ->currentBlock ->byteCodeUpwardExposedUsed ->Clear (dstStackSym->m_id );
2093
+ StackSym *dstStackSym = ProcessByteCodeUsesDst (byteCodeUsesInstr);
2078
2094
#if DBG
2079
- // We can only track first level function stack syms right now
2080
- if (dstStackSym->GetByteCodeFunc () == this ->func )
2081
- {
2082
- this ->currentBlock ->byteCodeRestoreSyms [dstStackSym->GetByteCodeRegSlot ()] = nullptr ;
2083
- }
2084
- #endif
2085
- }
2095
+ // We can only track first level function stack syms right now
2096
+ if (dstStackSym && dstStackSym->GetByteCodeFunc () == this ->func )
2097
+ {
2098
+ this ->currentBlock ->byteCodeRestoreSyms [dstStackSym->GetByteCodeRegSlot ()] = nullptr ;
2086
2099
}
2100
+ #endif
2087
2101
2088
- IR::ByteCodeUsesInstr *byteCodeUsesInstr = instr->AsByteCodeUsesInstr ();
2089
- if (byteCodeUsesInstr->GetByteCodeUpwardExposedUsed () != nullptr )
2090
- {
2091
- this ->currentBlock ->byteCodeUpwardExposedUsed ->Or (byteCodeUsesInstr->GetByteCodeUpwardExposedUsed ());
2102
+ const BVSparse<JitArenaAllocator>* byteCodeUpwardExposedUsed = ProcessByteCodeUsesSrcs (byteCodeUsesInstr);
2092
2103
#if DBG
2093
- FOREACH_BITSET_IN_SPARSEBV (symId, byteCodeUsesInstr->GetByteCodeUpwardExposedUsed ())
2104
+ if (byteCodeUpwardExposedUsed)
2105
+ {
2106
+ FOREACH_BITSET_IN_SPARSEBV (symId, byteCodeUpwardExposedUsed)
2094
2107
{
2095
2108
StackSym * stackSym = this ->func ->m_symTable ->FindStackSym (symId);
2096
2109
Assert (!stackSym->IsTypeSpec ());
@@ -2108,16 +2121,14 @@ BackwardPass::ProcessBailOutInfo(IR::Instr * instr)
2108
2121
}
2109
2122
}
2110
2123
NEXT_BITSET_IN_SPARSEBV;
2111
- #endif
2112
2124
}
2125
+ #endif
2113
2126
2114
- if (IsCollectionPass ())
2127
+ if (IsCollectionPass ())
2115
2128
{
2116
2129
return true ;
2117
2130
}
2118
2131
2119
- ProcessPendingPreOpBailOutInfo (instr);
2120
-
2121
2132
PropertySym *propertySymUse = byteCodeUsesInstr->propertySymUse ;
2122
2133
if (propertySymUse && !this ->currentBlock ->isDead )
2123
2134
{
@@ -2133,13 +2144,27 @@ BackwardPass::ProcessBailOutInfo(IR::Instr * instr)
2133
2144
}
2134
2145
2135
2146
this ->currentBlock ->RemoveInstr (instr);
2136
- return true ;
2147
+ }
2148
+ return true ;
2149
+ }
2150
+
2151
+ bool
2152
+ BackwardPass::ProcessBailOutInfo (IR::Instr * instr)
2153
+ {
2154
+ Assert (!instr->IsByteCodeUsesInstr ());
2155
+ if (this ->tag == Js::BackwardPhase)
2156
+ {
2157
+ // We don't need to fill in the bailout instruction in backward pass
2158
+ Assert (this ->func ->hasBailout || !instr->HasBailOutInfo ());
2159
+ Assert (!instr->HasBailOutInfo () || instr->GetBailOutInfo ()->byteCodeUpwardExposedUsed == nullptr || (this ->func ->HasTry () && this ->func ->DoOptimizeTry ()));
2160
+ return false ;
2137
2161
}
2138
2162
2139
2163
if (IsCollectionPass ())
2140
2164
{
2141
2165
return false ;
2142
2166
}
2167
+ Assert (tag == Js::DeadStorePhase);
2143
2168
2144
2169
if (instr->HasBailOutInfo ())
2145
2170
{
@@ -2398,22 +2423,30 @@ BackwardPass::NeedBailOutOnImplicitCallsForTypedArrayStore(IR::Instr* instr)
2398
2423
return false ;
2399
2424
}
2400
2425
2401
- void
2426
+ IR::Instr*
2402
2427
BackwardPass::ProcessPendingPreOpBailOutInfo (IR::Instr *const currentInstr)
2403
2428
{
2404
2429
Assert (!IsCollectionPass ());
2405
2430
2406
2431
if (!preOpBailOutInstrToProcess)
2407
2432
{
2408
- return ;
2433
+ return currentInstr-> m_prev ;
2409
2434
}
2435
+ Assert (preOpBailOutInstrToProcess == currentInstr);
2410
2436
2411
- IR::Instr *const prevInstr = currentInstr->m_prev ;
2412
- if (prevInstr &&
2413
- prevInstr->IsByteCodeUsesInstr () &&
2414
- prevInstr->AsByteCodeUsesInstr ()->GetByteCodeOffset () == preOpBailOutInstrToProcess->GetByteCodeOffset ())
2437
+ if (!this ->IsPrePass ())
2415
2438
{
2416
- return ;
2439
+ IR::Instr* prev = preOpBailOutInstrToProcess->m_prev ;
2440
+ while (prev && preOpBailOutInstrToProcess->CanAggregateByteCodeUsesAcrossInstr (prev))
2441
+ {
2442
+ IR::Instr* instr = prev;
2443
+ prev = prev->m_prev ;
2444
+ if (instr->IsByteCodeUsesInstrFor (preOpBailOutInstrToProcess))
2445
+ {
2446
+ // If instr is a ByteCodeUsesInstr, it will remove it
2447
+ ProcessByteCodeUsesInstr (instr);
2448
+ }
2449
+ }
2417
2450
}
2418
2451
2419
2452
// A pre-op bailout instruction was saved for bailout info processing after the instruction and relevant ByteCodeUses
@@ -2423,6 +2456,10 @@ BackwardPass::ProcessPendingPreOpBailOutInfo(IR::Instr *const currentInstr)
2423
2456
Assert (bailOutInfo->bailOutOffset == preOpBailOutInstrToProcess->GetByteCodeOffset ());
2424
2457
ProcessBailOutInfo (preOpBailOutInstrToProcess, bailOutInfo);
2425
2458
preOpBailOutInstrToProcess = nullptr ;
2459
+
2460
+ // We might have removed the prev instr if it was a ByteCodeUsesInstr
2461
+ // Update the prevInstr on the main loop
2462
+ return currentInstr->m_prev ;
2426
2463
}
2427
2464
2428
2465
void
@@ -2720,7 +2757,7 @@ BackwardPass::ProcessBlock(BasicBlock * block)
2720
2757
MarkScopeObjSymUseForStackArgOpt ();
2721
2758
ProcessBailOnStackArgsOutOfActualsRange ();
2722
2759
2723
- if (ProcessNoImplicitCallUses (instr) || this ->ProcessBailOutInfo (instr))
2760
+ if (ProcessNoImplicitCallUses (instr) || this ->ProcessByteCodeUsesInstr (instr) || this -> ProcessBailOutInfo (instr))
2724
2761
{
2725
2762
continue ;
2726
2763
}
@@ -3531,7 +3568,7 @@ BackwardPass::ProcessBlock(BasicBlock * block)
3531
3568
}
3532
3569
}
3533
3570
#endif
3534
- ProcessPendingPreOpBailOutInfo (instr);
3571
+ instrPrev = ProcessPendingPreOpBailOutInfo (instr);
3535
3572
3536
3573
#if DBG_DUMP
3537
3574
if (!IsCollectionPass () && IsTraceEnabled () && Js::Configuration::Global.flags .Verbose )
0 commit comments