Unreviewed rollout r200924. Caused js/regress/string-replace-generic.html to fail.
authorjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 May 2016 22:31:13 +0000 (22:31 +0000)
committerjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 May 2016 22:31:13 +0000 (22:31 +0000)
.:

* ManualTests/inspector/profiler-test-call.html: Added.
* ManualTests/inspector/profiler-test-many-calls-in-the-same-scope.html: Added.

Source/JavaScriptCore:

* API/JSProfilerPrivate.cpp: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
(JSStartProfiling):
(JSEndProfiling):
* API/JSProfilerPrivate.h: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::generateUnlinkedFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::unlinkedCodeBlockFor):
* bytecode/UnlinkedFunctionExecutable.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitCallVarargs):
(JSC::BytecodeGenerator::emitCallVarargsInTailPosition):
(JSC::BytecodeGenerator::emitConstructVarargs):
(JSC::BytecodeGenerator::emitConstruct):
* bytecompiler/BytecodeGenerator.h:
(JSC::CallArguments::profileHookRegister):
(JSC::BytecodeGenerator::shouldEmitProfileHooks):
* bytecompiler/NodesCodegen.cpp:
(JSC::CallArguments::CallArguments):
(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* inspector/InjectedScriptBase.cpp:
(Inspector::InjectedScriptBase::callFunctionWithEvalEnabled):
* inspector/protocol/Timeline.json:
* interpreter/Interpreter.cpp:
(JSC::UnwindFunctor::operator()):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_profile_will_call):
(JSC::JIT::emit_op_profile_did_call):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_profile_will_call):
(JSC::JIT::emit_op_profile_did_call):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jsc.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LLIntSlowPaths.h:
* llint/LowLevelInterpreter.asm:
* parser/ParserModes.h:
* profiler/CallIdentifier.h: Added.
(JSC::CallIdentifier::CallIdentifier):
(JSC::CallIdentifier::functionName):
(JSC::CallIdentifier::url):
(JSC::CallIdentifier::lineNumber):
(JSC::CallIdentifier::columnNumber):
(JSC::CallIdentifier::operator==):
(JSC::CallIdentifier::operator!=):
(JSC::CallIdentifier::Hash::hash):
(JSC::CallIdentifier::Hash::equal):
(JSC::CallIdentifier::hash):
(JSC::CallIdentifier::operator const char*):
(JSC::CallIdentifier::c_str):
(WTF::HashTraits<JSC::CallIdentifier>::constructDeletedValue):
(WTF::HashTraits<JSC::CallIdentifier>::isDeletedValue):
* profiler/LegacyProfiler.cpp: Added.
(JSC::LegacyProfiler::profiler):
(JSC::LegacyProfiler::startProfiling):
(JSC::LegacyProfiler::stopProfiling):
(JSC::callFunctionForProfilesWithGroup):
(JSC::LegacyProfiler::suspendProfiling):
(JSC::LegacyProfiler::unsuspendProfiling):
(JSC::LegacyProfiler::willExecute):
(JSC::LegacyProfiler::didExecute):
(JSC::LegacyProfiler::exceptionUnwind):
(JSC::LegacyProfiler::createCallIdentifier):
(JSC::createCallIdentifierFromFunctionImp):
* profiler/LegacyProfiler.h: Added.
(JSC::LegacyProfiler::currentProfiles):
* profiler/Profile.cpp: Added.
(JSC::Profile::create):
(JSC::Profile::Profile):
(JSC::Profile::~Profile):
(JSC::Profile::debugPrint):
(JSC::functionNameCountPairComparator):
(JSC::Profile::debugPrintSampleStyle):
* profiler/Profile.h: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
* profiler/ProfileGenerator.cpp: Added.
(JSC::ProfileGenerator::create):
(JSC::ProfileGenerator::ProfileGenerator):
(JSC::AddParentForConsoleStartFunctor::AddParentForConsoleStartFunctor):
(JSC::AddParentForConsoleStartFunctor::foundParent):
(JSC::AddParentForConsoleStartFunctor::operator()):
(JSC::ProfileGenerator::addParentForConsoleStart):
(JSC::ProfileGenerator::title):
(JSC::ProfileGenerator::beginCallEntry):
(JSC::ProfileGenerator::endCallEntry):
(JSC::ProfileGenerator::willExecute):
(JSC::ProfileGenerator::didExecute):
(JSC::ProfileGenerator::exceptionUnwind):
(JSC::ProfileGenerator::stopProfiling):
(JSC::ProfileGenerator::removeProfileStart):
(JSC::ProfileGenerator::removeProfileEnd):
* profiler/ProfileGenerator.h: Added.
(JSC::ProfileGenerator::profile):
(JSC::ProfileGenerator::origin):
(JSC::ProfileGenerator::profileGroup):
(JSC::ProfileGenerator::setIsSuspended):
* profiler/ProfileNode.cpp: Added.
(JSC::ProfileNode::ProfileNode):
(JSC::ProfileNode::addChild):
(JSC::ProfileNode::removeChild):
(JSC::ProfileNode::spliceNode):
(JSC::ProfileNode::traverseNextNodePostOrder):
(JSC::ProfileNode::debugPrint):
(JSC::ProfileNode::debugPrintSampleStyle):
(JSC::ProfileNode::debugPrintRecursively):
(JSC::ProfileNode::debugPrintSampleStyleRecursively):
* profiler/ProfileNode.h: Added.
(JSC::ProfileNode::create):
(JSC::ProfileNode::Call::Call):
(JSC::ProfileNode::Call::startTime):
(JSC::ProfileNode::Call::setStartTime):
(JSC::ProfileNode::Call::elapsedTime):
(JSC::ProfileNode::Call::setElapsedTime):
(JSC::ProfileNode::operator==):
(JSC::ProfileNode::callerCallFrame):
(JSC::ProfileNode::callIdentifier):
(JSC::ProfileNode::id):
(JSC::ProfileNode::functionName):
(JSC::ProfileNode::url):
(JSC::ProfileNode::lineNumber):
(JSC::ProfileNode::columnNumber):
(JSC::ProfileNode::parent):
(JSC::ProfileNode::setParent):
(JSC::ProfileNode::calls):
(JSC::ProfileNode::lastCall):
(JSC::ProfileNode::appendCall):
(JSC::ProfileNode::children):
(JSC::ProfileNode::firstChild):
(JSC::ProfileNode::lastChild):
(JSC::ProfileNode::nextSibling):
(JSC::ProfileNode::setNextSibling):
(JSC::ProfileNode::forEachNodePostorder):
(JSC::CalculateProfileSubtreeDataFunctor::operator()):
(JSC::CalculateProfileSubtreeDataFunctor::returnValue):
* profiler/ProfilerJettisonReason.cpp:
(WTF::printInternal):
* profiler/ProfilerJettisonReason.h:
* runtime/CodeCache.cpp:
(JSC::CodeCache::getGlobalCodeBlock):
(JSC::CodeCache::getProgramCodeBlock):
(JSC::CodeCache::getEvalCodeBlock):
(JSC::CodeCache::getModuleProgramCodeBlock):
* runtime/CodeCache.h:
* runtime/Executable.cpp:
(JSC::ScriptExecutable::newCodeBlockFor):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::~JSGlobalObject):
(JSC::JSGlobalObject::hasLegacyProfiler):
(JSC::JSGlobalObject::createProgramCodeBlock):
(JSC::JSGlobalObject::createEvalCodeBlock):
(JSC::JSGlobalObject::createModuleProgramCodeBlock):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::supportsLegacyProfiling):
* runtime/Options.h:
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::SetEnabledProfilerFunctor::operator()):
(JSC::VM::setEnabledProfiler):
* runtime/VM.h:
(JSC::VM::enabledProfiler):
(JSC::VM::enabledProfilerAddress):

Source/WebCore:

Tests: fast/profiler/*

* CMakeLists.txt:
* DerivedSources.cpp:
* DerivedSources.make:
* ForwardingHeaders/profiler/LegacyProfiler.h: Added.
* ForwardingHeaders/profiler/Profile.h: Added.
* ForwardingHeaders/profiler/ProfileNode.h: Added.
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSCustomXPathNSResolver.cpp:
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::supportsLegacyProfiling):
(WebCore::JSDOMWindowBase::supportsRichSourceInfo):
* bindings/js/JSDOMWindowBase.h:
* bindings/js/JSWorkerGlobalScopeBase.cpp:
(WebCore::JSWorkerGlobalScopeBase::supportsLegacyProfiling):
* bindings/js/JSWorkerGlobalScopeBase.h:
* bindings/js/ScriptCachedFrameData.cpp:
* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::clearWindowShell):
* bindings/js/ScriptProfile.h: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
* bindings/js/ScriptProfileNode.h: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
* bindings/scripts/CodeGeneratorJS.pm:
(AddClassForwardIfNeeded):
* bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::jsTestObjPrototypeFunctionMethodWithSequenceArg):
(WebCore::jsTestObjPrototypeFunctionMethodReturningSequence):
* bindings/scripts/test/TestObj.idl:
* css/CSSParser.cpp:
* dom/Document.cpp:
* inspector/InspectorConsoleInstrumentation.h:
(WebCore::InspectorInstrumentation::stopProfiling):
* inspector/InspectorController.cpp:
(WebCore::InspectorController::InspectorController):
(WebCore::InspectorController::legacyProfilerEnabled):
(WebCore::InspectorController::setLegacyProfilerEnabled):
* inspector/InspectorController.h:
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::stopProfilingImpl):
* inspector/InspectorInstrumentation.h:
* inspector/InspectorTimelineAgent.cpp:
(WebCore::InspectorTimelineAgent::startFromConsole):
(WebCore::InspectorTimelineAgent::stopFromConsole):
* inspector/InspectorTimelineAgent.h:
* inspector/PageDebuggerAgent.cpp:
* inspector/PageRuntimeAgent.cpp:
* inspector/ScriptProfile.idl: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
* inspector/ScriptProfileNode.idl: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
* inspector/TimelineRecordFactory.cpp:
(WebCore::buildAggregateCallInfoInspectorObject):
(WebCore::buildInspectorObject):
(WebCore::buildProfileInspectorObject):
(WebCore::TimelineRecordFactory::appendProfile):
* inspector/TimelineRecordFactory.h:
* page/DOMWindow.cpp:
* page/Page.cpp:
* page/PageConsoleClient.cpp:
(WebCore::PageConsoleClient::profileEnd):
(WebCore::PageConsoleClient::clearProfiles):
* page/PageConsoleClient.h:
* testing/Internals.cpp:
(WebCore::Internals::resetToConsistentState):
(WebCore::Internals::consoleProfiles):
(WebCore::Internals::setLegacyJavaScriptProfilingEnabled):
* testing/Internals.h:
* testing/Internals.idl:
* testing/js/WebCoreTestSupport.cpp:
* xml/XSLStyleSheetLibxslt.cpp:
* xml/XSLTProcessorLibxslt.cpp:

Source/WebKit/win:

* Interfaces/IWebInspector.idl:
* WebCoreStatistics.cpp:
* WebInspector.cpp:
(WebInspector::isJavaScriptProfilingEnabled):
(WebInspector::setJavaScriptProfilingEnabled):
* WebInspector.h:
* WebView.cpp:

LayoutTests:

* fast/profiler/anonymous-event-handler-expected.txt: Added.
* fast/profiler/anonymous-event-handler.html: Added.
* fast/profiler/anonymous-function-called-from-different-contexts-expected.txt: Added.
* fast/profiler/anonymous-function-called-from-different-contexts.html: Added.
* fast/profiler/anonymous-function-calls-built-in-functions-expected.txt: Added.
* fast/profiler/anonymous-function-calls-built-in-functions.html: Added.
* fast/profiler/anonymous-function-calls-eval-expected.txt: Added.
* fast/profiler/anonymous-function-calls-eval.html: Added.
* fast/profiler/anonymous-functions-with-display-names-expected.txt: Added.
* fast/profiler/anonymous-functions-with-display-names.html: Added.
* fast/profiler/apply-expected.txt: Added.
* fast/profiler/apply.html: Added.
* fast/profiler/built-in-function-calls-anonymous-expected.txt: Added.
* fast/profiler/built-in-function-calls-anonymous.html: Added.
* fast/profiler/built-in-function-calls-user-defined-function-expected.txt: Added.
* fast/profiler/built-in-function-calls-user-defined-function.html: Added.
* fast/profiler/call-expected.txt: Added.
* fast/profiler/call-register-leak-expected.txt: Added.
* fast/profiler/call-register-leak.html: Added.
* fast/profiler/call.html: Added.
* fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope-expected.txt: Added.
* fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope.html: Added.
* fast/profiler/compare-multiple-profiles-expected.txt: Added.
* fast/profiler/compare-multiple-profiles.html: Added.
* fast/profiler/constructor-expected.txt: Added.
* fast/profiler/constructor.html: Added.
* fast/profiler/dead-time-expected.txt: Added.
* fast/profiler/dead-time.html: Added.
* fast/profiler/document-dot-write-expected.txt: Added.
* fast/profiler/document-dot-write.html: Added.
* fast/profiler/event-handler-expected.txt: Added.
* fast/profiler/event-handler.html: Added.
* fast/profiler/execution-context-and-eval-on-same-line-expected.txt: Added.
* fast/profiler/execution-context-and-eval-on-same-line.html: Added.
* fast/profiler/inline-event-handler-expected.txt: Added.
* fast/profiler/inline-event-handler.html: Added.
* fast/profiler/many-calls-in-the-same-scope-expected.txt: Added.
* fast/profiler/many-calls-in-the-same-scope.html: Added.
* fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt: Added.
* fast/profiler/multiple-and-different-scoped-anonymous-function-calls.html: Added.
* fast/profiler/multiple-and-different-scoped-function-calls-expected.txt: Added.
* fast/profiler/multiple-and-different-scoped-function-calls.html: Added.
* fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt: Added.
* fast/profiler/multiple-anonymous-functions-called-from-the-same-function.html: Added.
* fast/profiler/multiple-frames-expected.txt: Added.
* fast/profiler/multiple-frames.html: Added.
* fast/profiler/named-functions-with-display-names-expected.txt: Added.
* fast/profiler/named-functions-with-display-names.html: Added.
* fast/profiler/nested-anonymous-functon-expected.txt: Added.
* fast/profiler/nested-anonymous-functon.html: Added.
* fast/profiler/nested-start-and-stop-profiler-expected.txt: Added.
* fast/profiler/nested-start-and-stop-profiler.html: Added.
* fast/profiler/no-execution-context-expected.txt: Added.
* fast/profiler/no-execution-context.html: Added.
* fast/profiler/one-execution-context-expected.txt: Added.
* fast/profiler/one-execution-context.html: Added.
* fast/profiler/profile-calls-in-included-file-expected.txt: Added.
* fast/profiler/profile-calls-in-included-file.html: Added.
* fast/profiler/profile-with-no-title-expected.txt: Added.
* fast/profiler/profile-with-no-title.html: Added.
* fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting-expected.txt: Added.
* fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting.html: Added.
* fast/profiler/profiling-from-a-nested-location-expected.txt: Added.
* fast/profiler/profiling-from-a-nested-location.html: Added.
* fast/profiler/resources/other-frame.html: Added.
* fast/profiler/resources/other-window.html: Added.
* fast/profiler/resources/profiler-test-JS-resources.js: Added.
(endTest):
(insertGivenText):
(insertNewText):
(arrayOperatorFunction):
(anonymousFunction):
(anotherAnonymousFunction):
(intermediaryFunction):
(isEqualToFive):
(startProfile):
(printHeavyProfilesDataWithoutTime):
(printProfilesDataWithoutTime):
(printProfileNodeWithoutTime):
* fast/profiler/simple-event-call-expected.txt: Added.
* fast/profiler/simple-event-call.html: Added.
* fast/profiler/simple-no-level-change-expected.txt: Added.
* fast/profiler/simple-no-level-change.html: Added.
* fast/profiler/start-and-stop-profiler-multiple-times-expected.txt: Added.
* fast/profiler/start-and-stop-profiler-multiple-times.html: Added.
* fast/profiler/start-and-stop-profiling-in-the-same-function-expected.txt: Added.
* fast/profiler/start-and-stop-profiling-in-the-same-function.html: Added.
* fast/profiler/start-but-dont-stop-profiling-expected.txt: Added.
* fast/profiler/start-but-dont-stop-profiling.html: Added.
* fast/profiler/stop-profiling-after-setTimeout-expected.txt: Added.
* fast/profiler/stop-profiling-after-setTimeout.html: Added.
* fast/profiler/stop-then-function-call-expected.txt: Added.
* fast/profiler/stop-then-function-call.html: Added.
* fast/profiler/throw-exception-from-eval-expected.txt: Added.
* fast/profiler/throw-exception-from-eval.html-disabled: Added.
* fast/profiler/two-execution-contexts-expected.txt: Added.
* fast/profiler/two-execution-contexts.html: Added.
* fast/profiler/user-defined-function-calls-built-in-functions-expected.txt: Added.
* fast/profiler/user-defined-function-calls-built-in-functions.html: Added.
* fast/profiler/window-dot-eval-expected.txt: Added.
* fast/profiler/window-dot-eval.html: Added.
* platform/efl/TestExpectations:
* platform/gtk/TestExpectations:
* platform/ios-simulator/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@200973 268f45cc-cd09-0410-ab3c-d52691b4dbfc

204 files changed:
ChangeLog
LayoutTests/ChangeLog
LayoutTests/fast/profiler/anonymous-event-handler-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/anonymous-event-handler.html [new file with mode: 0644]
LayoutTests/fast/profiler/anonymous-function-called-from-different-contexts-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/anonymous-function-called-from-different-contexts.html [new file with mode: 0644]
LayoutTests/fast/profiler/anonymous-function-calls-built-in-functions-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/anonymous-function-calls-built-in-functions.html [new file with mode: 0644]
LayoutTests/fast/profiler/anonymous-function-calls-eval-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/anonymous-function-calls-eval.html [new file with mode: 0644]
LayoutTests/fast/profiler/anonymous-functions-with-display-names-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/anonymous-functions-with-display-names.html [new file with mode: 0644]
LayoutTests/fast/profiler/apply-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/apply.html [new file with mode: 0644]
LayoutTests/fast/profiler/built-in-function-calls-anonymous-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/built-in-function-calls-anonymous.html [new file with mode: 0644]
LayoutTests/fast/profiler/built-in-function-calls-user-defined-function-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/built-in-function-calls-user-defined-function.html [new file with mode: 0644]
LayoutTests/fast/profiler/call-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/call-register-leak-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/call-register-leak.html [new file with mode: 0644]
LayoutTests/fast/profiler/call.html [new file with mode: 0644]
LayoutTests/fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope.html [new file with mode: 0644]
LayoutTests/fast/profiler/compare-multiple-profiles-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/compare-multiple-profiles.html [new file with mode: 0644]
LayoutTests/fast/profiler/constructor-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/constructor.html [new file with mode: 0644]
LayoutTests/fast/profiler/dead-time-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/dead-time.html [new file with mode: 0644]
LayoutTests/fast/profiler/document-dot-write-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/document-dot-write.html [new file with mode: 0644]
LayoutTests/fast/profiler/event-handler-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/event-handler.html [new file with mode: 0644]
LayoutTests/fast/profiler/execution-context-and-eval-on-same-line-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/execution-context-and-eval-on-same-line.html [new file with mode: 0644]
LayoutTests/fast/profiler/inline-event-handler-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/inline-event-handler.html [new file with mode: 0644]
LayoutTests/fast/profiler/many-calls-in-the-same-scope-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/many-calls-in-the-same-scope.html [new file with mode: 0644]
LayoutTests/fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/multiple-and-different-scoped-anonymous-function-calls.html [new file with mode: 0644]
LayoutTests/fast/profiler/multiple-and-different-scoped-function-calls-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/multiple-and-different-scoped-function-calls.html [new file with mode: 0644]
LayoutTests/fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/multiple-anonymous-functions-called-from-the-same-function.html [new file with mode: 0644]
LayoutTests/fast/profiler/multiple-frames-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/multiple-frames.html [new file with mode: 0644]
LayoutTests/fast/profiler/named-functions-with-display-names-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/named-functions-with-display-names.html [new file with mode: 0644]
LayoutTests/fast/profiler/nested-anonymous-functon-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/nested-anonymous-functon.html [new file with mode: 0644]
LayoutTests/fast/profiler/nested-start-and-stop-profiler-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/nested-start-and-stop-profiler.html [new file with mode: 0644]
LayoutTests/fast/profiler/no-execution-context-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/no-execution-context.html [new file with mode: 0644]
LayoutTests/fast/profiler/one-execution-context-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/one-execution-context.html [new file with mode: 0644]
LayoutTests/fast/profiler/profile-calls-in-included-file-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/profile-calls-in-included-file.html [new file with mode: 0644]
LayoutTests/fast/profiler/profile-with-no-title-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/profile-with-no-title.html [new file with mode: 0644]
LayoutTests/fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting.html [new file with mode: 0644]
LayoutTests/fast/profiler/profiling-from-a-nested-location-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/profiling-from-a-nested-location.html [new file with mode: 0644]
LayoutTests/fast/profiler/resources/other-frame.html [new file with mode: 0644]
LayoutTests/fast/profiler/resources/other-window.html [new file with mode: 0644]
LayoutTests/fast/profiler/resources/profiler-test-JS-resources.js [new file with mode: 0644]
LayoutTests/fast/profiler/simple-event-call-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/simple-event-call.html [new file with mode: 0644]
LayoutTests/fast/profiler/simple-no-level-change-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/simple-no-level-change.html [new file with mode: 0644]
LayoutTests/fast/profiler/start-and-stop-profiler-multiple-times-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/start-and-stop-profiler-multiple-times.html [new file with mode: 0644]
LayoutTests/fast/profiler/start-and-stop-profiling-in-the-same-function-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/start-and-stop-profiling-in-the-same-function.html [new file with mode: 0644]
LayoutTests/fast/profiler/start-but-dont-stop-profiling-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/start-but-dont-stop-profiling.html [new file with mode: 0644]
LayoutTests/fast/profiler/stop-profiling-after-setTimeout-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/stop-profiling-after-setTimeout.html [new file with mode: 0644]
LayoutTests/fast/profiler/stop-then-function-call-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/stop-then-function-call.html [new file with mode: 0644]
LayoutTests/fast/profiler/throw-exception-from-eval-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/throw-exception-from-eval.html-disabled [new file with mode: 0644]
LayoutTests/fast/profiler/two-execution-contexts-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/two-execution-contexts.html [new file with mode: 0644]
LayoutTests/fast/profiler/user-defined-function-calls-built-in-functions-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/user-defined-function-calls-built-in-functions.html [new file with mode: 0644]
LayoutTests/fast/profiler/window-dot-eval-expected.txt [new file with mode: 0644]
LayoutTests/fast/profiler/window-dot-eval.html [new file with mode: 0644]
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/gtk/TestExpectations
LayoutTests/platform/ios-simulator/TestExpectations
ManualTests/inspector/profiler-test-call.html [new file with mode: 0644]
ManualTests/inspector/profiler-test-many-calls-in-the-same-scope.html [new file with mode: 0644]
Source/JavaScriptCore/API/JSProfilerPrivate.cpp [new file with mode: 0644]
Source/JavaScriptCore/API/JSProfilerPrivate.h [new file with mode: 0644]
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/BytecodeList.json
Source/JavaScriptCore/bytecode/BytecodeUseDef.h
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.cpp
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/inspector/InjectedScriptBase.cpp
Source/JavaScriptCore/inspector/protocol/Timeline.json
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/JITOperations.h
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.h
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/parser/ParserModes.h
Source/JavaScriptCore/profiler/CallIdentifier.h [new file with mode: 0644]
Source/JavaScriptCore/profiler/LegacyProfiler.cpp [new file with mode: 0644]
Source/JavaScriptCore/profiler/LegacyProfiler.h [new file with mode: 0644]
Source/JavaScriptCore/profiler/Profile.cpp [new file with mode: 0644]
Source/JavaScriptCore/profiler/Profile.h [new file with mode: 0644]
Source/JavaScriptCore/profiler/ProfileGenerator.cpp [new file with mode: 0644]
Source/JavaScriptCore/profiler/ProfileGenerator.h [new file with mode: 0644]
Source/JavaScriptCore/profiler/ProfileNode.cpp [new file with mode: 0644]
Source/JavaScriptCore/profiler/ProfileNode.h [new file with mode: 0644]
Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp
Source/JavaScriptCore/profiler/ProfilerJettisonReason.h
Source/JavaScriptCore/runtime/CodeCache.cpp
Source/JavaScriptCore/runtime/CodeCache.h
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/Options.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/DerivedSources.cpp
Source/WebCore/DerivedSources.make
Source/WebCore/ForwardingHeaders/profiler/LegacyProfiler.h [new file with mode: 0644]
Source/WebCore/ForwardingHeaders/profiler/Profile.h [new file with mode: 0644]
Source/WebCore/ForwardingHeaders/profiler/ProfileNode.h [new file with mode: 0644]
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
Source/WebCore/bindings/js/JSDOMWindowBase.cpp
Source/WebCore/bindings/js/JSDOMWindowBase.h
Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp
Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h
Source/WebCore/bindings/js/ScriptCachedFrameData.cpp
Source/WebCore/bindings/js/ScriptController.cpp
Source/WebCore/bindings/js/ScriptProfile.h [new file with mode: 0644]
Source/WebCore/bindings/js/ScriptProfileNode.h [new file with mode: 0644]
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/bindings/scripts/test/TestObj.idl
Source/WebCore/css/CSSParser.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/inspector/InspectorConsoleInstrumentation.h
Source/WebCore/inspector/InspectorController.cpp
Source/WebCore/inspector/InspectorController.h
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/InspectorTimelineAgent.cpp
Source/WebCore/inspector/InspectorTimelineAgent.h
Source/WebCore/inspector/PageDebuggerAgent.cpp
Source/WebCore/inspector/PageRuntimeAgent.cpp
Source/WebCore/inspector/ScriptProfile.idl [new file with mode: 0644]
Source/WebCore/inspector/ScriptProfileNode.idl [new file with mode: 0644]
Source/WebCore/inspector/TimelineRecordFactory.cpp
Source/WebCore/inspector/TimelineRecordFactory.h
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/Page.cpp
Source/WebCore/page/PageConsoleClient.cpp
Source/WebCore/page/PageConsoleClient.h
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebCore/testing/js/WebCoreTestSupport.cpp
Source/WebCore/xml/XSLStyleSheetLibxslt.cpp
Source/WebCore/xml/XSLTProcessorLibxslt.cpp
Source/WebKit/win/ChangeLog
Source/WebKit/win/Interfaces/IWebInspector.idl
Source/WebKit/win/WebCoreStatistics.cpp
Source/WebKit/win/WebInspector.cpp
Source/WebKit/win/WebInspector.h
Source/WebKit/win/WebView.cpp

index b91ee62647c80ab66747efee2b665e7d86257a95..507d1738bcd276cbaa9c115be307f06c089ea331 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2016-05-16  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Unreviewed rollout r200924. Caused js/regress/string-replace-generic.html to fail.
+
+        * ManualTests/inspector/profiler-test-call.html: Added.
+        * ManualTests/inspector/profiler-test-many-calls-in-the-same-scope.html: Added.
+
 2016-05-14  Joseph Pecoraro  <pecoraro@apple.com>
 
         Remove LegacyProfiler
index 10fff0cb798d1802766680a13deac782137926f4..837e7c1113109cf22625e05612c787a4f97159a5 100644 (file)
@@ -1,3 +1,112 @@
+2016-05-16  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Unreviewed rollout r200924. Caused js/regress/string-replace-generic.html to fail.
+
+        * fast/profiler/anonymous-event-handler-expected.txt: Added.
+        * fast/profiler/anonymous-event-handler.html: Added.
+        * fast/profiler/anonymous-function-called-from-different-contexts-expected.txt: Added.
+        * fast/profiler/anonymous-function-called-from-different-contexts.html: Added.
+        * fast/profiler/anonymous-function-calls-built-in-functions-expected.txt: Added.
+        * fast/profiler/anonymous-function-calls-built-in-functions.html: Added.
+        * fast/profiler/anonymous-function-calls-eval-expected.txt: Added.
+        * fast/profiler/anonymous-function-calls-eval.html: Added.
+        * fast/profiler/anonymous-functions-with-display-names-expected.txt: Added.
+        * fast/profiler/anonymous-functions-with-display-names.html: Added.
+        * fast/profiler/apply-expected.txt: Added.
+        * fast/profiler/apply.html: Added.
+        * fast/profiler/built-in-function-calls-anonymous-expected.txt: Added.
+        * fast/profiler/built-in-function-calls-anonymous.html: Added.
+        * fast/profiler/built-in-function-calls-user-defined-function-expected.txt: Added.
+        * fast/profiler/built-in-function-calls-user-defined-function.html: Added.
+        * fast/profiler/call-expected.txt: Added.
+        * fast/profiler/call-register-leak-expected.txt: Added.
+        * fast/profiler/call-register-leak.html: Added.
+        * fast/profiler/call.html: Added.
+        * fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope-expected.txt: Added.
+        * fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope.html: Added.
+        * fast/profiler/compare-multiple-profiles-expected.txt: Added.
+        * fast/profiler/compare-multiple-profiles.html: Added.
+        * fast/profiler/constructor-expected.txt: Added.
+        * fast/profiler/constructor.html: Added.
+        * fast/profiler/dead-time-expected.txt: Added.
+        * fast/profiler/dead-time.html: Added.
+        * fast/profiler/document-dot-write-expected.txt: Added.
+        * fast/profiler/document-dot-write.html: Added.
+        * fast/profiler/event-handler-expected.txt: Added.
+        * fast/profiler/event-handler.html: Added.
+        * fast/profiler/execution-context-and-eval-on-same-line-expected.txt: Added.
+        * fast/profiler/execution-context-and-eval-on-same-line.html: Added.
+        * fast/profiler/inline-event-handler-expected.txt: Added.
+        * fast/profiler/inline-event-handler.html: Added.
+        * fast/profiler/many-calls-in-the-same-scope-expected.txt: Added.
+        * fast/profiler/many-calls-in-the-same-scope.html: Added.
+        * fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt: Added.
+        * fast/profiler/multiple-and-different-scoped-anonymous-function-calls.html: Added.
+        * fast/profiler/multiple-and-different-scoped-function-calls-expected.txt: Added.
+        * fast/profiler/multiple-and-different-scoped-function-calls.html: Added.
+        * fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt: Added.
+        * fast/profiler/multiple-anonymous-functions-called-from-the-same-function.html: Added.
+        * fast/profiler/multiple-frames-expected.txt: Added.
+        * fast/profiler/multiple-frames.html: Added.
+        * fast/profiler/named-functions-with-display-names-expected.txt: Added.
+        * fast/profiler/named-functions-with-display-names.html: Added.
+        * fast/profiler/nested-anonymous-functon-expected.txt: Added.
+        * fast/profiler/nested-anonymous-functon.html: Added.
+        * fast/profiler/nested-start-and-stop-profiler-expected.txt: Added.
+        * fast/profiler/nested-start-and-stop-profiler.html: Added.
+        * fast/profiler/no-execution-context-expected.txt: Added.
+        * fast/profiler/no-execution-context.html: Added.
+        * fast/profiler/one-execution-context-expected.txt: Added.
+        * fast/profiler/one-execution-context.html: Added.
+        * fast/profiler/profile-calls-in-included-file-expected.txt: Added.
+        * fast/profiler/profile-calls-in-included-file.html: Added.
+        * fast/profiler/profile-with-no-title-expected.txt: Added.
+        * fast/profiler/profile-with-no-title.html: Added.
+        * fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting-expected.txt: Added.
+        * fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting.html: Added.
+        * fast/profiler/profiling-from-a-nested-location-expected.txt: Added.
+        * fast/profiler/profiling-from-a-nested-location.html: Added.
+        * fast/profiler/resources/other-frame.html: Added.
+        * fast/profiler/resources/other-window.html: Added.
+        * fast/profiler/resources/profiler-test-JS-resources.js: Added.
+        (endTest):
+        (insertGivenText):
+        (insertNewText):
+        (arrayOperatorFunction):
+        (anonymousFunction):
+        (anotherAnonymousFunction):
+        (intermediaryFunction):
+        (isEqualToFive):
+        (startProfile):
+        (printHeavyProfilesDataWithoutTime):
+        (printProfilesDataWithoutTime):
+        (printProfileNodeWithoutTime):
+        * fast/profiler/simple-event-call-expected.txt: Added.
+        * fast/profiler/simple-event-call.html: Added.
+        * fast/profiler/simple-no-level-change-expected.txt: Added.
+        * fast/profiler/simple-no-level-change.html: Added.
+        * fast/profiler/start-and-stop-profiler-multiple-times-expected.txt: Added.
+        * fast/profiler/start-and-stop-profiler-multiple-times.html: Added.
+        * fast/profiler/start-and-stop-profiling-in-the-same-function-expected.txt: Added.
+        * fast/profiler/start-and-stop-profiling-in-the-same-function.html: Added.
+        * fast/profiler/start-but-dont-stop-profiling-expected.txt: Added.
+        * fast/profiler/start-but-dont-stop-profiling.html: Added.
+        * fast/profiler/stop-profiling-after-setTimeout-expected.txt: Added.
+        * fast/profiler/stop-profiling-after-setTimeout.html: Added.
+        * fast/profiler/stop-then-function-call-expected.txt: Added.
+        * fast/profiler/stop-then-function-call.html: Added.
+        * fast/profiler/throw-exception-from-eval-expected.txt: Added.
+        * fast/profiler/throw-exception-from-eval.html-disabled: Added.
+        * fast/profiler/two-execution-contexts-expected.txt: Added.
+        * fast/profiler/two-execution-contexts.html: Added.
+        * fast/profiler/user-defined-function-calls-built-in-functions-expected.txt: Added.
+        * fast/profiler/user-defined-function-calls-built-in-functions.html: Added.
+        * fast/profiler/window-dot-eval-expected.txt: Added.
+        * fast/profiler/window-dot-eval.html: Added.
+        * platform/efl/TestExpectations:
+        * platform/gtk/TestExpectations:
+        * platform/ios-simulator/TestExpectations:
+
 2016-05-16  Ryosuke Niwa  <rniwa@webkit.org>
 
         Focus ordering should respect slot elements
diff --git a/LayoutTests/fast/profiler/anonymous-event-handler-expected.txt b/LayoutTests/fast/profiler/anonymous-event-handler-expected.txt
new file mode 100644 (file)
index 0000000..848bf38
--- /dev/null
@@ -0,0 +1,18 @@
+This page has an anonymous event handler. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. It should show the anonymous function at the same level as the onload handler. 
+
+Profile title: Anonymous event handler
+Thread_1 (no file) (line 0:0)
+   startTest anonymous-event-handler.html (line 10:19)
+      getElementById (no file) (line 0:0)
+      click (no file) (line 0:0)
+         onclick anonymous-event-handler.html (line 15:51)
+            insertNewText profiler-test-JS-resources.js (line 17:23)
+               createElement (no file) (line 0:0)
+               createTextNode (no file) (line 0:0)
+               appendChild (no file) (line 0:0)
+               getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/anonymous-event-handler.html b/LayoutTests/fast/profiler/anonymous-event-handler.html
new file mode 100644 (file)
index 0000000..2bcffa5
--- /dev/null
@@ -0,0 +1,36 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Anonymous event handler");
+
+    var buttonWithAnonymousHandler = document.getElementById("buttonWithAnAnonymousEventHandler")
+    buttonWithAnonymousHandler.onclick = function () {
+        insertNewText();
+    }
+
+    buttonWithAnonymousHandler.click();
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page has an anonymous event handler.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  It should show the anonymous function at the same level as the onload
+handler.
+<input type="button" id="buttonWithAnAnonymousEventHandler" value="Button with an anonymous event handler">
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/anonymous-function-called-from-different-contexts-expected.txt b/LayoutTests/fast/profiler/anonymous-function-called-from-different-contexts-expected.txt
new file mode 100644 (file)
index 0000000..3cbbf04
--- /dev/null
@@ -0,0 +1,24 @@
+This page's JavaScript calls an anonymous function from different contexts. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. Beneath onload and startTest it should show three children, an anonymous function, script context, and the endTest call.
+
+Profile title: Same anonymous function called from different contexts
+Thread_1 (no file) (line 0:0)
+   startTest anonymous-function-called-from-different-contexts.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      eval (no file) (line 0:0)
+         (program) (no file) (line 1:1)
+            anonymousFunction profiler-test-JS-resources.js (line 29:34)
+               insertNewText profiler-test-JS-resources.js (line 17:23)
+                  createElement (no file) (line 0:0)
+                  createTextNode (no file) (line 0:0)
+                  appendChild (no file) (line 0:0)
+                  getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/anonymous-function-called-from-different-contexts.html b/LayoutTests/fast/profiler/anonymous-function-called-from-different-contexts.html
new file mode 100644 (file)
index 0000000..3ab8317
--- /dev/null
@@ -0,0 +1,31 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Same anonymous function called from different contexts");
+
+    anonymousFunction();
+    eval("anonymousFunction()");
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls an anonymous function from different contexts.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  Beneath onload and startTest it should show three children, an
+anonymous function, script context, and the endTest call.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/anonymous-function-calls-built-in-functions-expected.txt b/LayoutTests/fast/profiler/anonymous-function-calls-built-in-functions-expected.txt
new file mode 100644 (file)
index 0000000..9120600
--- /dev/null
@@ -0,0 +1,16 @@
+This page has an anonymous JavaScript function that calls built-in functions. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. Beneath onload and startTest it should show three children, an anonymous function, script context, and the endTest call.
+
+Profile title: Anonymous function calls built-in functions
+Thread_1 (no file) (line 0:0)
+   startTest anonymous-function-calls-built-in-functions.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/anonymous-function-calls-built-in-functions.html b/LayoutTests/fast/profiler/anonymous-function-calls-built-in-functions.html
new file mode 100644 (file)
index 0000000..5bc73b5
--- /dev/null
@@ -0,0 +1,28 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Anonymous function calls built-in functions");
+    anonymousFunction();
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page has an anonymous JavaScript function that calls built-in functions.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  Beneath onload and startTest it should show three children, an
+anonymous function, script context, and the endTest call.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/anonymous-function-calls-eval-expected.txt b/LayoutTests/fast/profiler/anonymous-function-calls-eval-expected.txt
new file mode 100644 (file)
index 0000000..9a0fd4b
--- /dev/null
@@ -0,0 +1,18 @@
+This page's JavaScript calls an anonymous function which calls eval(). 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. Beneath onload and startTest it should show an (anonymous function) which has a (program) child.
+
+Profile title: Anonymous function calles eval
+Thread_1 (no file) (line 0:0)
+   startTest anonymous-function-calls-eval.html (line 10:19)
+      variableThatPointsToAnAnonymousFunction anonymous-function-calls-eval.html (line 14:59)
+         eval (no file) (line 0:0)
+            (program) (no file) (line 1:1)
+               insertNewText profiler-test-JS-resources.js (line 17:23)
+                  createElement (no file) (line 0:0)
+                  createTextNode (no file) (line 0:0)
+                  appendChild (no file) (line 0:0)
+                  getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/anonymous-function-calls-eval.html b/LayoutTests/fast/profiler/anonymous-function-calls-eval.html
new file mode 100644 (file)
index 0000000..19f7666
--- /dev/null
@@ -0,0 +1,33 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Anonymous function calles eval");
+
+    var variableThatPointsToAnAnonymousFunction = function() {
+        eval("insertNewText()");
+    }
+
+    variableThatPointsToAnAnonymousFunction();
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls an anonymous function which calls eval().
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  Beneath onload and startTest it should show an (anonymous function)
+which has a (program) child.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/anonymous-functions-with-display-names-expected.txt b/LayoutTests/fast/profiler/anonymous-functions-with-display-names-expected.txt
new file mode 100644 (file)
index 0000000..7b8d807
--- /dev/null
@@ -0,0 +1,16 @@
+This page's JavaScript calls anonymous functions with display names. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. You should see functions named "[x] iterations function", and no anonymous functions.
+
+Profile title: Anonymous functions with display names
+Thread_1 (no file) (line 0:0)
+   startTest anonymous-functions-with-display-names.html (line 22:19)
+      anonymousFunctionGenerator anonymous-functions-with-display-names.html (line 10:36)
+      0 iterations function anonymous-functions-with-display-names.html (line 12:59)
+      1 iterations function anonymous-functions-with-display-names.html (line 12:59)
+      2 iterations function anonymous-functions-with-display-names.html (line 12:59)
+      20 iterations function anonymous-functions-with-display-names.html (line 12:59)
+      1000 iterations function anonymous-functions-with-display-names.html (line 12:59)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/anonymous-functions-with-display-names.html b/LayoutTests/fast/profiler/anonymous-functions-with-display-names.html
new file mode 100644 (file)
index 0000000..7b9fc34
--- /dev/null
@@ -0,0 +1,45 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function anonymousFunctionGenerator(iterations)
+{
+    var variableThatPointsToAnAnonymousFunction = function()
+    {
+        for (var i = 0; i < iterations; ++i) ;
+    }
+    
+    variableThatPointsToAnAnonymousFunction.displayName = iterations + " iterations function";
+    
+    return variableThatPointsToAnAnonymousFunction;
+}
+
+function startTest()
+{
+    console.profile("Anonymous functions with display names");
+
+    anonymousFunctionGenerator(0)();
+    anonymousFunctionGenerator(1)();
+    anonymousFunctionGenerator(2)();
+    anonymousFunctionGenerator(20)();
+    anonymousFunctionGenerator(1000)();
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls anonymous functions with display names.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  You should see functions named "[x] iterations function", and no anonymous functions.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/apply-expected.txt b/LayoutTests/fast/profiler/apply-expected.txt
new file mode 100644 (file)
index 0000000..708bd06
--- /dev/null
@@ -0,0 +1,12 @@
+This page's JavaScript has a call to apply() in it. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call to fakeInteriorFunction() and a call to apply().
+
+Profile title: Using the apply() method
+Thread_1 (no file) (line 0:0)
+   startTest apply.html (line 10:19)
+      fakeObject apply.html (line 17:21)
+         fakeInteriorFunction apply.html (line 23:30)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/apply.html b/LayoutTests/fast/profiler/apply.html
new file mode 100644 (file)
index 0000000..98d41ab
--- /dev/null
@@ -0,0 +1,40 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Using the apply() method");
+    var myObject = new fakeObject(1, 2);
+    endTest();
+}
+
+function fakeObject (x, y)
+{
+    this.x = x;
+    fakeInteriorFunction.apply(this, arguments);
+}
+
+function fakeInteriorFunction(x, y)
+{
+    this.y = y;
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript has a call to apply() in it.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to fakeInteriorFunction() and
+a call to apply().
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/built-in-function-calls-anonymous-expected.txt b/LayoutTests/fast/profiler/built-in-function-calls-anonymous-expected.txt
new file mode 100644 (file)
index 0000000..2a6baf3
--- /dev/null
@@ -0,0 +1,23 @@
+This page uses a built-in function to call an anonymous function. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile map() should be the sibling of an (anonymous function) which has arrayOperatorFunction() as a child.
+
+Profile title: Built-in function calls an anonymous function
+Thread_1 (no file) (line 0:0)
+   startTest built-in-function-calls-anonymous.html (line 10:19)
+      Array (no file) (line 0:0)
+      map (no file) (line 0:0)
+         Object (no file) (line 0:0)
+         toLength (no file) (line 0:0)
+            toInteger (no file) (line 0:0)
+               Number (no file) (line 0:0)
+               (anonymous function) (no file) (line 0:0)
+         isArray (no file) (line 0:0)
+         (anonymous function) (no file) (line 0:0)
+         speciesGetter (no file) (line 0:0)
+         Array (no file) (line 0:0)
+         myFunction built-in-function-calls-anonymous.html (line 14:30)
+            arrayOperatorFunction profiler-test-JS-resources.js (line 25:31)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/built-in-function-calls-anonymous.html b/LayoutTests/fast/profiler/built-in-function-calls-anonymous.html
new file mode 100644 (file)
index 0000000..05aed48
--- /dev/null
@@ -0,0 +1,35 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Built-in function calls an anonymous function");
+
+    var myFunction = function(arrayElement) {
+        return arrayOperatorFunction(arrayElement);
+    }
+
+    var myArray = new Array (0, 1, 2);
+    myArray.map(myFunction);
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page uses a built-in function to call an anonymous function.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile map() should be the sibling of an (anonymous function)
+which has arrayOperatorFunction() as a child.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/built-in-function-calls-user-defined-function-expected.txt b/LayoutTests/fast/profiler/built-in-function-calls-user-defined-function-expected.txt
new file mode 100644 (file)
index 0000000..57155e7
--- /dev/null
@@ -0,0 +1,22 @@
+This page uses a built-in function to call a user defined function. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile map() should have arrayOperatorFunction() as a child.
+
+Profile title: Built-in function calls a user defined function
+Thread_1 (no file) (line 0:0)
+   startTest built-in-function-calls-user-defined-function.html (line 10:19)
+      Array (no file) (line 0:0)
+      map (no file) (line 0:0)
+         Object (no file) (line 0:0)
+         toLength (no file) (line 0:0)
+            toInteger (no file) (line 0:0)
+               Number (no file) (line 0:0)
+               (anonymous function) (no file) (line 0:0)
+         isArray (no file) (line 0:0)
+         (anonymous function) (no file) (line 0:0)
+         speciesGetter (no file) (line 0:0)
+         Array (no file) (line 0:0)
+         arrayOperatorFunction profiler-test-JS-resources.js (line 25:31)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/built-in-function-calls-user-defined-function.html b/LayoutTests/fast/profiler/built-in-function-calls-user-defined-function.html
new file mode 100644 (file)
index 0000000..c663b69
--- /dev/null
@@ -0,0 +1,30 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Built-in function calls a user defined function");
+
+    var myArray = new Array (0, 1, 2);
+    myArray.map(arrayOperatorFunction);
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page uses a built-in function to call a user defined function.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile map() should have arrayOperatorFunction() as a child.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/call-expected.txt b/LayoutTests/fast/profiler/call-expected.txt
new file mode 100644 (file)
index 0000000..fc86fd9
--- /dev/null
@@ -0,0 +1,12 @@
+This page's JavaScript has a call to call() in it. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call to fakeObject() with call() as its child and a fakeInteriorFunction() as call()'s child.
+
+Profile title: Using the call() method
+Thread_1 (no file) (line 0:0)
+   startTest call.html (line 10:19)
+      fakeObject call.html (line 19:21)
+         fakeInteriorFunction call.html (line 25:30)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/call-register-leak-expected.txt b/LayoutTests/fast/profiler/call-register-leak-expected.txt
new file mode 100644 (file)
index 0000000..d3647bf
--- /dev/null
@@ -0,0 +1,17 @@
+This page tests that the generation of bytecode allocates registers correctly when profiling is enabled. To run the test manually, enable profiling in the web inspector and reload this page.
+
+PASS: localCallTest(1, 2) should be 2 and is.
+
+PASS: globalCallTest(1, 2) should be 2 and is.
+
+PASS: scopedCallTest(1, 2) should be 2 and is.
+
+PASS: resolveCallTest(1, 2) should be 2 and is.
+
+PASS: bracketCallTest(1, 2) should be 2 and is.
+
+PASS: dotCallTest(1, 2) should be 2 and is.
+
+PASS: newTest(1, 2) should be 2 and is.
+
+
diff --git a/LayoutTests/fast/profiler/call-register-leak.html b/LayoutTests/fast/profiler/call-register-leak.html
new file mode 100644 (file)
index 0000000..366b441
--- /dev/null
@@ -0,0 +1,105 @@
+<body>
+<head>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function log(s)
+{
+    if (this.document)
+        document.getElementById("console").appendChild(document.createTextNode(s + "\n"));
+    else
+        print(s + "\n");
+}
+
+function shouldBe(a, aDescription, b)
+{
+    if (a === b)
+        log("PASS: " + aDescription + " should be " + b + " and is.\n");
+    else
+        log("FAIL: " + aDescription + " should be " + b + " but instead is " + a + ".\n");
+}
+
+function localCallTest(a, b)
+{
+    function localCall(o)
+    {
+        return o.toString();
+    }
+    return [localCall(a), b][1];
+}
+
+function globalCall(o)
+{
+    return o.toString();
+}
+
+function globalCallTest(a, b)
+{
+    return [globalCall(a), b][1];
+}
+
+function scopedCallTest(a, b)
+{
+    function scopedCall(o)
+    {
+        return o.toString();
+    }
+
+    function f()
+    {
+        return [scopedCall(a), b][1];
+    }
+
+    return f();
+}
+
+function resolveCallTest(a, b)
+{
+    o = { resolvedCall: function(o) { return o.toString(); }};
+    with (o) {
+        return [resolvedCall(o), b][1];
+    }
+}
+
+function bracketCallTest(a, b)
+{
+    return [a["toString"](), b][1];
+}
+
+function dotCallTest(a, b)
+{
+    return [a.toString(), b][1];
+}
+
+function testConstructor(o)
+{
+    return o.toString();
+}
+
+function newTest(a, b)
+{
+    return [new testConstructor(a), b][1];
+}
+
+function startTest()
+{
+    shouldBe(localCallTest(1, 2), "localCallTest(1, 2)", 2);
+    shouldBe(globalCallTest(1, 2), "globalCallTest(1, 2)", 2);
+    shouldBe(scopedCallTest(1, 2), "scopedCallTest(1, 2)", 2);
+    shouldBe(resolveCallTest(1, 2), "resolveCallTest(1, 2)", 2);
+    shouldBe(bracketCallTest(1, 2), "bracketCallTest(1, 2)", 2);
+    shouldBe(dotCallTest(1, 2), "dotCallTest(1, 2)", 2);
+    shouldBe(newTest(1, 2), "newTest(1, 2)", 2);
+}
+</script>
+</head>
+<body onload="startTest()">
+<p>
+This page tests that the generation of bytecode allocates registers correctly when profiling is enabled. To run the test manually, enable profiling in the web inspector and reload this page.
+</p>
+<pre id="console"></pre>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/call.html b/LayoutTests/fast/profiler/call.html
new file mode 100644 (file)
index 0000000..2105c7a
--- /dev/null
@@ -0,0 +1,41 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Using the call() method");
+
+    var myObject = new fakeObject(1, 2);
+
+    endTest();
+}
+
+function fakeObject (x, y)
+{
+    this.x = x;
+    fakeInteriorFunction.call(this, y);
+}
+
+function fakeInteriorFunction(y)
+{
+    this.y = y;
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript has a call to call() in it.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to fakeObject() with call() as
+its child and a fakeInteriorFunction() as call()'s child.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope-expected.txt b/LayoutTests/fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope-expected.txt
new file mode 100644 (file)
index 0000000..6c2bb18
--- /dev/null
@@ -0,0 +1,12 @@
+This page's JavaScript starts profiling from within a function which is then called later from another context. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profiler you should see a call to indirection() and functionWichStartsAndStopsTheProfiler()
+
+Profile title: Calling the same function where the profile started from another function
+Thread_1 (no file) (line 0:0)
+   indirection calling-the-function-that-started-the-profiler-from-another-scope.html (line 17:21)
+      functionWichStartsAndStopsTheProfiler calling-the-function-that-started-the-profiler-from-another-scope.html (line 23:47)
+   functionWichStartsAndStopsTheProfiler calling-the-function-that-started-the-profiler-from-another-scope.html (line 23:47)
+   endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope.html b/LayoutTests/fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope.html
new file mode 100644 (file)
index 0000000..57567f2
--- /dev/null
@@ -0,0 +1,47 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    indirection();
+    functionWichStartsAndStopsTheProfiler();
+    endTest();
+}
+
+function indirection()
+{
+    functionWichStartsAndStopsTheProfiler();
+}
+
+var firstTime = true;
+function functionWichStartsAndStopsTheProfiler()
+{
+    if (firstTime) {
+        console.profile("Calling the same function where the profile started from another function");
+        firstTime = false;
+    }
+
+    for (var i = 0; i < 10000000; i++)
+        var b = i + 2;
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript starts profiling from within a function which is then called
+later from another context.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profiler you should see a call to indirection() and
+functionWichStartsAndStopsTheProfiler()
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/compare-multiple-profiles-expected.txt b/LayoutTests/fast/profiler/compare-multiple-profiles-expected.txt
new file mode 100644 (file)
index 0000000..c3bbe20
--- /dev/null
@@ -0,0 +1,17 @@
+This page has multiple profiles with the same name. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. It should not crash or hang and there should be multiple runs of the same named profile.
+
+Profile title: Test
+Thread_1 (no file) (line 0:0)
+   startTest compare-multiple-profiles.html (line 22:19)
+      test compare-multiple-profiles.html (line 11:14)
+         test2 compare-multiple-profiles.html (line 17:15)
+
+Profile title: Test
+Thread_1 (no file) (line 0:0)
+   startTest compare-multiple-profiles.html (line 22:19)
+      test compare-multiple-profiles.html (line 11:14)
+         test2 compare-multiple-profiles.html (line 17:15)
+
+
diff --git a/LayoutTests/fast/profiler/compare-multiple-profiles.html b/LayoutTests/fast/profiler/compare-multiple-profiles.html
new file mode 100644 (file)
index 0000000..a602b44
--- /dev/null
@@ -0,0 +1,46 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+var j = 0;
+function test(len) {
+    for (var i = 0; i < len; ++i)
+        ++j;
+    test2(2000 - len);
+}
+
+function test2(len) {
+    for (var i = 0; i < len; ++i)
+        --j;
+}
+
+function startTest()
+{
+    console.profile("Test");
+    test(100);
+    console.profileEnd("Test");
+
+    console.profile("Test");
+    test(1000);
+    console.profileEnd("Test");
+
+    printProfilesDataWithoutTime();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page has multiple profiles with the same name.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  It should not crash or hang and there should be multiple runs of the
+same named profile.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/constructor-expected.txt b/LayoutTests/fast/profiler/constructor-expected.txt
new file mode 100644 (file)
index 0000000..93d8963
--- /dev/null
@@ -0,0 +1,12 @@
+This page's JavaScript has a call to new() in it. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call to fakeObject() and Array() in it.
+
+Profile title: Using a constructor.
+Thread_1 (no file) (line 0:0)
+   startTest constructor.html (line 10:19)
+      fakeObject constructor.html (line 19:21)
+         Array (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/constructor.html b/LayoutTests/fast/profiler/constructor.html
new file mode 100644 (file)
index 0000000..bc63908
--- /dev/null
@@ -0,0 +1,36 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Using a constructor.");
+
+    var myObject = new fakeObject(1, 2);
+
+    endTest();
+}
+
+function fakeObject (x, y)
+{
+    var myArray = new Array()
+    myArray[0] = 5;
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript has a call to new() in it.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to fakeObject() and Array()
+in it.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/dead-time-expected.txt b/LayoutTests/fast/profiler/dead-time-expected.txt
new file mode 100644 (file)
index 0000000..1de64f6
--- /dev/null
@@ -0,0 +1,13 @@
+This page's JavaScript Has some dead time in the profile. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a large amount of the % spent in (non-JavaScript).
+
+Profile title: Dead time in profile.
+Thread_1 (no file) (line 0:0)
+   onload dead-time.html (line 21:44)
+      startTest dead-time.html (line 12:19)
+         setTimeout (no file) (line 0:0)
+   (program) dead-time.html (line 1:1)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/dead-time.html b/LayoutTests/fast/profiler/dead-time.html
new file mode 100644 (file)
index 0000000..a664ce0
--- /dev/null
@@ -0,0 +1,31 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Dead time in profile.");
+    setTimeout("endTest()", 1234);
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript Has some dead time in the profile.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a large amount of the % spent in 
+(non-JavaScript).
+<div id="output"></div>
+</body>
+</html>
+
diff --git a/LayoutTests/fast/profiler/document-dot-write-expected.txt b/LayoutTests/fast/profiler/document-dot-write-expected.txt
new file mode 100644 (file)
index 0000000..849f1bd
--- /dev/null
@@ -0,0 +1,8 @@
+
+Profile title: Call Document.write()
+Thread_1 (no file) (line 0:0)
+   startTest document-dot-write.html (line 10:19)
+      write (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/document-dot-write.html b/LayoutTests/fast/profiler/document-dot-write.html
new file mode 100644 (file)
index 0000000..af54f40
--- /dev/null
@@ -0,0 +1,28 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Call Document.write()");
+
+    document.write("<div id=\"output\"></div>");
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page calls document.write().
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  If there is a profile it should show write().
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/event-handler-expected.txt b/LayoutTests/fast/profiler/event-handler-expected.txt
new file mode 100644 (file)
index 0000000..15c48cd
--- /dev/null
@@ -0,0 +1,18 @@
+This page has an event handler. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile insertnewText() should be a sibling to onload(). 
+
+Profile title: Event handler
+Thread_1 (no file) (line 0:0)
+   startTest event-handler.html (line 10:19)
+      getElementById (no file) (line 0:0)
+      addEventListener (no file) (line 0:0)
+      click (no file) (line 0:0)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/event-handler.html b/LayoutTests/fast/profiler/event-handler.html
new file mode 100644 (file)
index 0000000..f6a461d
--- /dev/null
@@ -0,0 +1,32 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{    
+    console.profile("Event handler");
+
+    var myButton = document.getElementById("buttonWithAnEventListener");
+    myButton.addEventListener("click", insertNewText, false);
+    myButton.click();
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page has an event handler.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile insertnewText() should be a sibling to onload().
+<input type="button" id="buttonWithAnEventListener" value="Button with an event listener">
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/execution-context-and-eval-on-same-line-expected.txt b/LayoutTests/fast/profiler/execution-context-and-eval-on-same-line-expected.txt
new file mode 100644 (file)
index 0000000..d95c261
--- /dev/null
@@ -0,0 +1,16 @@
+This page has a call to eval and a script tag on the same line. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be multiple (program) elements and one that represents the eval().
+
+Profile title: Two Execution Contexts on the same line
+Thread_1 (no file) (line 0:0)
+   startTest execution-context-and-eval-on-same-line.html (line 10:19)
+      evalFunction (no file) (line 1:22)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/execution-context-and-eval-on-same-line.html b/LayoutTests/fast/profiler/execution-context-and-eval-on-same-line.html
new file mode 100644 (file)
index 0000000..a75b29a
--- /dev/null
@@ -0,0 +1,33 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Two Execution Contexts on the same line");
+
+    evalFunction();
+
+    endTest();
+}
+</script>
+<script>
+eval("function evalFunction() { insertNewText(); }");
+</script>
+</head>
+
+<body onload="startTest()">
+This page has a call to eval and a script tag on the same line.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be multiple (program) elements and
+one that represents the eval().
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/inline-event-handler-expected.txt b/LayoutTests/fast/profiler/inline-event-handler-expected.txt
new file mode 100644 (file)
index 0000000..a023e5f
--- /dev/null
@@ -0,0 +1,20 @@
+This page has an inline event handler. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile onclick() should be a sibling to onload() and onclick() should have eventListener() as a child. 
+
+Profile title: Inline event handler
+Thread_1 (no file) (line 0:0)
+   startTest inline-event-handler.html (line 10:19)
+      getElementById (no file) (line 0:0)
+      click (no file) (line 0:0)
+         onclick inline-event-handler.html (line 31:127)
+            eventListener inline-event-handler.html (line 17:23)
+               anonymousFunction profiler-test-JS-resources.js (line 29:34)
+                  insertNewText profiler-test-JS-resources.js (line 17:23)
+                     createElement (no file) (line 0:0)
+                     createTextNode (no file) (line 0:0)
+                     appendChild (no file) (line 0:0)
+                     getElementById (no file) (line 0:0)
+               endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/inline-event-handler.html b/LayoutTests/fast/profiler/inline-event-handler.html
new file mode 100644 (file)
index 0000000..5001463
--- /dev/null
@@ -0,0 +1,34 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{    
+    console.profile("Inline event handler");
+
+    document.getElementById("eventListenerSetInline").click();
+}
+
+function eventListener() {    
+    anonymousFunction();
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page has an inline event handler.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile onclick() should be a sibling to onload() and onclick()
+should have eventListener() as a child.
+<input type="button" onclick="eventListener()" id="eventListenerSetInline" value="Event Listener Set Inline">
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/many-calls-in-the-same-scope-expected.txt b/LayoutTests/fast/profiler/many-calls-in-the-same-scope-expected.txt
new file mode 100644 (file)
index 0000000..0cd45d1
--- /dev/null
@@ -0,0 +1,36 @@
+This page's JavaScript has many function calls in the same scope. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile many functions should be the children of startTest. Use the sorting capabilites to make sure the similarly named functions are sorted correctly.
+
+Profile title: Many Calls In The Same Scope
+Thread_1 (no file) (line 0:0)
+   startTest many-calls-in-the-same-scope.html (line 10:19)
+      insertNewText profiler-test-JS-resources.js (line 17:23)
+         createElement (no file) (line 0:0)
+         createTextNode (no file) (line 0:0)
+         appendChild (no file) (line 0:0)
+         getElementById (no file) (line 0:0)
+      insertGivenText profiler-test-JS-resources.js (line 9:25)
+         createElement (no file) (line 0:0)
+         createTextNode (no file) (line 0:0)
+         appendChild (no file) (line 0:0)
+         getElementById (no file) (line 0:0)
+      arrayOperatorFunction profiler-test-JS-resources.js (line 25:31)
+      intermediaryFunction profiler-test-JS-resources.js (line 32:30)
+         anonymousFunction profiler-test-JS-resources.js (line 29:34)
+            insertNewText profiler-test-JS-resources.js (line 17:23)
+               createElement (no file) (line 0:0)
+               createTextNode (no file) (line 0:0)
+               appendChild (no file) (line 0:0)
+               getElementById (no file) (line 0:0)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      end many-calls-in-the-same-scope.html (line 26:13)
+      endT many-calls-in-the-same-scope.html (line 31:14)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/many-calls-in-the-same-scope.html b/LayoutTests/fast/profiler/many-calls-in-the-same-scope.html
new file mode 100644 (file)
index 0000000..0719bce
--- /dev/null
@@ -0,0 +1,49 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Many Calls In The Same Scope");
+
+    insertNewText();
+    insertGivenText("This was a triumph.");
+    arrayOperatorFunction(7);
+    intermediaryFunction();
+    anonymousFunction();
+    end()
+    endT();
+    endT();
+
+    endTest();
+}
+
+function end()
+{
+    var x = 0;
+}
+
+function endT()
+{
+    var y = 1;
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript has many function calls in the same scope.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile many functions should be the children of startTest.
+Use the sorting capabilites to make sure the similarly named functions are sorted
+correctly.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt b/LayoutTests/fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt
new file mode 100644 (file)
index 0000000..051ec81
--- /dev/null
@@ -0,0 +1,23 @@
+This page's JavaScript calls the same anonymous function from multiple and differently scoped locations. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call to fakeObject with fakeInteriorFunction as its child, but call() should not be shown.
+
+Profile title: Multiple and different scoped calls to the same anonymous function
+Thread_1 (no file) (line 0:0)
+   startTest multiple-and-different-scoped-anonymous-function-calls.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      intermediaryFunction profiler-test-JS-resources.js (line 32:30)
+         anonymousFunction profiler-test-JS-resources.js (line 29:34)
+            insertNewText profiler-test-JS-resources.js (line 17:23)
+               createElement (no file) (line 0:0)
+               createTextNode (no file) (line 0:0)
+               appendChild (no file) (line 0:0)
+               getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/multiple-and-different-scoped-anonymous-function-calls.html b/LayoutTests/fast/profiler/multiple-and-different-scoped-anonymous-function-calls.html
new file mode 100644 (file)
index 0000000..c2d005a
--- /dev/null
@@ -0,0 +1,33 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Multiple and different scoped calls to the same anonymous function");
+
+    anonymousFunction();
+    anonymousFunction();
+
+    intermediaryFunction();
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls the same anonymous function from multiple and differently scoped locations.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to fakeObject with
+fakeInteriorFunction as its child, but call() should not be shown.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/multiple-and-different-scoped-function-calls-expected.txt b/LayoutTests/fast/profiler/multiple-and-different-scoped-function-calls-expected.txt
new file mode 100644 (file)
index 0000000..b9fdced
--- /dev/null
@@ -0,0 +1,22 @@
+This page's JavaScript calls the same function from multiple and differently scoped locations. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be two calls to insertNewText under startTest() and one under an (anonymous function) under intermediaryFunction().
+
+Profile title: Multiple and different scoped calls to the same function
+Thread_1 (no file) (line 0:0)
+   startTest multiple-and-different-scoped-function-calls.html (line 10:19)
+      insertNewText profiler-test-JS-resources.js (line 17:23)
+         createElement (no file) (line 0:0)
+         createTextNode (no file) (line 0:0)
+         appendChild (no file) (line 0:0)
+         getElementById (no file) (line 0:0)
+      intermediaryFunction profiler-test-JS-resources.js (line 32:30)
+         anonymousFunction profiler-test-JS-resources.js (line 29:34)
+            insertNewText profiler-test-JS-resources.js (line 17:23)
+               createElement (no file) (line 0:0)
+               createTextNode (no file) (line 0:0)
+               appendChild (no file) (line 0:0)
+               getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/multiple-and-different-scoped-function-calls.html b/LayoutTests/fast/profiler/multiple-and-different-scoped-function-calls.html
new file mode 100644 (file)
index 0000000..fc2e221
--- /dev/null
@@ -0,0 +1,33 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Multiple and different scoped calls to the same function");
+
+    insertNewText();
+    insertNewText();
+
+    intermediaryFunction();
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls the same function from multiple and differently scoped locations.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be two calls to insertNewText under
+startTest() and one under an (anonymous function) under intermediaryFunction().
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt b/LayoutTests/fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt
new file mode 100644 (file)
index 0000000..e401404
--- /dev/null
@@ -0,0 +1,22 @@
+This page's JavaScript calls the different anonymous functions the same scope. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call two entries named to (anonymous function), as opposed to one entry called twice.
+
+Profile title: Multiple calls to different anonymous functions
+Thread_1 (no file) (line 0:0)
+   startTest multiple-anonymous-functions-called-from-the-same-function.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      anotherAnonymousFunction profiler-test-JS-resources.js (line 30:41)
+         insertGivenText profiler-test-JS-resources.js (line 9:25)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/multiple-anonymous-functions-called-from-the-same-function.html b/LayoutTests/fast/profiler/multiple-anonymous-functions-called-from-the-same-function.html
new file mode 100644 (file)
index 0000000..fb1cf2d
--- /dev/null
@@ -0,0 +1,31 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Multiple calls to different anonymous functions");
+
+    anonymousFunction();
+    anotherAnonymousFunction();
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls the different anonymous functions the same scope.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call two entries named to (anonymous function),
+as opposed to one entry called twice.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/multiple-frames-expected.txt b/LayoutTests/fast/profiler/multiple-frames-expected.txt
new file mode 100644 (file)
index 0000000..2e23f4c
--- /dev/null
@@ -0,0 +1,18 @@
+This test has JS executing in another window. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call to functionInOtherFrame().
+
+Profile title: Other window executing JavaScript
+Thread_1 (no file) (line 0:0)
+   startTest multiple-frames.html (line 10:19)
+      getElementById (no file) (line 0:0)
+      functionInOtherFrame other-frame.html (line 4:30)
+         functionInParentFrame multiple-frames.html (line 21:31)
+      insertGivenText profiler-test-JS-resources.js (line 9:25)
+         createElement (no file) (line 0:0)
+         createTextNode (no file) (line 0:0)
+         appendChild (no file) (line 0:0)
+         getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/multiple-frames.html b/LayoutTests/fast/profiler/multiple-frames.html
new file mode 100644 (file)
index 0000000..d1b4ff6
--- /dev/null
@@ -0,0 +1,36 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Other window executing JavaScript");
+
+    var myFrame = document.getElementById("mySubFrame");
+    var secret = myFrame.contentWindow.functionInOtherFrame();
+    insertGivenText(secret);
+
+    endTest();
+}
+
+function functionInParentFrame() {
+    return "Pi";
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This test has JS executing in another window.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to functionInOtherFrame().
+<div id="output"></div>
+<iframe src="resources/other-frame.html" id="mySubFrame"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/named-functions-with-display-names-expected.txt b/LayoutTests/fast/profiler/named-functions-with-display-names-expected.txt
new file mode 100644 (file)
index 0000000..190a64c
--- /dev/null
@@ -0,0 +1,16 @@
+This page's JavaScript calls named functions and changes their display names. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. You should see functions named "[x] iteration[s] function", and not "function[x]"
+
+Profile title: Named functions with display names
+Thread_1 (no file) (line 0:0)
+   startTest named-functions-with-display-names.html (line 53:19)
+      0 iterations function named-functions-with-display-names.html (line 10:19)
+      1 iteration function named-functions-with-display-names.html (line 17:19)
+      2 iterations function named-functions-with-display-names.html (line 24:19)
+      20 iterations function named-functions-with-display-names.html (line 31:20)
+      1000 iterations function named-functions-with-display-names.html (line 38:22)
+      bogusDisplayNameFunction named-functions-with-display-names.html (line 46:34)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/named-functions-with-display-names.html b/LayoutTests/fast/profiler/named-functions-with-display-names.html
new file mode 100644 (file)
index 0000000..7af2ec0
--- /dev/null
@@ -0,0 +1,77 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function function0()
+{
+    for (var i = 0; i < 0; ++i) ;
+}
+
+function0.displayName = "0 iterations function";
+
+function function1()
+{
+    for (var i = 0; i < 1; ++i) ;
+}
+
+function1.displayName = "1 iteration function";
+
+function function2()
+{
+    for (var i = 0; i < 2; ++i) ;
+}
+
+function2.displayName = "2 iterations function";
+
+function function20()
+{
+    for (var i = 0; i < 20; ++i) ;
+}
+
+function20.displayName = "20 iterations function";
+
+function function1000()
+{
+    for (var i = 0; i < 1000; ++i) ;
+}
+
+function1000.displayName = "1000 iterations function";
+
+
+function bogusDisplayNameFunction()
+{
+    for (var i = 0; i < 0; ++i) ;
+}
+
+bogusDisplayNameFunction.displayName = bogusDisplayNameFunction;
+
+function startTest()
+{
+    console.profile("Named functions with display names");
+
+    function0();
+    function1();
+    function2();
+    function20();
+    function1000();
+    bogusDisplayNameFunction();
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls named functions and changes their display names.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  You should see functions named "[x] iteration[s] function", and not "function[x]"
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/nested-anonymous-functon-expected.txt b/LayoutTests/fast/profiler/nested-anonymous-functon-expected.txt
new file mode 100644 (file)
index 0000000..d229a42
--- /dev/null
@@ -0,0 +1,17 @@
+This page's JavaScript calls an anonymous which calls a nested anonymous function. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be an (anonymous function) with a child (anonymous function).
+
+Profile title: Nested anonymous functions called
+Thread_1 (no file) (line 0:0)
+   startTest nested-anonymous-functon.html (line 10:19)
+      AnonymousFunctionWichCallsAnAnonymousFunction nested-anonymous-functon.html (line 14:65)
+         anonymousFunction profiler-test-JS-resources.js (line 29:34)
+            insertNewText profiler-test-JS-resources.js (line 17:23)
+               createElement (no file) (line 0:0)
+               createTextNode (no file) (line 0:0)
+               appendChild (no file) (line 0:0)
+               getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/nested-anonymous-functon.html b/LayoutTests/fast/profiler/nested-anonymous-functon.html
new file mode 100644 (file)
index 0000000..f6b925a
--- /dev/null
@@ -0,0 +1,34 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Nested anonymous functions called");
+
+    var AnonymousFunctionWichCallsAnAnonymousFunction = function() {
+        anonymousFunction();
+    }
+
+    AnonymousFunctionWichCallsAnAnonymousFunction();
+
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls an anonymous which calls a nested anonymous function.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be an (anonymous function) with a child
+(anonymous function).
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/nested-start-and-stop-profiler-expected.txt b/LayoutTests/fast/profiler/nested-start-and-stop-profiler-expected.txt
new file mode 100644 (file)
index 0000000..15a309d
--- /dev/null
@@ -0,0 +1,186 @@
+This page's JavaScript calls console.profile() three times then console.profileEnd() three times. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profiler there should be three profiles.
+
+Profile title: Start the profiler the third time.
+Thread_1 (no file) (line 0:0)
+   startTest nested-start-and-stop-profiler.html (line 10:19)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
+Profile title: Start the profiler the third time.
+Thread_1 (no file) (line 0:0)
+   startTest nested-start-and-stop-profiler.html (line 10:19)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+Profile title: Start the profiler the second time.
+Thread_1 (no file) (line 0:0)
+   startTest nested-start-and-stop-profiler.html (line 10:19)
+      endTest profiler-test-JS-resources.js (line 1:17)
+         profileEnd (no file) (line 0:0)
+         printProfilesDataWithoutTime profiler-test-JS-resources.js (line 62:38)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+               replace (no file) (line 0:0)
+                  hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                     (anonymous function) (no file) (line 0:0)
+                  anonymous (no file) (line 0:0)
+               createTextNode (no file) (line 0:0)
+               appendChild (no file) (line 0:0)
+               children (no file) (line 0:0)
+               printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                  replace (no file) (line 0:0)
+                     hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                        (anonymous function) (no file) (line 0:0)
+                     anonymous (no file) (line 0:0)
+                  createTextNode (no file) (line 0:0)
+                  appendChild (no file) (line 0:0)
+                  children (no file) (line 0:0)
+                  printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                     replace (no file) (line 0:0)
+                        hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                           (anonymous function) (no file) (line 0:0)
+                        anonymous (no file) (line 0:0)
+                     createTextNode (no file) (line 0:0)
+                     appendChild (no file) (line 0:0)
+                     children (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+         notifyDone (no file) (line 0:0)
+
+
+Profile title: Start the profiler the third time.
+Thread_1 (no file) (line 0:0)
+   startTest nested-start-and-stop-profiler.html (line 10:19)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+Profile title: Start the profiler the second time.
+Thread_1 (no file) (line 0:0)
+   startTest nested-start-and-stop-profiler.html (line 10:19)
+      endTest profiler-test-JS-resources.js (line 1:17)
+         profileEnd (no file) (line 0:0)
+         printProfilesDataWithoutTime profiler-test-JS-resources.js (line 62:38)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+               replace (no file) (line 0:0)
+                  hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                     (anonymous function) (no file) (line 0:0)
+                  anonymous (no file) (line 0:0)
+               createTextNode (no file) (line 0:0)
+               appendChild (no file) (line 0:0)
+               children (no file) (line 0:0)
+               printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                  replace (no file) (line 0:0)
+                     hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                        (anonymous function) (no file) (line 0:0)
+                     anonymous (no file) (line 0:0)
+                  createTextNode (no file) (line 0:0)
+                  appendChild (no file) (line 0:0)
+                  children (no file) (line 0:0)
+                  printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                     replace (no file) (line 0:0)
+                        hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                           (anonymous function) (no file) (line 0:0)
+                        anonymous (no file) (line 0:0)
+                     createTextNode (no file) (line 0:0)
+                     appendChild (no file) (line 0:0)
+                     children (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+         notifyDone (no file) (line 0:0)
+
+Profile title: Start the profiler the first time.
+Thread_1 (no file) (line 0:0)
+   startTest nested-start-and-stop-profiler.html (line 10:19)
+      endTest profiler-test-JS-resources.js (line 1:17)
+         profileEnd (no file) (line 0:0)
+         printProfilesDataWithoutTime profiler-test-JS-resources.js (line 62:38)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+               replace (no file) (line 0:0)
+                  hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                     (anonymous function) (no file) (line 0:0)
+                  anonymous (no file) (line 0:0)
+               createTextNode (no file) (line 0:0)
+               appendChild (no file) (line 0:0)
+               children (no file) (line 0:0)
+               printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                  replace (no file) (line 0:0)
+                     hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                        (anonymous function) (no file) (line 0:0)
+                     anonymous (no file) (line 0:0)
+                  createTextNode (no file) (line 0:0)
+                  appendChild (no file) (line 0:0)
+                  children (no file) (line 0:0)
+                  printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                     replace (no file) (line 0:0)
+                        hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                           (anonymous function) (no file) (line 0:0)
+                        anonymous (no file) (line 0:0)
+                     createTextNode (no file) (line 0:0)
+                     appendChild (no file) (line 0:0)
+                     children (no file) (line 0:0)
+                     printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                        replace (no file) (line 0:0)
+                           hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                              (anonymous function) (no file) (line 0:0)
+                           anonymous (no file) (line 0:0)
+                        createTextNode (no file) (line 0:0)
+                        appendChild (no file) (line 0:0)
+                        children (no file) (line 0:0)
+                        printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                           replace (no file) (line 0:0)
+                              hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                                 (anonymous function) (no file) (line 0:0)
+                              anonymous (no file) (line 0:0)
+                           createTextNode (no file) (line 0:0)
+                           appendChild (no file) (line 0:0)
+                           children (no file) (line 0:0)
+                           printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                              replace (no file) (line 0:0)
+                                 hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                                    (anonymous function) (no file) (line 0:0)
+                                 anonymous (no file) (line 0:0)
+                              createTextNode (no file) (line 0:0)
+                              appendChild (no file) (line 0:0)
+                              children (no file) (line 0:0)
+                              printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                                 replace (no file) (line 0:0)
+                                    hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                                       (anonymous function) (no file) (line 0:0)
+                                    anonymous (no file) (line 0:0)
+                                 createTextNode (no file) (line 0:0)
+                                 appendChild (no file) (line 0:0)
+                                 children (no file) (line 0:0)
+                                 printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                                    replace (no file) (line 0:0)
+                                       hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                                          (anonymous function) (no file) (line 0:0)
+                                       anonymous (no file) (line 0:0)
+                                    createTextNode (no file) (line 0:0)
+                                    appendChild (no file) (line 0:0)
+                                    children (no file) (line 0:0)
+                                    printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                                       replace (no file) (line 0:0)
+                                          hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                                             (anonymous function) (no file) (line 0:0)
+                                          anonymous (no file) (line 0:0)
+                                       createTextNode (no file) (line 0:0)
+                                       appendChild (no file) (line 0:0)
+                                       children (no file) (line 0:0)
+                                       printProfileNodeWithoutTime profiler-test-JS-resources.js (line 77:37)
+                                          replace (no file) (line 0:0)
+                                             hasObservableSideEffectsForStringReplace (no file) (line 0:0)
+                                                (anonymous function) (no file) (line 0:0)
+                                             anonymous (no file) (line 0:0)
+                                          createTextNode (no file) (line 0:0)
+                                          appendChild (no file) (line 0:0)
+                                          children (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+         notifyDone (no file) (line 0:0)
+
+
diff --git a/LayoutTests/fast/profiler/nested-start-and-stop-profiler.html b/LayoutTests/fast/profiler/nested-start-and-stop-profiler.html
new file mode 100644 (file)
index 0000000..2e78723
--- /dev/null
@@ -0,0 +1,31 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Start the profiler the first time.");
+    console.profile("Start the profiler the second time.");
+    console.profile("Start the profiler the third time.");
+    endTest();
+    endTest();
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls console.profile() three times then console.profileEnd()
+three times.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profiler there should be three profiles.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/no-execution-context-expected.txt b/LayoutTests/fast/profiler/no-execution-context-expected.txt
new file mode 100644 (file)
index 0000000..755dccb
--- /dev/null
@@ -0,0 +1,5 @@
+This page has a no profiling information. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. You should not see any profile date in the WebInspector.
+
+
diff --git a/LayoutTests/fast/profiler/no-execution-context.html b/LayoutTests/fast/profiler/no-execution-context.html
new file mode 100644 (file)
index 0000000..19c8539
--- /dev/null
@@ -0,0 +1,20 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+</script>
+</head>
+
+<body onload="printProfilesDataWithoutTime()">
+This page has a no profiling information.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  You should not see any profile date in the WebInspector.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/one-execution-context-expected.txt b/LayoutTests/fast/profiler/one-execution-context-expected.txt
new file mode 100644 (file)
index 0000000..f8dd670
--- /dev/null
@@ -0,0 +1,10 @@
+This page has a single script tag with some simple JavaScript. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile.
+
+Profile title: One Execution Context
+Thread_1 (no file) (line 0:0)
+   startTest one-execution-context.html (line 10:19)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/one-execution-context.html b/LayoutTests/fast/profiler/one-execution-context.html
new file mode 100644 (file)
index 0000000..d55f873
--- /dev/null
@@ -0,0 +1,27 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("One Execution Context");
+    endTest();
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page has a single script tag with some simple JavaScript.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/profile-calls-in-included-file-expected.txt b/LayoutTests/fast/profiler/profile-calls-in-included-file-expected.txt
new file mode 100644 (file)
index 0000000..c42d171
--- /dev/null
@@ -0,0 +1,10 @@
+This page calls the profiler from the included file. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. If there is a profile that is sufficient for this test.
+
+Profile title: Profile call in included file
+Thread_1 (no file) (line 0:0)
+   startProfile profiler-test-JS-resources.js (line 42:22)
+   endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/profile-calls-in-included-file.html b/LayoutTests/fast/profiler/profile-calls-in-included-file.html
new file mode 100644 (file)
index 0000000..af0f8f2
--- /dev/null
@@ -0,0 +1,28 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    startProfile("Profile call in included file");
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page calls the profiler from the included file.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  If there is a profile that is sufficient for this test.
+<div id="output"></div>
+<script>
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/profile-with-no-title-expected.txt b/LayoutTests/fast/profiler/profile-with-no-title-expected.txt
new file mode 100644 (file)
index 0000000..18dacdb
--- /dev/null
@@ -0,0 +1,10 @@
+This page creates a profile without a title. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. If there is a profile that is sufficient for this test.
+
+Profile title: 
+Thread_1 (no file) (line 0:0)
+   startTest profile-with-no-title.html (line 10:19)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/profile-with-no-title.html b/LayoutTests/fast/profiler/profile-with-no-title.html
new file mode 100644 (file)
index 0000000..ea525bc
--- /dev/null
@@ -0,0 +1,28 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile();
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page creates a profile without a title.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  If there is a profile that is sufficient for this test.
+<div id="output"></div>
+<script>
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting-expected.txt b/LayoutTests/fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting-expected.txt
new file mode 100644 (file)
index 0000000..156a2b3
--- /dev/null
@@ -0,0 +1,10 @@
+This page's JavaScript starts profiling from within a nested location but stops the profiler from a different level of nesting. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call to functionWichStartsAndStopsTheProfiler().
+
+Profile title: Profiling From A Nested Location But Stop Profiling Outside The Nesting
+Thread_1 (no file) (line 0:0)
+   functionWichStartsTheProfiler profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting.html (line 16:39)
+   endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting.html b/LayoutTests/fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting.html
new file mode 100644 (file)
index 0000000..48b5f77
--- /dev/null
@@ -0,0 +1,36 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    functionWichStartsTheProfiler();
+    endTest();
+}
+
+function functionWichStartsTheProfiler()
+{
+    console.profile("Profiling From A Nested Location But Stop Profiling Outside The Nesting");
+
+    for (var i = 0; i < 10000000; i++)
+        var b = i + 2;
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript starts profiling from within a nested location but stops the profiler
+from a different level of nesting.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to functionWichStartsAndStopsTheProfiler().
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/profiling-from-a-nested-location-expected.txt b/LayoutTests/fast/profiler/profiling-from-a-nested-location-expected.txt
new file mode 100644 (file)
index 0000000..484283b
--- /dev/null
@@ -0,0 +1,10 @@
+This page's JavaScript starts profiling from within a nested location. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call to functionWichStartsAndStopsTheProfiler().
+
+Profile title: Profiling From A Nested Location
+Thread_1 (no file) (line 0:0)
+   functionWichStartsAndStopsTheProfiler profiling-from-a-nested-location.html (line 15:47)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/profiling-from-a-nested-location.html b/LayoutTests/fast/profiler/profiling-from-a-nested-location.html
new file mode 100644 (file)
index 0000000..281fd03
--- /dev/null
@@ -0,0 +1,36 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    functionWichStartsAndStopsTheProfiler();
+}
+
+function functionWichStartsAndStopsTheProfiler()
+{
+    console.profile("Profiling From A Nested Location");
+
+    for (var i = 0; i < 10000000; i++)
+        var b = i + 2;
+
+    endTest();
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript starts profiling from within a nested location.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to functionWichStartsAndStopsTheProfiler().
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/resources/other-frame.html b/LayoutTests/fast/profiler/resources/other-frame.html
new file mode 100644 (file)
index 0000000..e836fbf
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+<head>
+<script>
+function functionInOtherFrame() {
+        return parent.functionInParentFrame();
+}
+</script>
+</head>
+
+<body>
+This file contains some JavaScript.
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/fast/profiler/resources/other-window.html b/LayoutTests/fast/profiler/resources/other-window.html
new file mode 100644 (file)
index 0000000..34841a8
--- /dev/null
@@ -0,0 +1,22 @@
+<html>
+<head>
+<script src="profiler-test-JS-resources.js"></script>
+<script>
+var interestingKnowledge;
+function otherTestStart()
+{
+    interestingKnowledge = isEqualToFive(3);
+    opener.windowFinishedLoading();
+}
+
+function functionInOtherWindow() {
+        return interestingKnowledge;
+}
+</script>
+</head>
+
+<body onload="otherTestStart()">
+This file executes some JavaScript.
+</body>
+</html>
+
diff --git a/LayoutTests/fast/profiler/resources/profiler-test-JS-resources.js b/LayoutTests/fast/profiler/resources/profiler-test-JS-resources.js
new file mode 100644 (file)
index 0000000..763542f
--- /dev/null
@@ -0,0 +1,95 @@
+function endTest() {
+    console.profileEnd();
+    printProfilesDataWithoutTime();
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function insertGivenText(text) {
+    var paragraph = document.createElement("p");
+    paragraph.appendChild(document.createTextNode(text));
+    paragraph.style.display = "none"; // Hidden since this isn't important in the test results.
+
+    document.getElementById("output").appendChild(paragraph);
+}
+
+function insertNewText() {
+    var paragraph = document.createElement("p");
+    paragraph.appendChild(document.createTextNode("This is inserted Text"));
+    paragraph.style.display = "none"; // Hidden since this isn't important in the test results.
+
+    document.getElementById("output").appendChild(paragraph);
+}
+
+function arrayOperatorFunction(arrayElement) {
+    return arrayElement + 5;
+}
+
+var anonymousFunction = function () { insertNewText(); };
+var anotherAnonymousFunction = function () { insertGivenText("Another anonymous function was called.") };
+
+function intermediaryFunction()
+{
+    anonymousFunction();
+}
+
+function isEqualToFive(input)
+{
+    return input === 5;
+}
+
+function startProfile(title)
+{
+    console.profile(title);
+}
+
+function printHeavyProfilesDataWithoutTime()
+{
+    var preElement = document.createElement("pre");
+    preElement.appendChild(document.createTextNode("\n"));
+
+    var profiles = internals.consoleProfiles;
+    for (var i = 0; i < profiles.length; ++i) {
+        preElement.appendChild(document.createTextNode("Profile title: " + profiles[i].title + "\n"));
+        printProfileNodeWithoutTime(preElement, profiles[i].heavyProfile.rootNode, 0);
+        preElement.appendChild(document.createTextNode("\n"));
+    }
+
+    document.getElementById("output").appendChild(preElement);
+}
+
+function printProfilesDataWithoutTime()
+{
+    var preElement = document.createElement("pre");
+    preElement.appendChild(document.createTextNode("\n"));
+
+    var profiles = internals.consoleProfiles;
+    for (var i = 0; i < profiles.length; ++i) {
+        preElement.appendChild(document.createTextNode("Profile title: " + profiles[i].title + "\n"));
+        printProfileNodeWithoutTime(preElement, profiles[i].rootNode, 0);
+        preElement.appendChild(document.createTextNode("\n"));
+    }
+
+    document.getElementById("output").appendChild(preElement);
+}
+
+function printProfileNodeWithoutTime(preElement, node, indentLevel)
+{
+    var space = "";
+    for (var i = 0; i < indentLevel; ++i)
+        space += "   "
+
+    ++indentLevel;
+
+    var strippedURL = node.url.replace(/.*\//, "");
+    if (!strippedURL)
+        strippedURL = "(no file)";
+
+    var line = space + node.functionName + " " + strippedURL + " (line " + node.lineNumber + ":" + node.columnNumber + ")\n";
+    preElement.appendChild(document.createTextNode(line));
+
+    var children = node.children();
+    for (var i = 0; i < children.length; ++i)
+        printProfileNodeWithoutTime(preElement, children[i], indentLevel);
+}
diff --git a/LayoutTests/fast/profiler/simple-event-call-expected.txt b/LayoutTests/fast/profiler/simple-event-call-expected.txt
new file mode 100644 (file)
index 0000000..c4cee3d
--- /dev/null
@@ -0,0 +1,10 @@
+This page's JavaScript has an onload event. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. There should be only one onload node.
+
+Profile title: A simple profile test where an event happens.
+Thread_1 (no file) (line 0:0)
+   startTest simple-event-call.html (line 10:19)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/simple-event-call.html b/LayoutTests/fast/profiler/simple-event-call.html
new file mode 100644 (file)
index 0000000..d4bdb50
--- /dev/null
@@ -0,0 +1,27 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("A simple profile test where an event happens.");
+    // FIXME: this is not testing what it says it is.
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript has an onload event.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  There should be only one onload node.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/simple-no-level-change-expected.txt b/LayoutTests/fast/profiler/simple-no-level-change-expected.txt
new file mode 100644 (file)
index 0000000..8bc38a5
--- /dev/null
@@ -0,0 +1,10 @@
+This page's JavaScript starts and stops profiling from the same scope. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. There should be no function calls between console.profile() and console.profileEnd().
+
+Profile title: A simple profile test where no scope chagnes
+Thread_1 (no file) (line 0:0)
+   functionWichStartsAndStopsTheProfiler simple-no-level-change.html (line 15:47)
+      getElementById (no file) (line 0:0)
+
+
diff --git a/LayoutTests/fast/profiler/simple-no-level-change.html b/LayoutTests/fast/profiler/simple-no-level-change.html
new file mode 100644 (file)
index 0000000..a362c83
--- /dev/null
@@ -0,0 +1,39 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    functionWichStartsAndStopsTheProfiler();
+}
+
+function functionWichStartsAndStopsTheProfiler()
+{
+    console.profile("A simple profile test where no scope chagnes");
+
+    for (var i = 0; i < 10000000; i++)
+        var b = i + 2;
+
+    document.getElementById("output");
+
+    console.profileEnd();
+    printProfilesDataWithoutTime();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript starts and stops profiling from the same scope.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  There should be no function calls between console.profile() and
+console.profileEnd().
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/start-and-stop-profiler-multiple-times-expected.txt b/LayoutTests/fast/profiler/start-and-stop-profiler-multiple-times-expected.txt
new file mode 100644 (file)
index 0000000..281e4bf
--- /dev/null
@@ -0,0 +1,73 @@
+This page's JavaScript calls console.profile() and console.profileEnd() three times. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profiler there should be three profiles.
+
+Profile title: Start the profiler the first time.
+Thread_1 (no file) (line 0:0)
+   startTest start-and-stop-profiler-multiple-times.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
+Profile title: Start the profiler the first time.
+Thread_1 (no file) (line 0:0)
+   startTest start-and-stop-profiler-multiple-times.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+Profile title: Start the profiler the second time.
+Thread_1 (no file) (line 0:0)
+   startTest start-and-stop-profiler-multiple-times.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
+Profile title: Start the profiler the first time.
+Thread_1 (no file) (line 0:0)
+   startTest start-and-stop-profiler-multiple-times.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+Profile title: Start the profiler the second time.
+Thread_1 (no file) (line 0:0)
+   startTest start-and-stop-profiler-multiple-times.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+Profile title: Start the profiler the third time.
+Thread_1 (no file) (line 0:0)
+   startTest start-and-stop-profiler-multiple-times.html (line 10:19)
+      anonymousFunction profiler-test-JS-resources.js (line 29:34)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/start-and-stop-profiler-multiple-times.html b/LayoutTests/fast/profiler/start-and-stop-profiler-multiple-times.html
new file mode 100644 (file)
index 0000000..169a763
--- /dev/null
@@ -0,0 +1,33 @@
+ <html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Start the profiler the first time.");
+    anonymousFunction();
+    endTest();
+    console.profile("Start the profiler the second time.");
+    anonymousFunction();
+    endTest();
+    console.profile("Start the profiler the third time.");
+    anonymousFunction();
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls console.profile() and console.profileEnd() three times.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profiler there should be three profiles.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/start-and-stop-profiling-in-the-same-function-expected.txt b/LayoutTests/fast/profiler/start-and-stop-profiling-in-the-same-function-expected.txt
new file mode 100644 (file)
index 0000000..7a8f5a6
--- /dev/null
@@ -0,0 +1,10 @@
+This page's JavaScript starts profiling from within a nested location. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call to functionWichStopsTheProfiler().
+
+Profile title: Profiling From A Nested Location
+Thread_1 (no file) (line 0:0)
+   startTest start-and-stop-profiling-in-the-same-function.html (line 10:19)
+      functionWichStopsTheProfiler start-and-stop-profiling-in-the-same-function.html (line 17:38)
+
+
diff --git a/LayoutTests/fast/profiler/start-and-stop-profiling-in-the-same-function.html b/LayoutTests/fast/profiler/start-and-stop-profiling-in-the-same-function.html
new file mode 100644 (file)
index 0000000..3ec0731
--- /dev/null
@@ -0,0 +1,37 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Profiling From A Nested Location");
+
+    functionWichStopsTheProfiler();
+}
+
+function functionWichStopsTheProfiler()
+{
+    for (var i = 0; i < 10000000; i++)
+        var b = i + 2;
+
+    console.profileEnd("Profiling From A Nested Location");
+    printProfilesDataWithoutTime();
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript starts profiling from within a nested location.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to functionWichStopsTheProfiler().
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/start-but-dont-stop-profiling-expected.txt b/LayoutTests/fast/profiler/start-but-dont-stop-profiling-expected.txt
new file mode 100644 (file)
index 0000000..4dbc12d
--- /dev/null
@@ -0,0 +1,5 @@
+This page's JavaScript calls console.profile() but not console.profileEnd(). 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. You should see the profile running (when that feature is implemented 6060556). Then navigate to another page and check the WebInspector again. Safari should not have crashed and the Inspector should not show a profile (unless we allow cross-load profiling in the future 5951478 & 5954912).
+
+
diff --git a/LayoutTests/fast/profiler/start-but-dont-stop-profiling.html b/LayoutTests/fast/profiler/start-but-dont-stop-profiling.html
new file mode 100644 (file)
index 0000000..7136d73
--- /dev/null
@@ -0,0 +1,30 @@
+ <html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Start the profiler but don't stop it.");
+    anonymousFunction();
+    printProfilesDataWithoutTime();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript calls console.profile() but not console.profileEnd().
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  You should see the profile running (when that feature is implemented 6060556).
+Then navigate to another page and check the WebInspector again. Safari should not
+have crashed and the Inspector should not show a profile (unless we allow cross-load
+profiling in the future 5951478 &amp; 5954912).
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/stop-profiling-after-setTimeout-expected.txt b/LayoutTests/fast/profiler/stop-profiling-after-setTimeout-expected.txt
new file mode 100644 (file)
index 0000000..b325da4
--- /dev/null
@@ -0,0 +1,13 @@
+This page's JavaScript stops profiling from a timeout. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile endProfile() should not be a child of (program).
+
+Profile title: Stop profiling from a timeout
+Thread_1 (no file) (line 0:0)
+   onload stop-profiling-after-setTimeout.html (line 21:44)
+      startTest stop-profiling-after-setTimeout.html (line 12:19)
+         setTimeout (no file) (line 0:0)
+   (program) stop-profiling-after-setTimeout.html (line 1:1)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/stop-profiling-after-setTimeout.html b/LayoutTests/fast/profiler/stop-profiling-after-setTimeout.html
new file mode 100644 (file)
index 0000000..19fd58e
--- /dev/null
@@ -0,0 +1,29 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Stop profiling from a timeout");    
+    setTimeout("endTest()", 20);
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript stops profiling from a timeout.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile endProfile() should not be a child of (program).
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/stop-then-function-call-expected.txt b/LayoutTests/fast/profiler/stop-then-function-call-expected.txt
new file mode 100644 (file)
index 0000000..1c05045
--- /dev/null
@@ -0,0 +1,10 @@
+This page has an anonymous JavaScript function that calls built-in functions. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. There should be two nodes in the profile, a "(program)" node with one child that is "test".
+
+Profile title: Test
+Thread_1 (no file) (line 0:0)
+   (program) (no file) (line 1:16)
+      test stop-then-function-call.html (line 11:14)
+
+
diff --git a/LayoutTests/fast/profiler/stop-then-function-call.html b/LayoutTests/fast/profiler/stop-then-function-call.html
new file mode 100644 (file)
index 0000000..916a19a
--- /dev/null
@@ -0,0 +1,43 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+var j = 0;
+function test(len) {
+    for (var i = 0; i < len; ++i)
+        ++j;
+}
+
+function test2(len) {
+    for (var i = 0; i < len; ++i)
+        --j;
+}
+
+function startTest()
+{
+    var script = "console.profile('Test');\n";
+    script += "test(1000);\n";
+    script += "console.profileEnd('Test');\n";
+    script += "test2(1000);\n";
+
+    eval(script);
+
+    printProfilesDataWithoutTime();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page has an anonymous JavaScript function that calls built-in functions.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile. There should be two nodes in the profile, a "(program)" node with one child that is "test".
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/throw-exception-from-eval-expected.txt b/LayoutTests/fast/profiler/throw-exception-from-eval-expected.txt
new file mode 100644 (file)
index 0000000..007c9ea
--- /dev/null
@@ -0,0 +1,23 @@
+CONSOLE MESSAGE: Test exception.
+This page throws an exception from within eval(). 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. The profiler should not crash and still show the stack under insertnewText().
+
+Profile title: Throw within an eval.
+Thread_1 (no file) (line 0)
+   (program) throw-exception-from-eval.html (line 19)
+      (program) throw-exception-from-eval.html (line 10)
+         (program) throw-exception-from-eval.html (line 4)
+         (program) throw-exception-from-eval.html (line 19)
+            eval (no file) (line 0)
+               (program) (no file) (line 1)
+   onload throw-exception-from-eval.html (line 24)
+      startTest throw-exception-from-eval.html (line 13)
+         insertNewText profiler-test-JS-resources.js (line 17)
+            createElement (no file) (line 0)
+            createTextNode (no file) (line 0)
+            appendChild (no file) (line 0)
+            getElementById (no file) (line 0)
+         endTest profiler-test-JS-resources.js (line 1)
+
+
diff --git a/LayoutTests/fast/profiler/throw-exception-from-eval.html-disabled b/LayoutTests/fast/profiler/throw-exception-from-eval.html-disabled
new file mode 100644 (file)
index 0000000..87eac9a
--- /dev/null
@@ -0,0 +1,33 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.settings.setLegacyJavaScriptProfilingEnabled(true);
+
+console.profile("Throw within an eval.");
+
+function startTest()
+{
+    insertNewText();
+
+    endTest();
+}
+</script>
+<script>
+eval("throw('Test exception.');");
+</script>
+</head>
+
+<body onload="startTest()">
+This page throws an exception from within eval().
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  The profiler should not crash and still show the stack under
+insertnewText().
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/two-execution-contexts-expected.txt b/LayoutTests/fast/profiler/two-execution-contexts-expected.txt
new file mode 100644 (file)
index 0000000..01e9dd1
--- /dev/null
@@ -0,0 +1,11 @@
+This page has two script tags with some simple JavaScript. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be two (program) elements.
+
+Profile title: Two Execution Contexts
+Thread_1 (no file) (line 0:0)
+   startTest two-execution-contexts.html (line 10:19)
+      intermediaryFunction two-execution-contexts.html (line 17:30)
+         testEnd two-execution-contexts.html (line 33:17)
+
+
diff --git a/LayoutTests/fast/profiler/two-execution-contexts.html b/LayoutTests/fast/profiler/two-execution-contexts.html
new file mode 100644 (file)
index 0000000..6851655
--- /dev/null
@@ -0,0 +1,38 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Two Execution Contexts");
+
+    intermediaryFunction();
+}
+
+function intermediaryFunction()
+{
+    testEnd();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page has two script tags with some simple JavaScript.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be two (program) elements.
+<div id="output"></div>
+</body>
+<script>
+function testEnd() {
+    console.profileEnd();
+    printProfilesDataWithoutTime();
+}
+</script>
+</html>
diff --git a/LayoutTests/fast/profiler/user-defined-function-calls-built-in-functions-expected.txt b/LayoutTests/fast/profiler/user-defined-function-calls-built-in-functions-expected.txt
new file mode 100644 (file)
index 0000000..d6ce551
--- /dev/null
@@ -0,0 +1,16 @@
+This page has JavaScript that calls built-in functions. 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be calls to createElement() createTextNode() appendChild() and testEnd(), among others.
+This is inserted Text
+
+
+Profile title: User defined function calles built-in functions
+Thread_1 (no file) (line 0:0)
+   startTest user-defined-function-calls-built-in-functions.html (line 10:19)
+      createElement (no file) (line 0:0)
+      createTextNode (no file) (line 0:0)
+      appendChild (no file) (line 0:0)
+      getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/user-defined-function-calls-built-in-functions.html b/LayoutTests/fast/profiler/user-defined-function-calls-built-in-functions.html
new file mode 100644 (file)
index 0000000..c7527b7
--- /dev/null
@@ -0,0 +1,34 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("User defined function calles built-in functions");
+
+    var newP = document.createElement("p");
+    var textNode =document.createTextNode("This is inserted Text");
+    newP.appendChild(textNode);
+    var output = document.getElementById("output");
+    output.appendChild(newP);
+    
+    endTest();
+}
+</script>
+</head>
+
+<body onload="startTest()">
+This page has JavaScript that calls built-in functions.
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be calls to createElement() createTextNode()
+appendChild() and testEnd(), among others.
+<div id="output"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/profiler/window-dot-eval-expected.txt b/LayoutTests/fast/profiler/window-dot-eval-expected.txt
new file mode 100644 (file)
index 0000000..dce88dc
--- /dev/null
@@ -0,0 +1,16 @@
+This page has a call to window.eval(). 
+
+To run this test manually, load it in the browser then load the WebInspector and look at the profile. In the profile there should be a call to eval().
+
+Profile title: Call window.eval()
+Thread_1 (no file) (line 0:0)
+   startTest window-dot-eval.html (line 10:19)
+      evalFunction (no file) (line 1:22)
+         insertNewText profiler-test-JS-resources.js (line 17:23)
+            createElement (no file) (line 0:0)
+            createTextNode (no file) (line 0:0)
+            appendChild (no file) (line 0:0)
+            getElementById (no file) (line 0:0)
+      endTest profiler-test-JS-resources.js (line 1:17)
+
+
diff --git a/LayoutTests/fast/profiler/window-dot-eval.html b/LayoutTests/fast/profiler/window-dot-eval.html
new file mode 100644 (file)
index 0000000..87a2b3c
--- /dev/null
@@ -0,0 +1,32 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.setLegacyJavaScriptProfilingEnabled(true);
+
+function startTest()
+{
+    console.profile("Call window.eval()");
+
+    evalFunction();
+
+    endTest();
+}
+</script>
+<script>
+window.eval("function evalFunction() { insertNewText(); }");
+</script>
+</head>
+
+<body onload="startTest()">
+This page has a call to window.eval().
+<br>
+<br>
+To run this test manually, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to eval().
+<div id="output"></div>
+</body>
+</html>
index bac8169189d8a962c1a0c5acd6707cc12c61b7a4..10a6749485fb5ad8eef79770ef0a173a39afd4dc 100644 (file)
@@ -1021,6 +1021,9 @@ webkit.org/b/142156 css3/shapes/spec-examples/shape-outside-011.html [ Failure P
 webkit.org/b/142156 css3/shapes/spec-examples/shape-outside-012.html [ Failure Pass ]
 webkit.org/b/142156 css3/shapes/spec-examples/shape-outside-019.html [ Failure Pass ]
 
+webkit.org/b/142157 fast/profiler/dead-time.html [ Failure Pass ]
+webkit.org/b/142157 fast/profiler/stop-profiling-after-setTimeout.html [ Failure Pass ]
+
 webkit.org/b/95551 fast/forms/datalist/update-range-with-datalist.html [ ImageOnlyFailure Pass ]
 
 webkit.org/b/129820 svg/clip-path/mask-nested-clip-path-006.svg [ Pass ImageOnlyFailure ]
index ddb6fd156084009be6e1cb1ef634fe315fc683d8..7b4b19971ea8ebf5f77c012960bea1941a05978e 100644 (file)
@@ -1203,6 +1203,9 @@ webkit.org/b/136066 animations/missing-keyframe-properties.html [ Crash Pass ]
 webkit.org/b/136066 animations/missing-values-first-keyframe.html [ Crash Pass ]
 webkit.org/b/136066 animations/state-at-end-event.html [ Crash Pass ]
 
+webkit.org/b/136067 fast/profiler/dead-time.html [ Failure Pass ]
+webkit.org/b/136067 fast/profiler/stop-profiling-after-setTimeout.html [ Failure Pass ]
+
 webkit.org/b/136070 fast/forms/label/label-becomes-visible-while-clicking-on-label.html [ Failure Pass ]
 
 webkit.org/b/136580 media/context-menu-actions.html [ Timeout Pass ]
index 20323fd46a1e837db7b38041c4dc25d2c1a5e8c2..37b35ad197eb5abc0a079838e76702c6c3852be9 100644 (file)
@@ -1894,6 +1894,7 @@ fast/parser/nested-fragment-parser-crash.html [ Failure ]
 fast/preloader/document-write-2.html [ Failure ]
 fast/preloader/document-write.html [ Failure ]
 fast/preloader/image-srcset.html [ Failure ]
+fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting.html [ Failure ]
 fast/regions/absolute-in-relative-overflow.html [ ImageOnlyFailure ]
 fast/regions/absolute-pos-elem-in-region.html [ ImageOnlyFailure ]
 fast/regions/animation-element-in-region-flowed-to-other-thread.html [ ImageOnlyFailure ]
diff --git a/ManualTests/inspector/profiler-test-call.html b/ManualTests/inspector/profiler-test-call.html
new file mode 100644 (file)
index 0000000..572a2e9
--- /dev/null
@@ -0,0 +1,35 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+console.profile("Using the call() method");
+function startTest()
+{
+    var myObject = new fakeObject(1, 2);
+    endTest();
+}
+
+function fakeObject (x, y)
+{
+    this.x = x;
+    fakeInteriorFunction.call(this, y);
+}
+
+function fakeInteriorFunction(y)
+{
+    this.y = y;
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript has a call to call() in it.
+<br>
+<br>
+To use this test, load it in the browser then load the WebInspector and look at
+the profile.  In the profile there should be a call to fakeObject() with call() as
+its child and a fakeInteriorFunction() as call()'s child.
+<div id="output"></div>
+</body>
+</html>
diff --git a/ManualTests/inspector/profiler-test-many-calls-in-the-same-scope.html b/ManualTests/inspector/profiler-test-many-calls-in-the-same-scope.html
new file mode 100644 (file)
index 0000000..da5be42
--- /dev/null
@@ -0,0 +1,42 @@
+<html>
+<head>
+<script src="resources/profiler-test-JS-resources.js"></script>
+<script>
+console.profile("Many Calls In The Same Scope");
+function startTest()
+{
+    insertNewText();
+    insertGivenText("This was a triumph.");
+    arrayOperatorFunction(7);
+    intermediaryFunction();
+    anonymousFunction();
+    end()
+    endT();
+    endT();
+    endTest();
+}
+
+function end()
+{
+    var x = 0;
+}
+
+function endT()
+{
+    var y = 1;
+}
+
+</script>
+</head>
+
+<body onload="startTest()">
+This page's JavaScript has many function calls in the same scope.
+<br>
+<br>
+To use this test, load it in the browser then load the WebInspector and look at
+the profile.  In the profile many functions should be the children of startTest.
+Use the sorting capabilites to make sure the similarly named functions are sorted
+correctly.
+<div id="output"></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/Source/JavaScriptCore/API/JSProfilerPrivate.cpp b/Source/JavaScriptCore/API/JSProfilerPrivate.cpp
new file mode 100644 (file)
index 0000000..ac112ae
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "JSProfilerPrivate.h"
+
+#include "APICast.h"
+#include "LegacyProfiler.h"
+#include "OpaqueJSString.h"
+
+using namespace JSC;
+
+void JSStartProfiling(JSContextRef ctx, JSStringRef title)
+{
+    // Use an independent stopwatch for API-initiated profiling, since the user will expect it
+    // to be relative to when their command was issued.
+    RefPtr<Stopwatch> stopwatch = Stopwatch::create();
+    stopwatch->start();
+    LegacyProfiler::profiler()->startProfiling(toJS(ctx), title->string(), stopwatch.release());
+}
+
+void JSEndProfiling(JSContextRef ctx, JSStringRef title)
+{
+    ExecState* exec = toJS(ctx);
+    LegacyProfiler* profiler = LegacyProfiler::profiler();
+    profiler->stopProfiling(exec, title->string());
+}
+
diff --git a/Source/JavaScriptCore/API/JSProfilerPrivate.h b/Source/JavaScriptCore/API/JSProfilerPrivate.h
new file mode 100644 (file)
index 0000000..34f26a2
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef JSProfiler_h
+#define JSProfiler_h
+
+#include <JavaScriptCore/JSBase.h>
+
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+@function JSStartProfiling
+@abstract Enables the profler.
+@param ctx The execution context to use.
+@param title The title of the profile.
+@result The profiler is turned on.
+*/
+JS_EXPORT void JSStartProfiling(JSContextRef ctx, JSStringRef title);
+
+/*!
+@function JSEndProfiling
+@abstract Disables the profler.
+@param ctx The execution context to use.
+@param title The title of the profile.
+@result The profiler is turned off. If there is no name, the most recently started
+        profile is stopped. If the name does not match any profile then no profile
+        is stopped.
+*/
+JS_EXPORT void JSEndProfiling(JSContextRef ctx, JSStringRef title);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JSProfiler_h */
index 61621af599d89e9bae80b643fa287d717b587e3d..bf52181bc6a5860e9828d5ff6612971dde96e9f8 100644 (file)
@@ -54,6 +54,7 @@ set(JavaScriptCore_SOURCES
     API/JSClassRef.cpp
     API/JSContextRef.cpp
     API/JSObjectRef.cpp
+    API/JSProfilerPrivate.cpp
     API/JSTypedArray.cpp
     API/JSScriptRef.cpp
     API/JSStringRef.cpp
@@ -585,6 +586,10 @@ set(JavaScriptCore_SOURCES
     parser/SourceProviderCache.cpp
     parser/VariableEnvironment.cpp
 
+    profiler/LegacyProfiler.cpp
+    profiler/Profile.cpp
+    profiler/ProfileGenerator.cpp
+    profiler/ProfileNode.cpp
     profiler/ProfilerBytecode.cpp
     profiler/ProfilerBytecodeSequence.cpp
     profiler/ProfilerBytecodes.cpp
index b6bd57189f86223e9708e6711e5b34212f66e8fb..ed6448660d53fe350048f1f375a7edbde1c95189 100644 (file)
@@ -1,3 +1,206 @@
+2016-05-16  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Unreviewed rollout r200924. Caused js/regress/string-replace-generic.html to fail.
+
+        * API/JSProfilerPrivate.cpp: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
+        (JSStartProfiling):
+        (JSEndProfiling):
+        * API/JSProfilerPrivate.h: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::generateUnlinkedFunctionCodeBlock):
+        (JSC::UnlinkedFunctionExecutable::unlinkedCodeBlockFor):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitCall):
+        (JSC::BytecodeGenerator::emitCallVarargs):
+        (JSC::BytecodeGenerator::emitCallVarargsInTailPosition):
+        (JSC::BytecodeGenerator::emitConstructVarargs):
+        (JSC::BytecodeGenerator::emitConstruct):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::CallArguments::profileHookRegister):
+        (JSC::BytecodeGenerator::shouldEmitProfileHooks):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::CallArguments::CallArguments):
+        (JSC::CallFunctionCallDotNode::emitBytecode):
+        (JSC::ApplyFunctionCallDotNode::emitBytecode):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * inspector/InjectedScriptBase.cpp:
+        (Inspector::InjectedScriptBase::callFunctionWithEvalEnabled):
+        * inspector/protocol/Timeline.json:
+        * interpreter/Interpreter.cpp:
+        (JSC::UnwindFunctor::operator()):
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_profile_will_call):
+        (JSC::JIT::emit_op_profile_did_call):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_profile_will_call):
+        (JSC::JIT::emit_op_profile_did_call):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * jsc.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * llint/LLIntSlowPaths.h:
+        * llint/LowLevelInterpreter.asm:
+        * parser/ParserModes.h:
+        * profiler/CallIdentifier.h: Added.
+        (JSC::CallIdentifier::CallIdentifier):
+        (JSC::CallIdentifier::functionName):
+        (JSC::CallIdentifier::url):
+        (JSC::CallIdentifier::lineNumber):
+        (JSC::CallIdentifier::columnNumber):
+        (JSC::CallIdentifier::operator==):
+        (JSC::CallIdentifier::operator!=):
+        (JSC::CallIdentifier::Hash::hash):
+        (JSC::CallIdentifier::Hash::equal):
+        (JSC::CallIdentifier::hash):
+        (JSC::CallIdentifier::operator const char*):
+        (JSC::CallIdentifier::c_str):
+        (WTF::HashTraits<JSC::CallIdentifier>::constructDeletedValue):
+        (WTF::HashTraits<JSC::CallIdentifier>::isDeletedValue):
+        * profiler/LegacyProfiler.cpp: Added.
+        (JSC::LegacyProfiler::profiler):
+        (JSC::LegacyProfiler::startProfiling):
+        (JSC::LegacyProfiler::stopProfiling):
+        (JSC::callFunctionForProfilesWithGroup):
+        (JSC::LegacyProfiler::suspendProfiling):
+        (JSC::LegacyProfiler::unsuspendProfiling):
+        (JSC::LegacyProfiler::willExecute):
+        (JSC::LegacyProfiler::didExecute):
+        (JSC::LegacyProfiler::exceptionUnwind):
+        (JSC::LegacyProfiler::createCallIdentifier):
+        (JSC::createCallIdentifierFromFunctionImp):
+        * profiler/LegacyProfiler.h: Added.
+        (JSC::LegacyProfiler::currentProfiles):
+        * profiler/Profile.cpp: Added.
+        (JSC::Profile::create):
+        (JSC::Profile::Profile):
+        (JSC::Profile::~Profile):
+        (JSC::Profile::debugPrint):
+        (JSC::functionNameCountPairComparator):
+        (JSC::Profile::debugPrintSampleStyle):
+        * profiler/Profile.h: Copied from Source/JavaScriptCore/profiler/ProfilerJettisonReason.h.
+        * profiler/ProfileGenerator.cpp: Added.
+        (JSC::ProfileGenerator::create):
+        (JSC::ProfileGenerator::ProfileGenerator):
+        (JSC::AddParentForConsoleStartFunctor::AddParentForConsoleStartFunctor):
+        (JSC::AddParentForConsoleStartFunctor::foundParent):
+        (JSC::AddParentForConsoleStartFunctor::operator()):
+        (JSC::ProfileGenerator::addParentForConsoleStart):
+        (JSC::ProfileGenerator::title):
+        (JSC::ProfileGenerator::beginCallEntry):
+        (JSC::ProfileGenerator::endCallEntry):
+        (JSC::ProfileGenerator::willExecute):
+        (JSC::ProfileGenerator::didExecute):
+        (JSC::ProfileGenerator::exceptionUnwind):
+        (JSC::ProfileGenerator::stopProfiling):
+        (JSC::ProfileGenerator::removeProfileStart):
+        (JSC::ProfileGenerator::removeProfileEnd):
+        * profiler/ProfileGenerator.h: Added.
+        (JSC::ProfileGenerator::profile):
+        (JSC::ProfileGenerator::origin):
+        (JSC::ProfileGenerator::profileGroup):
+        (JSC::ProfileGenerator::setIsSuspended):
+        * profiler/ProfileNode.cpp: Added.
+        (JSC::ProfileNode::ProfileNode):
+        (JSC::ProfileNode::addChild):
+        (JSC::ProfileNode::removeChild):
+        (JSC::ProfileNode::spliceNode):
+        (JSC::ProfileNode::traverseNextNodePostOrder):
+        (JSC::ProfileNode::debugPrint):
+        (JSC::ProfileNode::debugPrintSampleStyle):
+        (JSC::ProfileNode::debugPrintRecursively):
+        (JSC::ProfileNode::debugPrintSampleStyleRecursively):
+        * profiler/ProfileNode.h: Added.
+        (JSC::ProfileNode::create):
+        (JSC::ProfileNode::Call::Call):
+        (JSC::ProfileNode::Call::startTime):
+        (JSC::ProfileNode::Call::setStartTime):
+        (JSC::ProfileNode::Call::elapsedTime):
+        (JSC::ProfileNode::Call::setElapsedTime):
+        (JSC::ProfileNode::operator==):
+        (JSC::ProfileNode::callerCallFrame):
+        (JSC::ProfileNode::callIdentifier):
+        (JSC::ProfileNode::id):
+        (JSC::ProfileNode::functionName):
+        (JSC::ProfileNode::url):
+        (JSC::ProfileNode::lineNumber):
+        (JSC::ProfileNode::columnNumber):
+        (JSC::ProfileNode::parent):
+        (JSC::ProfileNode::setParent):
+        (JSC::ProfileNode::calls):
+        (JSC::ProfileNode::lastCall):
+        (JSC::ProfileNode::appendCall):
+        (JSC::ProfileNode::children):
+        (JSC::ProfileNode::firstChild):
+        (JSC::ProfileNode::lastChild):
+        (JSC::ProfileNode::nextSibling):
+        (JSC::ProfileNode::setNextSibling):
+        (JSC::ProfileNode::forEachNodePostorder):
+        (JSC::CalculateProfileSubtreeDataFunctor::operator()):
+        (JSC::CalculateProfileSubtreeDataFunctor::returnValue):
+        * profiler/ProfilerJettisonReason.cpp:
+        (WTF::printInternal):
+        * profiler/ProfilerJettisonReason.h:
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::getGlobalCodeBlock):
+        (JSC::CodeCache::getProgramCodeBlock):
+        (JSC::CodeCache::getEvalCodeBlock):
+        (JSC::CodeCache::getModuleProgramCodeBlock):
+        * runtime/CodeCache.h:
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::newCodeBlockFor):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::~JSGlobalObject):
+        (JSC::JSGlobalObject::hasLegacyProfiler):
+        (JSC::JSGlobalObject::createProgramCodeBlock):
+        (JSC::JSGlobalObject::createEvalCodeBlock):
+        (JSC::JSGlobalObject::createModuleProgramCodeBlock):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::supportsLegacyProfiling):
+        * runtime/Options.h:
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::SetEnabledProfilerFunctor::operator()):
+        (JSC::VM::setEnabledProfiler):
+        * runtime/VM.h:
+        (JSC::VM::enabledProfiler):
+        (JSC::VM::enabledProfilerAddress):
+
 2016-05-16  Konstantin Tokarev  <annulen@yandex.ru>
 
         Unreviewed, fixed typo in a comment.
index e73cf231422ac21982748fe84796505726c793d3..bd9a7bbc431c9c706be79d6fc873bad2f4697379 100644 (file)
                933040040E6A749400786E6A /* SmallStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 93303FEA0E6A72C000786E6A /* SmallStrings.h */; settings = {ATTRIBUTES = (Private, ); }; };
                9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93303FE80E6A72B500786E6A /* SmallStrings.cpp */; };
                9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93345A8712D838C400302BE3 /* StringRecursionChecker.cpp */; };
+               9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 952C63AC0E4777D600C13936 /* JSProfilerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               95742F650DD11F5A000917FB /* Profile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95742F630DD11F5A000917FB /* Profile.cpp */; };
+               95AB83420DA4322500BC83F3 /* LegacyProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95AB832E0DA42CAD00BC83F3 /* LegacyProfiler.cpp */; };
+               95AB83560DA43C3000BC83F3 /* ProfileNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95AB83540DA43B4400BC83F3 /* ProfileNode.cpp */; };
+               95CD45760E1C4FDD0085358E /* ProfileGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95CD45740E1C4FDD0085358E /* ProfileGenerator.cpp */; };
+               95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 95CD45750E1C4FDD0085358E /* ProfileGenerator.h */; settings = {ATTRIBUTES = (); }; };
+               95E3BC050E1AE68200B2D1C1 /* CallIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 95E3BC040E1AE68200B2D1C1 /* CallIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               95F6E6950E5B5F970091E860 /* JSProfilerPrivate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95988BA90E477BEC00D28D4D /* JSProfilerPrivate.cpp */; };
                960097A60EBABB58007A7297 /* LabelScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 960097A50EBABB58007A7297 /* LabelScope.h */; };
                9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC18C4460E16F5CD00B34460 /* ObjectPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC18C4480E16F5CD00B34460 /* Operations.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8780255597D01FF60F7 /* Operations.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F0B3AA09BB4DC00068FCE3 /* Parser.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               BC18C4500E16F5CD00B34460 /* Profile.h in Headers */ = {isa = PBXBuildFile; fileRef = 95742F640DD11F5A000917FB /* Profile.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AB83550DA43B4400BC83F3 /* ProfileNode.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               BC18C4520E16F5CD00B34460 /* LegacyProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AB832F0DA42CAD00BC83F3 /* LegacyProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC18C4540E16F5CD00B34460 /* PropertyNameArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 65400C100A69BAF200509887 /* PropertyNameArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */ = {isa = PBXBuildFile; fileRef = 65621E6C089E859700760F35 /* PropertySlot.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC18C4560E16F5CD00B34460 /* Protect.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C02FBB0637462A003E7EE6 /* Protect.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93F0B3A909BB4DC00068FCE3 /* Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Parser.cpp; sourceTree = "<group>"; };
                93F0B3AA09BB4DC00068FCE3 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Parser.h; sourceTree = "<group>"; };
                93F1981A08245AAE001E9ABC /* Keywords.table */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = text; path = Keywords.table; sourceTree = "<group>"; tabWidth = 8; };
+               952C63AC0E4777D600C13936 /* JSProfilerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSProfilerPrivate.h; sourceTree = "<group>"; };
+               95742F630DD11F5A000917FB /* Profile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Profile.cpp; path = profiler/Profile.cpp; sourceTree = "<group>"; };
+               95742F640DD11F5A000917FB /* Profile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Profile.h; path = profiler/Profile.h; sourceTree = "<group>"; };
+               95988BA90E477BEC00D28D4D /* JSProfilerPrivate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSProfilerPrivate.cpp; sourceTree = "<group>"; };
+               95AB832E0DA42CAD00BC83F3 /* LegacyProfiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LegacyProfiler.cpp; path = profiler/LegacyProfiler.cpp; sourceTree = "<group>"; };
+               95AB832F0DA42CAD00BC83F3 /* LegacyProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LegacyProfiler.h; path = profiler/LegacyProfiler.h; sourceTree = "<group>"; };
+               95AB83540DA43B4400BC83F3 /* ProfileNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfileNode.cpp; path = profiler/ProfileNode.cpp; sourceTree = "<group>"; };
+               95AB83550DA43B4400BC83F3 /* ProfileNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfileNode.h; path = profiler/ProfileNode.h; sourceTree = "<group>"; };
                95C18D3E0C90E7EF00E72F73 /* JSRetainPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRetainPtr.h; sourceTree = "<group>"; };
+               95CD45740E1C4FDD0085358E /* ProfileGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfileGenerator.cpp; path = profiler/ProfileGenerator.cpp; sourceTree = "<group>"; };
+               95CD45750E1C4FDD0085358E /* ProfileGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfileGenerator.h; path = profiler/ProfileGenerator.h; sourceTree = "<group>"; };
+               95E3BC040E1AE68200B2D1C1 /* CallIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CallIdentifier.h; path = profiler/CallIdentifier.h; sourceTree = "<group>"; };
                960097A50EBABB58007A7297 /* LabelScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelScope.h; sourceTree = "<group>"; };
                9688CB130ED12B4E001D649F /* AssemblerBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssemblerBuffer.h; sourceTree = "<group>"; };
                9688CB140ED12B4E001D649F /* X86Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86Assembler.h; sourceTree = "<group>"; };
                                1482B7E20A43076000517CFC /* JSObjectRef.cpp */,
                                1482B7E10A43076000517CFC /* JSObjectRef.h */,
                                A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */,
+                               95988BA90E477BEC00D28D4D /* JSProfilerPrivate.cpp */,
+                               952C63AC0E4777D600C13936 /* JSProfilerPrivate.h */,
                                A552C37D1ADDB8FE00139726 /* JSRemoteInspector.cpp */,
                                A552C37E1ADDB8FE00139726 /* JSRemoteInspector.h */,
                                95C18D3E0C90E7EF00E72F73 /* JSRetainPtr.h */,
                95AB831A0DA42C6900BC83F3 /* profiler */ = {
                        isa = PBXGroup;
                        children = (
+                               95E3BC040E1AE68200B2D1C1 /* CallIdentifier.h */,
+                               95AB832E0DA42CAD00BC83F3 /* LegacyProfiler.cpp */,
+                               95AB832F0DA42CAD00BC83F3 /* LegacyProfiler.h */,
+                               95742F630DD11F5A000917FB /* Profile.cpp */,
+                               95742F640DD11F5A000917FB /* Profile.h */,
+                               95CD45740E1C4FDD0085358E /* ProfileGenerator.cpp */,
+                               95CD45750E1C4FDD0085358E /* ProfileGenerator.h */,
+                               95AB83540DA43B4400BC83F3 /* ProfileNode.cpp */,
+                               95AB83550DA43B4400BC83F3 /* ProfileNode.h */,
                                0FF72992166AD347000F5BA3 /* ProfilerBytecode.cpp */,
                                0FF72993166AD347000F5BA3 /* ProfilerBytecode.h */,
                                0FF72994166AD347000F5BA3 /* ProfilerBytecodes.cpp */,
                                1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */,
                                62EC9BB71B7EB07C00303AD1 /* CallFrameShuffleData.h in Headers */,
                                62D755D71B84FB4A001801FA /* CallFrameShuffler.h in Headers */,
+                               95E3BC050E1AE68200B2D1C1 /* CallIdentifier.h in Headers */,
                                0F0B83B114BCF71800885B4F /* CallLinkInfo.h in Headers */,
                                0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */,
                                627673241B680C1E00FD9F2E /* CallMode.h in Headers */,
                                A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */,
                                A7F9935F0FD7325100A0B2D0 /* JSONObject.h in Headers */,
                                BC87CDB910712AD4000614CF /* JSONObject.lut.h in Headers */,
+                               9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */,
                                7C184E1B17BEDBD3007CB63A /* JSPromise.h in Headers */,
                                7C184E2317BEE240007CB63A /* JSPromiseConstructor.h in Headers */,
                                996B731E1BDA08EF00331B84 /* JSPromiseConstructor.lut.h in Headers */,
                                960097A60EBABB58007A7297 /* LabelScope.h in Headers */,
                                0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */,
                                99DA00B01BD5994E00F4575C /* lazywriter.py in Headers */,
+                               BC18C4520E16F5CD00B34460 /* LegacyProfiler.h in Headers */,
                                BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */,
                                BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */,
                                DCF3D56B1CD29472003D5C65 /* LazyClassStructureInlines.h in Headers */,
                                0FE834181A6EF97B00D04847 /* PolymorphicCallStubRoutine.h in Headers */,
                                0F98206116BFE38300240D02 /* PreciseJumpTargets.h in Headers */,
                                868916B0155F286300CB2B9A /* PrivateName.h in Headers */,
+                               BC18C4500E16F5CD00B34460 /* Profile.h in Headers */,
+                               95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */,
+                               BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */,
                                0FF729A5166AD351000F5BA3 /* ProfilerBytecode.h in Headers */,
                                0FF729B9166AD360000F5BA3 /* ProfilerBytecodes.h in Headers */,
                                0F13912A16771C36009CCB07 /* ProfilerBytecodeSequence.h in Headers */,
                                147F39D4107EC37600427A48 /* JSObject.cpp in Sources */,
                                1482B7E40A43076000517CFC /* JSObjectRef.cpp in Sources */,
                                A7F993600FD7325100A0B2D0 /* JSONObject.cpp in Sources */,
+                               95F6E6950E5B5F970091E860 /* JSProfilerPrivate.cpp in Sources */,
                                7C184E1A17BEDBD3007CB63A /* JSPromise.cpp in Sources */,
                                7C184E2217BEE240007CB63A /* JSPromiseConstructor.cpp in Sources */,
                                7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */,
                                14280870107EC1340013E7B2 /* JSWrapperObject.cpp in Sources */,
                                BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */,
                                0FB5467914F5C46B002C2989 /* LazyOperandValueProfile.cpp in Sources */,
+                               95AB83420DA4322500BC83F3 /* LegacyProfiler.cpp in Sources */,
                                148F21B0107EC5410042EC2C /* Lexer.cpp in Sources */,
                                0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */,
                                A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */,
                                0FE834171A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp in Sources */,
                                0F338E141BF0276C0013C88F /* B3ValueKey.cpp in Sources */,
                                0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */,
+                               95742F650DD11F5A000917FB /* Profile.cpp in Sources */,
+                               95CD45760E1C4FDD0085358E /* ProfileGenerator.cpp in Sources */,
+                               95AB83560DA43C3000BC83F3 /* ProfileNode.cpp in Sources */,
                                0FF729AD166AD35C000F5BA3 /* ProfilerBytecode.cpp in Sources */,
                                0FF729AE166AD35C000F5BA3 /* ProfilerBytecodes.cpp in Sources */,
                                0F13912916771C33009CCB07 /* ProfilerBytecodeSequence.cpp in Sources */,
index 91a96c6502ec8235bc05cabd0193ccc801d72cd2..7b49c645b23c181e8e506a0d8ce77700d2efdc08 100644 (file)
             { "name" : "op_throw", "length" : 2 },
             { "name" : "op_throw_static_error", "length" : 3 },
             { "name" : "op_debug", "length" : 3 },
+            { "name" : "op_profile_will_call", "length" : 2 },
+            { "name" : "op_profile_did_call", "length" : 2 },
             { "name" : "op_end", "length" : 2 },
             { "name" : "op_profile_type", "length" : 6 },
             { "name" : "op_profile_control_flow", "length" : 2 },
index 7cf0d57bfd2e46b1d85ee5cbcb0f69a0e7147002..4a1672ed465cf8120c010937f1de9951fae4045c 100644 (file)
@@ -62,6 +62,8 @@ void computeUsesForBytecodeOffset(
     case op_get_scope:
     case op_to_this:
     case op_check_tdz:
+    case op_profile_will_call:
+    case op_profile_did_call:
     case op_profile_type:
     case op_throw:
     case op_end:
@@ -310,6 +312,8 @@ void computeDefsForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* bloc
     case op_copy_rest:
     case op_put_to_scope:
     case op_end:
+    case op_profile_will_call:
+    case op_profile_did_call:
     case op_throw:
     case op_throw_static_error:
     case op_save:
index 41e8cf960c47c67500d4da8503ca8cc73b972636..3a808cb4c8d3457648041a2a4db1c4a8a120aa83 100644 (file)
@@ -1654,6 +1654,16 @@ void CodeBlock::dumpBytecode(
             out.printf("%s, %d", registerName(condition).data(), line);
             break;
         }
+        case op_profile_will_call: {
+            int function = (++it)->u.operand;
+            printLocationOpAndRegisterOperand(out, exec, location, it, "profile_will_call", function);
+            break;
+        }
+        case op_profile_did_call: {
+            int function = (++it)->u.operand;
+            printLocationOpAndRegisterOperand(out, exec, location, it, "profile_did_call", function);
+            break;
+        }
         case op_end: {
             int r0 = (++it)->u.operand;
             printLocationOpAndRegisterOperand(out, exec, location, it, "end", r0);
index 34619b6fcd6b09dc66e853a1b3c27f269c17bd29..66278844b681894612ec759a2a7711306e378b57 100644 (file)
@@ -49,7 +49,7 @@ const ClassInfo UnlinkedFunctionExecutable::s_info = { "UnlinkedFunctionExecutab
 
 static UnlinkedFunctionCodeBlock* generateUnlinkedFunctionCodeBlock(
     VM& vm, UnlinkedFunctionExecutable* executable, const SourceCode& source,
-    CodeSpecializationKind kind, DebuggerMode debuggerMode,
+    CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode,
     UnlinkedFunctionKind functionKind, ParserError& error, SourceParseMode parseMode)
 {
     JSParserBuiltinMode builtinMode = executable->isBuiltinFunction() ? JSParserBuiltinMode::Builtin : JSParserBuiltinMode::NotBuiltin;
@@ -70,7 +70,7 @@ static UnlinkedFunctionCodeBlock* generateUnlinkedFunctionCodeBlock(
 
     UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext, EvalContextType::FunctionEvalContext));
 
-    error = BytecodeGenerator::generate(vm, function.get(), result, debuggerMode, executable->parentScopeTDZVariables());
+    error = BytecodeGenerator::generate(vm, function.get(), result, debuggerMode, profilerMode, executable->parentScopeTDZVariables());
 
     if (error.isValid())
         return nullptr;
@@ -191,7 +191,7 @@ UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(
 
 UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::unlinkedCodeBlockFor(
     VM& vm, const SourceCode& source, CodeSpecializationKind specializationKind, 
-    DebuggerMode debuggerMode, ParserError& error, SourceParseMode parseMode)
+    DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error, SourceParseMode parseMode)
 {
     switch (specializationKind) {
     case CodeForCall:
@@ -205,7 +205,7 @@ UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::unlinkedCodeBlockFor(
     }
 
     UnlinkedFunctionCodeBlock* result = generateUnlinkedFunctionCodeBlock(
-        vm, this, source, specializationKind, debuggerMode, 
+        vm, this, source, specializationKind, debuggerMode, profilerMode, 
         isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, 
         error, parseMode);
     
index 646b0a682d7078abcd6f68887923a8cbbc521985..b3591949fbf86bce9dead9a7f8daaef54c3ff79b 100644 (file)
@@ -101,7 +101,7 @@ public:
     void setInvalidTypeProfilingOffsets();
 
     UnlinkedFunctionCodeBlock* unlinkedCodeBlockFor(
-        VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode,
+        VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, 
         ParserError&, SourceParseMode);
 
     static UnlinkedFunctionExecutable* fromGlobalCode(
index 94f22417f1d41dc230bf716e4638ff183c12998c..ec110f954812c8624c99616ab7c62bed37a43a3e 100644 (file)
@@ -147,8 +147,9 @@ ParserError BytecodeGenerator::generate()
     return ParserError(ParserError::ErrorNone);
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, const VariableEnvironment* parentScopeTDZVariables)
+BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables)
     : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
+    , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
     , m_scopeNode(programNode)
     , m_codeBlock(vm, codeBlock)
     , m_thisRegister(CallFrame::thisArgumentOffset())
@@ -192,8 +193,9 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedP
     }
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, const VariableEnvironment* parentScopeTDZVariables)
+BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables)
     : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
+    , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
     , m_scopeNode(functionNode)
     , m_codeBlock(vm, codeBlock)
     , m_codeType(FunctionCode)
@@ -205,7 +207,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
     // op_will_call / op_did_call pairs before and after a call, which are not
     // compatible with tail calls (we have no way of emitting op_did_call).
     // https://bugs.webkit.org/show_bug.cgi?id=148819
-    , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && isStrictMode())
+    , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && isStrictMode() && !m_shouldEmitProfileHooks)
     , m_needsToUpdateArrowFunctionContext(functionNode->usesArrowFunction() || functionNode->usesEval())
     , m_derivedContextType(codeBlock->derivedContextType())
 {
@@ -592,8 +594,9 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
     pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, const VariableEnvironment* parentScopeTDZVariables)
+BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables)
     : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
+    , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
     , m_scopeNode(evalNode)
     , m_codeBlock(vm, codeBlock)
     , m_thisRegister(CallFrame::thisArgumentOffset())
@@ -649,8 +652,9 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod
     pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, const VariableEnvironment* parentScopeTDZVariables)
+BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables)
     : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
+    , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
     , m_scopeNode(moduleProgramNode)
     , m_codeBlock(vm, codeBlock)
     , m_thisRegister(CallFrame::thisArgumentOffset())
@@ -3049,6 +3053,9 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     ASSERT(opcodeID == op_call || opcodeID == op_call_eval || opcodeID == op_tail_call);
     ASSERT(func->refCount());
     
+    if (m_shouldEmitProfileHooks)
+        emitMove(callArguments.profileHookRegister(), func);
+
     // Generate code for arguments.
     unsigned argument = 0;
     if (callArguments.argumentsNode()) {
@@ -3059,7 +3066,7 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
             RefPtr<RegisterID> argumentRegister;
             argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
             RefPtr<RegisterID> thisRegister = emitMove(newTemporary(), callArguments.thisRegister());
-            return emitCallVarargs(opcodeID == op_tail_call ? op_tail_call_varargs : op_call_varargs, dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd);
+            return emitCallVarargs(opcodeID == op_tail_call ? op_tail_call_varargs : op_call_varargs, dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
         }
         for (; n; n = n->m_next)
             emitNode(callArguments.argumentRegister(argument++), n);
@@ -3070,6 +3077,11 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
         callFrame.append(newTemporary());
 
+    if (m_shouldEmitProfileHooks) {
+        emitOpcode(op_profile_will_call);
+        instructions().append(callArguments.profileHookRegister()->index());
+    }
+
     emitExpressionInfo(divot, divotStart, divotEnd);
 
     RefPtr<Label> done = newLabel();
@@ -3095,26 +3107,37 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     if (expectedFunction != NoExpectedFunction)
         emitLabel(done.get());
 
+    if (m_shouldEmitProfileHooks) {
+        emitOpcode(op_profile_did_call);
+        instructions().append(callArguments.profileHookRegister()->index());
+    }
+
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
 {
-    return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd);
+    return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
 }
 
-RegisterID* BytecodeGenerator::emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+RegisterID* BytecodeGenerator::emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
 {
-    return emitCallVarargs(m_inTailPosition ? op_tail_call_varargs : op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd);
+    return emitCallVarargs(m_inTailPosition ? op_tail_call_varargs : op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
 }
 
-RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
 {
-    return emitCallVarargs(op_construct_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd);
+    return emitCallVarargs(op_construct_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
 }
     
-RegisterID* BytecodeGenerator::emitCallVarargs(OpcodeID opcode, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+RegisterID* BytecodeGenerator::emitCallVarargs(OpcodeID opcode, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
 {
+    if (m_shouldEmitProfileHooks) {
+        emitMove(profileHookRegister, func);
+        emitOpcode(op_profile_will_call);
+        instructions().append(profileHookRegister->index());
+    }
+    
     emitExpressionInfo(divot, divotStart, divotEnd);
 
     if (opcode == op_tail_call_varargs)
@@ -3132,6 +3155,10 @@ RegisterID* BytecodeGenerator::emitCallVarargs(OpcodeID opcode, RegisterID* dst,
     instructions().append(firstVarArgOffset);
     instructions().append(arrayProfile);
     instructions().append(profile);
+    if (m_shouldEmitProfileHooks) {
+        emitOpcode(op_profile_did_call);
+        instructions().append(profileHookRegister->index());
+    }
     return dst;
 }
 
@@ -3222,6 +3249,9 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
 {
     ASSERT(func->refCount());
 
+    if (m_shouldEmitProfileHooks)
+        emitMove(callArguments.profileHookRegister(), func);
+
     // Generate code for arguments.
     unsigned argument = 0;
     if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
@@ -3232,13 +3262,18 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
             auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
             RefPtr<RegisterID> argumentRegister;
             argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
-            return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd);
+            return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
         }
         
         for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
             emitNode(callArguments.argumentRegister(argument++), n);
     }
 
+    if (m_shouldEmitProfileHooks) {
+        emitOpcode(op_profile_will_call);
+        instructions().append(callArguments.profileHookRegister()->index());
+    }
+
     // Reserve space for call frame.
     Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
     for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
@@ -3263,6 +3298,11 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
     if (expectedFunction != NoExpectedFunction)
         emitLabel(done.get());
 
+    if (m_shouldEmitProfileHooks) {
+        emitOpcode(op_profile_did_call);
+        instructions().append(callArguments.profileHookRegister()->index());
+    }
+
     return dst;
 }
 
index 22ce4a3fc3091600fa1d8114148c01a19ca033ea..99bc7973f5bfbb6c19a30206eeaae84c42d168bf 100644 (file)
@@ -75,9 +75,11 @@ namespace JSC {
         RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
         unsigned stackOffset() { return -m_argv[0]->index() + JSStack::CallFrameHeaderSize; }
         unsigned argumentCountIncludingThis() { return m_argv.size() - m_padding; }
+        RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
         ArgumentsNode* argumentsNode() { return m_argumentsNode; }
 
     private:
+        RefPtr<RegisterID> m_profileHookRegister;
         ArgumentsNode* m_argumentsNode;
         Vector<RefPtr<RegisterID>, 8, UnsafeVectorOverflow> m_argv;
         unsigned m_padding;
@@ -267,10 +269,10 @@ namespace JSC {
     public:
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
-        BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, const VariableEnvironment*);
-        BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, const VariableEnvironment*);
-        BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, const VariableEnvironment*);
-        BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, DebuggerMode, const VariableEnvironment*);
+        BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
+        BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
+        BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
+        BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
 
         ~BytecodeGenerator();
         
@@ -575,8 +577,8 @@ namespace JSC {
         RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
         RegisterID* emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
         RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
-        RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
-        RegisterID* emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+        RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+        RegisterID* emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
 
         enum PropertyDescriptorOption {
             PropertyConfigurable = 1,
@@ -702,6 +704,7 @@ namespace JSC {
 
         CodeType codeType() const { return m_codeType; }
 
+        bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
         bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
         
         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
@@ -846,8 +849,8 @@ namespace JSC {
 
         void getVariablesUnderTDZ(VariableEnvironment&);
 
-        RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
-        RegisterID* emitCallVarargs(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+        RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+        RegisterID* emitCallVarargs(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
         
         void emitLogShadowChickenPrologueIfNecessary();
         void emitLogShadowChickenTailIfNecessary();
@@ -869,6 +872,7 @@ namespace JSC {
         Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions;
 
         bool m_shouldEmitDebugHooks;
+        bool m_shouldEmitProfileHooks;
 
         struct SymbolTableStackEntry {
             SymbolTable* m_symbolTable;
index 3bbd2f17ebc3febb21a5b2fe79000b36d8988250..f2530eec3794c5361009120556f90d9a7fe1aee5 100644 (file)
@@ -707,6 +707,9 @@ CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argume
     : m_argumentsNode(argumentsNode)
     , m_padding(0)
 {
+    if (generator.shouldEmitProfileHooks())
+        m_profileHookRegister = generator.newTemporary();
+
     size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
     if (argumentsNode) {
         for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
@@ -1018,13 +1021,16 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
     RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
     {
         if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) {
+            RefPtr<RegisterID> profileHookRegister;
+            if (generator.shouldEmitProfileHooks())
+                profileHookRegister = generator.newTemporary();
             SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
             ExpressionNode* subject = spread->expression();
             RefPtr<RegisterID> argumentsRegister;
             argumentsRegister = generator.emitNode(subject);
             generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
             RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
-            generator.emitCallVarargsInTailPosition(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, divot(), divotStart(), divotEnd());
+            generator.emitCallVarargsInTailPosition(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
         } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
             ArgumentListNode* oldList = m_args->m_listNode;
             m_args->m_listNode = m_args->m_listNode->m_next;
@@ -1088,6 +1094,9 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
             ArgumentListNode* oldList = m_args->m_listNode;
             if (m_args->m_listNode->m_expr->isSpreadExpression()) {
                 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
+                RefPtr<RegisterID> profileHookRegister;
+                if (generator.shouldEmitProfileHooks())
+                    profileHookRegister = generator.newTemporary();
                 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
                 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
                 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
@@ -1111,7 +1120,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
                     generator.emitLabel(end.get());
                 };
                 generator.emitEnumeration(this, spread->expression(), extractor);
-                generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd());
+                generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
             } else if (m_args->m_listNode->m_next) {
                 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
                 ASSERT(!m_args->m_listNode->m_next->m_next);
@@ -1136,6 +1145,9 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
         }
     } else {
         ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
+        RefPtr<RegisterID> profileHookRegister;
+        if (generator.shouldEmitProfileHooks())
+            profileHookRegister = generator.newTemporary();
         RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
         RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
         RefPtr<RegisterID> argsRegister;
@@ -1147,7 +1159,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
         while ((args = args->m_next))
             generator.emitNode(args->m_expr);
 
-        generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd());
+        generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
     }
     if (emitCallCheck) {
         generator.emitJump(end.get());
index d0832a673a24ec8e6989c86602aac21439aef2a9..09091ecf3cb1f54da1b931d71e41af331d36d25a 100644 (file)
@@ -2844,6 +2844,8 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case LogShadowChickenTail:
         break;
 
+    case ProfileWillCall:
+    case ProfileDidCall:
     case ProfileType:
     case ProfileControlFlow:
     case Phantom:
index 85d8d21949896e6b4bdfea205f7053a3af646e89..6d079f62afab0f8b8d9ebe618b412c068d8b2f73 100644 (file)
@@ -3799,6 +3799,16 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             NEXT_OPCODE(op_debug);
         }
 
+        case op_profile_will_call: {
+            addToGraph(ProfileWillCall);
+            NEXT_OPCODE(op_profile_will_call);
+        }
+
+        case op_profile_did_call: {
+            addToGraph(ProfileDidCall);
+            NEXT_OPCODE(op_profile_did_call);
+        }
+
         case op_mov: {
             Node* op = get(VirtualRegister(currentInstruction[2].u.operand));
             set(VirtualRegister(currentInstruction[1].u.operand), op);
index 06669d4068fe834b84bcaeb98bbc60da7c7ee24c..cc2d47482497a2d33717f5b4c3922128ea22541b 100644 (file)
@@ -124,6 +124,8 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruc
     case op_mod:
     case op_div:
     case op_debug:
+    case op_profile_will_call:
+    case op_profile_did_call:
     case op_profile_type:
     case op_profile_control_flow:
     case op_mov:
index da3098c261c3bb614f439894f6ceeae426f8de17..fa7694031c52dac4b6223631dd0177f31daccb68 100644 (file)
@@ -372,6 +372,8 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
     case CheckTierUpAtReturn:
     case CheckTierUpAndOSREnter:
     case LoopHint:
+    case ProfileWillCall:
+    case ProfileDidCall:
     case ProfileType:
     case ProfileControlFlow:
     case StoreBarrier:
index 5ff2ecfed84d3993a86f140587e5a4da59dcbf51..6cf0d0b873c52d1cacc30e3747cf93cc1cb1f06f 100644 (file)
@@ -150,6 +150,8 @@ bool doesGC(Graph& graph, Node* node)
     case ConstructForwardVarargs:
     case TailCallForwardVarargs:
     case TailCallForwardVarargsInlinedCaller:
+    case ProfileWillCall:
+    case ProfileDidCall:
     case ProfileType:
     case ProfileControlFlow:
     case OverridesHasInstance:
index e09de55599e9cd04d0b29b22b35f898319aff107..ff2644113a4cdc362fde8e3d7f96acfd98296838 100644 (file)
@@ -1534,6 +1534,8 @@ private:
         case NewObject:
         case NewArrayBuffer:
         case NewRegexp:
+        case ProfileWillCall:
+        case ProfileDidCall:
         case DeleteById:
         case DeleteByVal:
         case IsArrayObject:
index 197876f01462bba3d68a320dfbc0545ed390670e..181c790a1d2420478e44f08685109d8ad8c3ce7f 100644 (file)
@@ -303,6 +303,8 @@ namespace JSC { namespace DFG {
     macro(MaterializeCreateActivation, NodeResultJS | NodeHasVarArgs) \
     \
     /* Nodes for misc operations. */\
+    macro(ProfileWillCall, NodeMustGenerate) \
+    macro(ProfileDidCall, NodeMustGenerate) \
     macro(OverridesHasInstance, NodeMustGenerate | NodeResultBoolean) \
     macro(InstanceOf, NodeResultBoolean) \
     macro(InstanceOfCustom, NodeMustGenerate | NodeResultBoolean) \
index 50684f22ce55d963c52955fa02bb6b2246c77302..1661e94bfbe7813738025bb71d21eaa4cc7d4da0 100644 (file)
@@ -1035,6 +1035,8 @@ private:
         case DFG::Jump:
         case Branch:
         case Switch:
+        case ProfileWillCall:
+        case ProfileDidCall:
         case ProfileType:
         case ProfileControlFlow:
         case ThrowReferenceError:
index 629e0586c8cc9846415f68c989f3625abe5cfe5f..f9bdeb9cd2d18b62143b356e5128916b8e9cc54d 100644 (file)
@@ -250,6 +250,8 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
     case NewArrayWithSize:
     case NewArrayBuffer:
     case NewRegexp:
+    case ProfileWillCall:
+    case ProfileDidCall:
     case ProfileType:
     case ProfileControlFlow:
     case CheckTypeInfoFlags:
index 338aba721de0c594a774fc2b5b938362c462318f..d740d775e9ad15de63dd598cd3bf7c6152677014 100644 (file)
@@ -5197,6 +5197,8 @@ void SpeculativeJIT::compile(Node* node)
         noResult(node);
         break;
 
+    case ProfileWillCall:
+    case ProfileDidCall:
     case PhantomLocal:
     case LoopHint:
         // This is a no-op.
index 4821cd839e66098e7674cbe76338ad7c8aa8ea35..1400ea5245b8becc2586ad74ae965ef181156c05 100644 (file)
@@ -4812,6 +4812,8 @@ void SpeculativeJIT::compile(Node* node)
         noResult(node);
         break;
         
+    case ProfileWillCall:
+    case ProfileDidCall:
     case PhantomLocal:
     case LoopHint:
         // This is a no-op.
index 9caa4eb93fe7f9e328dd3299021395cc32a49ad4..1864e842ca3a90043f6a685b15f5993f227a5a42 100644 (file)
@@ -36,6 +36,7 @@
 #include "InspectorValues.h"
 #include "JSCInlines.h"
 #include "JSGlobalObject.h"
+#include "LegacyProfiler.h"
 #include "ScriptFunctionCall.h"
 #include <wtf/text/WTFString.h>
 
@@ -71,8 +72,17 @@ const Deprecated::ScriptObject& InjectedScriptBase::injectedScriptObject() const
 JSC::JSValue InjectedScriptBase::callFunctionWithEvalEnabled(Deprecated::ScriptFunctionCall& function, bool& hadException) const
 {
     JSC::ExecState* scriptState = m_injectedScriptObject.scriptState();
-    JSC::DebuggerEvalEnabler evalEnabler(scriptState);
-    return function.call(hadException);
+    JSC::LegacyProfiler::profiler()->suspendProfiling(scriptState);
+
+    JSC::JSValue resultValue;
+    {
+        JSC::DebuggerEvalEnabler evalEnabler(scriptState);
+        resultValue = function.call(hadException);
+    }
+
+    JSC::LegacyProfiler::profiler()->unsuspendProfiling(scriptState);
+
+    return resultValue;
 }
 
 void InjectedScriptBase::makeCall(Deprecated::ScriptFunctionCall& function, RefPtr<InspectorValue>* result)
index 69169e0e7ebb5f8b58817d650d1d396f883ae015..822ff86722bdc9183b2cdc52896fefad91a94f3f 100644 (file)
                 { "name": "data", "type": "object", "description": "Event data." },
                 { "name": "children", "type": "array", "optional": true, "items": { "$ref": "TimelineEvent" }, "description": "Nested records." }
             ]
+        },
+        {
+            "id": "CPUProfileNodeAggregateCallInfo",
+            "type": "object",
+            "description": "Aggregate CPU Profile call info. Holds time information for all the calls that happened on a node.",
+            "properties": [
+                { "name": "callCount", "type": "number", "description": "Total number of calls." },
+                { "name": "startTime", "type": "number", "description": "Start time for the first call." },
+                { "name": "endTime", "type": "number", "description": "End time for the last call." },
+                { "name": "totalTime", "type": "number", "description": "Total execution time for all calls combined." }
+            ]
+        },
+        {
+            "id": "CPUProfileNode",
+            "type": "object",
+            "description": "CPU Profile node. Holds callsite information, execution statistics and child nodes.",
+            "properties": [
+                { "name": "id", "type": "integer", "description": "Unique identifier for this call site." },
+                { "name": "callInfo", "$ref": "CPUProfileNodeAggregateCallInfo", "description": "Aggregate info about all the calls that making up this node." },
+                { "name": "functionName", "type": "string", "optional": true, "description": "Function name." },
+                { "name": "url", "type": "string", "optional": true, "description": "URL." },
+                { "name": "lineNumber", "type": "integer", "optional": true, "description": "Line number." },
+                { "name": "columnNumber", "type": "integer", "optional": true, "description": "Column number." },
+                { "name": "children", "type": "array", "items": { "$ref": "CPUProfileNode" }, "optional": true, "description": "Child nodes." }
+            ]
+        },
+        {
+            "id": "CPUProfile",
+            "type": "object",
+            "description": "Profile.",
+            "properties": [
+                { "name": "rootNodes", "type": "array", "items": { "$ref": "CPUProfileNode" }, "description": "Top level nodes in the stack." },
+                { "name": "idleTime", "type": "number", "optional": true }
+            ]
         }
     ],
     "commands": [
index bf62ed04c48539deb6402f825cfb350696de676c..8930ac3745d1c72aac7b01ebe09a2605cbe594c7 100644 (file)
@@ -53,6 +53,7 @@
 #include "JSWithScope.h"
 #include "LLIntCLoop.h"
 #include "LLIntThunks.h"
+#include "LegacyProfiler.h"
 #include "LiteralParser.h"
 #include "ObjectPrototype.h"
 #include "Parser.h"
@@ -674,6 +675,7 @@ public:
     StackVisitor::Status operator()(StackVisitor& visitor) const
     {
         visitor.unwindToMachineCodeBlockFrame();
+        VM& vm = m_callFrame->vm();
         m_callFrame = visitor->callFrame();
         m_codeBlock = visitor->codeBlock();
 
@@ -690,6 +692,9 @@ public:
 
         bool shouldStopUnwinding = visitor->callerIsVMEntryFrame();
         if (shouldStopUnwinding) {
+            if (LegacyProfiler* profiler = vm.enabledProfiler())
+                profiler->exceptionUnwind(m_callFrame);
+
             copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
 
             return StackVisitor::Done;
@@ -949,9 +954,15 @@ failedJSONP:
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), thisObj, 1);
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->willExecute(callFrame, program->sourceURL(), program->firstLine(), program->startColumn());
+
     // Execute the code:
     JSValue result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->didExecute(callFrame, program->sourceURL(), program->firstLine(), program->startColumn());
+
     return checkedReturn(result);
 }
 
@@ -1000,6 +1011,9 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(newCodeBlock, function, thisValue, argsCount, args.data());
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->willExecute(callFrame, function);
+
     JSValue result;
     {
         // Execute the code:
@@ -1012,6 +1026,9 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
         }
     }
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->didExecute(callFrame, function);
+
     return checkedReturn(result);
 }
 
@@ -1062,6 +1079,9 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(newCodeBlock, constructor, newTarget, argsCount, args.data());
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->willExecute(callFrame, constructor);
+
     JSValue result;
     {
         // Execute the code.
@@ -1075,6 +1095,9 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
         }
     }
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->didExecute(callFrame, constructor);
+
     if (callFrame->hadException())
         return 0;
     ASSERT(result.isObject());
@@ -1117,12 +1140,18 @@ JSValue Interpreter::execute(CallFrameClosure& closure)
 
     StackStats::CheckPoint stackCheckPoint;
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->willExecute(closure.oldCallFrame, closure.function);
+
     if (UNLIKELY(vm.shouldTriggerTermination(closure.oldCallFrame)))
         return throwTerminatedExecutionException(closure.oldCallFrame);
 
     // Execute the code:
     JSValue result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame);
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->didExecute(closure.oldCallFrame, closure.function);
+
     return checkedReturn(result);
 }
 
@@ -1220,9 +1249,15 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), thisValue, 1);
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->willExecute(callFrame, eval->sourceURL(), eval->firstLine(), eval->startColumn());
+
     // Execute the code:
     JSValue result = eval->generatedJITCode()->execute(&vm, &protoCallFrame);
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->didExecute(callFrame, eval->sourceURL(), eval->firstLine(), eval->startColumn());
+
     return checkedReturn(result);
 }
 
@@ -1257,9 +1292,15 @@ JSValue Interpreter::execute(ModuleProgramExecutable* executable, CallFrame* cal
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), jsUndefined(), 1);
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->willExecute(callFrame, executable->sourceURL(), executable->firstLine(), executable->startColumn());
+
     // Execute the code:
     JSValue result = executable->generatedJITCode()->execute(&vm, &protoCallFrame);
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->didExecute(callFrame, executable->sourceURL(), executable->firstLine(), executable->startColumn());
+
     return checkedReturn(result);
 }
 
index adaa8607f6c44ac043259ec47e507ce0fc930686..1d50abaeee899dd58871c6b781cf967cc0bb271b 100644 (file)
@@ -290,6 +290,8 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_nstricteq)
         DEFINE_OP(op_dec)
         DEFINE_OP(op_inc)
+        DEFINE_OP(op_profile_did_call)
+        DEFINE_OP(op_profile_will_call)
         DEFINE_OP(op_profile_type)
         DEFINE_OP(op_profile_control_flow)
         DEFINE_OP(op_push_with_scope)
index 43fbebfafa8b84798c8969af3f188b00a95fb1f9..511400642b05acbc8cfff2c2804060ad797c4245 100644 (file)
@@ -560,6 +560,8 @@ namespace JSC {
         void emit_op_nstricteq(Instruction*);
         void emit_op_dec(Instruction*);
         void emit_op_inc(Instruction*);
+        void emit_op_profile_did_call(Instruction*);
+        void emit_op_profile_will_call(Instruction*);
         void emit_op_profile_type(Instruction*);
         void emit_op_profile_control_flow(Instruction*);
         void emit_op_push_with_scope(Instruction*);
index 6d45bb3147cdadb32130f35ce3fd9a5db57db64f..f0a75191c015e89a3f11a577b680ed6ab2b35b7c 100644 (file)
@@ -774,6 +774,22 @@ void JIT::emitSlow_op_check_tdz(Instruction* currentInstruction, Vector<SlowCase
     slowPathCall.call();
 }
 
+void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
+{
+    Jump profilerDone = branchTestPtr(Zero, AbsoluteAddress(m_vm->enabledProfilerAddress()));
+    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+    callOperation(operationProfileWillCall, regT0);
+    profilerDone.link(this);
+}
+
+void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
+{
+    Jump profilerDone = branchTestPtr(Zero, AbsoluteAddress(m_vm->enabledProfilerAddress()));
+    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+    callOperation(operationProfileDidCall, regT0);
+    profilerDone.link(this);
+}
+
 
 // Slow cases
 
index 64ab065a37477d7cb49f90287b040debfefbb1ba..cf04ca9a3f777e9b458975d6b681f16c64f0775a 100644 (file)
@@ -1060,6 +1060,24 @@ void JIT::emitSlow_op_check_tdz(Instruction* currentInstruction, Vector<SlowCase
     slowPathCall.call();
 }
 
+void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
+{
+    load32(m_vm->enabledProfilerAddress(), regT0);
+    Jump profilerDone = branchTestPtr(Zero, regT0);
+    emitLoad(currentInstruction[1].u.operand, regT1, regT0);
+    callOperation(operationProfileWillCall, regT1, regT0);
+    profilerDone.link(this);
+}
+
+void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
+{
+    load32(m_vm->enabledProfilerAddress(), regT0);
+    Jump profilerDone = branchTestPtr(Zero, regT0);
+    emitLoad(currentInstruction[1].u.operand, regT1, regT0);
+    callOperation(operationProfileDidCall, regT1, regT0);
+    profilerDone.link(this);
+}
+
 void JIT::emit_op_has_structure_property(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
index 39304bf1f5bc4601dcdfc6f429747ddf1c05487f..bc81c5c9042d34f6712fd17760c272bd93992086 100644 (file)
@@ -53,6 +53,7 @@
 #include "JSPropertyNameEnumerator.h"
 #include "JSStackInlines.h"
 #include "JSWithScope.h"
+#include "LegacyProfiler.h"
 #include "ObjectConstructor.h"
 #include "PolymorphicAccess.h"
 #include "PropertyName.h"
@@ -1241,6 +1242,12 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
         return encodeResult(0, 0);
     }
     
+    if (vm.enabledProfiler()) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("profiler is enabled"));
+        updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
+        return encodeResult(0, 0);
+    }
+
     Debugger* debugger = codeBlock->globalObject()->debugger();
     if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests())) {
         CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("debugger is stepping or has requests"));
@@ -1552,6 +1559,24 @@ void JIT_OPERATION operationPopScope(ExecState* exec, int32_t scopeReg)
     exec->uncheckedR(scopeReg) = scope->next();
 }
 
+void JIT_OPERATION operationProfileDidCall(ExecState* exec, EncodedJSValue encodedValue)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->didExecute(exec, JSValue::decode(encodedValue));
+}
+
+void JIT_OPERATION operationProfileWillCall(ExecState* exec, EncodedJSValue encodedValue)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->willExecute(exec, JSValue::decode(encodedValue));
+}
+
 int32_t JIT_OPERATION operationInstanceOfCustom(ExecState* exec, EncodedJSValue encodedValue, JSObject* constructor, EncodedJSValue encodedHasInstance)
 {
     VM& vm = exec->vm();
@@ -2333,6 +2358,9 @@ int32_t JIT_OPERATION operationCheckIfExceptionIsUncatchableAndNotifyProfiler(Ex
     NativeCallFrameTracer tracer(&vm, exec);
     RELEASE_ASSERT(!!vm.exception());
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->exceptionUnwind(exec);
+
     if (isTerminatedExecutionException(vm.exception())) {
         genericUnwind(&vm, exec);
         return 1;
index 57f78b85425fcff67048118c79093dae32d8d4da..21297032030d42210224d7eb30f2e7b63bd04756 100644 (file)
@@ -370,6 +370,8 @@ void JIT_OPERATION operationPutGetterSetter(ExecState*, JSCell*, UniquedStringIm
 #endif
 void JIT_OPERATION operationPushFunctionNameScope(ExecState*, int32_t, SymbolTable*, EncodedJSValue) WTF_INTERNAL;
 void JIT_OPERATION operationPopScope(ExecState*, int32_t) WTF_INTERNAL;
+void JIT_OPERATION operationProfileDidCall(ExecState*, EncodedJSValue) WTF_INTERNAL;
+void JIT_OPERATION operationProfileWillCall(ExecState*, EncodedJSValue) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
index e17536d3f836b4d5e0b5080fc0ae362f85dfdd07..b3268fe9a65f2639d59c6e0fb05e4490c716bc64 100644 (file)
@@ -864,7 +864,7 @@ protected:
 };
 
 const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
-const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, nullptr, nullptr };
+const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsLegacyProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, nullptr, nullptr };
 
 
 GlobalObject::GlobalObject(VM& vm, Structure* structure)
index 8bfa7cd52dfca82c7be049e30c1df946319a4ded..ccc58d1780e336189263753201d696e03345ea7b 100644 (file)
@@ -50,6 +50,7 @@
 #include "JSWithScope.h"
 #include "LLIntCommon.h"
 #include "LLIntExceptions.h"
+#include "LegacyProfiler.h"
 #include "LowLevelInterpreter.h"
 #include "ObjectConstructor.h"
 #include "ProtoCallFrame.h"
@@ -1425,6 +1426,22 @@ LLINT_SLOW_PATH_DECL(slow_path_debug)
     LLINT_END();
 }
 
+LLINT_SLOW_PATH_DECL(slow_path_profile_will_call)
+{
+    LLINT_BEGIN();
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->willExecute(exec, LLINT_OP(1).jsValue());
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_profile_did_call)
+{
+    LLINT_BEGIN();
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->didExecute(exec, LLINT_OP(1).jsValue());
+    LLINT_END();
+}
+
 LLINT_SLOW_PATH_DECL(slow_path_handle_exception)
 {
     LLINT_BEGIN_NO_SET_PC();
@@ -1513,6 +1530,9 @@ LLINT_SLOW_PATH_DECL(slow_path_check_if_exception_is_uncatchable_and_notify_prof
     LLINT_BEGIN();
     RELEASE_ASSERT(!!vm.exception());
 
+    if (LegacyProfiler* profiler = vm.enabledProfiler())
+        profiler->exceptionUnwind(exec);
+
     if (isTerminatedExecutionException(vm.exception()))
         LLINT_RETURN_TWO(pc, bitwise_cast<void*>(static_cast<uintptr_t>(1)));
     LLINT_RETURN_TWO(pc, 0);
index 24995428b54ccce5485890a9607dc5f8441ce407..e3d41e45827fb0dc5bfd515e6307c21103a03f36 100644 (file)
@@ -117,6 +117,8 @@ LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_throw);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_throw_static_error);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_handle_watchdog_timer);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_debug);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_profile_will_call);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_profile_did_call);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_handle_exception);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_from_scope);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_to_scope);
index a0878f824a5509e4227c67247f47d5831a0b37d4..43bf77ed16c9cc6ae7f95537d03237c6daad7947 100644 (file)
@@ -1662,6 +1662,28 @@ _llint_op_throw_static_error:
     dispatch(3)
 
 
+_llint_op_profile_will_call:
+    traceExecution()
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_vm[t0], t0
+    loadi VM::m_enabledProfiler[t0], t0
+    btpz t0, .opProfilerWillCallDone
+    callSlowPath(_llint_slow_path_profile_will_call)
+.opProfilerWillCallDone:
+    dispatch(2)
+
+
+_llint_op_profile_did_call:
+    traceExecution()
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_vm[t0], t0
+    loadi VM::m_enabledProfiler[t0], t0
+    btpz t0, .opProfilerDidCallDone
+    callSlowPath(_llint_slow_path_profile_did_call)
+.opProfilerDidCallDone:
+    dispatch(2)
+
+
 _llint_op_debug:
     traceExecution()
     loadp CodeBlock[cfr], t0
index 2b7953a3d668131dc7376c9c7cd86e12d7709f8d..f0c3a229b32f35976c6bcb72e096efbbe649db57 100644 (file)
@@ -39,6 +39,7 @@ enum class ConstructorKind { None, Base, Derived };
 enum class SuperBinding { Needed, NotNeeded };
 enum class ThisTDZMode { AlwaysCheck, CheckIfNeeded };
 
+enum ProfilerMode { ProfilerOff, ProfilerOn };
 enum DebuggerMode { DebuggerOff, DebuggerOn };
 
 enum class FunctionMode { FunctionExpression, FunctionDeclaration, MethodDefinition };
diff --git a/Source/JavaScriptCore/profiler/CallIdentifier.h b/Source/JavaScriptCore/profiler/CallIdentifier.h
new file mode 100644 (file)
index 0000000..691fc62
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef CallIdentifier_h
+#define CallIdentifier_h
+
+#include <wtf/text/CString.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+    struct CallIdentifier {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        CallIdentifier()
+            : m_lineNumber(0)
+            , m_columnNumber(0)
+        {
+        }
+
+        CallIdentifier(const String& functionName, const String& url, unsigned lineNumber, unsigned columnNumber)
+            : m_functionName(functionName)
+            , m_url(!url.isNull() ? url : "")
+            , m_lineNumber(lineNumber)
+            , m_columnNumber(columnNumber)
+        {
+        }
+
+        const String& functionName() const { return m_functionName; }
+
+        const String& url() const { return m_url; }
+        unsigned lineNumber() const { return m_lineNumber; }
+        unsigned columnNumber() const { return m_columnNumber; }
+
+        inline bool operator==(const CallIdentifier& other) const { return other.m_lineNumber == m_lineNumber && other.m_columnNumber == m_columnNumber && other.m_functionName == m_functionName && other.m_url == m_url; }
+        inline bool operator!=(const CallIdentifier& other) const { return !(*this == other); }
+
+        struct Hash {
+            static unsigned hash(const CallIdentifier& key)
+            {
+                unsigned hashCodes[4] = {
+                    key.m_functionName.impl()->hash(),
+                    key.m_url.impl()->hash(),
+                    key.m_lineNumber,
+                    key.m_columnNumber
+                };
+                return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
+            }
+
+            static bool equal(const CallIdentifier& a, const CallIdentifier& b) { return a == b; }
+            static const bool safeToCompareToEmptyOrDeleted = true;
+        };
+
+        unsigned hash() const { return Hash::hash(*this); }
+
+#ifndef NDEBUG
+        operator const char*() const { return c_str(); }
+        const char* c_str() const { return m_functionName.utf8().data(); }
+#endif
+
+    private:
+        String m_functionName;
+        String m_url;
+        unsigned m_lineNumber;
+        unsigned m_columnNumber;
+    };
+
+} // namespace JSC
+
+namespace WTF {
+
+    template<> struct DefaultHash<JSC::CallIdentifier> { typedef JSC::CallIdentifier::Hash Hash; };
+
+    template<> struct HashTraits<JSC::CallIdentifier> : GenericHashTraits<JSC::CallIdentifier> {
+        static void constructDeletedValue(JSC::CallIdentifier& slot)
+        {
+            new (NotNull, &slot) JSC::CallIdentifier(String(), String(), std::numeric_limits<unsigned>::max(), std::numeric_limits<unsigned>::max());
+        }
+
+        static bool isDeletedValue(const JSC::CallIdentifier& value)
+        {
+            return value.functionName().isNull() && value.url().isNull() && value.lineNumber() == std::numeric_limits<unsigned>::max() && value.columnNumber() == std::numeric_limits<unsigned>::max();
+        }
+    };
+
+} // namespace WTF
+
+#endif  // CallIdentifier_h
diff --git a/Source/JavaScriptCore/profiler/LegacyProfiler.cpp b/Source/JavaScriptCore/profiler/LegacyProfiler.cpp
new file mode 100644 (file)
index 0000000..787d362
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2008, 2012, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LegacyProfiler.h"
+
+#include "CallFrame.h"
+#include "CodeBlock.h"
+#include "CommonIdentifiers.h"
+#include "InternalFunction.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "Nodes.h"
+#include "JSCInlines.h"
+#include "Profile.h"
+#include "ProfileGenerator.h"
+#include "ProfileNode.h"
+
+namespace JSC {
+
+static const char* GlobalCodeExecution = "(program)";
+static const char* AnonymousFunction = "(anonymous function)";
+static unsigned ProfilesUID = 0;
+
+static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber);
+
+LegacyProfiler* LegacyProfiler::s_sharedLegacyProfiler = nullptr;
+
+LegacyProfiler* LegacyProfiler::profiler()
+{
+    if (!s_sharedLegacyProfiler)
+        s_sharedLegacyProfiler = new LegacyProfiler();
+    return s_sharedLegacyProfiler;
+}
+
+void LegacyProfiler::startProfiling(ExecState* exec, const String& title, PassRefPtr<Stopwatch> stopwatch)
+{
+    if (!exec)
+        return;
+
+    // Check if we currently have a Profile for this global ExecState and title.
+    // If so return early and don't create a new Profile.
+    JSGlobalObject* origin = exec->lexicalGlobalObject();
+
+    for (size_t i = 0; i < m_currentProfiles.size(); ++i) {
+        ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
+        if (profileGenerator->origin() == origin && profileGenerator->title() == title)
+            return;
+    }
+
+    exec->vm().setEnabledProfiler(this);
+    RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID, stopwatch);
+    m_currentProfiles.append(profileGenerator);
+}
+
+RefPtr<Profile> LegacyProfiler::stopProfiling(ExecState* exec, const String& title)
+{
+    if (!exec)
+        return nullptr;
+
+    JSGlobalObject* origin = exec->lexicalGlobalObject();
+    for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
+        ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
+        if (profileGenerator->origin() == origin && (title.isNull() || profileGenerator->title() == title)) {
+            profileGenerator->stopProfiling();
+            RefPtr<Profile> returnProfile = profileGenerator->profile();
+
+            m_currentProfiles.remove(i);
+            if (!m_currentProfiles.size())
+                exec->vm().setEnabledProfiler(nullptr);
+
+            return returnProfile;
+        }
+    }
+
+    return nullptr;
+}
+
+void LegacyProfiler::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())
+                origin->vm().setEnabledProfiler(nullptr);
+        }
+    }
+}
+
+static inline void callFunctionForProfilesWithGroup(std::function<void(ProfileGenerator*)> callback, const Vector<RefPtr<ProfileGenerator>>& profiles, unsigned targetProfileGroup)
+{
+    for (const RefPtr<ProfileGenerator>& profile : profiles) {
+        if (profile->profileGroup() == targetProfileGroup || !profile->origin())
+            callback(profile.get());
+    }
+}
+
+void LegacyProfiler::suspendProfiling(JSC::ExecState* exec)
+{
+    if (!exec)
+        return;
+
+    callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::setIsSuspended, std::placeholders::_1, true), m_currentProfiles, exec->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::unsuspendProfiling(JSC::ExecState* exec)
+{
+    if (!exec)
+        return;
+
+    callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::setIsSuspended, std::placeholders::_1, false), m_currentProfiles, exec->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::willExecute(ExecState* callerCallFrame, JSValue function)
+{
+    ASSERT(!m_currentProfiles.isEmpty());
+
+    CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, function, StringImpl::empty(), 0, 0);
+
+    callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::willExecute, std::placeholders::_1, callerCallFrame, callIdentifier), m_currentProfiles, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::willExecute(ExecState* callerCallFrame, const String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber)
+{
+    ASSERT(!m_currentProfiles.isEmpty());
+
+    CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber, startingColumnNumber);
+
+    callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::willExecute, std::placeholders::_1, callerCallFrame, callIdentifier), m_currentProfiles, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::didExecute(ExecState* callerCallFrame, JSValue function)
+{
+    ASSERT(!m_currentProfiles.isEmpty());
+
+    CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, function, StringImpl::empty(), 0, 0);
+
+    callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::didExecute, std::placeholders::_1, callerCallFrame, callIdentifier), m_currentProfiles, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::didExecute(ExecState* callerCallFrame, const String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber)
+{
+    ASSERT(!m_currentProfiles.isEmpty());
+
+    CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber, startingColumnNumber);
+
+    callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::didExecute, std::placeholders::_1, callerCallFrame, callIdentifier), m_currentProfiles, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::exceptionUnwind(ExecState* handlerCallFrame)
+{
+    ASSERT(!m_currentProfiles.isEmpty());
+
+    CallIdentifier callIdentifier = createCallIdentifier(handlerCallFrame, JSValue(), StringImpl::empty(), 0, 0);
+
+    callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::exceptionUnwind, std::placeholders::_1, handlerCallFrame, callIdentifier), m_currentProfiles, handlerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+CallIdentifier LegacyProfiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber)
+{
+    if (!functionValue)
+        return CallIdentifier(ASCIILiteral(GlobalCodeExecution), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+    if (!functionValue.isObject())
+        return CallIdentifier(ASCIILiteral("(unknown)"), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+    if (asObject(functionValue)->inherits(JSFunction::info()) || asObject(functionValue)->inherits(InternalFunction::info()))
+        return createCallIdentifierFromFunctionImp(exec, asObject(functionValue), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+    if (asObject(functionValue)->inherits(JSCallee::info()))
+        return CallIdentifier(ASCIILiteral(GlobalCodeExecution), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+    return CallIdentifier(asObject(functionValue)->methodTable()->className(asObject(functionValue)), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+}
+
+CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSObject* function, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber)
+{
+    const String& name = getCalculatedDisplayName(exec, function);
+    JSFunction* jsFunction = jsDynamicCast<JSFunction*>(function);
+    if (jsFunction && !jsFunction->isHostOrBuiltinFunction())
+        return CallIdentifier(name.isEmpty() ? ASCIILiteral(AnonymousFunction) : name, jsFunction->jsExecutable()->sourceURL(), jsFunction->jsExecutable()->firstLine(), jsFunction->jsExecutable()->startColumn());
+    return CallIdentifier(name.isEmpty() ? ASCIILiteral(AnonymousFunction) : name, defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/LegacyProfiler.h b/Source/JavaScriptCore/profiler/LegacyProfiler.h
new file mode 100644 (file)
index 0000000..af0ab41
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008, 2012, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LegacyProfiler_h
+#define LegacyProfiler_h
+
+#include "Profile.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Stopwatch.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class ExecState;
+class JSGlobalObject;
+class JSObject;
+class JSValue;
+class ProfileGenerator;
+struct CallIdentifier;
+
+class LegacyProfiler {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    JS_EXPORT_PRIVATE static LegacyProfiler* profiler();
+    static CallIdentifier createCallIdentifier(ExecState*, JSValue, const WTF::String& sourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber);
+
+    JS_EXPORT_PRIVATE void startProfiling(ExecState*, const WTF::String& title, PassRefPtr<Stopwatch>);
+    JS_EXPORT_PRIVATE RefPtr<Profile> stopProfiling(ExecState*, const WTF::String& title);
+    void stopProfiling(JSGlobalObject*);
+
+    // Used to ignore profile node subtrees rooted at InjectedScript calls.
+    JS_EXPORT_PRIVATE void suspendProfiling(ExecState*);
+    JS_EXPORT_PRIVATE void unsuspendProfiling(ExecState*);
+
+    void willExecute(ExecState* callerCallFrame, JSValue function);
+    void willExecute(ExecState* callerCallFrame, const WTF::String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber);
+    void didExecute(ExecState* callerCallFrame, JSValue function);
+    void didExecute(ExecState* callerCallFrame, const WTF::String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber);
+
+    void exceptionUnwind(ExecState* handlerCallFrame);
+
+    const Vector<RefPtr<ProfileGenerator>>& currentProfiles() { return m_currentProfiles; };
+
+private:
+    Vector<RefPtr<ProfileGenerator>> m_currentProfiles;
+    static LegacyProfiler* s_sharedLegacyProfiler;
+};
+
+} // namespace JSC
+
+#endif // LegacyProfiler_h
diff --git a/Source/JavaScriptCore/profiler/Profile.cpp b/Source/JavaScriptCore/profiler/Profile.cpp
new file mode 100644 (file)
index 0000000..f3d450a
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Profile.h"
+
+#include "ProfileNode.h"
+#include <wtf/DataLog.h>
+
+namespace JSC {
+
+Ref<Profile> Profile::create(const String& title, unsigned uid, double startTime)
+{
+    return adoptRef(*new Profile(title, uid, startTime));
+}
+
+Profile::Profile(const String& title, unsigned uid, double startTime)
+    : m_title(title)
+    , m_uid(uid)
+{
+    // FIXME: When multi-threading is supported this will be a vector and calls
+    // into the profiler will need to know which thread it is executing on.
+    m_rootNode = ProfileNode::create(nullptr, CallIdentifier(ASCIILiteral("Thread_1"), String(), 0, 0), nullptr);
+    m_rootNode->appendCall(ProfileNode::Call(startTime));
+}
+
+Profile::~Profile()
+{
+}
+
+#ifndef NDEBUG
+void Profile::debugPrint()
+{
+    CalculateProfileSubtreeDataFunctor functor;
+    m_rootNode->forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+    dataLogF("Call graph:\n");
+    m_rootNode->debugPrintRecursively(0, data);
+}
+
+typedef WTF::KeyValuePair<FunctionCallHashCount::ValueType, unsigned> NameCountPair;
+
+static inline bool functionNameCountPairComparator(const NameCountPair& a, const NameCountPair& b)
+{
+    return a.value > b.value;
+}
+
+void Profile::debugPrintSampleStyle()
+{
+    typedef Vector<NameCountPair> NameCountPairVector;
+
+    CalculateProfileSubtreeDataFunctor functor;
+    m_rootNode->forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+    FunctionCallHashCount countedFunctions;
+    dataLogF("Call graph:\n");
+    m_rootNode->debugPrintSampleStyleRecursively(0, countedFunctions, data);
+
+    dataLogF("\nTotal number in stack:\n");
+    NameCountPairVector sortedFunctions(countedFunctions.size());
+    copyToVector(countedFunctions, sortedFunctions);
+
+    std::sort(sortedFunctions.begin(), sortedFunctions.end(), functionNameCountPairComparator);
+    for (NameCountPairVector::iterator it = sortedFunctions.begin(); it != sortedFunctions.end(); ++it)
+        dataLogF("        %-12d%s\n", (*it).value, String((*it).key).utf8().data());
+
+    dataLogF("\nSort by top of stack, same collapsed (when >= 5):\n");
+}
+#endif
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/Profile.h b/Source/JavaScriptCore/profiler/Profile.h
new file mode 100644 (file)
index 0000000..41cb670
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef Profile_h
+#define Profile_h
+
+#include "ProfileNode.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class JS_EXPORT_PRIVATE Profile : public RefCounted<Profile> {
+public:
+    static Ref<Profile> create(const String& title, unsigned uid, double);
+    virtual ~Profile();
+
+    const String& title() const { return m_title; }
+    unsigned uid() const { return m_uid; }
+
+    ProfileNode* rootNode() const { return m_rootNode.get(); }
+    void setRootNode(PassRefPtr<ProfileNode> rootNode) { m_rootNode = rootNode; }
+
+#ifndef NDEBUG
+    void debugPrint();
+    void debugPrintSampleStyle();
+#endif
+
+protected:
+    Profile(const String& title, unsigned uid, double startTime);
+
+private:
+    void removeProfileStart();
+    void removeProfileEnd();
+
+    String m_title;
+    RefPtr<ProfileNode> m_rootNode;
+    unsigned m_uid;
+};
+
+} // namespace JSC
+
+#endif // Profile_h
diff --git a/Source/JavaScriptCore/profiler/ProfileGenerator.cpp b/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
new file mode 100644 (file)
index 0000000..25f8a43
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2008, 2014, 2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfileGenerator.h"
+
+#include "CallFrame.h"
+#include "CodeBlock.h"
+#include "JSGlobalObject.h"
+#include "JSStringRef.h"
+#include "JSFunction.h"
+#include "LegacyProfiler.h"
+#include "JSCInlines.h"
+#include "Profile.h"
+#include "StackVisitor.h"
+
+namespace JSC {
+
+Ref<ProfileGenerator> ProfileGenerator::create(ExecState* exec, const String& title, unsigned uid, PassRefPtr<Stopwatch> stopwatch)
+{
+    return adoptRef(*new ProfileGenerator(exec, title, uid, stopwatch));
+}
+
+ProfileGenerator::ProfileGenerator(ExecState* exec, const String& title, unsigned uid, PassRefPtr<Stopwatch> stopwatch)
+    : m_origin(exec ? exec->lexicalGlobalObject() : nullptr)
+    , m_profileGroup(exec ? exec->lexicalGlobalObject()->profileGroup() : 0)
+    , m_stopwatch(stopwatch)
+    , m_foundConsoleStartParent(false)
+    , m_suspended(false)
+{
+    double startTime = m_stopwatch->elapsedTime();
+    m_profile = Profile::create(title, uid, startTime);
+    m_currentNode = m_rootNode = m_profile->rootNode();
+    if (exec)
+        addParentForConsoleStart(exec, startTime);
+}
+
+class AddParentForConsoleStartFunctor {
+public:
+    AddParentForConsoleStartFunctor(ExecState* exec, RefPtr<ProfileNode>& rootNode, RefPtr<ProfileNode>& currentNode, double startTime)
+        : m_exec(exec)
+        , m_hasSkippedFirstFrame(false)
+        , m_foundParent(false)
+        , m_rootNode(rootNode)
+        , m_currentNode(currentNode)
+        , m_startTime(startTime)
+    {
+    }
+
+    bool foundParent() const { return m_foundParent; }
+
+    StackVisitor::Status operator()(StackVisitor& visitor) const
+    {
+        if (!m_hasSkippedFirstFrame) {
+            m_hasSkippedFirstFrame = true;
+            return StackVisitor::Continue;
+        }
+
+        unsigned line = 0;
+        unsigned column = 0;
+        visitor->computeLineAndColumn(line, column);
+        m_currentNode = ProfileNode::create(m_exec, LegacyProfiler::createCallIdentifier(m_exec, visitor->callee(), visitor->sourceURL(), line, column), m_rootNode.get());
+        m_currentNode->appendCall(ProfileNode::Call(m_startTime));
+        m_rootNode->spliceNode(m_currentNode.get());
+
+        m_foundParent = true;
+        return StackVisitor::Done;
+    }
+
+private:
+    ExecState* m_exec;
+    mutable bool m_hasSkippedFirstFrame;
+    mutable bool m_foundParent;
+    RefPtr<ProfileNode>& m_rootNode;
+    RefPtr<ProfileNode>& m_currentNode;
+    double m_startTime;
+};
+
+void ProfileGenerator::addParentForConsoleStart(ExecState* exec, double startTime)
+{
+    AddParentForConsoleStartFunctor functor(exec, m_rootNode, m_currentNode, startTime);
+    exec->iterate(functor);
+
+    m_foundConsoleStartParent = functor.foundParent();
+}
+
+const String& ProfileGenerator::title() const
+{
+    return m_profile->title();
+}
+
+void ProfileGenerator::beginCallEntry(ProfileNode* node, double startTime)
+{
+    ASSERT_ARG(node, node);
+
+    if (std::isnan(startTime))
+        startTime = m_stopwatch->elapsedTime();
+
+    node->appendCall(ProfileNode::Call(startTime));
+}
+
+void ProfileGenerator::endCallEntry(ProfileNode* node)
+{
+    ASSERT_ARG(node, node);
+
+    ProfileNode::Call& last = node->lastCall();
+
+    double previousElapsedTime = std::isnan(last.elapsedTime()) ? 0.0 : last.elapsedTime();
+    double newlyElapsedTime = m_stopwatch->elapsedTime() - last.startTime();
+    last.setElapsedTime(previousElapsedTime + newlyElapsedTime);
+}
+
+void ProfileGenerator::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
+{
+    if (!m_origin)
+        return;
+
+    if (m_suspended)
+        return;
+
+    RefPtr<ProfileNode> calleeNode = nullptr;
+
+    // Find or create a node for the callee call frame.
+    for (const RefPtr<ProfileNode>& child : m_currentNode->children()) {
+        if (child->callIdentifier() == callIdentifier)
+            calleeNode = child;
+    }
+
+    if (!calleeNode) {
+        calleeNode = ProfileNode::create(callerCallFrame, callIdentifier, m_currentNode.get());
+        m_currentNode->addChild(calleeNode);
+    }
+
+    m_currentNode = calleeNode;
+    beginCallEntry(calleeNode.get(), m_stopwatch->elapsedTime());
+}
+
+void ProfileGenerator::didExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
+{
+    if (!m_origin)
+        return;
+
+    if (m_suspended)
+        return;
+
+    // Make a new node if the caller node has never seen this callee call frame before.
+    // This can happen if |console.profile()| is called several frames deep in the call stack.
+    ASSERT(m_currentNode);
+    if (m_currentNode->callIdentifier() != callIdentifier) {
+        RefPtr<ProfileNode> calleeNode = ProfileNode::create(callerCallFrame, callIdentifier, m_currentNode.get());
+        beginCallEntry(calleeNode.get(), m_currentNode->lastCall().startTime());
+        endCallEntry(calleeNode.get());
+        m_currentNode->spliceNode(calleeNode.release());
+        return;
+    }
+
+    endCallEntry(m_currentNode.get());
+    m_currentNode = m_currentNode->parent();
+}
+
+void ProfileGenerator::exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&)
+{
+    if (m_suspended)
+        return;
+
+    // If the current node was called by the handler (==) or any
+    // more nested function (>) the we have exited early from it.
+    ASSERT(m_currentNode);
+    while (m_currentNode->callerCallFrame() >= handlerCallFrame) {
+        didExecute(m_currentNode->callerCallFrame(), m_currentNode->callIdentifier());
+        ASSERT(m_currentNode);
+    }
+}
+
+void ProfileGenerator::stopProfiling()
+{
+    for (ProfileNode* node = m_currentNode.get(); node != m_profile->rootNode(); node = node->parent())
+        endCallEntry(node);
+
+    if (m_foundConsoleStartParent) {
+        removeProfileStart();
+        removeProfileEnd();
+    }
+
+    ASSERT(m_currentNode);
+
+    // Set the current node to the parent, because we are in a call that
+    // will not get didExecute call.
+    m_currentNode = m_currentNode->parent();
+}
+
+// The console.profile that started this ProfileGenerator will be the first child.
+void ProfileGenerator::removeProfileStart()
+{
+    ProfileNode* currentNode = nullptr;
+    for (ProfileNode* next = m_rootNode.get(); next; next = next->firstChild())
+        currentNode = next;
+
+    if (currentNode->callIdentifier().functionName() != "profile")
+        return;
+
+    currentNode->parent()->removeChild(currentNode);
+}
+
+// The console.profileEnd that stopped this ProfileGenerator will be the last child.
+void ProfileGenerator::removeProfileEnd()
+{
+    ProfileNode* currentNode = nullptr;
+    for (ProfileNode* next = m_rootNode.get(); next; next = next->lastChild())
+        currentNode = next;
+
+    if (currentNode->callIdentifier().functionName() != "profileEnd")
+        return;
+
+    ASSERT(currentNode->callIdentifier() == (currentNode->parent()->children()[currentNode->parent()->children().size() - 1])->callIdentifier());
+    currentNode->parent()->removeChild(currentNode);
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/ProfileGenerator.h b/Source/JavaScriptCore/profiler/ProfileGenerator.h
new file mode 100644 (file)
index 0000000..387ed5f
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfileGenerator_h
+#define ProfileGenerator_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Stopwatch.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+    class DebuggerCallFrame;
+    class ExecState;
+    class JSGlobalObject;
+    class Profile;
+    class ProfileNode;
+    struct CallIdentifier;
+
+    class ProfileGenerator : public RefCounted<ProfileGenerator>  {
+    public:
+        static Ref<ProfileGenerator> create(ExecState*, const WTF::String& title, unsigned uid, PassRefPtr<Stopwatch>);
+
+        // Members
+        const WTF::String& title() const;
+        PassRefPtr<Profile> profile() const { return m_profile; }
+        JSGlobalObject* origin() const { return m_origin; }
+        unsigned profileGroup() const { return m_profileGroup; }
+
+        void willExecute(ExecState* callerCallFrame, const CallIdentifier&);
+        void didExecute(ExecState* callerCallFrame, const CallIdentifier&);
+        void exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&);
+
+        void setIsSuspended(bool suspended) { ASSERT(m_suspended != suspended); m_suspended = suspended; }
+
+        void stopProfiling();
+
+    private:
+        ProfileGenerator(ExecState*, const WTF::String& title, unsigned uid, PassRefPtr<Stopwatch>);
+        void addParentForConsoleStart(ExecState*, double);
+
+        void removeProfileStart();
+        void removeProfileEnd();
+
+        void beginCallEntry(ProfileNode*, double startTime);
+        void endCallEntry(ProfileNode*);
+
+        RefPtr<Profile> m_profile;
+        JSGlobalObject* m_origin;
+        unsigned m_profileGroup;
+        RefPtr<Stopwatch> m_stopwatch;
+        RefPtr<ProfileNode> m_rootNode;
+        RefPtr<ProfileNode> m_currentNode;
+        bool m_foundConsoleStartParent;
+        bool m_suspended;
+    };
+
+} // namespace JSC
+
+#endif // ProfileGenerator_h
diff --git a/Source/JavaScriptCore/profiler/ProfileNode.cpp b/Source/JavaScriptCore/profiler/ProfileNode.cpp
new file mode 100644 (file)
index 0000000..9bcf375
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfileNode.h"
+
+#include "LegacyProfiler.h"
+#include <wtf/DateMath.h>
+#include <wtf/DataLog.h>
+#include <wtf/text/StringHash.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
+    : m_callerCallFrame(callerCallFrame)
+    , m_callIdentifier(callIdentifier)
+    , m_parent(parentNode)
+#ifndef NDEBUG
+    , m_nextSibling(nullptr)
+#endif
+{
+}
+
+ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy)
+    : m_callerCallFrame(callerCallFrame)
+    , m_callIdentifier(nodeToCopy->callIdentifier())
+    , m_parent(nodeToCopy->parent())
+    , m_calls(nodeToCopy->calls())
+#ifndef NDEBUG
+    , m_nextSibling(nullptr)
+#endif
+{
+}
+
+void ProfileNode::addChild(PassRefPtr<ProfileNode> prpChild)
+{
+    RefPtr<ProfileNode> child = prpChild;
+    child->setParent(this);
+#ifndef NDEBUG
+    if (m_children.size())
+        m_children.last()->setNextSibling(child.get());
+#endif
+    m_children.append(child.release());
+}
+
+void ProfileNode::removeChild(ProfileNode* node)
+{
+    if (!node)
+        return;
+
+    m_children.removeFirstMatching([node] (const RefPtr<ProfileNode>& 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::spliceNode(PassRefPtr<ProfileNode> prpNode)
+{
+    RefPtr<ProfileNode> node = prpNode;
+
+    for (unsigned i = 0; i < m_children.size(); ++i)
+        node->addChild(m_children[i].release());
+
+    m_children.clear();
+    m_children.append(node.release());
+}
+
+#ifndef NDEBUG
+ProfileNode* ProfileNode::traverseNextNodePostOrder() const
+{
+    ProfileNode* next = m_nextSibling;
+    if (!next)
+        return m_parent;
+    while (ProfileNode* firstChild = next->firstChild())
+        next = firstChild;
+    return next;
+}
+
+void ProfileNode::debugPrint()
+{
+    CalculateProfileSubtreeDataFunctor functor;
+    forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+    debugPrintRecursively(0, data);
+}
+
+void ProfileNode::debugPrintSampleStyle()
+{
+    FunctionCallHashCount countedFunctions;
+
+    CalculateProfileSubtreeDataFunctor functor;
+    forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+    debugPrintSampleStyleRecursively(0, countedFunctions, data);
+}
+
+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(),
+        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)->debugPrintRecursively(indentLevel, data);
+}
+
+// print the profiled data in a format that matches the tool sample's output.
+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 = nodeTotalTime * 1000;
+    if (indentLevel) {
+        for (int i = 0; i < indentLevel; ++i)
+            dataLogF("  ");
+
+         countedFunctions.add(functionName().impl());
+
+        dataLogF("%.0f %s\n", sampleCount ? sampleCount : 1, name);
+    } else
+        dataLogF("%s\n", name);
+
+    ++indentLevel;
+
+    // Print children's names and information
+    double sumOfChildrensCount = 0.0;
+    for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
+        sumOfChildrensCount += (*currentChild)->debugPrintSampleStyleRecursively(indentLevel, countedFunctions, data);
+
+    sumOfChildrensCount *= 1000;    //
+    // Print remainder of samples to match sample's output
+    if (sumOfChildrensCount < sampleCount) {
+        dataLogF("    ");
+        while (indentLevel--)
+            dataLogF("  ");
+
+        dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
+    }
+
+    return nodeTotalTime;
+}
+#endif
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/ProfileNode.h b/Source/JavaScriptCore/profiler/ProfileNode.h
new file mode 100644 (file)
index 0000000..7ad149e
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfileNode_h
+#define ProfileNode_h
+
+#include "CallIdentifier.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+    class ExecState;
+    class ProfileNode;
+
+    typedef HashCountedSet<StringImpl*> FunctionCallHashCount;
+
+    class ProfileNode : public RefCounted<ProfileNode> {
+    public:
+        static Ref<ProfileNode> create(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
+        {
+            return adoptRef(*new ProfileNode(callerCallFrame, callIdentifier, parentNode));
+        }
+
+        static Ref<ProfileNode> create(ExecState* callerCallFrame, ProfileNode* node)
+        {
+            return adoptRef(*new ProfileNode(callerCallFrame, node));
+        }
+
+        struct Call {
+        public:
+            Call(double startTime, double elapsedTime = NAN)
+                : m_startTime(startTime)
+                , m_elapsedTime(elapsedTime)
+            {
+            }
+
+            double startTime() const { return m_startTime; }
+            void setStartTime(double time)
+            {
+                ASSERT_ARG(time, time >= 0.0 || std::isnan(time));
+                m_startTime = time;
+            }
+
+            double elapsedTime() const { return m_elapsedTime; }
+            void setElapsedTime(double time)
+            {
+                ASSERT_ARG(time, time >= 0.0 || std::isnan(time));
+                m_elapsedTime = time;
+            }
+
+        private:
+            double m_startTime;
+            double m_elapsedTime;
+        };
+
+        bool operator==(ProfileNode* node) { return m_callIdentifier == node->callIdentifier(); }
+
+        ExecState* callerCallFrame() const { return m_callerCallFrame; }
+        const CallIdentifier& callIdentifier() const { return m_callIdentifier; }
+        unsigned id() const { return m_callIdentifier.hash(); }
+        const String& functionName() const { return m_callIdentifier.functionName(); }
+        const String& url() const { return m_callIdentifier.url(); }
+        unsigned lineNumber() const { return m_callIdentifier.lineNumber(); }
+        unsigned columnNumber() const { return m_callIdentifier.columnNumber(); }
+
+        ProfileNode* parent() const { return m_parent; }
+        void setParent(ProfileNode* parent) { m_parent = parent; }
+
+        const Vector<Call>& calls() const { return m_calls; }
+        Call& lastCall() { ASSERT(!m_calls.isEmpty()); return m_calls.last(); }
+        void appendCall(Call call) { m_calls.append(call); }
+
+        const Vector<RefPtr<ProfileNode>>& children() const { return m_children; }
+        ProfileNode* firstChild() const { return m_children.size() ? m_children.first().get() : nullptr; }
+        ProfileNode* lastChild() const { return m_children.size() ? m_children.last().get() : nullptr; }
+
+        void removeChild(ProfileNode*);
+        void addChild(PassRefPtr<ProfileNode>);
+        // Reparent our child nodes to the passed node, and make it a child node of |this|.
+        void spliceNode(PassRefPtr<ProfileNode>);
+
+#ifndef NDEBUG
+        struct ProfileSubtreeData {
+            HashMap<ProfileNode*, std::pair<double, double>> selfAndTotalTimes;
+            double rootTotalTime;
+        };
+
+        // Use these functions to dump the subtree rooted at this node.
+        void debugPrint();
+        void debugPrintSampleStyle();
+
+        // These are used to recursively print entire subtrees using precomputed self and total times.
+        template <typename Functor> void forEachNodePostorder(Functor&);
+
+        void debugPrintRecursively(int indentLevel, const ProfileSubtreeData&);
+        double debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount&, const ProfileSubtreeData&);
+#endif
+
+    private:
+        typedef Vector<RefPtr<ProfileNode>>::const_iterator StackIterator;
+
+        ProfileNode(ExecState* callerCallFrame, const CallIdentifier&, ProfileNode* parentNode);
+        ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy);
+
+#ifndef NDEBUG
+        ProfileNode* nextSibling() const { return m_nextSibling; }
+        void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; }
+
+        ProfileNode* traverseNextNodePostOrder() const;
+#endif
+
+        ExecState* m_callerCallFrame;
+        CallIdentifier m_callIdentifier;
+        ProfileNode* m_parent;
+        Vector<Call> m_calls;
+        Vector<RefPtr<ProfileNode>> m_children;
+
+#ifndef NDEBUG
+        ProfileNode* m_nextSibling;
+#endif
+    };
+
+#ifndef NDEBUG
+    template <typename Functor> inline void ProfileNode::forEachNodePostorder(Functor& functor)
+    {
+        ProfileNode* currentNode = this;
+        // Go down to the first node of the traversal, and slowly walk back up.
+        for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode->firstChild())
+            currentNode = nextNode;
+
+        ProfileNode* endNode = this;
+        while (currentNode && currentNode != endNode) {
+            functor(currentNode);
+            currentNode = currentNode->traverseNextNodePostOrder();
+        }
+
+        functor(endNode);
+    }
+
+    struct CalculateProfileSubtreeDataFunctor {
+        void operator()(ProfileNode* node)
+        {
+            double selfTime = 0.0;
+            for (const ProfileNode::Call& call : node->calls())
+                selfTime += call.elapsedTime();
+
+            double totalTime = selfTime;
+            for (RefPtr<ProfileNode> child : node->children()) {
+                auto it = m_data.selfAndTotalTimes.find(child.get());
+                if (it != m_data.selfAndTotalTimes.end())
+                    totalTime += it->value.second;
+            }
+
+            ASSERT(node);
+            m_data.selfAndTotalTimes.set(node, std::make_pair(selfTime, totalTime));
+        }
+
+        ProfileNode::ProfileSubtreeData returnValue() { return WTFMove(m_data); }
+
+        ProfileNode::ProfileSubtreeData m_data;
+    };
+#endif
+
+} // namespace JSC
+
+#endif // ProfileNode_h
index 3751feda08f4682c73f4d837474bdf1410201617..3068ff34c2334fc3aeb99fbeedcf5b87c1178bf4 100644 (file)
@@ -47,6 +47,9 @@ void printInternal(PrintStream& out, JettisonReason reason)
     case JettisonDueToDebuggerStepping:
         out.print("DebuggerStepping");
         return;
+    case JettisonDueToLegacyProfiler:
+        out.print("LegacyProfiler");
+        return;
     case JettisonDueToBaselineLoopReoptimizationTrigger:
         out.print("BaselineLoopReoptimizationTrigger");
         return;
index 5300a20a19614b3d0d21567b7a7b39062128ec88..6a793260422b7568199317cdf9024fac1748ee37 100644 (file)
@@ -33,6 +33,7 @@ enum JettisonReason {
     JettisonDueToWeakReference,
     JettisonDueToDebuggerBreakpoint,
     JettisonDueToDebuggerStepping,
+    JettisonDueToLegacyProfiler,
     JettisonDueToBaselineLoopReoptimizationTrigger,
     JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail,
     JettisonDueToOSRExit,
index 3b77d373f286223fafb24c0040f3abc73a643808..281273eab288af18f7953b956c9bc7f4a2fb4e1f 100644 (file)
@@ -81,13 +81,13 @@ template <> struct CacheTypes<UnlinkedModuleProgramCodeBlock> {
 };
 
 template <class UnlinkedCodeBlockType, class ExecutableType>
-UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, ThisTDZMode thisTDZMode, DebuggerMode debuggerMode, ParserError& error, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)
+UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, ThisTDZMode thisTDZMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)
 {
     SourceCodeKey key = SourceCodeKey(source, String(), CacheTypes<UnlinkedCodeBlockType>::codeType, builtinMode, strictMode, thisTDZMode);
     SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
     // FIXME: We should do something smart for TDZ instead of just disabling caching.
     // https://bugs.webkit.org/show_bug.cgi?id=154010
-    bool canCache = debuggerMode == DebuggerOff && !vm.typeProfiler() && !vm.controlFlowProfiler() && !variablesUnderTDZ->size();
+    bool canCache = debuggerMode == DebuggerOff && profilerMode == ProfilerOff && !vm.typeProfiler() && !vm.controlFlowProfiler() && !variablesUnderTDZ->size();
     if (cache && canCache) {
         UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(cache->cell.get());
         unsigned firstLine = source.firstLine() + unlinkedCodeBlock->firstLine();
@@ -120,7 +120,7 @@ UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* exe
     unlinkedCodeBlock->setSourceURLDirective(source.provider()->sourceURL());
     unlinkedCodeBlock->setSourceMappingURLDirective(source.provider()->sourceMappingURL());
 
-    error = BytecodeGenerator::generate(vm, rootNode.get(), unlinkedCodeBlock, debuggerMode, variablesUnderTDZ);
+    error = BytecodeGenerator::generate(vm, rootNode.get(), unlinkedCodeBlock, debuggerMode, profilerMode, variablesUnderTDZ);
 
     if (error.isValid())
         return nullptr;
@@ -132,21 +132,21 @@ UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* exe
     return unlinkedCodeBlock;
 }
 
-UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ParserError& error)
+UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
 {
     VariableEnvironment emptyParentTDZVariables;
-    return getGlobalCodeBlock<UnlinkedProgramCodeBlock>(vm, executable, source, builtinMode, strictMode, ThisTDZMode::CheckIfNeeded, debuggerMode, error, EvalContextType::None, &emptyParentTDZVariables);
+    return getGlobalCodeBlock<UnlinkedProgramCodeBlock>(vm, executable, source, builtinMode, strictMode, ThisTDZMode::CheckIfNeeded, debuggerMode, profilerMode, error, EvalContextType::None, &emptyParentTDZVariables);
 }
 
-UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, EvalExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, ThisTDZMode thisTDZMode, DebuggerMode debuggerMode, ParserError& error, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)
+UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, EvalExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, ThisTDZMode thisTDZMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)
 {
-    return getGlobalCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, builtinMode, strictMode, thisTDZMode, debuggerMode, error, evalContextType, variablesUnderTDZ);
+    return getGlobalCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, builtinMode, strictMode, thisTDZMode, debuggerMode, profilerMode, error, evalContextType, variablesUnderTDZ);
 }
 
-UnlinkedModuleProgramCodeBlock* CodeCache::getModuleProgramCodeBlock(VM& vm, ModuleProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, DebuggerMode debuggerMode, ParserError& error)
+UnlinkedModuleProgramCodeBlock* CodeCache::getModuleProgramCodeBlock(VM& vm, ModuleProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
 {
     VariableEnvironment emptyParentTDZVariables;
-    return getGlobalCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, executable, source, builtinMode, JSParserStrictMode::Strict, ThisTDZMode::CheckIfNeeded, debuggerMode, error, EvalContextType::None, &emptyParentTDZVariables);
+    return getGlobalCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, executable, source, builtinMode, JSParserStrictMode::Strict, ThisTDZMode::CheckIfNeeded, debuggerMode, profilerMode, error, EvalContextType::None, &emptyParentTDZVariables);
 }
 
 // FIXME: There's no need to add the function's name to the key here. It's already in the source code.
index 0070d902f9c72caea064878574be6880c90e82a4..e5e211b5db333da92e41f8c3f4861ce45dd13186 100644 (file)
@@ -187,9 +187,9 @@ public:
     CodeCache();
     ~CodeCache();
 
-    UnlinkedProgramCodeBlock* getProgramCodeBlock(VM&, ProgramExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, DebuggerMode, ParserError&);
-    UnlinkedEvalCodeBlock* getEvalCodeBlock(VM&, EvalExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, ThisTDZMode, DebuggerMode, ParserError&, EvalContextType, const VariableEnvironment*);
-    UnlinkedModuleProgramCodeBlock* getModuleProgramCodeBlock(VM&, ModuleProgramExecutable*, const SourceCode&, JSParserBuiltinMode, DebuggerMode, ParserError&);
+    UnlinkedProgramCodeBlock* getProgramCodeBlock(VM&, ProgramExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, DebuggerMode, ProfilerMode, ParserError&);
+    UnlinkedEvalCodeBlock* getEvalCodeBlock(VM&, EvalExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, ThisTDZMode, DebuggerMode, ProfilerMode, ParserError&, EvalContextType, const VariableEnvironment*);
+    UnlinkedModuleProgramCodeBlock* getModuleProgramCodeBlock(VM&, ModuleProgramExecutable*, const SourceCode&, JSParserBuiltinMode, DebuggerMode, ProfilerMode, ParserError&);
     UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(VM&, const Identifier&, const SourceCode&, ParserError&);
 
     void clear()
@@ -199,7 +199,7 @@ public:
 
 private:
     template <class UnlinkedCodeBlockType, class ExecutableType> 
-    UnlinkedCodeBlockType* getGlobalCodeBlock(VM&, ExecutableType*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, ThisTDZMode, DebuggerMode, ParserError&, EvalContextType, const VariableEnvironment*);
+    UnlinkedCodeBlockType* getGlobalCodeBlock(VM&, ExecutableType*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, ThisTDZMode, DebuggerMode, ProfilerMode, ParserError&, EvalContextType, const VariableEnvironment*);
 
     CodeCacheMap m_sourceCode;
 };
index 9fcddf4adbd20170fad20e2e0cbbd9050978d8b5..9195d559397f8bdfa2a2c2850f973b9a506212b8 100644 (file)
@@ -312,9 +312,10 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
     JSGlobalObject* globalObject = scope->globalObject();
     ParserError error;
     DebuggerMode debuggerMode = globalObject->hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
+    ProfilerMode profilerMode = globalObject->hasLegacyProfiler() ? ProfilerOn : ProfilerOff;
     UnlinkedFunctionCodeBlock* unlinkedCodeBlock = 
         executable->m_unlinkedExecutable->unlinkedCodeBlockFor(
-            *vm, executable->m_source, kind, debuggerMode, error, 
+            *vm, executable->m_source, kind, debuggerMode, profilerMode, error, 
             executable->parseMode());
     recordParse(
         executable->m_unlinkedExecutable->features(), 
index 6c147320f9bb2c8872ab5dbd9b7487865ac077ff..d770549c67485fa12957fef7df196d38728d1138 100644 (file)
 #include "JSWithScope.h"
 #include "LazyClassStructureInlines.h"
 #include "LazyPropertyInlines.h"
+#include "LegacyProfiler.h"
 #include "Lookup.h"
 #include "MapConstructor.h"
 #include "MapIteratorPrototype.h"
@@ -207,7 +208,7 @@ namespace JSC {
 
 const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &Base::s_info, &globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) };
 
-const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, nullptr, &shouldInterruptScriptBeforeTimeout, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsLegacyProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, nullptr, &shouldInterruptScriptBeforeTimeout, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
 
 /* Source for JSGlobalObject.lut.h
 @begin globalObjectTable
@@ -296,6 +297,9 @@ JSGlobalObject::~JSGlobalObject()
 
     if (m_debugger)
         m_debugger->detach(this, Debugger::GlobalObjectIsDestructing);
+
+    if (LegacyProfiler* profiler = vm().enabledProfiler())
+        profiler->stopProfiling(this);
 }
 
 void JSGlobalObject::destroy(JSCell* cell)
@@ -833,6 +837,11 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
     resetPrototype(vm, getPrototypeDirect());
 }
 
+bool JSGlobalObject::hasLegacyProfiler() const
+{
+    return globalObjectMethodTable()->supportsLegacyProfiling(this);
+}
+
 bool JSGlobalObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
 {
     JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell);
@@ -1222,9 +1231,10 @@ UnlinkedProgramCodeBlock* JSGlobalObject::createProgramCodeBlock(CallFrame* call
     ParserError error;
     JSParserStrictMode strictMode = executable->isStrictMode() ? JSParserStrictMode::Strict : JSParserStrictMode::NotStrict;
     DebuggerMode debuggerMode = hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
+    ProfilerMode profilerMode = hasLegacyProfiler() ? ProfilerOn : ProfilerOff;
     UnlinkedProgramCodeBlock* unlinkedCodeBlock = vm().codeCache()->getProgramCodeBlock(
         vm(), executable, executable->source(), JSParserBuiltinMode::NotBuiltin, strictMode, 
-        debuggerMode, error);
+        debuggerMode, profilerMode, error);
 
     if (hasDebugger())
         debugger()->sourceParsed(callFrame, executable->source().provider(), error.line(), error.message());
@@ -1244,8 +1254,9 @@ UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame,
     DebuggerMode debuggerMode = hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
     EvalContextType evalContextType = executable->executableInfo().evalContextType();
     
+    ProfilerMode profilerMode = hasLegacyProfiler() ? ProfilerOn : ProfilerOff;
     UnlinkedEvalCodeBlock* unlinkedCodeBlock = vm().codeCache()->getEvalCodeBlock(
-        vm(), executable, executable->source(), JSParserBuiltinMode::NotBuiltin, strictMode, thisTDZMode, debuggerMode, error, evalContextType, variablesUnderTDZ);
+        vm(), executable, executable->source(), JSParserBuiltinMode::NotBuiltin, strictMode, thisTDZMode, debuggerMode, profilerMode, error, evalContextType, variablesUnderTDZ);
 
     if (hasDebugger())
         debugger()->sourceParsed(callFrame, executable->source().provider(), error.line(), error.message());
@@ -1262,8 +1273,9 @@ UnlinkedModuleProgramCodeBlock* JSGlobalObject::createModuleProgramCodeBlock(Cal
 {
     ParserError error;
     DebuggerMode debuggerMode = hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
+    ProfilerMode profilerMode = hasLegacyProfiler() ? ProfilerOn : ProfilerOff;
     UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = vm().codeCache()->getModuleProgramCodeBlock(
-        vm(), executable, executable->source(), JSParserBuiltinMode::NotBuiltin, debuggerMode, error);
+        vm(), executable, executable->source(), JSParserBuiltinMode::NotBuiltin, debuggerMode, profilerMode, error);
 
     if (hasDebugger())
         debugger()->sourceParsed(callFrame, executable->source().provider(), error.line(), error.message());
index 96aecec50fb4a273a505c6da086cb6f566f11fa0..f580476a1e0bf7dd1e65093ce5b594d9a16ef765 100644 (file)
@@ -151,6 +151,9 @@ struct GlobalObjectMethodTable {
     typedef bool (*AllowsAccessFromFunctionPtr)(const JSGlobalObject*, ExecState*);
     AllowsAccessFromFunctionPtr allowsAccessFrom;
 
+    typedef bool (*SupportsLegacyProfilingFunctionPtr)(const JSGlobalObject*);
+    SupportsLegacyProfilingFunctionPtr supportsLegacyProfiling;
+
     typedef bool (*SupportsRichSourceInfoFunctionPtr)(const JSGlobalObject*);
     SupportsRichSourceInfoFunctionPtr supportsRichSourceInfo;
 
@@ -404,6 +407,7 @@ public:
 
     bool hasDebugger() const;
     bool hasInteractiveDebugger() const;
+    bool hasLegacyProfiler() const;
     const RuntimeFlags& runtimeFlags() const { return m_runtimeFlags; }
 
 protected:
@@ -713,6 +717,7 @@ public:
     const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }
 
     static bool allowsAccessFrom(const JSGlobalObject*, ExecState*) { return true; }
+    static bool supportsLegacyProfiling(const JSGlobalObject*) { return false; }
     static bool supportsRichSourceInfo(const JSGlobalObject*) { return true; }
 
     JS_EXPORT_PRIVATE ExecState* globalExec();
index 25de20b0e06dc805701008af7f2acd4dd621afea..1d0e5647b37b34468e384e65fb9ed6a1a949c6c1 100644 (file)
@@ -131,6 +131,7 @@ typedef const char* optionString;
     v(bool, dumpBytecodeLivenessResults, false, Normal, nullptr) \
     v(bool, validateBytecode, false, Normal, nullptr) \
     v(bool, forceDebuggerBytecodeGeneration, false, Normal, nullptr) \
+    v(bool, forceProfilerBytecodeGeneration, false, Normal, nullptr) \
     \
     v(bool, useFunctionDotArguments, true, Normal, nullptr) \
     v(bool, useTailCalls, true, Normal, nullptr) \
index d47f4458f69e0521dfba8f839d72b4d1f6ac8e7c..dc31c43f8fb0a65abf22d95289488f71691090ce 100644 (file)
@@ -194,6 +194,7 @@ VM::VM(VMType vmType, HeapType heapType)
 #endif
     , m_inDefineOwnProperty(false)
     , m_codeCache(std::make_unique<CodeCache>())
+    , m_enabledProfiler(nullptr)
     , m_builtinExecutables(std::make_unique<BuiltinExecutables>(*this))
     , m_typeProfilerEnabledCount(0)
     , m_controlFlowProfilerEnabledCount(0)
@@ -776,6 +777,25 @@ void VM::addImpureProperty(const String& propertyName)
         watchpointSet->fireAll("Impure property added");
 }
 
+class SetEnabledProfilerFunctor {
+public:
+    bool operator()(CodeBlock* codeBlock) const
+    {
+        if (JITCode::isOptimizingJIT(codeBlock->jitType()))
+            codeBlock->jettison(Profiler::JettisonDueToLegacyProfiler);
+        return false;
+    }
+};
+
+void VM::setEnabledProfiler(LegacyProfiler* profiler)
+{
+    m_enabledProfiler = profiler;
+    if (m_enabledProfiler) {
+        SetEnabledProfilerFunctor functor;
+        heap.forEachCodeBlock(functor);
+    }
+}
+
 stati