Skip to content

Commit

Permalink
Fix handling of changing function return status and checking of cyclic
Browse files Browse the repository at this point in the history
dependencies
1. Even blocked frame can have a changed return status, so need to
resume delayed caller
2. Due to parallel parsing, when a thread parses a call site, the
callee may still have a UNSET return status, and the callee is being
parsed by another thread. When all threads' work is done, the UNSET
return status is expired, and we need to revalidate delayed work
  • Loading branch information
mxz297 committed May 31, 2018
1 parent 9f497d9 commit d62e349
Showing 1 changed file with 21 additions and 20 deletions.
41 changes: 21 additions & 20 deletions parseAPI/src/Parser.C
Expand Up @@ -503,6 +503,7 @@ LockFreeQueueItem<ParseFrame *> *Parser::postProcessFrame(ParseFrame *pf, bool r
}

}
resumeFrames(pf->func, work);
break;
}
case ParseFrame::PARSED:{
Expand Down Expand Up @@ -667,12 +668,30 @@ Parser::parse_frames(LockFreeQueue<ParseFrame *> &work, bool recursive)
bool done = false, cycle = false;
{
boost::lock_guard<DelayedFrames> g(delayed_frames);
if(delayed_frames.frames.empty()) {

// Check if we can resume any frames yet
vector<Function *> updated;
for (auto iter = delayed_frames.frames.begin();
iter != delayed_frames.frames.end();
++iter) {
if (iter->first->retstatus() != UNSET) {
updated.push_back(iter->first);
}
}
if (updated.size()) {
for (auto uIter = updated.begin();
uIter != updated.end();
++uIter) {
resumeFrames((*uIter), work);
}
}

if(delayed_frames.frames.empty() && updated.empty()) {
parsing_printf("[%s] Fixed point reached (0 funcs with unknown return status)\n)",
__FILE__);
delayed_frames.size = 0;
done = true;
} else if(delayed_frames.size == delayed_frames.frames.size()) {
} else if(delayed_frames.size == delayed_frames.frames.size() && updated.empty()) {
cycle = true;
}
}
Expand All @@ -699,24 +718,6 @@ void Parser::processFixedPoint(LockFreeQueue<ParseFrame *> &work, bool recursive

// Update delayed_frames.size for next iteration
delayed_frames.size = delayed_frames.frames.size();

// Check if we can resume any frames yet
vector<Function *> updated;
for (auto iter = delayed_frames.frames.begin();
iter != delayed_frames.frames.end();
++iter) {
if (iter->first->retstatus() != UNSET) {
updated.push_back(iter->first);
}
}

if (updated.size()) {
for (auto uIter = updated.begin();
uIter != updated.end();
++uIter) {
resumeFrames((*uIter), work);
}
}
}
// Recurse through parse_frames
parsing_printf("[%s] Calling parse_frames again... \n", __FILE__);
Expand Down

0 comments on commit d62e349

Please sign in to comment.