X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/2d39b0e377c0896910ee49ae70082ba665faf986..refs/heads/master:/profiler/ProfileNode.cpp?ds=sidebyside diff --git a/profiler/ProfileNode.cpp b/profiler/ProfileNode.cpp index cb86787..9bcf375 100644 --- a/profiler/ProfileNode.cpp +++ b/profiler/ProfileNode.cpp @@ -38,58 +38,35 @@ using namespace WTF; namespace JSC { -ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode) +ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode) : m_callerCallFrame(callerCallFrame) , m_callIdentifier(callIdentifier) - , m_head(headNode) , m_parent(parentNode) +#ifndef NDEBUG , m_nextSibling(nullptr) - , m_totalTime(0) - , m_selfTime(0) +#endif { - startTimer(); } -ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy) +ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy) : m_callerCallFrame(callerCallFrame) , m_callIdentifier(nodeToCopy->callIdentifier()) - , m_head(headNode) , m_parent(nodeToCopy->parent()) - , m_nextSibling(0) - , m_totalTime(nodeToCopy->totalTime()) - , m_selfTime(nodeToCopy->selfTime()) , m_calls(nodeToCopy->calls()) +#ifndef NDEBUG + , m_nextSibling(nullptr) +#endif { } -ProfileNode* ProfileNode::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier) -{ - for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) { - if ((*currentChild)->callIdentifier() == callIdentifier) { - (*currentChild)->startTimer(); - return (*currentChild).get(); - } - } - - RefPtr newChild = ProfileNode::create(callerCallFrame, callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head. - if (m_children.size()) - m_children.last()->setNextSibling(newChild.get()); - m_children.append(newChild.release()); - return m_children.last().get(); -} - -ProfileNode* ProfileNode::didExecute() -{ - endAndRecordCall(); - return m_parent; -} - void ProfileNode::addChild(PassRefPtr prpChild) { RefPtr child = prpChild; child->setParent(this); +#ifndef NDEBUG if (m_children.size()) m_children.last()->setNextSibling(child.get()); +#endif m_children.append(child.release()); } @@ -98,17 +75,18 @@ void ProfileNode::removeChild(ProfileNode* node) if (!node) return; - for (size_t i = 0; i < m_children.size(); ++i) { - if (*node == m_children[i].get()) { - m_children.remove(i); - break; - } - } - - resetChildrensSiblings(); + m_children.removeFirstMatching([node] (const RefPtr& current) { + return *node == current.get(); + }); + +#ifndef NDEBUG + size_t size = m_children.size(); + for (size_t i = 0; i < size; ++i) + m_children[i]->setNextSibling(i + 1 == size ? nullptr : m_children[i + 1].get()); +#endif } -void ProfileNode::insertNode(PassRefPtr prpNode) +void ProfileNode::spliceNode(PassRefPtr prpNode) { RefPtr node = prpNode; @@ -119,21 +97,7 @@ void ProfileNode::insertNode(PassRefPtr prpNode) m_children.append(node.release()); } -void ProfileNode::stopProfiling() -{ - ASSERT(!m_calls.isEmpty()); - - if (isnan(m_calls.last().totalTime())) - endAndRecordCall(); - - // Because we iterate in post order all of our children have been stopped before us. - for (unsigned i = 0; i < m_children.size(); ++i) - m_selfTime += m_children[i]->totalTime(); - - ASSERT(m_selfTime <= m_totalTime); - m_selfTime = m_totalTime - m_selfTime; -} - +#ifndef NDEBUG ProfileNode* ProfileNode::traverseNextNodePostOrder() const { ProfileNode* next = m_nextSibling; @@ -144,55 +108,63 @@ ProfileNode* ProfileNode::traverseNextNodePostOrder() const return next; } -void ProfileNode::endAndRecordCall() +void ProfileNode::debugPrint() { - Call& last = lastCall(); - ASSERT(isnan(last.totalTime())); - - last.setTotalTime(currentTime() - last.startTime()); + CalculateProfileSubtreeDataFunctor functor; + forEachNodePostorder(functor); + ProfileNode::ProfileSubtreeData data = functor.returnValue(); - m_totalTime += last.totalTime(); + debugPrintRecursively(0, data); } -void ProfileNode::startTimer() +void ProfileNode::debugPrintSampleStyle() { - m_calls.append(Call(currentTime())); -} + FunctionCallHashCount countedFunctions; -void ProfileNode::resetChildrensSiblings() -{ - unsigned size = m_children.size(); - for (unsigned i = 0; i < size; ++i) - m_children[i]->setNextSibling(i + 1 == size ? 0 : m_children[i + 1].get()); + CalculateProfileSubtreeDataFunctor functor; + forEachNodePostorder(functor); + ProfileNode::ProfileSubtreeData data = functor.returnValue(); + + debugPrintSampleStyleRecursively(0, countedFunctions, data); } -#ifndef NDEBUG -void ProfileNode::debugPrintData(int indentLevel) const +void ProfileNode::debugPrintRecursively(int indentLevel, const ProfileSubtreeData& data) { // Print function names for (int i = 0; i < indentLevel; ++i) dataLogF(" "); + auto it = data.selfAndTotalTimes.find(this); + ASSERT(it != data.selfAndTotalTimes.end()); + + double nodeSelfTime = it->value.first; + double nodeTotalTime = it->value.second; + double rootTotalTime = data.rootTotalTime; + dataLogF("Function Name %s %zu SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% Next Sibling %s\n", functionName().utf8().data(), - numberOfCalls(), m_selfTime, selfPercent(), m_totalTime, totalPercent(), + m_calls.size(), nodeSelfTime, nodeSelfTime / rootTotalTime * 100.0, nodeTotalTime, nodeTotalTime / rootTotalTime * 100.0, m_nextSibling ? m_nextSibling->functionName().utf8().data() : ""); ++indentLevel; // Print children's names and information for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) - (*currentChild)->debugPrintData(indentLevel); + (*currentChild)->debugPrintRecursively(indentLevel, data); } // print the profiled data in a format that matches the tool sample's output. -double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const +double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount& countedFunctions, const ProfileSubtreeData& data) { dataLogF(" "); + auto it = data.selfAndTotalTimes.find(this); + ASSERT(it != data.selfAndTotalTimes.end()); + double nodeTotalTime = it->value.second; + // Print function names const char* name = functionName().utf8().data(); - double sampleCount = m_totalTime * 1000; + double sampleCount = nodeTotalTime * 1000; if (indentLevel) { for (int i = 0; i < indentLevel; ++i) dataLogF(" "); @@ -208,7 +180,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC // Print children's names and information double sumOfChildrensCount = 0.0; for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) - sumOfChildrensCount += (*currentChild)->debugPrintDataSampleStyle(indentLevel, countedFunctions); + sumOfChildrensCount += (*currentChild)->debugPrintSampleStyleRecursively(indentLevel, countedFunctions, data); sumOfChildrensCount *= 1000; // // Print remainder of samples to match sample's output @@ -220,7 +192,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data()); } - return m_totalTime; + return nodeTotalTime; } #endif