ControlFlowProfiler.cpp [plain text]
#include "config.h"
#include "ControlFlowProfiler.h"
#include "VM.h"
namespace JSC {
ControlFlowProfiler::ControlFlowProfiler()
: m_dummyBasicBlock(BasicBlockLocation(-1, -1))
{
}
ControlFlowProfiler::~ControlFlowProfiler()
{
for (const BlockLocationCache& cache : m_sourceIDBuckets.values()) {
for (BasicBlockLocation* block : cache.values())
delete block;
}
}
BasicBlockLocation* ControlFlowProfiler::getBasicBlockLocation(intptr_t sourceID, int startOffset, int endOffset)
{
auto addResult = m_sourceIDBuckets.add(sourceID, BlockLocationCache());
BlockLocationCache& blockLocationCache = addResult.iterator->value;
BasicBlockKey key(startOffset, endOffset);
auto addResultForBasicBlock = blockLocationCache.add(key, nullptr);
if (addResultForBasicBlock.isNewEntry)
addResultForBasicBlock.iterator->value = new BasicBlockLocation(startOffset, endOffset);
return addResultForBasicBlock.iterator->value;
}
void ControlFlowProfiler::dumpData() const
{
auto iter = m_sourceIDBuckets.begin();
auto end = m_sourceIDBuckets.end();
for (; iter != end; ++iter) {
dataLog("SourceID: ", iter->key, "\n");
for (const BasicBlockLocation* block : iter->value.values())
block->dumpData();
}
}
Vector<BasicBlockRange> ControlFlowProfiler::getBasicBlocksForSourceID(intptr_t sourceID, VM& vm) const
{
Vector<BasicBlockRange> result(0);
auto bucketFindResult = m_sourceIDBuckets.find(sourceID);
if (bucketFindResult == m_sourceIDBuckets.end())
return result;
const BlockLocationCache& cache = bucketFindResult->value;
for (const BasicBlockLocation* block : cache.values()) {
bool hasExecuted = block->hasExecuted();
const Vector<BasicBlockLocation::Gap>& blockRanges = block->getExecutedRanges();
for (BasicBlockLocation::Gap gap : blockRanges) {
BasicBlockRange range;
range.m_hasExecuted = hasExecuted;
range.m_startOffset = gap.first;
range.m_endOffset = gap.second;
result.append(range);
}
}
const Vector<std::tuple<bool, unsigned, unsigned>>& unexecutedFunctionRanges = vm.functionHasExecutedCache()->getFunctionRanges(sourceID);
for (const auto& functionRange : unexecutedFunctionRanges) {
BasicBlockRange range;
range.m_hasExecuted = std::get<0>(functionRange);
range.m_startOffset = static_cast<int>(std::get<1>(functionRange));
range.m_endOffset = static_cast<int>(std::get<2>(functionRange));
result.append(range);
}
return result;
}
bool ControlFlowProfiler::hasBasicBlockAtTextOffsetBeenExecuted(int offset, intptr_t sourceID, VM& vm)
{
const Vector<BasicBlockRange>& blocks = getBasicBlocksForSourceID(sourceID, vm);
int bestDistance = INT_MAX;
BasicBlockRange bestRange;
bestRange.m_startOffset = bestRange.m_endOffset = -1;
bestRange.m_hasExecuted = false; for (BasicBlockRange range : blocks) {
if (range.m_startOffset <= offset && offset <= range.m_endOffset && (range.m_endOffset - range.m_startOffset) < bestDistance) {
RELEASE_ASSERT(range.m_endOffset - range.m_startOffset >= 0);
bestDistance = range.m_endOffset - range.m_startOffset;
bestRange = range;
}
}
RELEASE_ASSERT(bestRange.m_startOffset != -1 && bestRange.m_endOffset != -1);
return bestRange.m_hasExecuted;
}
}