|
@@ -92,119 +92,135 @@ GlobOpt::CaptureValuesIncremental(BasicBlock * block,
|
|
|
|
|
|
|
|
FOREACH_BITSET_IN_SPARSEBV(symId, block->globOptData.changedSyms)
|
|
FOREACH_BITSET_IN_SPARSEBV(symId, block->globOptData.changedSyms)
|
|
|
{
|
|
{
|
|
|
- Sym * sym = hasConstValue ? iterConst.Data().Key() : nullptr;
|
|
|
|
|
Value * val = nullptr;
|
|
Value * val = nullptr;
|
|
|
- HashBucket<Sym *, Value *> * symIdBucket = nullptr;
|
|
|
|
|
|
|
|
|
|
- // copy unchanged sym to new capturedValues
|
|
|
|
|
- while (sym && sym->m_id < symId)
|
|
|
|
|
|
|
+ // First process all unchanged syms with m_id < symId. Then, recapture the current changed sym.
|
|
|
|
|
+
|
|
|
|
|
+ // copy unchanged const sym to new capturedValues
|
|
|
|
|
+ Sym * constSym = hasConstValue ? iterConst.Data().Key() : nullptr;
|
|
|
|
|
+ while (constSym && constSym->m_id < symId)
|
|
|
{
|
|
{
|
|
|
- Assert(sym->IsStackSym());
|
|
|
|
|
- if (!sym->AsStackSym()->HasArgSlotNum())
|
|
|
|
|
|
|
+ Assert(constSym->IsStackSym());
|
|
|
|
|
+ if (!constSym->AsStackSym()->HasArgSlotNum())
|
|
|
{
|
|
{
|
|
|
- bailOutConstValuesIter.InsertNodeBefore(this->func->m_alloc, sym->AsStackSym(), iterConst.Data().Value());
|
|
|
|
|
|
|
+ bailOutConstValuesIter.InsertNodeBefore(this->func->m_alloc, constSym->AsStackSym(), iterConst.Data().Value());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
hasConstValue = iterConst.Next();
|
|
hasConstValue = iterConst.Next();
|
|
|
- sym = hasConstValue ? iterConst.Data().Key() : nullptr;
|
|
|
|
|
|
|
+ constSym = hasConstValue ? iterConst.Data().Key() : nullptr;
|
|
|
}
|
|
}
|
|
|
- if (sym && sym->m_id == symId)
|
|
|
|
|
|
|
+ if (constSym && constSym->m_id == symId)
|
|
|
{
|
|
{
|
|
|
hasConstValue = iterConst.Next();
|
|
hasConstValue = iterConst.Next();
|
|
|
}
|
|
}
|
|
|
- if (symId != Js::Constants::InvalidSymID)
|
|
|
|
|
- {
|
|
|
|
|
- // recapture changed constant sym
|
|
|
|
|
|
|
|
|
|
- symIdBucket = block->globOptData.symToValueMap->GetBucket(symId);
|
|
|
|
|
- if (symIdBucket == nullptr)
|
|
|
|
|
- {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- Sym * symIdSym = symIdBucket->value;
|
|
|
|
|
- Assert(symIdSym->IsStackSym() && (symIdSym->AsStackSym()->HasByteCodeRegSlot() || symIdSym->AsStackSym()->HasArgSlotNum()));
|
|
|
|
|
-
|
|
|
|
|
- val = symIdBucket->element;
|
|
|
|
|
- ValueInfo* valueInfo = val->GetValueInfo();
|
|
|
|
|
-
|
|
|
|
|
- if (valueInfo->GetSymStore() != nullptr)
|
|
|
|
|
- {
|
|
|
|
|
- int32 intConstValue;
|
|
|
|
|
- BailoutConstantValue constValue;
|
|
|
|
|
-
|
|
|
|
|
- if (valueInfo->TryGetIntConstantValue(&intConstValue))
|
|
|
|
|
- {
|
|
|
|
|
- constValue.InitIntConstValue(intConstValue);
|
|
|
|
|
- bailOutConstValuesIter.InsertNodeBefore(this->func->m_alloc, symIdSym->AsStackSym(), constValue);
|
|
|
|
|
-
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- else if(valueInfo->IsVarConstant())
|
|
|
|
|
- {
|
|
|
|
|
- constValue.InitVarConstValue(valueInfo->AsVarConstant()->VarValue());
|
|
|
|
|
- bailOutConstValuesIter.InsertNodeBefore(this->func->m_alloc, symIdSym->AsStackSym(), constValue);
|
|
|
|
|
-
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- else if (!valueInfo->HasIntConstantValue())
|
|
|
|
|
- {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- sym = hasCopyPropSym ? iterCopyPropSym.Data().Key() : nullptr;
|
|
|
|
|
-
|
|
|
|
|
- // process unchanged sym, but copy sym might have changed
|
|
|
|
|
- while (sym && sym->m_id < symId)
|
|
|
|
|
|
|
+ // process unchanged sym; copy-prop sym might have changed
|
|
|
|
|
+ Sym * capturedSym = hasCopyPropSym ? iterCopyPropSym.Data().Key() : nullptr;
|
|
|
|
|
+ while (capturedSym && capturedSym->m_id < symId)
|
|
|
{
|
|
{
|
|
|
- StackSym * copyPropSym = iterCopyPropSym.Data().Value();
|
|
|
|
|
|
|
+ StackSym * capturedCopyPropSym = iterCopyPropSym.Data().Value();
|
|
|
|
|
|
|
|
- Assert(sym->IsStackSym());
|
|
|
|
|
|
|
+ Assert(capturedSym->IsStackSym());
|
|
|
|
|
|
|
|
- if (!block->globOptData.changedSyms->Test(copyPropSym->m_id))
|
|
|
|
|
|
|
+ if (!block->globOptData.changedSyms->Test(capturedCopyPropSym->m_id))
|
|
|
{
|
|
{
|
|
|
- if (!sym->AsStackSym()->HasArgSlotNum())
|
|
|
|
|
|
|
+ if (!capturedSym->AsStackSym()->HasArgSlotNum())
|
|
|
{
|
|
{
|
|
|
- bailOutCopySymsIter.InsertNodeBefore(this->func->m_alloc, sym->AsStackSym(), copyPropSym);
|
|
|
|
|
|
|
+ bailOutCopySymsIter.InsertNodeBefore(this->func->m_alloc, capturedSym->AsStackSym(), capturedCopyPropSym);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- if (!sym->AsStackSym()->HasArgSlotNum())
|
|
|
|
|
|
|
+ if (!capturedSym->AsStackSym()->HasArgSlotNum())
|
|
|
{
|
|
{
|
|
|
- val = this->currentBlock->globOptData.FindValue(sym);
|
|
|
|
|
|
|
+ val = this->currentBlock->globOptData.FindValue(capturedSym);
|
|
|
if (val != nullptr)
|
|
if (val != nullptr)
|
|
|
{
|
|
{
|
|
|
- CaptureCopyPropValue(block, sym, val, bailOutCopySymsIter);
|
|
|
|
|
|
|
+ CaptureCopyPropValue(block, capturedSym, val, bailOutCopySymsIter);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
hasCopyPropSym = iterCopyPropSym.Next();
|
|
hasCopyPropSym = iterCopyPropSym.Next();
|
|
|
- sym = hasCopyPropSym ? iterCopyPropSym.Data().Key() : nullptr;
|
|
|
|
|
|
|
+ capturedSym = hasCopyPropSym ? iterCopyPropSym.Data().Key() : nullptr;
|
|
|
}
|
|
}
|
|
|
- if (sym && sym->m_id == symId)
|
|
|
|
|
|
|
+ if (capturedSym && capturedSym->m_id == symId)
|
|
|
{
|
|
{
|
|
|
hasCopyPropSym = iterCopyPropSym.Next();
|
|
hasCopyPropSym = iterCopyPropSym.Next();
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // recapture changed sym
|
|
|
|
|
+ HashBucket<Sym *, Value *> * symIdBucket = nullptr;
|
|
|
if (symId != Js::Constants::InvalidSymID)
|
|
if (symId != Js::Constants::InvalidSymID)
|
|
|
{
|
|
{
|
|
|
- // recapture changed copy prop sym
|
|
|
|
|
symIdBucket = block->globOptData.symToValueMap->GetBucket(symId);
|
|
symIdBucket = block->globOptData.symToValueMap->GetBucket(symId);
|
|
|
if (symIdBucket != nullptr)
|
|
if (symIdBucket != nullptr)
|
|
|
{
|
|
{
|
|
|
Sym * symIdSym = symIdBucket->value;
|
|
Sym * symIdSym = symIdBucket->value;
|
|
|
- val = this->currentBlock->globOptData.FindValue(symIdSym);
|
|
|
|
|
- if (val != nullptr)
|
|
|
|
|
|
|
+ Assert(symIdSym->IsStackSym() && (symIdSym->AsStackSym()->HasByteCodeRegSlot() || symIdSym->AsStackSym()->HasArgSlotNum()));
|
|
|
|
|
+
|
|
|
|
|
+ val = symIdBucket->element;
|
|
|
|
|
+ Assert(val);
|
|
|
|
|
+ ValueInfo* valueInfo = val->GetValueInfo();
|
|
|
|
|
+
|
|
|
|
|
+ if (valueInfo->GetSymStore() != nullptr)
|
|
|
{
|
|
{
|
|
|
- CaptureCopyPropValue(block, symIdSym, val, bailOutCopySymsIter);
|
|
|
|
|
|
|
+ int32 intConstValue;
|
|
|
|
|
+ BailoutConstantValue constValue;
|
|
|
|
|
+
|
|
|
|
|
+ if (valueInfo->TryGetIntConstantValue(&intConstValue))
|
|
|
|
|
+ {
|
|
|
|
|
+ constValue.InitIntConstValue(intConstValue);
|
|
|
|
|
+ bailOutConstValuesIter.InsertNodeBefore(this->func->m_alloc, symIdSym->AsStackSym(), constValue);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (valueInfo->IsVarConstant())
|
|
|
|
|
+ {
|
|
|
|
|
+ constValue.InitVarConstValue(valueInfo->AsVarConstant()->VarValue());
|
|
|
|
|
+ bailOutConstValuesIter.InsertNodeBefore(this->func->m_alloc, symIdSym->AsStackSym(), constValue);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ CaptureCopyPropValue(block, symIdSym, val, bailOutCopySymsIter);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
NEXT_BITSET_IN_SPARSEBV
|
|
NEXT_BITSET_IN_SPARSEBV
|
|
|
|
|
+
|
|
|
|
|
+ // If, after going over the set of changed syms since the last time we captured values,
|
|
|
|
|
+ // there are remaining unprocessed entries in the current captured values set,
|
|
|
|
|
+ // they can simply be copied over to the new bailout info.
|
|
|
|
|
+ while (hasConstValue)
|
|
|
|
|
+ {
|
|
|
|
|
+ Sym * constSym = iterConst.Data().Key();
|
|
|
|
|
+ Assert(constSym->IsStackSym());
|
|
|
|
|
+ Assert(!block->globOptData.changedSyms->Test(constSym->m_id));
|
|
|
|
|
+
|
|
|
|
|
+ if (!constSym->AsStackSym()->HasArgSlotNum())
|
|
|
|
|
+ {
|
|
|
|
|
+ bailOutConstValuesIter.InsertNodeBefore(this->func->m_alloc, constSym->AsStackSym(), iterConst.Data().Value());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hasConstValue = iterConst.Next();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ while (hasCopyPropSym)
|
|
|
|
|
+ {
|
|
|
|
|
+ Sym * capturedSym = iterCopyPropSym.Data().Key();
|
|
|
|
|
+ StackSym * capturedCopyPropSym = iterCopyPropSym.Data().Value();
|
|
|
|
|
+
|
|
|
|
|
+ Assert(capturedSym->IsStackSym());
|
|
|
|
|
+ Assert(!block->globOptData.changedSyms->Test(capturedSym->m_id) &&
|
|
|
|
|
+ !block->globOptData.changedSyms->Test(capturedCopyPropSym->m_id));
|
|
|
|
|
+
|
|
|
|
|
+ if (!capturedSym->AsStackSym()->HasArgSlotNum())
|
|
|
|
|
+ {
|
|
|
|
|
+ bailOutCopySymsIter.InsertNodeBefore(this->func->m_alloc, capturedSym->AsStackSym(), capturedCopyPropSym);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hasCopyPropSym = iterCopyPropSym.Next();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|