Mark all stack values available in an inlined callee
For DecRef -> DecRefNZ transitions. Any value on the stack at the callsite must outlive the callee.
Esse commit está contido em:
@@ -38,11 +38,10 @@ StackValueInfo getStackValue(SSATmp* sp, uint32_t index) {
|
||||
case DefSP:
|
||||
return {};
|
||||
|
||||
case ReDefGeneratorSP: {
|
||||
auto srcInst = inst->getSrc(0)->inst();
|
||||
assert(srcInst->op() == StashGeneratorSP);
|
||||
return getStackValue(srcInst->getSrc(0), index);
|
||||
}
|
||||
case ReDefGeneratorSP:
|
||||
case StashGeneratorSP:
|
||||
return getStackValue(inst->getSrc(0), index);
|
||||
|
||||
case ReDefSP:
|
||||
return getStackValue(inst->getSrc(1), index);
|
||||
|
||||
@@ -153,6 +152,18 @@ StackValueInfo getStackValue(SSATmp* sp, uint32_t index) {
|
||||
not_reached();
|
||||
}
|
||||
|
||||
smart::vector<SSATmp*> collectStackValues(SSATmp* sp, uint32_t stackDepth) {
|
||||
smart::vector<SSATmp*> ret;
|
||||
ret.reserve(stackDepth);
|
||||
for (uint32_t i = 0; i < stackDepth; ++i) {
|
||||
auto const value = getStackValue(sp, i).value;
|
||||
if (value) {
|
||||
ret.push_back(value);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void copyPropSrc(IRInstruction* inst, int index) {
|
||||
|
||||
@@ -167,6 +167,15 @@ struct StackValueInfo {
|
||||
*/
|
||||
StackValueInfo getStackValue(SSATmp* stack, uint32_t index);
|
||||
|
||||
/*
|
||||
* Return this list of all values that are known to be on the stack
|
||||
* given the particular depth.
|
||||
*
|
||||
* This function is used for computing available value for
|
||||
* DecRef->DecRefNZ conversions in tracebuilder.
|
||||
*/
|
||||
smart::vector<SSATmp*> collectStackValues(SSATmp* sp, uint32_t stackDepth);
|
||||
|
||||
/*
|
||||
* Propagate very simple copies on the given instruction.
|
||||
* Specifically, Movs, and also IncRefs of non-refcounted types.
|
||||
|
||||
@@ -73,7 +73,7 @@ bool TraceBuilder::isValueAvailable(SSATmp* tmp) const {
|
||||
while (true) {
|
||||
if (m_refCountedMemValue == tmp) return true;
|
||||
if (anyLocalHasValue(tmp)) return true;
|
||||
if (callerLocalHasValue(tmp)) return true;
|
||||
if (callerHasValueAvailable(tmp)) return true;
|
||||
|
||||
IRInstruction* srcInstr = tmp->inst();
|
||||
Opcode srcOpcode = srcInstr->op();
|
||||
@@ -126,6 +126,12 @@ void TraceBuilder::trackDefInlineFP(IRInstruction* inst) {
|
||||
m_spOffset = savedSPOff;
|
||||
m_spValue = savedSP;
|
||||
|
||||
auto const stackValues = collectStackValues(m_spValue, m_spOffset);
|
||||
for (DEBUG_ONLY auto& val : stackValues) {
|
||||
FTRACE(4, " marking caller stack value available: {}\n",
|
||||
val->toString());
|
||||
}
|
||||
|
||||
m_inlineSavedStates.push_back(createState());
|
||||
|
||||
/*
|
||||
@@ -146,6 +152,9 @@ void TraceBuilder::trackDefInlineFP(IRInstruction* inst) {
|
||||
m_callerAvailableValues.insert(m_callerAvailableValues.end(),
|
||||
m_localValues.begin(),
|
||||
m_localValues.end());
|
||||
m_callerAvailableValues.insert(m_callerAvailableValues.end(),
|
||||
stackValues.begin(),
|
||||
stackValues.end());
|
||||
|
||||
m_localValues.clear();
|
||||
m_localTypes.clear();
|
||||
@@ -603,7 +612,7 @@ SSATmp* TraceBuilder::preOptimizeDecRefThis(IRInstruction* inst) {
|
||||
* frame, so debug_backtrace() can't see a non-live pointer value.
|
||||
*/
|
||||
if (thisInst->op() == IncRef &&
|
||||
callerLocalHasValue(thisInst->getSrc(0))) {
|
||||
callerHasValueAvailable(thisInst->getSrc(0))) {
|
||||
gen(DecRefNZ, thiss);
|
||||
inst->convertToNop();
|
||||
return nullptr;
|
||||
@@ -919,7 +928,7 @@ bool TraceBuilder::anyLocalHasValue(SSATmp* tmp) const {
|
||||
tmp) != m_localValues.end();
|
||||
}
|
||||
|
||||
bool TraceBuilder::callerLocalHasValue(SSATmp* tmp) const {
|
||||
bool TraceBuilder::callerHasValueAvailable(SSATmp* tmp) const {
|
||||
return std::find(m_callerAvailableValues.begin(),
|
||||
m_callerAvailableValues.end(),
|
||||
tmp) != m_callerAvailableValues.end();
|
||||
|
||||
@@ -316,7 +316,7 @@ private:
|
||||
SSATmp* getLocalValue(unsigned id) const;
|
||||
bool isValueAvailable(SSATmp*) const;
|
||||
bool anyLocalHasValue(SSATmp*) const;
|
||||
bool callerLocalHasValue(SSATmp*) const;
|
||||
bool callerHasValueAvailable(SSATmp*) const;
|
||||
void updateLocalRefValues(SSATmp* oldRef, SSATmp* newRef);
|
||||
void trackDefInlineFP(IRInstruction* inst);
|
||||
void trackInlineReturn(IRInstruction* inst);
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário