Internal JSC profiler should have a timestamped log of events for each code block
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 May 2016 00:08:50 +0000 (00:08 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 May 2016 00:08:50 +0000 (00:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157538

Reviewed by Benjamin Poulain.
Source/JavaScriptCore:

For example, in 3d-cube, I can query the events for MMulti and I get:

1462917476.17083  MMulti#DTZ7qc                          installCode
1462917476.179663 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline installCode
1462917476.179664 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline osrEntry           at bc#49
1462917476.185651 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 1011.214233/1717.000000, -707
1462917476.187913 MMulti#DTZ7qc MMulti#DTZ7qc-2-DFG      installCode
1462917476.187917 MMulti#DTZ7qc MMulti#DTZ7qc-2-DFG      osrEntry           at bc#49
1462917476.205365 MMulti#DTZ7qc MMulti#DTZ7qc-2-DFG      jettison           due to OSRExit, counting = true, detail = (null)
1462917476.205368 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline frequentExit       bc#65: BadCache/FromDFG
1462917476.205369 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline installCode
1462917476.205482 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 1013.000000/3434.000000, -1000
1462917476.211547 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 2013.000000/3434.000000, -1000
1462917476.213721 MMulti#DTZ7qc MMulti#DTZ7qc-3-DFG      installCode
1462917476.213726 MMulti#DTZ7qc MMulti#DTZ7qc-3-DFG      osrEntry           at bc#49
1462917476.223976 MMulti#DTZ7qc MMulti#DTZ7qc-3-DFG      jettison           due to OSRExit, counting = true, detail = (null)
1462917476.223981 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline frequentExit       bc#77: BadCache/FromDFG
1462917476.223982 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline frequentExit       bc#94: BadCache/FromDFG
1462917476.223982 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline installCode
1462917476.224064 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 1013.000000/6868.000000, -1000
1462917476.224151 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 2013.000000/6868.000000, -1000
1462917476.224258 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 3013.000000/6868.000000, -1000
1462917476.224337 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 4023.000000/6868.000000, -1000
1462917476.224425 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 5023.000000/6868.000000, -1000
1462917476.224785 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 6023.396484/6868.000000, -862
1462917476.227669 MMulti#DTZ7qc MMulti#DTZ7qc-4-DFG      installCode
1462917476.227675 MMulti#DTZ7qc MMulti#DTZ7qc-4-DFG      osrEntry           at bc#0

The output is ugly but useful. We can make it less ugly later.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::jettison):
* bytecode/CodeBlock.h:
(JSC::ScriptExecutable::forEachCodeBlock):
* bytecode/DFGExitProfile.cpp:
(JSC::DFG::ExitProfile::add):
* dfg/DFGJITFinalizer.cpp:
(JSC::DFG::JITFinalizer::finalizeCommon):
* dfg/DFGOperations.cpp:
* ftl/FTLJITFinalizer.cpp:
(JSC::FTL::JITFinalizer::finalizeFunction):
* jit/JIT.cpp:
(JSC::JIT::privateCompile):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::jitCompileAndSetHeuristics):
(JSC::LLInt::entryOSR):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* profiler/ProfilerCompilation.cpp:
(JSC::Profiler::Compilation::Compilation):
(JSC::Profiler::Compilation::setJettisonReason):
(JSC::Profiler::Compilation::dump):
(JSC::Profiler::Compilation::toJS):
* profiler/ProfilerCompilation.h:
(JSC::Profiler::Compilation::uid):
* profiler/ProfilerDatabase.cpp:
(JSC::Profiler::Database::ensureBytecodesFor):
(JSC::Profiler::Database::notifyDestruction):
(JSC::Profiler::Database::addCompilation):
(JSC::Profiler::Database::toJS):
(JSC::Profiler::Database::registerToSaveAtExit):
(JSC::Profiler::Database::logEvent):
(JSC::Profiler::Database::addDatabaseToAtExit):
* profiler/ProfilerDatabase.h:
* profiler/ProfilerEvent.cpp: Added.
(JSC::Profiler::Event::dump):
(JSC::Profiler::Event::toJS):
* profiler/ProfilerEvent.h: Added.
(JSC::Profiler::Event::Event):
(JSC::Profiler::Event::operator bool):
(JSC::Profiler::Event::time):
(JSC::Profiler::Event::bytecodes):
(JSC::Profiler::Event::compilation):
(JSC::Profiler::Event::summary):
(JSC::Profiler::Event::detail):
* profiler/ProfilerUID.cpp: Added.
(JSC::Profiler::UID::create):
(JSC::Profiler::UID::dump):
(JSC::Profiler::UID::toJS):
* profiler/ProfilerUID.h: Added.
(JSC::Profiler::UID::UID):
(JSC::Profiler::UID::fromInt):
(JSC::Profiler::UID::toInt):
(JSC::Profiler::UID::operator==):
(JSC::Profiler::UID::operator!=):
(JSC::Profiler::UID::operator bool):
(JSC::Profiler::UID::isHashTableDeletedValue):
(JSC::Profiler::UID::hash):
(JSC::Profiler::UIDHash::hash):
(JSC::Profiler::UIDHash::equal):
* runtime/CommonIdentifiers.h:
* runtime/Executable.cpp:
(JSC::ScriptExecutable::installCode):
* runtime/VM.h:
(JSC::VM::bytecodeIntrinsicRegistry):
(JSC::VM::shadowChicken):
* runtime/VMInlines.h:
(JSC::VM::shouldTriggerTermination):
(JSC::VM::logEvent):

Source/WTF:

* wtf/PrintStream.h:
(WTF::PrintStream::print):

Tools:

* Scripts/display-profiler-output:

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

31 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/DFGExitProfile.cpp
Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITDisassembler.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
Source/JavaScriptCore/profiler/ProfilerCompilation.h
Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
Source/JavaScriptCore/profiler/ProfilerDatabase.h
Source/JavaScriptCore/profiler/ProfilerEvent.cpp [new file with mode: 0644]
Source/JavaScriptCore/profiler/ProfilerEvent.h [new file with mode: 0644]
Source/JavaScriptCore/profiler/ProfilerUID.cpp [new file with mode: 0644]
Source/JavaScriptCore/profiler/ProfilerUID.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/CommonIdentifiers.h
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/runtime/VMInlines.h
Source/WTF/ChangeLog
Source/WTF/wtf/PrintStream.h
Tools/ChangeLog
Tools/Scripts/display-profiler-output

index 8ea5a7a..bf52181 100644 (file)
@@ -597,12 +597,14 @@ set(JavaScriptCore_SOURCES
     profiler/ProfilerCompilationKind.cpp
     profiler/ProfilerCompiledBytecode.cpp
     profiler/ProfilerDatabase.cpp
+    profiler/ProfilerEvent.cpp
     profiler/ProfilerJettisonReason.cpp
     profiler/ProfilerOSRExit.cpp
     profiler/ProfilerOSRExitSite.cpp
     profiler/ProfilerOrigin.cpp
     profiler/ProfilerOriginStack.cpp
     profiler/ProfilerProfiledBytecodes.cpp
+    profiler/ProfilerUID.cpp
 
     runtime/ArgList.cpp
     runtime/ArrayBuffer.cpp
index 9403203..115bca3 100644 (file)
@@ -1,3 +1,112 @@
+2016-05-10  Filip Pizlo  <fpizlo@apple.com>
+
+        Internal JSC profiler should have a timestamped log of events for each code block
+        https://bugs.webkit.org/show_bug.cgi?id=157538
+
+        Reviewed by Benjamin Poulain.
+        
+        For example, in 3d-cube, I can query the events for MMulti and I get:
+
+        1462917476.17083  MMulti#DTZ7qc                          installCode        
+        1462917476.179663 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline installCode        
+        1462917476.179664 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline osrEntry           at bc#49
+        1462917476.185651 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 1011.214233/1717.000000, -707
+        1462917476.187913 MMulti#DTZ7qc MMulti#DTZ7qc-2-DFG      installCode        
+        1462917476.187917 MMulti#DTZ7qc MMulti#DTZ7qc-2-DFG      osrEntry           at bc#49
+        1462917476.205365 MMulti#DTZ7qc MMulti#DTZ7qc-2-DFG      jettison           due to OSRExit, counting = true, detail = (null)
+        1462917476.205368 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline frequentExit       bc#65: BadCache/FromDFG
+        1462917476.205369 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline installCode        
+        1462917476.205482 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 1013.000000/3434.000000, -1000
+        1462917476.211547 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 2013.000000/3434.000000, -1000
+        1462917476.213721 MMulti#DTZ7qc MMulti#DTZ7qc-3-DFG      installCode        
+        1462917476.213726 MMulti#DTZ7qc MMulti#DTZ7qc-3-DFG      osrEntry           at bc#49
+        1462917476.223976 MMulti#DTZ7qc MMulti#DTZ7qc-3-DFG      jettison           due to OSRExit, counting = true, detail = (null)
+        1462917476.223981 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline frequentExit       bc#77: BadCache/FromDFG
+        1462917476.223982 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline frequentExit       bc#94: BadCache/FromDFG
+        1462917476.223982 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline installCode        
+        1462917476.224064 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 1013.000000/6868.000000, -1000
+        1462917476.224151 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 2013.000000/6868.000000, -1000
+        1462917476.224258 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 3013.000000/6868.000000, -1000
+        1462917476.224337 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 4023.000000/6868.000000, -1000
+        1462917476.224425 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 5023.000000/6868.000000, -1000
+        1462917476.224785 MMulti#DTZ7qc MMulti#DTZ7qc-1-Baseline delayOptimizeToDFG counter = 6023.396484/6868.000000, -862
+        1462917476.227669 MMulti#DTZ7qc MMulti#DTZ7qc-4-DFG      installCode        
+        1462917476.227675 MMulti#DTZ7qc MMulti#DTZ7qc-4-DFG      osrEntry           at bc#0
+        
+        The output is ugly but useful. We can make it less ugly later.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::jettison):
+        * bytecode/CodeBlock.h:
+        (JSC::ScriptExecutable::forEachCodeBlock):
+        * bytecode/DFGExitProfile.cpp:
+        (JSC::DFG::ExitProfile::add):
+        * dfg/DFGJITFinalizer.cpp:
+        (JSC::DFG::JITFinalizer::finalizeCommon):
+        * dfg/DFGOperations.cpp:
+        * ftl/FTLJITFinalizer.cpp:
+        (JSC::FTL::JITFinalizer::finalizeFunction):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompile):
+        * jit/JITOperations.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::jitCompileAndSetHeuristics):
+        (JSC::LLInt::entryOSR):
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * profiler/ProfilerCompilation.cpp:
+        (JSC::Profiler::Compilation::Compilation):
+        (JSC::Profiler::Compilation::setJettisonReason):
+        (JSC::Profiler::Compilation::dump):
+        (JSC::Profiler::Compilation::toJS):
+        * profiler/ProfilerCompilation.h:
+        (JSC::Profiler::Compilation::uid):
+        * profiler/ProfilerDatabase.cpp:
+        (JSC::Profiler::Database::ensureBytecodesFor):
+        (JSC::Profiler::Database::notifyDestruction):
+        (JSC::Profiler::Database::addCompilation):
+        (JSC::Profiler::Database::toJS):
+        (JSC::Profiler::Database::registerToSaveAtExit):
+        (JSC::Profiler::Database::logEvent):
+        (JSC::Profiler::Database::addDatabaseToAtExit):
+        * profiler/ProfilerDatabase.h:
+        * profiler/ProfilerEvent.cpp: Added.
+        (JSC::Profiler::Event::dump):
+        (JSC::Profiler::Event::toJS):
+        * profiler/ProfilerEvent.h: Added.
+        (JSC::Profiler::Event::Event):
+        (JSC::Profiler::Event::operator bool):
+        (JSC::Profiler::Event::time):
+        (JSC::Profiler::Event::bytecodes):
+        (JSC::Profiler::Event::compilation):
+        (JSC::Profiler::Event::summary):
+        (JSC::Profiler::Event::detail):
+        * profiler/ProfilerUID.cpp: Added.
+        (JSC::Profiler::UID::create):
+        (JSC::Profiler::UID::dump):
+        (JSC::Profiler::UID::toJS):
+        * profiler/ProfilerUID.h: Added.
+        (JSC::Profiler::UID::UID):
+        (JSC::Profiler::UID::fromInt):
+        (JSC::Profiler::UID::toInt):
+        (JSC::Profiler::UID::operator==):
+        (JSC::Profiler::UID::operator!=):
+        (JSC::Profiler::UID::operator bool):
+        (JSC::Profiler::UID::isHashTableDeletedValue):
+        (JSC::Profiler::UID::hash):
+        (JSC::Profiler::UIDHash::hash):
+        (JSC::Profiler::UIDHash::equal):
+        * runtime/CommonIdentifiers.h:
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::installCode):
+        * runtime/VM.h:
+        (JSC::VM::bytecodeIntrinsicRegistry):
+        (JSC::VM::shadowChicken):
+        * runtime/VMInlines.h:
+        (JSC::VM::shouldTriggerTermination):
+        (JSC::VM::logEvent):
+
 2016-05-10  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Backend should initiate timeline recordings on page navigations to ensure nothing is missed
index f3a980b..f12bfd5 100644 (file)
                DC17E81A1C9C91E9008A6AB3 /* CCallHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC17E8161C9C802B008A6AB3 /* CCallHelpers.cpp */; };
                DC2143071CA32E55000A8869 /* ICStats.h in Headers */ = {isa = PBXBuildFile; fileRef = DC2143061CA32E52000A8869 /* ICStats.h */; };
                DC2143081CA32E58000A8869 /* ICStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC2143051CA32E52000A8869 /* ICStats.cpp */; };
+               DC605B5D1CE26EA000593718 /* ProfilerEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC605B591CE26E9800593718 /* ProfilerEvent.cpp */; };
+               DC605B5E1CE26EA200593718 /* ProfilerEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = DC605B5A1CE26E9800593718 /* ProfilerEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               DC605B5F1CE26EA500593718 /* ProfilerUID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC605B5B1CE26E9800593718 /* ProfilerUID.cpp */; };
+               DC605B601CE26EA700593718 /* ProfilerUID.h in Headers */ = {isa = PBXBuildFile; fileRef = DC605B5C1CE26E9800593718 /* ProfilerUID.h */; settings = {ATTRIBUTES = (Private, ); }; };
                DC7997831CDE9FA0004D4A09 /* TagRegistersMode.h in Headers */ = {isa = PBXBuildFile; fileRef = DC7997821CDE9F9E004D4A09 /* TagRegistersMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                DC7997841CDE9FA2004D4A09 /* TagRegistersMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC7997811CDE9F9E004D4A09 /* TagRegistersMode.cpp */; };
                DCF3D5691CD2946D003D5C65 /* LazyClassStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCF3D5641CD29468003D5C65 /* LazyClassStructure.cpp */; };
                DC17E8161C9C802B008A6AB3 /* CCallHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCallHelpers.cpp; sourceTree = "<group>"; };
                DC2143051CA32E52000A8869 /* ICStats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ICStats.cpp; sourceTree = "<group>"; };
                DC2143061CA32E52000A8869 /* ICStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ICStats.h; sourceTree = "<group>"; };
+               DC605B591CE26E9800593718 /* ProfilerEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerEvent.cpp; path = profiler/ProfilerEvent.cpp; sourceTree = "<group>"; };
+               DC605B5A1CE26E9800593718 /* ProfilerEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerEvent.h; path = profiler/ProfilerEvent.h; sourceTree = "<group>"; };
+               DC605B5B1CE26E9800593718 /* ProfilerUID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerUID.cpp; path = profiler/ProfilerUID.cpp; sourceTree = "<group>"; };
+               DC605B5C1CE26E9800593718 /* ProfilerUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerUID.h; path = profiler/ProfilerUID.h; sourceTree = "<group>"; };
                DC7997811CDE9F9E004D4A09 /* TagRegistersMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TagRegistersMode.cpp; sourceTree = "<group>"; };
                DC7997821CDE9F9E004D4A09 /* TagRegistersMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TagRegistersMode.h; sourceTree = "<group>"; };
                DCF3D5641CD29468003D5C65 /* LazyClassStructure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyClassStructure.cpp; sourceTree = "<group>"; };
                                0FF7299B166AD347000F5BA3 /* ProfilerCompiledBytecode.h */,
                                0FF7299C166AD347000F5BA3 /* ProfilerDatabase.cpp */,
                                0FF7299D166AD347000F5BA3 /* ProfilerDatabase.h */,
+                               DC605B591CE26E9800593718 /* ProfilerEvent.cpp */,
+                               DC605B5A1CE26E9800593718 /* ProfilerEvent.h */,
                                0FF7299E166AD347000F5BA3 /* ProfilerExecutionCounter.h */,
                                0F190CAA189D82F6000AE5F0 /* ProfilerJettisonReason.cpp */,
                                0F190CAB189D82F6000AE5F0 /* ProfilerJettisonReason.h */,
                                0FB1058A1675482E00F8AB6E /* ProfilerOSRExitSite.h */,
                                0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */,
                                0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */,
+                               DC605B5B1CE26E9800593718 /* ProfilerUID.cpp */,
+                               DC605B5C1CE26E9800593718 /* ProfilerUID.h */,
                        );
                        name = profiler;
                        sourceTree = "<group>";
                                70B7919C1C024A49002481E2 /* JSGeneratorFunction.h in Headers */,
                                BC18C42A0E16F5CD00B34460 /* JSType.h in Headers */,
                                0F2B66FB17B6B5AB00A7AE3F /* JSTypedArrayConstructors.h in Headers */,
+                               DC605B601CE26EA700593718 /* ProfilerUID.h in Headers */,
                                0F2B66FD17B6B5AB00A7AE3F /* JSTypedArrayPrototypes.h in Headers */,
                                0F2B66FF17B6B5AB00A7AE3F /* JSTypedArrays.h in Headers */,
                                534C457C1BC72411007476A7 /* JSTypedArrayViewConstructor.h in Headers */,
                                86E3C615167BABD7006D760A /* JSVirtualMachine.h in Headers */,
                                86E3C61D167BABEE006D760A /* JSVirtualMachineInternal.h in Headers */,
                                7B98D1371B60CD620023B1A4 /* JSWASMModule.h in Headers */,
+                               DC605B5E1CE26EA200593718 /* ProfilerEvent.h in Headers */,
                                A7CA3AE817DA41AE006538AF /* JSWeakMap.h in Headers */,
                                A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */,
                                A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */,
                                A700873D17CBE8D300C3E643 /* MapPrototype.cpp in Sources */,
                                C2B916C514DA040C00CBAC86 /* MarkedAllocator.cpp in Sources */,
                                142D6F0813539A2800B02E86 /* MarkedBlock.cpp in Sources */,
+                               DC605B5D1CE26EA000593718 /* ProfilerEvent.cpp in Sources */,
                                14D2F3DA139F4BE200491031 /* MarkedSpace.cpp in Sources */,
                                142D6F1113539A4100B02E86 /* MarkStack.cpp in Sources */,
                                70B791981C024A29002481E2 /* GeneratorPrototype.cpp in Sources */,
                                705B41AF1A6E501E00716757 /* SymbolObject.cpp in Sources */,
                                705B41B11A6E501E00716757 /* SymbolPrototype.cpp in Sources */,
                                0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */,
+                               DC605B5F1CE26EA500593718 /* ProfilerUID.cpp in Sources */,
                                70ECA6071AFDBEA200449739 /* TemplateRegistry.cpp in Sources */,
                                0FC314131814559100033232 /* TempRegisterSet.cpp in Sources */,
                                0FA2C17B17D7CF84009D015F /* TestRunnerUtils.cpp in Sources */,
index d39c30c..3a808cb 100644 (file)
@@ -63,6 +63,7 @@
 #include "TypeLocationCache.h"
 #include "TypeProfiler.h"
 #include "UnlinkedInstructionStream.h"
+#include "VMInlines.h"
 #include <wtf/BagToHashMap.h>
 #include <wtf/CommaPrinter.h>
 #include <wtf/StringExtras.h>
@@ -3310,6 +3311,8 @@ void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mod
     UNUSED_PARAM(mode);
     UNUSED_PARAM(detail);
 #endif
+    
+    CODEBLOCK_LOG_EVENT(this, "jettison", ("due to ", reason, ", counting = ", mode == CountReoptimization, ", detail = ", pointerDump(detail)));
 
     RELEASE_ASSERT(reason != Profiler::NotJettisoned);
     
index edce4a0..d201f39 100644 (file)
@@ -59,7 +59,6 @@
 #include "LazyOperandValueProfile.h"
 #include "ObjectAllocationProfile.h"
 #include "Options.h"
-#include "ProfilerCompilation.h"
 #include "ProfilerJettisonReason.h"
 #include "PutPropertySlot.h"
 #include "RegExpObject.h"
@@ -1404,6 +1403,9 @@ template <typename Functor> inline void ScriptExecutable::forEachCodeBlock(Funct
     }
 }
 
+#define CODEBLOCK_LOG_EVENT(codeBlock, summary, details) \
+    (codeBlock->vm()->logEvent(codeBlock, summary, [&] () { return toCString details; }))
+
 } // namespace JSC
 
 #endif // CodeBlock_h
index 06b7d9b..67b9852 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(DFG_JIT)
 
 #include "CodeBlock.h"
+#include "VMInlines.h"
 
 namespace JSC { namespace DFG {
 
@@ -44,6 +45,8 @@ bool ExitProfile::add(const ConcurrentJITLocker&, CodeBlock* owner, const Freque
 {
     ASSERT(site.jitType() != ExitFromAnything);
 
+    CODEBLOCK_LOG_EVENT(owner, "frequentExit", (site));
+    
     if (Options::verboseExitProfile())
         dataLog(pointerDump(owner), ": Adding exit site: ", site, "\n");
     
index 57a5a1c..d673c94 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2015-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
@@ -91,7 +91,7 @@ void JITFinalizer::finalizeCommon()
 #endif // ENABLE(FTL_JIT)
     
     if (m_plan.compilation)
-        m_plan.vm.m_perBytecodeProfiler->addCompilation(m_plan.compilation);
+        m_plan.vm.m_perBytecodeProfiler->addCompilation(m_plan.codeBlock, m_plan.compilation);
     
     if (!m_plan.willTryToTierUp)
         m_plan.codeBlock->baselineVersion()->m_didFailFTLCompilation = true;
index e54f1da..865d52b 100644 (file)
 #include "ValueProfile.h"
 #include <wtf/ListDump.h>
 
-namespace JSC { namespace DFG {
+namespace JSC {
+
+namespace Profiler {
+class ExecutionCounter;
+}
+
+namespace DFG {
 
 class Graph;
 class PromotedLocationDescriptor;
index 0f2e505..0198066 100644 (file)
@@ -57,7 +57,7 @@
 #include "Symbol.h"
 #include "TypeProfilerLog.h"
 #include "TypedArrayInlines.h"
-#include "VM.h"
+#include "VMInlines.h"
 #include <wtf/InlineASM.h>
 
 #if ENABLE(JIT)
@@ -1765,6 +1765,7 @@ extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSR
 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
 {
     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
         if (Options::verboseOSR())
             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
         jitCode->dontOptimizeAnytimeSoon(codeBlock);
@@ -1773,6 +1774,7 @@ static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
 
     if (!codeBlock->hasOptimizedReplacement()
         && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
         if (Options::verboseOSR())
             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
         return false;
@@ -1790,12 +1792,14 @@ static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode*
         worklistState = Worklist::NotKnown;
     
     if (worklistState == Worklist::Compiling) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
         jitCode->setOptimizationThresholdBasedOnCompilationResult(
             codeBlock, CompilationDeferred);
         return;
     }
     
     if (codeBlock->hasOptimizedReplacement()) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
         // That's great, we've compiled the code - next time we call this function,
         // we'll enter that replacement.
         jitCode->optimizeSoon(codeBlock);
@@ -1803,6 +1807,7 @@ static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode*
     }
     
     if (worklistState == Worklist::Compiled) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
         // This means that we finished compiling, but failed somehow; in that case the
         // thresholds will be set appropriately.
         if (Options::verboseOSR())
@@ -1810,6 +1815,7 @@ static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode*
         return;
     }
 
+    CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
     // We need to compile the code.
     compile(
         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
@@ -1845,12 +1851,14 @@ void JIT_OPERATION triggerTierUpNow(ExecState* exec)
 
     if (codeBlock->hasOptimizedReplacement()) {
         if (jitCode->tierUpEntryTriggers.isEmpty()) {
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
             // There is nothing more we can do, the only way this will be entered
             // is through the function entry point.
             jitCode->dontOptimizeAnytimeSoon(codeBlock);
             return;
         }
         if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
             // There is only one outer loop and its trigger must have been set
             // when the plan completed.
             // Exiting the inner loop is useless, we can ignore the counter and leave
@@ -1876,12 +1884,14 @@ static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigne
 
     JITCode* jitCode = codeBlock->jitCode()->dfg();
     if (worklistState == Worklist::Compiling) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
         jitCode->setOptimizationThresholdBasedOnCompilationResult(
             codeBlock, CompilationDeferred);
         return nullptr;
     }
 
     if (worklistState == Worklist::Compiled) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
         // This means that compilation failed and we already set the thresholds.
         if (Options::verboseOSR())
             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
@@ -1892,8 +1902,10 @@ static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigne
     if (originBytecodeIndex == osrEntryBytecodeIndex) {
         unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
         if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
-            if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex))
+            if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
+                CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at bc#", originBytecodeIndex));
                 return static_cast<char*>(address);
+            }
         }
     }
 
@@ -1911,14 +1923,17 @@ static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigne
             return nullptr;
 
         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
             jitCode->osrEntryRetry++;
             return nullptr;
         }
-    }
+    } else
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
 
     // It's time to try to compile code for OSR entry.
     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
             jitCode->osrEntryRetry++;
             jitCode->setOptimizationThresholdBasedOnCompilationResult(
                 codeBlock, CompilationDeferred);
@@ -1929,6 +1944,7 @@ static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigne
         entryCode->countEntryFailure();
         if (entryCode->entryFailureCount() <
             Options::ftlOSREntryFailureCountForReoptimization()) {
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
             jitCode->setOptimizationThresholdBasedOnCompilationResult(
                 codeBlock, CompilationDeferred);
             return nullptr;
@@ -1936,6 +1952,7 @@ static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigne
 
         // OSR entry failed. Oh no! This implies that we need to retry. We retry
         // without exponential backoff and we only do this for the entry code block.
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
         unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
         jitCode->clearOSREntryBlock();
         jitCode->osrEntryRetry = 0;
@@ -1967,6 +1984,7 @@ static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigne
         exec, codeBlock, CodeOrigin(osrEntryBytecodeIndex), streamIndex, mustHandleValues);
     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
 
+    CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
     CompilationResult forEntryResult = compile(
         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, osrEntryBytecodeIndex,
         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
@@ -1975,11 +1993,13 @@ static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigne
         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
 
     if (forEntryResult != CompilationSuccessful) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
         jitCode->setOptimizationThresholdBasedOnCompilationResult(
             codeBlock, CompilationDeferred);
         return nullptr;
     }
-
+    
+    CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", originBytecodeIndex));
     // It's possible that the for-entry compile already succeeded. In that case OSR
     // entry will succeed unless we ran out of stack. It's not clear what we should do.
     // We signal to try again after a while if that happens.
@@ -2016,8 +2036,10 @@ void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeInde
         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
 
     // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
-    if (codeBlock->hasOptimizedReplacement())
+    if (codeBlock->hasOptimizedReplacement()) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
+    }
 }
 
 char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
index 56bd9ee..e66c89f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-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
@@ -83,7 +83,7 @@ bool JITFinalizer::finalizeFunction()
     m_plan.codeBlock->setJITCode(jitCode);
 
     if (m_plan.compilation)
-        m_plan.vm.m_perBytecodeProfiler->addCompilation(m_plan.compilation);
+        m_plan.vm.m_perBytecodeProfiler->addCompilation(m_plan.codeBlock, m_plan.compilation);
     
     return true;
 }
index c228a85..f70988e 100644 (file)
@@ -81,6 +81,10 @@ JIT::JIT(VM* vm, CodeBlock* codeBlock)
 {
 }
 
+JIT::~JIT()
+{
+}
+
 #if ENABLE(DFG_JIT)
 void JIT::emitEnterOptimizationCheck()
 {
@@ -738,7 +742,7 @@ CompilationResult JIT::privateCompile(JITCompilationEffort effort)
     if (m_compilation) {
         if (Options::disassembleBaselineForProfiler())
             m_disassembler->reportToProfiler(m_compilation.get(), patchBuffer);
-        m_vm->m_perBytecodeProfiler->addCompilation(m_compilation);
+        m_vm->m_perBytecodeProfiler->addCompilation(m_codeBlock, m_compilation);
     }
 
     if (m_pcToCodeOriginMapBuilder.didBuildMapping())
index 5fe3c6e..5114006 100644 (file)
@@ -257,6 +257,7 @@ namespace JSC {
 
     private:
         JIT(VM*, CodeBlock* = 0);
+        ~JIT();
 
         void privateCompileMainPass();
         void privateCompileLinkPass();
index 04e1b4d..7aa21d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2013, 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
@@ -33,6 +33,7 @@
 #include "JIT.h"
 #include "JSCInlines.h"
 #include "LinkBuffer.h"
+#include "ProfilerCompilation.h"
 #include <wtf/StringPrintStream.h>
 
 namespace JSC {
index efae064..bc81c5c 100644 (file)
@@ -1235,6 +1235,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
     }
 
     if (!codeBlock->checkIfOptimizationThresholdReached()) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("counter = ", codeBlock->jitExecuteCounter()));
         codeBlock->updateAllPredictions();
         if (Options::verboseOSR())
             dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
@@ -1242,17 +1243,20 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
     }
     
     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"));
         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
         return encodeResult(0, 0);
     }
 
     if (codeBlock->m_shouldAlwaysBeInlined) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("should always be inlined"));
         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
         if (Options::verboseOSR())
             dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
@@ -1293,6 +1297,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
         worklistState = DFG::Worklist::NotKnown;
 
     if (worklistState == DFG::Worklist::Compiling) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("compiling"));
         // We cannot be in the process of asynchronous compilation and also have an optimized
         // replacement.
         RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
@@ -1307,6 +1312,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
         // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
         // nothing left to do.
         if (!codeBlock->hasOptimizedReplacement()) {
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("compiled and failed"));
             codeBlock->updateAllPredictions();
             if (Options::verboseOSR())
                 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
@@ -1329,6 +1335,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
         // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
         // additional checking anyway, to reduce the amount of recompilation thrashing.
         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("should reoptimize from loop now"));
             if (Options::verboseOSR()) {
                 dataLog(
                     "Triggering reoptimization of ", *codeBlock,
@@ -1339,6 +1346,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
         }
     } else {
         if (!codeBlock->shouldOptimizeNow()) {
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("insufficient profiling"));
             if (Options::verboseOSR()) {
                 dataLog(
                     "Delaying optimization for ", *codeBlock,
@@ -1369,14 +1377,17 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
             vm, replacementCodeBlock, nullptr, DFG::DFGMode, bytecodeIndex,
             mustHandleValues, JITToDFGDeferredCompilationCallback::create());
         
-        if (result != CompilationSuccessful)
+        if (result != CompilationSuccessful) {
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("compilation failed"));
             return encodeResult(0, 0);
+        }
     }
     
     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
     
     if (void* dataBuffer = DFG::prepareOSREntry(exec, optimizedCodeBlock, bytecodeIndex)) {
+        CODEBLOCK_LOG_EVENT(optimizedCodeBlock, "osrEntry", ("at bc#", bytecodeIndex));
         if (Options::verboseOSR()) {
             dataLog(
                 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ".\n");
@@ -1406,6 +1417,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
     // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
     // reoptimization trigger.
     if (optimizedCodeBlock->shouldReoptimizeNow()) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("should reoptimize now"));
         if (Options::verboseOSR()) {
             dataLog(
                 "Triggering reoptimization of ", *codeBlock, " -> ",
@@ -1419,6 +1431,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
     // longer and then try again.
     codeBlock->optimizeAfterWarmUp();
     
+    CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("OSR failed"));
     return encodeResult(0, 0);
 }
 #endif
index a1b1511..ccc58d1 100644 (file)
@@ -319,6 +319,7 @@ inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec)
     codeBlock->updateAllValueProfilePredictions();
 
     if (!codeBlock->checkIfJITThresholdReached()) {
+        CODEBLOCK_LOG_EVENT(codeBlock, "delayJITCompile", ("threshold not reached, counter = ", codeBlock->llintExecuteCounter()));
         if (Options::verboseOSR())
             dataLogF("    JIT threshold should be lifted.\n");
         return false;
@@ -335,6 +336,7 @@ inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec)
         CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationCanFail);
         switch (result) {
         case CompilationFailed:
+            CODEBLOCK_LOG_EVENT(codeBlock, "delayJITCompile", ("compilation failed"));
             if (Options::verboseOSR())
                 dataLogF("    JIT compilation failed.\n");
             codeBlock->dontJITAnytimeSoon();
@@ -372,6 +374,8 @@ static SlowPathReturnType entryOSR(ExecState* exec, Instruction*, CodeBlock* cod
     if (!jitCompileAndSetHeuristics(codeBlock, exec))
         LLINT_RETURN_TWO(0, 0);
     
+    CODEBLOCK_LOG_EVENT(codeBlock, "OSR entry", ("in prologue"));
+    
     if (kind == Prologue)
         LLINT_RETURN_TWO(codeBlock->jitCode()->executableAddress(), 0);
     ASSERT(kind == ArityCheck);
@@ -429,6 +433,8 @@ LLINT_SLOW_PATH_DECL(loop_osr)
     if (!jitCompileAndSetHeuristics(codeBlock, exec))
         LLINT_RETURN_TWO(0, 0);
     
+    CODEBLOCK_LOG_EVENT(codeBlock, "osrEntry", ("at bc#", pc - codeBlock->instructions().begin()));
+
     ASSERT(codeBlock->jitType() == JITCode::BaselineJIT);
     
     Vector<BytecodeAndMachineOffset> map;
index 488f563..4e1d602 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-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
@@ -42,6 +42,7 @@ Compilation::Compilation(Bytecodes* bytecodes, CompilationKind kind)
     , m_numInlinedGetByIds(0)
     , m_numInlinedPutByIds(0)
     , m_numInlinedCalls(0)
+    , m_uid(UID::create())
 {
 }
 
@@ -106,6 +107,11 @@ void Compilation::setJettisonReason(JettisonReason jettisonReason, const FireDet
         m_additionalJettisonReason = CString();
 }
 
+void Compilation::dump(PrintStream& out) const
+{
+    out.print("Comp", m_uid);
+}
+
 JSValue Compilation::toJS(ExecState* exec) const
 {
     JSObject* result = constructEmptyObject(exec);
@@ -149,6 +155,8 @@ JSValue Compilation::toJS(ExecState* exec) const
     if (!m_additionalJettisonReason.isNull())
         result->putDirect(exec->vm(), exec->propertyNames().additionalJettisonReason, jsString(exec, String::fromUTF8(m_additionalJettisonReason)));
     
+    result->putDirect(exec->vm(), exec->propertyNames().uid, m_uid.toJS(exec));
+    
     return result;
 }
 
index b358b65..d23e2b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-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
@@ -36,6 +36,7 @@
 #include "ProfilerOSRExitSite.h"
 #include "ProfilerOriginStack.h"
 #include "ProfilerProfiledBytecodes.h"
+#include "ProfilerUID.h"
 #include <wtf/RefCounted.h>
 #include <wtf/SegmentedVector.h>
 
@@ -75,6 +76,9 @@ public:
     
     void setJettisonReason(JettisonReason, const FireDetail*);
     
+    UID uid() const { return m_uid; }
+    
+    void dump(PrintStream&) const;
     JSValue toJS(ExecState*) const;
     
 private:
@@ -90,6 +94,7 @@ private:
     unsigned m_numInlinedGetByIds;
     unsigned m_numInlinedPutByIds;
     unsigned m_numInlinedCalls;
+    UID m_uid;
 };
 
 } } // namespace JSC::Profiler
index fc952c0..93ddb11 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2013, 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
@@ -30,6 +30,7 @@
 #include "JSONObject.h"
 #include "ObjectConstructor.h"
 #include "JSCInlines.h"
+#include <wtf/CurrentTime.h>
 
 namespace JSC { namespace Profiler {
 
@@ -58,7 +59,11 @@ Database::~Database()
 Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
 {
     LockHolder locker(m_lock);
-    
+    return ensureBytecodesFor(locker, codeBlock);
+}
+
+Bytecodes* Database::ensureBytecodesFor(const LockHolder&, CodeBlock* codeBlock)
+{
     codeBlock = codeBlock->baselineVersion();
     
     HashMap<CodeBlock*, Bytecodes*>::iterator iter = m_bytecodesMap.find(codeBlock);
@@ -78,13 +83,18 @@ void Database::notifyDestruction(CodeBlock* codeBlock)
     LockHolder locker(m_lock);
     
     m_bytecodesMap.remove(codeBlock);
+    m_compilationMap.remove(codeBlock);
 }
 
-void Database::addCompilation(PassRefPtr<Compilation> compilation)
+void Database::addCompilation(CodeBlock* codeBlock, PassRefPtr<Compilation> passedCompilation)
 {
+    LockHolder locker(m_lock);
     ASSERT(!isCompilationThread());
+
+    RefPtr<Compilation> compilation = passedCompilation;
     
     m_compilations.append(compilation);
+    m_compilationMap.set(codeBlock, compilation);
 }
 
 JSValue Database::toJS(ExecState* exec) const
@@ -101,6 +111,11 @@ JSValue Database::toJS(ExecState* exec) const
         compilations->putDirectIndex(exec, i, m_compilations[i]->toJS(exec));
     result->putDirect(exec->vm(), exec->propertyNames().compilations, compilations);
     
+    JSArray* events = constructEmptyArray(exec, 0);
+    for (unsigned i = 0; i < m_events.size(); ++i)
+        events->putDirectIndex(exec, i, m_events[i].toJS(exec));
+    result->putDirect(exec->vm(), exec->propertyNames().events, events);
+    
     return result;
 }
 
@@ -133,6 +148,15 @@ void Database::registerToSaveAtExit(const char* filename)
     m_shouldSaveAtExit = true;
 }
 
+void Database::logEvent(CodeBlock* codeBlock, const char* summary, const CString& detail)
+{
+    LockHolder locker(m_lock);
+    
+    Bytecodes* bytecodes = ensureBytecodesFor(locker, codeBlock);
+    Compilation* compilation = m_compilationMap.get(codeBlock);
+    m_events.append(Event(currentTime(), bytecodes, compilation, summary, detail));
+}
+
 void Database::addDatabaseToAtExit()
 {
     if (++didRegisterAtExit == 1)
index 9bb64cf..db0f407 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2013, 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
@@ -30,6 +30,7 @@
 #include "ProfilerBytecodes.h"
 #include "ProfilerCompilation.h"
 #include "ProfilerCompilationKind.h"
+#include "ProfilerEvent.h"
 #include <wtf/FastMalloc.h>
 #include <wtf/HashMap.h>
 #include <wtf/Lock.h>
@@ -52,7 +53,7 @@ public:
     Bytecodes* ensureBytecodesFor(CodeBlock*);
     void notifyDestruction(CodeBlock*);
     
-    void addCompilation(PassRefPtr<Compilation>);
+    void addCompilation(CodeBlock*, PassRefPtr<Compilation>);
     
     // Converts the database to a JavaScript object that is suitable for JSON stringification.
     // Note that it's probably a good idea to use an ExecState* associated with a global
@@ -70,7 +71,11 @@ public:
 
     void registerToSaveAtExit(const char* filename);
     
+    JS_EXPORT_PRIVATE void logEvent(CodeBlock* codeBlock, const char* summary, const CString& detail);
+    
 private:
+    Bytecodes* ensureBytecodesFor(const LockHolder&, CodeBlock*);
+    
     void addDatabaseToAtExit();
     void removeDatabaseFromAtExit();
     void performAtExitSave() const;
@@ -82,6 +87,8 @@ private:
     SegmentedVector<Bytecodes> m_bytecodes;
     HashMap<CodeBlock*, Bytecodes*> m_bytecodesMap;
     Vector<RefPtr<Compilation>> m_compilations;
+    HashMap<CodeBlock*, RefPtr<Compilation>> m_compilationMap;
+    Vector<Event> m_events;
     bool m_shouldSaveAtExit;
     CString m_atExitSaveFilename;
     Database* m_nextRegisteredDatabase;
diff --git a/Source/JavaScriptCore/profiler/ProfilerEvent.cpp b/Source/JavaScriptCore/profiler/ProfilerEvent.cpp
new file mode 100644 (file)
index 0000000..e84ef6f
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 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 "ProfilerEvent.h"
+
+#include "JSCInlines.h"
+#include "ObjectConstructor.h"
+#include "ProfilerBytecodes.h"
+#include "ProfilerCompilation.h"
+#include "ProfilerUID.h"
+
+namespace JSC { namespace Profiler {
+
+void Event::dump(PrintStream& out) const
+{
+    out.print(m_time, ": ", pointerDump(m_bytecodes));
+    if (m_compilation)
+        out.print(" ", *m_compilation);
+    out.print(": ", m_summary);
+    if (m_detail.length())
+        out.print(" (", m_detail, ")");
+}
+
+JSValue Event::toJS(ExecState* exec) const
+{
+    JSObject* result = constructEmptyObject(exec);
+    
+    result->putDirect(exec->vm(), exec->propertyNames().time, jsNumber(m_time));
+    result->putDirect(exec->vm(), exec->propertyNames().bytecodesID, jsNumber(m_bytecodes->id()));
+    if (m_compilation)
+        result->putDirect(exec->vm(), exec->propertyNames().compilationUID, m_compilation->uid().toJS(exec));
+    result->putDirect(exec->vm(), exec->propertyNames().summary, jsString(exec, String::fromUTF8(m_summary)));
+    if (m_detail.length())
+        result->putDirect(exec->vm(), exec->propertyNames().detail, jsString(exec, String::fromUTF8(m_detail)));
+    
+    return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerEvent.h b/Source/JavaScriptCore/profiler/ProfilerEvent.h
new file mode 100644 (file)
index 0000000..ad924ca
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 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. 
+ */
+
+#ifndef ProfilerEvent_h
+#define ProfilerEvent_h
+
+#include "JSCJSValue.h"
+#include <wtf/PrintStream.h>
+#include <wtf/text/CString.h>
+
+namespace JSC { namespace Profiler {
+
+class Bytecodes;
+class Compilation;
+
+class Event {
+public:
+    Event()
+    {
+    }
+    
+    Event(double time, Bytecodes* bytecodes, Compilation* compilation, const char* summary, const CString& detail)
+        : m_time(time)
+        , m_bytecodes(bytecodes)
+        , m_compilation(compilation)
+        , m_summary(summary)
+        , m_detail(detail)
+    {
+    }
+    
+    explicit operator bool() const
+    {
+        return m_bytecodes;
+    }
+    
+    double time() const { return m_time; }
+    Bytecodes* bytecodes() const { return m_bytecodes; }
+    Compilation* compilation() const { return m_compilation; }
+    const char* summary() const { return m_summary; }
+    const CString& detail() const { return m_detail; }
+    
+    void dump(PrintStream&) const;
+    JSValue toJS(ExecState*) const;
+    
+private:
+    double m_time { 0 };
+    Bytecodes* m_bytecodes { nullptr };
+    Compilation* m_compilation { nullptr };
+    const char* m_summary { nullptr };
+    CString m_detail;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerEvent_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerUID.cpp b/Source/JavaScriptCore/profiler/ProfilerUID.cpp
new file mode 100644 (file)
index 0000000..228988b
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 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 "ProfilerUID.h"
+
+#include "JSCInlines.h"
+#include <wtf/Lock.h>
+
+namespace JSC { namespace Profiler {
+
+UID UID::create()
+{
+    static StaticLock lock;
+    static uint64_t counter;
+    
+    LockHolder locker(lock);
+    UID result;
+    result.m_uid = ++counter;
+    return result;
+}
+
+void UID::dump(PrintStream& out) const
+{
+    out.print(m_uid);
+}
+
+JSValue UID::toJS(ExecState* exec) const
+{
+    return jsString(exec, toString(*this));
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerUID.h b/Source/JavaScriptCore/profiler/ProfilerUID.h
new file mode 100644 (file)
index 0000000..50a42f4
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 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. 
+ */
+
+#ifndef ProfilerUID_h
+#define ProfilerUID_h
+
+#include "JSCJSValue.h"
+#include <wtf/HashMap.h>
+#include <wtf/PrintStream.h>
+
+namespace JSC { namespace Profiler {
+
+class UID {
+public:
+    UID()
+        : m_uid(0)
+    {
+    }
+    
+    static UID fromInt(uint64_t value)
+    {
+        UID result;
+        result.m_uid = value;
+        return result;
+    }
+    
+    UID(WTF::HashTableDeletedValueType)
+        : m_uid(std::numeric_limits<uint64_t>::max())
+    {
+    }
+    
+    static UID create();
+    
+    uint64_t toInt() const
+    {
+        return m_uid;
+    }
+    
+    bool operator==(const UID& other) const
+    {
+        return m_uid == other.m_uid;
+    }
+    
+    bool operator!=(const UID& other) const
+    {
+        return !(*this == other);
+    }
+    
+    explicit operator bool() const
+    {
+        return *this != UID();
+    }
+    
+    bool isHashTableDeletedValue() const
+    {
+        return *this != UID(WTF::HashTableDeletedValue);
+    }
+    
+    unsigned hash() const
+    {
+        return IntHash<uint64_t>::hash(m_uid);
+    }
+    
+    void dump(PrintStream&) const;
+    JSValue toJS(ExecState*) const;
+    
+private:
+    uint64_t m_uid;
+};
+
+struct UIDHash {
+    static unsigned hash(const UID& key) { return key.hash(); }
+    static bool equal(const UID& a, const UID& b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::Profiler
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::Profiler::UID> {
+    typedef JSC::Profiler::UIDHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::Profiler::UID> : SimpleClassHashTraits<JSC::Profiler::UID> { };
+
+} // namespace WTF
+
+#endif // ProfilerUID_h
+
index 91ece9b..9c89c5d 100644 (file)
     macro(collation) \
     macro(column) \
     macro(compilationKind) \
+    macro(compilationUID) \
     macro(compilations) \
     macro(compile) \
     macro(configurable) \
     macro(defineProperty) \
     macro(description) \
     macro(descriptions) \
+    macro(detail) \
     macro(displayName) \
     macro(document) \
     macro(done) \
     macro(enumerable) \
     macro(era) \
     macro(eval) \
+    macro(events) \
     macro(exec) \
     macro(executionCount) \
     macro(exitKind) \
     macro(stack) \
     macro(sticky) \
     macro(subarray) \
+    macro(summary) \
     macro(target) \
     macro(test) \
     macro(then) \
+    macro(time) \
     macro(timeZone) \
     macro(timeZoneName) \
     macro(toExponential) \
     macro(toPrecision) \
     macro(toString) \
     macro(top) \
+    macro(uid) \
     macro(unicode) \
     macro(usage) \
     macro(value) \
index 4fb958c..9195d55 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2010, 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 2013, 2015-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
@@ -36,6 +36,7 @@
 #include "Parser.h"
 #include "ProfilerDatabase.h"
 #include "TypeProfiler.h"
+#include "VMInlines.h"
 #include "WASMFunctionParser.h"
 #include <wtf/CommaPrinter.h>
 #include <wtf/Vector.h>
@@ -176,6 +177,8 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
 {
     ASSERT(vm.heap.isDeferred());
     
+    CODEBLOCK_LOG_EVENT(genericCodeBlock, "installCode", ());
+    
     CodeBlock* oldCodeBlock = nullptr;
     
     switch (codeType) {
index d7e5e10..ba07c93 100644 (file)
@@ -612,6 +612,9 @@ public:
     BytecodeIntrinsicRegistry& bytecodeIntrinsicRegistry() { return *m_bytecodeIntrinsicRegistry; }
     
     ShadowChicken& shadowChicken() { return *m_shadowChicken; }
+    
+    template<typename Func>
+    void logEvent(CodeBlock*, const char* summary, const Func& func);
 
 private:
     friend class LLIntOffsetsExtractor;
index 7a63935..7f91869 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-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
@@ -26,6 +26,7 @@
 #ifndef VMInlines_h
 #define VMInlines_h
 
+#include "ProfilerDatabase.h"
 #include "VM.h"
 #include "Watchdog.h"
 
@@ -38,6 +39,15 @@ bool VM::shouldTriggerTermination(ExecState* exec)
     return watchdog()->shouldTerminate(exec);
 }
 
+template<typename Func>
+void VM::logEvent(CodeBlock* codeBlock, const char* summary, const Func& func)
+{
+    if (LIKELY(!m_perBytecodeProfiler))
+        return;
+    
+    m_perBytecodeProfiler->logEvent(codeBlock, summary, func());
+}
+
 } // namespace JSC
 
 #endif // LLIntData_h
index 8fae3be..74583c3 100644 (file)
@@ -1,3 +1,13 @@
+2016-05-10  Filip Pizlo  <fpizlo@apple.com>
+
+        Internal JSC profiler should have a timestamped log of events for each code block
+        https://bugs.webkit.org/show_bug.cgi?id=157538
+
+        Reviewed by Benjamin Poulain.
+
+        * wtf/PrintStream.h:
+        (WTF::PrintStream::print):
+
 2016-05-10  Chris Dumez  <cdumez@apple.com>
 
         Get rid of a lot of calls to RefPtr::release()
index a5f5f03..c9bc0b5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 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
@@ -55,6 +55,8 @@ public:
     // Typically a no-op for many subclasses of PrintStream, this is a hint that
     // the implementation should flush its buffers if it had not done so already.
     virtual void flush();
+    
+    void print() { }
 
     template<typename T>
     void print(const T& value)
index b267073..ecdd4eb 100644 (file)
@@ -1,3 +1,12 @@
+2016-05-10  Filip Pizlo  <fpizlo@apple.com>
+
+        Internal JSC profiler should have a timestamped log of events for each code block
+        https://bugs.webkit.org/show_bug.cgi?id=157538
+
+        Reviewed by Benjamin Poulain.
+
+        * Scripts/display-profiler-output:
+
 2016-05-10  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         [Linux] Remove seccomp filters support
index 50f17bd..374d666 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env ruby
 
-# Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+# Copyright (C) 2012-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
@@ -331,7 +331,7 @@ end
 class Compilation
     attr_accessor :bytecode, :engine, :descriptions, :counters, :compilationIndex
     attr_accessor :osrExits, :profiledBytecodes, :numInlinedGetByIds, :numInlinedPutByIds
-    attr_accessor :numInlinedCalls, :jettisonReason, :additionalJettisonReason
+    attr_accessor :numInlinedCalls, :jettisonReason, :additionalJettisonReason, :uid
     
     def initialize(json)
         @bytecode = $bytecodes[json["bytecodesID"].to_i]
@@ -386,6 +386,7 @@ class Compilation
         @numInlinedCalls = json["numInlinedCalls"]
         @jettisonReason = json["jettisonReason"]
         @additionalJettisonReason = json["additionalJettisonReason"]
+        @uid = json["uid"]
     end
     
     def codeHashSortKey
@@ -438,6 +439,20 @@ class DescriptionLine
     end
 end
 
+class Event
+    attr_reader :time, :bytecode, :compilation, :summary, :detail
+    
+    def initialize(json)
+        @time = json["time"].to_f
+        @bytecode = $bytecodes[json["bytecodesID"].to_i]
+        if json["compilationUID"]
+            @compilation = $compilationMap[json["compilationUID"]]
+        end
+        @summary = json["summary"]
+        @detail = json["detail"]
+    end
+end
+
 def originToPrintStack(origin)
     (0...(origin.size - 1)).map {
         | index |
@@ -468,6 +483,15 @@ $compilations = $json["compilations"].map {
     | subJson |
     Compilation.new(subJson)
 }
+$compilationMap = {}
+$compilations.each {
+    | compilation |
+    $compilationMap[compilation.uid] = compilation
+}
+$events = $json["events"].map {
+    | subJson |
+    Event.new(subJson)
+}
 $engines = ["Baseline", "DFG", "FTL", "FTLForOSREntry"]
 
 def isOptimizing(engine)
@@ -477,15 +501,17 @@ end
 $showCounts = true
 $sortMode = :time
 
-def lpad(str,chars)
-  if str.length>chars
-    str
-  else
-    "%#{chars}s"%(str)
-  end
+def lpad(str, chars)
+    str = str.to_s
+    if str.length > chars
+        str
+    else
+        "%#{chars}s"%(str)
+    end
 end
 
 def rpad(str, chars)
+    str = str.to_s
     while str.length < chars
         str += " "
     end
@@ -493,6 +519,7 @@ def rpad(str, chars)
 end
 
 def center(str, chars)
+    str = str.to_s
     while str.length < chars
         str += " "
         if str.length < chars
@@ -736,6 +763,7 @@ def executeCommand(*commandArray)
         puts "bytecode (b)    Show the bytecode for a code block, with counts."
         puts "profiling (p)   Show the (internal) profiling data for a code block."
         puts "log (l)         List the compilations, exits, and jettisons involving this code block."
+        puts "events (e)      List of events involving this code block."
         puts "display (d)     Display details for a code block."
         puts "inlines         Show all inlining stacks that the code block was on."
         puts "counts          Set whether to show counts for 'bytecode' and 'display'."
@@ -875,6 +903,52 @@ def executeCommand(*commandArray)
                 end
             end
         }
+    when "events", "e"
+        if args.length != 1
+            puts "Usage: inlines <code block hash>"
+            return
+        end
+        
+        hash = Regexp.new(Regexp.escape(args[0]))
+        
+        events = []
+        $events.each {
+            | event |
+            if event.bytecode.to_s =~ hash
+                events << event
+            end
+        }
+        
+        timeCols = 0
+        hashCols = 0
+        compilationCols = 0
+        summaryCols = 0
+        events.each {
+            | event |
+            timeCols = [event.time.to_s.size, timeCols].max
+            hashCols = [event.bytecode.to_s.size, hashCols].max
+            if event.compilation
+                compilationCols = [event.compilation.to_s.size, compilationCols].max
+            end
+            summaryCols = [event.summary.size, summaryCols].max
+        }
+        
+        events.each {
+            | event |
+            print rpad(event.time.to_s, timeCols)
+            print " "
+            print rpad(event.bytecode.to_s, hashCols)
+            print " "
+            compilationStr = ""
+            if event.compilation
+                compilationStr = event.compilation.to_s
+            end
+            print rpad(compilationStr, compilationCols)
+            print " "
+            print rpad(event.summary, summaryCols)
+            print " "
+            puts event.detail
+        }
     when "inlines"
         if args.length != 1
             puts "Usage: inlines <code block hash>"