Changeset 99374 in webkit for trunk/Source/JavaScriptCore
- Timestamp:
- Nov 6, 2011, 3:39:12 AM (14 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r99358 r99374 1 2011-11-03 Filip Pizlo <[email protected]> 2 3 JSC should be able to sample itself in a more flexible way than just sampling flags 4 https://bugs.webkit.org/show_bug.cgi?id=71522 5 6 Reviewed by Gavin Barraclough. 7 8 Added a construct that looks like SamplingRegion samplingRegion("name"). 9 10 * JavaScriptCore.exp: 11 * JavaScriptCore.xcodeproj/project.pbxproj: 12 * bytecode/SamplingTool.cpp: 13 (JSC::SamplingRegion::Locker::Locker): 14 (JSC::SamplingRegion::Locker::~Locker): 15 (JSC::SamplingRegion::sample): 16 (JSC::SamplingRegion::dump): 17 (JSC::SamplingRegion::dumpInternal): 18 (JSC::SamplingThread::threadStartFunc): 19 * bytecode/SamplingTool.h: 20 (JSC::SamplingRegion::SamplingRegion): 21 (JSC::SamplingRegion::~SamplingRegion): 22 (JSC::SamplingRegion::exchangeCurrent): 23 * bytecompiler/BytecodeGenerator.cpp: 24 (JSC::BytecodeGenerator::generate): 25 * dfg/DFGDriver.cpp: 26 (JSC::DFG::compile): 27 * heap/Heap.cpp: 28 (JSC::Heap::markRoots): 29 (JSC::Heap::collect): 30 * heap/VTableSpectrum.cpp: 31 (JSC::VTableSpectrum::countVPtr): 32 (JSC::VTableSpectrum::dump): 33 * heap/VTableSpectrum.h: 34 * jsc.cpp: 35 (main): 36 (runWithScripts): 37 * parser/Parser.h: 38 (JSC::parse): 39 * runtime/Executable.cpp: 40 (JSC::EvalExecutable::compileInternal): 41 (JSC::ProgramExecutable::compileInternal): 42 (JSC::FunctionExecutable::compileForCallInternal): 43 (JSC::FunctionExecutable::compileForConstructInternal): 44 * wtf/Atomics.h: 45 (WTF::weakCompareAndSwap): 46 * wtf/Platform.h: 47 * wtf/Spectrum.h: Added. 48 (WTF::Spectrum::Spectrum): 49 (WTF::Spectrum::add): 50 (WTF::Spectrum::get): 51 (WTF::Spectrum::begin): 52 (WTF::Spectrum::end): 53 (WTF::Spectrum::KeyAndCount::KeyAndCount): 54 (WTF::Spectrum::KeyAndCount::operator<): 55 (WTF::Spectrum::buildList): 56 * wtf/wtf.pri: 57 1 58 2011-11-05 Sam Weinig <[email protected]> 2 59 -
trunk/Source/JavaScriptCore/JavaScriptCore.exp
r99357 r99374 180 180 __ZN3JSC14MachineThreads16addCurrentThreadEv 181 181 __ZN3JSC14MarkStackArray6expandEv 182 __ZN3JSC14SamplingRegion4dumpEv 182 183 __ZN3JSC14SamplingThread4stopEv 183 184 __ZN3JSC14SamplingThread5startEj -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r99144 r99374 51 51 0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; }; 52 52 0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; }; 53 0F2E5BF7146357D5003EB2EB /* Spectrum.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2E5BF5146357D2003EB2EB /* Spectrum.h */; settings = {ATTRIBUTES = (Private, ); }; }; 53 54 0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A451460CBAB00131F8F /* ValueRecovery.h */; settings = {ATTRIBUTES = (Private, ); }; }; 54 55 0F426A491460CBB700131F8F /* VirtualRegister.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A461460CBAB00131F8F /* VirtualRegister.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 814 815 0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; }; 815 816 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; }; 817 0F2E5BF5146357D2003EB2EB /* Spectrum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Spectrum.h; sourceTree = "<group>"; }; 816 818 0F426A451460CBAB00131F8F /* ValueRecovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueRecovery.h; sourceTree = "<group>"; }; 817 819 0F426A461460CBAB00131F8F /* VirtualRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VirtualRegister.h; sourceTree = "<group>"; }; … … 1856 1858 isa = PBXGroup; 1857 1859 children = ( 1860 0F2E5BF5146357D2003EB2EB /* Spectrum.h */, 1858 1861 0FD52AAC1430359D0026DC9F /* UnionFind.h */, 1859 1862 0F636D9F142D27D200B2E66A /* PackedIntVector.h */, … … 2898 2901 0F426A491460CBB700131F8F /* VirtualRegister.h in Headers */, 2899 2902 0F426A4B1460CD6E00131F8F /* DataFormat.h in Headers */, 2903 0F2E5BF7146357D5003EB2EB /* Spectrum.h in Headers */, 2900 2904 ); 2901 2905 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/JavaScriptCore/bytecode/SamplingTool.cpp
r95901 r99374 84 84 #endif 85 85 86 #if ENABLE(SAMPLING_REGIONS) 87 volatile uintptr_t SamplingRegion::s_currentOrReserved; 88 Spectrum<const char*>* SamplingRegion::s_spectrum; 89 unsigned long SamplingRegion::s_noneOfTheAbove; 90 unsigned SamplingRegion::s_numberOfSamplesSinceDump; 91 92 SamplingRegion::Locker::Locker() 93 { 94 uintptr_t previous; 95 while (true) { 96 previous = s_currentOrReserved; 97 if (previous & 1) { 98 #if OS(UNIX) 99 sched_yield(); 100 #endif 101 continue; 102 } 103 if (WTF::weakCompareAndSwap(&s_currentOrReserved, previous, previous | 1)) 104 break; 105 } 106 } 107 108 SamplingRegion::Locker::~Locker() 109 { 110 // We don't need the CAS, but we do it out of an 111 // abundance of caution (and because it gives us a memory fence, which is 112 // never bad). 113 uintptr_t previous; 114 do { 115 previous = s_currentOrReserved; 116 } while (!WTF::weakCompareAndSwap(&s_currentOrReserved, previous, previous & ~1)); 117 } 118 119 void SamplingRegion::sample() 120 { 121 // Make sure we lock s_current. 122 Locker locker; 123 124 // Create a spectrum if we don't have one already. 125 if (!s_spectrum) 126 s_spectrum = new Spectrum<const char*>(); 127 128 ASSERT(s_currentOrReserved & 1); 129 130 // Walk the region stack, and record each region we see. 131 SamplingRegion* region = bitwise_cast<SamplingRegion*>(s_currentOrReserved & ~1); 132 if (region) { 133 for (; region; region = region->m_previous) 134 s_spectrum->add(region->m_name); 135 } else 136 s_noneOfTheAbove++; 137 138 if (s_numberOfSamplesSinceDump++ == SamplingThread::s_hertz) { 139 s_numberOfSamplesSinceDump = 0; 140 dumpInternal(); 141 } 142 } 143 144 void SamplingRegion::dump() 145 { 146 Locker locker; 147 148 dumpInternal(); 149 } 150 151 void SamplingRegion::dumpInternal() 152 { 153 if (!s_spectrum) { 154 printf("\nSamplingRegion: was never sampled.\n\n"); 155 return; 156 } 157 158 Vector<Spectrum<const char*>::KeyAndCount> list = s_spectrum->buildList(); 159 160 unsigned long total = s_noneOfTheAbove; 161 for (unsigned i = list.size(); i--;) 162 total += list[i].count; 163 164 printf("\nSamplingRegion: sample counts for regions: (%lu samples)\n", total); 165 166 for (unsigned i = list.size(); i--;) 167 printf(" %3.2lf%% %s\n", (100.0 * list[i].count) / total, list[i].key); 168 } 169 #else // ENABLE(SAMPLING_REGIONS) 170 void SamplingRegion::dump() { } 171 #endif // ENABLE(SAMPLING_REGIONS) 172 86 173 /* 87 174 Start with flag 16 set. … … 131 218 #if ENABLE(SAMPLING_FLAGS) 132 219 SamplingFlags::sample(); 220 #endif 221 #if ENABLE(SAMPLING_REGIONS) 222 SamplingRegion::sample(); 133 223 #endif 134 224 #if ENABLE(OPCODE_SAMPLING) -
trunk/Source/JavaScriptCore/bytecode/SamplingTool.h
r95901 r99374 35 35 #include "SamplingCounter.h" 36 36 #include <wtf/Assertions.h> 37 #include <wtf/Atomics.h> 37 38 #include <wtf/HashMap.h> 39 #include <wtf/MainThread.h> 38 40 #include <wtf/Threading.h> 39 41 … … 93 95 #endif 94 96 }; 97 98 #if ENABLE(SAMPLING_REGIONS) 99 class SamplingRegion { 100 public: 101 // Create a scoped sampling region using a C string constant name that describes 102 // what you are doing. This must be a string constant that persists for the 103 // lifetime of the process and is immutable. 104 SamplingRegion(const char* name) 105 { 106 if (!isMainThread()) { 107 m_name = 0; 108 return; 109 } 110 111 m_name = name; 112 exchangeCurrent(this, &m_previous); 113 ASSERT(!m_previous || m_previous > this); 114 } 115 116 ~SamplingRegion() 117 { 118 if (!m_name) 119 return; 120 121 ASSERT(bitwise_cast<SamplingRegion*>(s_currentOrReserved & ~1) == this); 122 exchangeCurrent(m_previous); 123 } 124 125 static void sample(); 126 127 static void dump(); 128 129 private: 130 const char* m_name; 131 SamplingRegion* m_previous; 132 133 static void exchangeCurrent(SamplingRegion* current, SamplingRegion** previousPtr = 0) 134 { 135 uintptr_t previous; 136 while (true) { 137 previous = s_currentOrReserved; 138 139 // If it's reserved (i.e. sampling thread is reading it), loop around. 140 if (previous & 1) { 141 #if OS(UNIX) 142 sched_yield(); 143 #endif 144 continue; 145 } 146 147 // If we're going to CAS, then make sure previous is set. 148 if (previousPtr) 149 *previousPtr = bitwise_cast<SamplingRegion*>(previous); 150 151 if (WTF::weakCompareAndSwap(&s_currentOrReserved, previous, bitwise_cast<uintptr_t>(current))) 152 break; 153 } 154 } 155 156 static void dumpInternal(); 157 158 class Locker { 159 public: 160 Locker(); 161 ~Locker(); 162 }; 163 164 static volatile uintptr_t s_currentOrReserved; 165 166 // rely on identity hashing of string constants 167 static Spectrum<const char*>* s_spectrum; 168 169 static unsigned long s_noneOfTheAbove; 170 171 static unsigned s_numberOfSamplesSinceDump; 172 }; 173 #else // ENABLE(SAMPLING_REGIONS) 174 class SamplingRegion { 175 public: 176 SamplingRegion(const char*) { } 177 void dump(); 178 }; 179 #endif // ENABLE(SAMPLING_REGIONS) 95 180 96 181 class CodeBlock; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r98302 r99374 141 141 JSObject* BytecodeGenerator::generate() 142 142 { 143 SamplingRegion samplingRegion("Bytecode Generation"); 144 143 145 m_codeBlock->setThisRegister(m_thisRegister.index()); 144 146 -
trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp
r98082 r99374 38 38 inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck) 39 39 { 40 SamplingRegion samplingRegion("DFG Compilation (Driver)"); 41 40 42 JSGlobalData* globalData = &exec->globalData(); 41 43 Graph dfg; -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r98937 r99374 554 554 void Heap::markRoots(bool fullGC) 555 555 { 556 SamplingRegion samplingRegion("Garbage Collection: Tracing"); 557 556 558 COND_GCPHASE(fullGC, MarkFullRoots, MarkYoungRoots); 557 559 UNUSED_PARAM(fullGC); … … 760 762 void Heap::collect(SweepToggle sweepToggle) 761 763 { 764 SamplingRegion samplingRegion("Garbage Collection"); 765 762 766 GCPHASE(Collect); 763 767 ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); … … 793 797 794 798 if (sweepToggle == DoSweep) { 799 SamplingRegion samplingRegion("Garbage Collection: Sweeping"); 795 800 GCPHASE(Sweeping); 796 801 sweep(); -
trunk/Source/JavaScriptCore/heap/VTableSpectrum.cpp
r95901 r99374 50 50 void VTableSpectrum::countVPtr(void* vTablePointer) 51 51 { 52 std::pair<HashMap<void*, unsigned long>::iterator, bool> result = m_map.add(vTablePointer, 1); 53 if (!result.second) 54 result.first->second++; 52 add(vTablePointer); 55 53 } 56 54 … … 60 58 } 61 59 62 struct VTableAndCount {63 void* vtable;64 unsigned long count;65 66 VTableAndCount() { }67 68 VTableAndCount(void* vtable, unsigned long count)69 : vtable(vtable)70 , count(count)71 {72 }73 74 bool operator<(const VTableAndCount& other) const75 {76 if (count != other.count)77 return count < other.count;78 return vtable > other.vtable; // this results in lower-addressed vtables being printed first79 }80 };81 82 60 void VTableSpectrum::dump(FILE* output, const char* comment) 83 61 { 84 62 fprintf(output, "%s:\n", comment); 85 63 86 HashMap<void*, unsigned long>::iterator begin = m_map.begin(); 87 HashMap<void*, unsigned long>::iterator end = m_map.end(); 88 89 Vector<VTableAndCount, 0> list; 90 91 for (HashMap<void*, unsigned long>::iterator iter = begin; iter != end; ++iter) 92 list.append(VTableAndCount(iter->first, iter->second)); 93 94 std::sort(list.begin(), list.end()); 64 Vector<KeyAndCount> list = buildList(); 95 65 96 66 for (size_t index = list.size(); index-- > 0;) { 97 VTableAndCount item = list.at(index);67 KeyAndCount item = list.at(index); 98 68 #if PLATFORM(MAC) 99 69 Dl_info info; 100 if (dladdr(item. vtable, &info)) {70 if (dladdr(item.key, &info)) { 101 71 char* findResult = strrchr(info.dli_fname, '/'); 102 72 const char* strippedFileName; … … 107 77 strippedFileName = info.dli_fname; 108 78 109 fprintf(output, " %s:%s(%p): %lu\n", strippedFileName, info.dli_sname, item. vtable, item.count);79 fprintf(output, " %s:%s(%p): %lu\n", strippedFileName, info.dli_sname, item.key, item.count); 110 80 continue; 111 81 } 112 82 #endif 113 fprintf(output, " %p: %lu\n", item. vtable, item.count);83 fprintf(output, " %p: %lu\n", item.key, item.count); 114 84 } 115 85 -
trunk/Source/JavaScriptCore/heap/VTableSpectrum.h
r95901 r99374 28 28 29 29 #include <stdio.h> 30 #include <wtf/ HashMap.h>30 #include <wtf/Spectrum.h> 31 31 32 32 namespace JSC { … … 34 34 class JSCell; 35 35 36 class VTableSpectrum {36 class VTableSpectrum: Spectrum<void*> { 37 37 public: 38 38 VTableSpectrum(); … … 43 43 44 44 void dump(FILE* output, const char* comment); 45 46 private:47 HashMap<void*, unsigned long> m_map;48 45 }; 49 46 -
trunk/Source/JavaScriptCore/jsc.cpp
r99223 r99374 32 32 #include "JSLock.h" 33 33 #include "JSString.h" 34 #include "MainThread.h" 34 35 #include "SamplingTool.h" 35 36 #include <math.h> … … 405 406 406 407 // Initialize JSC before getting JSGlobalData. 408 WTF::initializeMainThread(); 407 409 JSC::initializeThreading(); 408 410 … … 472 474 #if ENABLE(SAMPLING_FLAGS) 473 475 SamplingFlags::stop(); 476 #endif 477 #if ENABLE(SAMPLING_REGIONS) 478 SamplingRegion::dump(); 474 479 #endif 475 480 globalData.dumpSampleData(globalObject->globalExec()); -
trunk/Source/JavaScriptCore/parser/Parser.h
r98887 r99374 1030 1030 PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, Debugger* debugger, ExecState* execState, JSObject** exception) 1031 1031 { 1032 SamplingRegion samplingRegion("Parsing"); 1032 1033 Parser parser(globalData, source, parameters, strictness, parserMode); 1033 1034 return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception); -
trunk/Source/JavaScriptCore/runtime/Executable.cpp
r98916 r99374 149 149 JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType) 150 150 { 151 SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)"); 152 151 153 #if !ENABLE(JIT) 152 154 UNUSED_PARAM(jitType); … … 281 283 JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType) 282 284 { 285 SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)"); 286 283 287 #if !ENABLE(JIT) 284 288 UNUSED_PARAM(jitType); … … 456 460 JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType) 457 461 { 462 SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)"); 463 458 464 #if !ENABLE(JIT) 459 465 UNUSED_PARAM(exec); … … 516 522 JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType) 517 523 { 524 SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)"); 525 518 526 #if !ENABLE(JIT) 519 527 UNUSED_PARAM(jitType); -
trunk/Source/JavaScriptCore/wtf/Atomics.h
r98937 r99374 127 127 "lock; cmpxchgl %3, %2\n\t" 128 128 "sete %1" 129 : "+a"(expected), "= r"(result), "+m"(*location)129 : "+a"(expected), "=q"(result), "+m"(*location) 130 130 : "r"(newValue) 131 131 : "memory" … … 141 141 } 142 142 143 inline bool weakCompareAndSwap(void*volatile* location, void* expected, void* newValue) 144 { 145 // FIXME: Implement COMPARE_AND_SWAP on other architectures and compilers. Currently 146 // it only works on X86 or X86_64 with a GCC-style compiler. 147 #if ENABLE(COMPARE_AND_SWAP) 148 bool result; 149 asm volatile( 150 #if CPU(X86_64) 151 "lock; cmpxchgq %3, %2\n\t" 152 #else 153 "lock; cmpxchgl %3, %2\n\t" 154 #endif 155 "sete %1" 156 : "+a"(expected), "=q"(result), "+m"(*location) 157 : "r"(newValue) 158 : "memory" 159 ); 160 return result; 161 #else // ENABLE(COMPARE_AND_SWAP) 162 UNUSED_PARAM(location); 163 UNUSED_PARAM(expected); 164 UNUSED_PARAM(newValue); 165 CRASH(); 166 return 0; 167 #endif // ENABLE(COMPARE_AND_SWAP) 168 } 169 170 inline bool weakCompareAndSwap(volatile uintptr_t* location, uintptr_t expected, uintptr_t newValue) 171 { 172 return weakCompareAndSwap(reinterpret_cast<void*volatile*>(location), reinterpret_cast<void*>(expected), reinterpret_cast<void*>(newValue)); 173 } 174 143 175 } // namespace WTF 144 176 -
trunk/Source/JavaScriptCore/wtf/Platform.h
r99222 r99374 809 809 #define ENABLE_SAMPLING_COUNTERS 0 810 810 #define ENABLE_SAMPLING_FLAGS 0 811 #define ENABLE_SAMPLING_REGIONS 0 811 812 #define ENABLE_OPCODE_SAMPLING 0 812 813 #define ENABLE_CODEBLOCK_SAMPLING 0 … … 814 815 #error "CODEBLOCK_SAMPLING requires OPCODE_SAMPLING" 815 816 #endif 816 #if ENABLE(OPCODE_SAMPLING) || ENABLE(SAMPLING_FLAGS) 817 #if ENABLE(OPCODE_SAMPLING) || ENABLE(SAMPLING_FLAGS) || ENABLE(SAMPLING_REGIONS) 817 818 #define ENABLE_SAMPLING_THREAD 1 818 819 #endif -
trunk/Source/JavaScriptCore/wtf/wtf.pri
r99274 r99374 98 98 wtf/RetainPtr.h \ 99 99 wtf/SHA1.h \ 100 wtf/Spectrum.h \ 100 101 wtf/StackBounds.h \ 101 102 wtf/StaticConstructors.h \
Note:
See TracChangeset
for help on using the changeset viewer.