X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..1df5f87f1309a8daa30dabdee855f48ae40d14ab:/profiler/Profiler.cpp diff --git a/profiler/Profiler.cpp b/profiler/Profiler.cpp index e103fd1..bcaaaac 100644 --- a/profiler/Profiler.cpp +++ b/profiler/Profiler.cpp @@ -31,12 +31,15 @@ #include "CommonIdentifiers.h" #include "CallFrame.h" +#include "CodeBlock.h" +#include "InternalFunction.h" #include "JSFunction.h" #include "JSGlobalObject.h" #include "Nodes.h" #include "Profile.h" #include "ProfileGenerator.h" #include "ProfileNode.h" +#include "UStringConcatenate.h" #include namespace JSC { @@ -45,7 +48,7 @@ static const char* GlobalCodeExecution = "(program)"; static const char* AnonymousFunction = "(anonymous function)"; static unsigned ProfilesUID = 0; -static CallIdentifier createCallIdentifierFromFunctionImp(JSGlobalData*, JSFunction*); +static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSFunction*); Profiler* Profiler::s_sharedProfiler = 0; Profiler* Profiler::s_sharedEnabledProfilerReference = 0; @@ -63,25 +66,25 @@ void Profiler::startProfiling(ExecState* exec, const UString& title) // Check if we currently have a Profile for this global ExecState and title. // If so return early and don't create a new Profile. - ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0; + JSGlobalObject* origin = exec ? exec->lexicalGlobalObject() : 0; for (size_t i = 0; i < m_currentProfiles.size(); ++i) { ProfileGenerator* profileGenerator = m_currentProfiles[i].get(); - if (profileGenerator->originatingGlobalExec() == globalExec && profileGenerator->title() == title) + if (profileGenerator->origin() == origin && profileGenerator->title() == title) return; } s_sharedEnabledProfilerReference = this; - RefPtr profileGenerator = ProfileGenerator::create(title, exec, ++ProfilesUID); + RefPtr profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID); m_currentProfiles.append(profileGenerator); } PassRefPtr Profiler::stopProfiling(ExecState* exec, const UString& title) { - ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0; + JSGlobalObject* origin = exec ? exec->lexicalGlobalObject() : 0; for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) { ProfileGenerator* profileGenerator = m_currentProfiles[i].get(); - if (profileGenerator->originatingGlobalExec() == globalExec && (title.isNull() || profileGenerator->title() == title)) { + if (profileGenerator->origin() == origin && (title.isNull() || profileGenerator->title() == title)) { profileGenerator->stopProfiling(); RefPtr returnProfile = profileGenerator->profile(); @@ -96,64 +99,87 @@ PassRefPtr Profiler::stopProfiling(ExecState* exec, const UString& titl return 0; } -static inline void dispatchFunctionToProfiles(const Vector >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup) +void Profiler::stopProfiling(JSGlobalObject* origin) +{ + for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) { + ProfileGenerator* profileGenerator = m_currentProfiles[i].get(); + if (profileGenerator->origin() == origin) { + profileGenerator->stopProfiling(); + m_currentProfiles.remove(i); + if (!m_currentProfiles.size()) + s_sharedEnabledProfilerReference = 0; + } + } +} + +static inline void dispatchFunctionToProfiles(ExecState* callerOrHandlerCallFrame, const Vector >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup) { for (size_t i = 0; i < profiles.size(); ++i) { - if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->originatingGlobalExec()) - (profiles[i].get()->*function)(callIdentifier); + if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->origin()) + (profiles[i].get()->*function)(callerOrHandlerCallFrame, callIdentifier); } } -void Profiler::willExecute(ExecState* exec, JSValue function) +void Profiler::willExecute(ExecState* callerCallFrame, JSValue function) { ASSERT(!m_currentProfiles.isEmpty()); - dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(&exec->globalData(), function, "", 0), exec->lexicalGlobalObject()->profileGroup()); + dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup()); } -void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber) +void Profiler::willExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber) { ASSERT(!m_currentProfiles.isEmpty()); - CallIdentifier callIdentifier = createCallIdentifier(&exec->globalData(), JSValue(), sourceURL, startingLineNumber); + CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber); + + dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, callerCallFrame->lexicalGlobalObject()->profileGroup()); +} + +void Profiler::didExecute(ExecState* callerCallFrame, JSValue function) +{ + ASSERT(!m_currentProfiles.isEmpty()); - dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup()); + dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup()); } -void Profiler::didExecute(ExecState* exec, JSValue function) +void Profiler::didExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber) { ASSERT(!m_currentProfiles.isEmpty()); - dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), function, "", 0), exec->lexicalGlobalObject()->profileGroup()); + dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber), callerCallFrame->lexicalGlobalObject()->profileGroup()); } -void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber) +void Profiler::exceptionUnwind(ExecState* handlerCallFrame) { ASSERT(!m_currentProfiles.isEmpty()); - dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup()); + dispatchFunctionToProfiles(handlerCallFrame, m_currentProfiles, &ProfileGenerator::exceptionUnwind, createCallIdentifier(handlerCallFrame, JSValue(), "", 0), handlerCallFrame->lexicalGlobalObject()->profileGroup()); } -CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValue function, const UString& defaultSourceURL, int defaultLineNumber) +CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber) { - if (!function) + if (!functionValue) return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber); - if (!function.isObject()) + if (!functionValue.isObject()) return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber); - if (asObject(function)->inherits(&JSFunction::info)) { - JSFunction* func = asFunction(function); - if (!func->isHostFunction()) - return createCallIdentifierFromFunctionImp(globalData, func); + if (asObject(functionValue)->inherits(&JSFunction::s_info)) { + JSFunction* function = asFunction(functionValue); + if (!function->executable()->isHostFunction()) + return createCallIdentifierFromFunctionImp(exec, function); } - if (asObject(function)->inherits(&InternalFunction::info)) - return CallIdentifier(static_cast(asObject(function))->name(globalData), defaultSourceURL, defaultLineNumber); - return CallIdentifier("(" + asObject(function)->className() + " object)", defaultSourceURL, defaultLineNumber); + if (asObject(functionValue)->inherits(&JSFunction::s_info)) + return CallIdentifier(static_cast(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber); + if (asObject(functionValue)->inherits(&InternalFunction::s_info)) + return CallIdentifier(static_cast(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber); + return CallIdentifier(makeUString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber); } -CallIdentifier createCallIdentifierFromFunctionImp(JSGlobalData* globalData, JSFunction* function) +CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function) { - const UString& name = function->calculatedDisplayName(globalData); - return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->body()->sourceURL(), function->body()->lineNo()); + ASSERT(!function->isHostFunction()); + const UString& name = function->calculatedDisplayName(exec); + return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->jsExecutable()->sourceURL(), function->jsExecutable()->lineNo()); } } // namespace JSC