]>
git.saurik.com Git - apple/javascriptcore.git/blob - profiler/ProfileGenerator.cpp
   2  * Copyright (C) 2008 Apple Inc. All Rights Reserved. 
   4  * Redistribution and use in source and binary forms, with or without 
   5  * modification, are permitted provided that the following conditions 
   7  * 1. Redistributions of source code must retain the above copyright 
   8  *    notice, this list of conditions and the following disclaimer. 
   9  * 2. Redistributions in binary form must reproduce the above copyright 
  10  *    notice, this list of conditions and the following disclaimer in the 
  11  *    documentation and/or other materials provided with the distribution. 
  13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 
  14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR 
  17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
  19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
  21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
  22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
  23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  27 #include "ProfileGenerator.h" 
  29 #include "CallFrame.h" 
  30 #include "CodeBlock.h" 
  31 #include "JSGlobalObject.h" 
  32 #include "JSStringRef.h" 
  33 #include "JSFunction.h" 
  34 #include "Interpreter.h" 
  35 #include "LegacyProfiler.h" 
  36 #include "Operations.h" 
  42 static const char* NonJSExecution 
= "(idle)"; 
  44 PassRefPtr
<ProfileGenerator
> ProfileGenerator::create(ExecState
* exec
, const String
& title
, unsigned uid
) 
  46     return adoptRef(new ProfileGenerator(exec
, title
, uid
)); 
  49 ProfileGenerator::ProfileGenerator(ExecState
* exec
, const String
& title
, unsigned uid
) 
  50     : m_origin(exec 
? exec
->lexicalGlobalObject() : 0) 
  51     , m_profileGroup(exec 
? exec
->lexicalGlobalObject()->profileGroup() : 0) 
  53     m_profile 
= Profile::create(title
, uid
); 
  54     m_currentNode 
= m_head 
= m_profile
->head(); 
  56         addParentForConsoleStart(exec
); 
  59 void ProfileGenerator::addParentForConsoleStart(ExecState
* exec
) 
  66     exec
->interpreter()->retrieveLastCaller(exec
, lineNumber
, sourceID
, sourceURL
, function
); 
  67     m_currentNode 
= ProfileNode::create(exec
, LegacyProfiler::createCallIdentifier(exec
, function 
? function
.toThisObject(exec
) : 0, sourceURL
, lineNumber
), m_head
.get(), m_head
.get()); 
  68     m_head
->insertNode(m_currentNode
.get()); 
  71 const String
& ProfileGenerator::title() const 
  73     return m_profile
->title(); 
  76 void ProfileGenerator::willExecute(ExecState
* callerCallFrame
, const CallIdentifier
& callIdentifier
) 
  78     if (JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED()) { 
  79         CString name 
= callIdentifier
.m_name
.utf8(); 
  80         CString url 
= callIdentifier
.m_url
.utf8(); 
  81         JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(m_profileGroup
, const_cast<char*>(name
.data()), const_cast<char*>(url
.data()), callIdentifier
.m_lineNumber
); 
  87     ASSERT(m_currentNode
); 
  88     m_currentNode 
= m_currentNode
->willExecute(callerCallFrame
, callIdentifier
); 
  91 void ProfileGenerator::didExecute(ExecState
* callerCallFrame
, const CallIdentifier
& callIdentifier
) 
  93     if (JAVASCRIPTCORE_PROFILE_DID_EXECUTE_ENABLED()) { 
  94         CString name 
= callIdentifier
.m_name
.utf8(); 
  95         CString url 
= callIdentifier
.m_url
.utf8(); 
  96         JAVASCRIPTCORE_PROFILE_DID_EXECUTE(m_profileGroup
, const_cast<char*>(name
.data()), const_cast<char*>(url
.data()), callIdentifier
.m_lineNumber
); 
 102     ASSERT(m_currentNode
); 
 103     if (m_currentNode
->callIdentifier() != callIdentifier
) { 
 104         RefPtr
<ProfileNode
> returningNode 
= ProfileNode::create(callerCallFrame
, callIdentifier
, m_head
.get(), m_currentNode
.get()); 
 105         returningNode
->setStartTime(m_currentNode
->startTime()); 
 106         returningNode
->didExecute(); 
 107         m_currentNode
->insertNode(returningNode
.release()); 
 111     m_currentNode 
= m_currentNode
->didExecute(); 
 114 void ProfileGenerator::exceptionUnwind(ExecState
* handlerCallFrame
, const CallIdentifier
&) 
 116     // If the current node was called by the handler (==) or any 
 117     // more nested function (>) the we have exited early from it. 
 118     ASSERT(m_currentNode
); 
 119     while (m_currentNode
->callerCallFrame() >= handlerCallFrame
) { 
 120         didExecute(m_currentNode
->callerCallFrame(), m_currentNode
->callIdentifier()); 
 121         ASSERT(m_currentNode
); 
 125 void ProfileGenerator::stopProfiling() 
 127     m_profile
->forEach(&ProfileNode::stopProfiling
); 
 129     removeProfileStart(); 
 132     ASSERT(m_currentNode
); 
 134     // Set the current node to the parent, because we are in a call that 
 135     // will not get didExecute call. 
 136     m_currentNode 
= m_currentNode
->parent(); 
 138    if (double headSelfTime 
= m_head
->selfTime()) { 
 139         RefPtr
<ProfileNode
> idleNode 
= ProfileNode::create(0, CallIdentifier(NonJSExecution
, String(), 0), m_head
.get(), m_head
.get()); 
 141         idleNode
->setTotalTime(headSelfTime
); 
 142         idleNode
->setSelfTime(headSelfTime
); 
 143         idleNode
->setVisible(true); 
 145         m_head
->setSelfTime(0.0); 
 146         m_head
->addChild(idleNode
.release()); 
 150 // The console.ProfileGenerator that started this ProfileGenerator will be the first child. 
 151 void ProfileGenerator::removeProfileStart() 
 153     ProfileNode
* currentNode 
= 0; 
 154     for (ProfileNode
* next 
= m_head
.get(); next
; next 
= next
->firstChild()) 
 157     if (currentNode
->callIdentifier().m_name 
!= "profile") 
 160     // Attribute the time of the node aobut to be removed to the self time of its parent 
 161     currentNode
->parent()->setSelfTime(currentNode
->parent()->selfTime() + currentNode
->totalTime()); 
 162     currentNode
->parent()->removeChild(currentNode
); 
 165 // The console.ProfileGeneratorEnd that stopped this ProfileGenerator will be the last child. 
 166 void ProfileGenerator::removeProfileEnd() 
 168     ProfileNode
* currentNode 
= 0; 
 169     for (ProfileNode
* next 
= m_head
.get(); next
; next 
= next
->lastChild()) 
 172     if (currentNode
->callIdentifier().m_name 
!= "profileEnd") 
 175     // Attribute the time of the node aobut to be removed to the self time of its parent 
 176     currentNode
->parent()->setSelfTime(currentNode
->parent()->selfTime() + currentNode
->totalTime()); 
 178     ASSERT(currentNode
->callIdentifier() == (currentNode
->parent()->children()[currentNode
->parent()->children().size() - 1])->callIdentifier()); 
 179     currentNode
->parent()->removeChild(currentNode
);