Changeset 244745 in webkit
- Timestamp:
- Apr 29, 2019 12:21:02 PM (5 years ago)
- Location:
- trunk/Source
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r244741 r244745 1 2019-04-29 Yusuke Suzuki <ysuzuki@apple.com> 2 3 JITStubRoutineSet wastes 180KB of HashTable capacity on can.com 4 https://bugs.webkit.org/show_bug.cgi?id=186732 5 6 Reviewed by Saam Barati. 7 8 Our current mechanism of JITStubRoutineSet consumes more memory than needed. Basically we have HashMap<uintptr_t, StubRoutine*> and register 9 each executable address by 16 byte to this entry. So if your StubRoutine has 128bytes, it just adds 8 entries to this hash table. 10 In Gmail, we see a ~2MB table size. 11 12 Instead, this patch uses Vector<pair<uintptr_t, StubRoutine*>> and performs binary search onto this sorted vector. Before conservative 13 scanning, we sort this vector. And doing binary search with the sorted vector to find executing stub routines from the conservative roots. 14 This vector includes uintptr_t startAddress to make binary searching fast. 15 16 Large amount of conservative scan should be filtered by range check, so I think binary search here is OK, but we can decide based on what the 17 performance bots say. 18 19 * heap/Heap.cpp: 20 (JSC::Heap::addCoreConstraints): 21 * heap/JITStubRoutineSet.cpp: 22 (JSC::JITStubRoutineSet::~JITStubRoutineSet): 23 (JSC::JITStubRoutineSet::add): 24 (JSC::JITStubRoutineSet::prepareForConservativeScan): 25 (JSC::JITStubRoutineSet::clearMarks): 26 (JSC::JITStubRoutineSet::markSlow): 27 (JSC::JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines): 28 (JSC::JITStubRoutineSet::traceMarkedStubRoutines): 29 * heap/JITStubRoutineSet.h: 30 (JSC::JITStubRoutineSet::mark): 31 (JSC::JITStubRoutineSet::prepareForConservativeScan): 32 (JSC::JITStubRoutineSet::size const): Deleted. 33 (JSC::JITStubRoutineSet::at const): Deleted. 34 1 35 2019-04-29 Basuke Suzuki <Basuke.Suzuki@sony.com> 2 36 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r243560 r244745 2688 2688 TimingScope preConvergenceTimingScope(*this, "Constraint: conservative scan"); 2689 2689 m_objectSpace.prepareForConservativeScan(); 2690 m_jitStubRoutines->prepareForConservativeScan(); 2690 2691 2691 2692 { -
trunk/Source/JavaScriptCore/heap/JITStubRoutineSet.cpp
r164229 r244745 38 38 JITStubRoutineSet::~JITStubRoutineSet() 39 39 { 40 for (size_t i = m_listOfRoutines.size(); i--;) { 41 GCAwareJITStubRoutine* routine = m_listOfRoutines[i]; 42 40 for (auto& entry : m_routines) { 41 GCAwareJITStubRoutine* routine = entry.routine; 43 42 routine->m_mayBeExecuting = false; 44 43 … … 58 57 ASSERT(!routine->m_isJettisoned); 59 58 60 m_listOfRoutines.append(routine); 61 62 uintptr_t start = routine->startAddress(); 63 uintptr_t end = routine->endAddress(); 64 uintptr_t step = JITStubRoutine::addressStep(); 65 for (uintptr_t iter = start; iter < end; iter += step) { 66 ASSERT(m_addressToRoutineMap.find(iter) == m_addressToRoutineMap.end()); 67 m_addressToRoutineMap.add(iter, routine); 59 m_routines.append(Routine { 60 routine->startAddress(), 61 routine 62 }); 63 } 64 65 void JITStubRoutineSet::prepareForConservativeScan() 66 { 67 if (m_routines.isEmpty()) { 68 m_range = Range<uintptr_t> { 0, 0 }; 69 return; 68 70 } 71 std::sort( 72 m_routines.begin(), m_routines.end(), 73 [&] (const Routine& a, const Routine& b) { 74 return a.startAddress < b.startAddress; 75 }); 76 m_range = Range<uintptr_t> { 77 m_routines.first().startAddress, 78 m_routines.last().routine->endAddress() 79 }; 69 80 } 70 81 71 82 void JITStubRoutineSet::clearMarks() 72 83 { 73 for ( size_t i = m_listOfRoutines.size(); i--;)74 m_listOfRoutines[i]->m_mayBeExecuting = false;84 for (auto& entry : m_routines) 85 entry.routine->m_mayBeExecuting = false; 75 86 } 76 87 77 88 void JITStubRoutineSet::markSlow(uintptr_t address) 78 89 { 79 HashMap<uintptr_t, GCAwareJITStubRoutine*>::iterator iter = 80 m_addressToRoutineMap.find(address & ~(JITStubRoutine::addressStep() - 1)); 81 82 if (iter == m_addressToRoutineMap.end()) 83 return; 84 85 iter->value->m_mayBeExecuting = true; 90 ASSERT(isJITPC(bitwise_cast<void*>(address))); 91 ASSERT(!m_routines.isEmpty()); 92 93 Routine* result = approximateBinarySearch<Routine>( 94 m_routines.begin(), m_routines.size(), address, 95 [] (const Routine* routine) -> uintptr_t { return routine->startAddress; }); 96 if (result) { 97 auto markIfContained = [&] (const Routine& routine, uintptr_t address) { 98 if (routine.startAddress <= address && address < routine.routine->endAddress()) { 99 routine.routine->m_mayBeExecuting = true; 100 return true; 101 } 102 return false; 103 }; 104 105 if (result > m_routines.begin()) { 106 if (markIfContained(result[-1], address)) 107 return; 108 } 109 if (markIfContained(result[0], address)) 110 return; 111 if (result + 1 < m_routines.end()) { 112 if (markIfContained(result[1], address)) 113 return; 114 } 115 } 86 116 } 87 117 88 118 void JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines() 89 119 { 90 for (size_t i = 0; i < m_listOfRoutines.size(); i++) { 91 GCAwareJITStubRoutine* routine = m_listOfRoutines[i]; 92 if (!routine->m_isJettisoned || routine->m_mayBeExecuting) 120 unsigned srcIndex = 0; 121 unsigned dstIndex = srcIndex; 122 while (srcIndex < m_routines.size()) { 123 Routine routine = m_routines[srcIndex++]; 124 if (!routine.routine->m_isJettisoned || routine.routine->m_mayBeExecuting) { 125 m_routines[dstIndex++] = routine; 93 126 continue; 94 95 uintptr_t start = routine->startAddress();96 uintptr_t end = routine->endAddress();97 uintptr_t step = JITStubRoutine::addressStep();98 for (uintptr_t iter = start; iter < end; iter += step) {99 ASSERT(m_addressToRoutineMap.find(iter) != m_addressToRoutineMap.end());100 ASSERT(m_addressToRoutineMap.find(iter)->value == routine);101 m_addressToRoutineMap.remove(iter);102 127 } 103 104 routine->deleteFromGC(); 105 106 m_listOfRoutines[i] = m_listOfRoutines.last(); 107 m_listOfRoutines.removeLast(); 108 i--; 128 routine.routine->deleteFromGC(); 109 129 } 130 m_routines.shrink(dstIndex); 110 131 } 111 132 112 133 void JITStubRoutineSet::traceMarkedStubRoutines(SlotVisitor& visitor) 113 134 { 114 for ( size_t i = m_listOfRoutines.size(); i--;) {115 GCAwareJITStubRoutine* routine = m_listOfRoutines[i];135 for (auto& entry : m_routines) { 136 GCAwareJITStubRoutine* routine = entry.routine; 116 137 if (!routine->m_mayBeExecuting) 117 138 continue; -
trunk/Source/JavaScriptCore/heap/JITStubRoutineSet.h
r230129 r244745 29 29 #include <wtf/FastMalloc.h> 30 30 #include <wtf/HashMap.h> 31 #include <wtf/Range.h> 31 32 #include <wtf/Vector.h> 32 33 … … 53 54 { 54 55 uintptr_t address = removeCodePtrTag<uintptr_t>(candidateAddress); 55 if (! JITStubRoutine::passesFilter(address))56 if (!m_range.contains(address)) 56 57 return; 57 58 58 markSlow(address); 59 59 } 60 61 void prepareForConservativeScan(); 60 62 61 63 void deleteUnmarkedJettisonedStubRoutines(); … … 63 65 void traceMarkedStubRoutines(SlotVisitor&); 64 66 65 unsigned size() const { return m_listOfRoutines.size(); }66 GCAwareJITStubRoutine* at(unsigned i) const { return m_listOfRoutines[i]; }67 68 67 private: 69 68 void markSlow(uintptr_t address); 70 69 71 HashMap<uintptr_t, GCAwareJITStubRoutine*> m_addressToRoutineMap; 72 Vector<GCAwareJITStubRoutine*> m_listOfRoutines; 70 struct Routine { 71 uintptr_t startAddress; 72 GCAwareJITStubRoutine* routine; 73 }; 74 Vector<Routine> m_routines; 75 Range<uintptr_t> m_range { 0, 0 }; 73 76 }; 74 77 … … 86 89 void clearMarks() { } 87 90 void mark(void*) { } 91 void prepareForConservativeScan() { } 88 92 void deleteUnmarkedJettisonedStubRoutines() { } 89 93 void traceMarkedStubRoutines(SlotVisitor&) { } -
trunk/Source/WTF/ChangeLog
r244741 r244745 1 2019-04-29 Yusuke Suzuki <ysuzuki@apple.com> 2 3 JITStubRoutineSet wastes 180KB of HashTable capacity on can.com 4 https://bugs.webkit.org/show_bug.cgi?id=186732 5 6 Reviewed by Saam Barati. 7 8 * wtf/Range.h: 9 (WTF::Range::contains const): 10 1 11 2019-04-29 Basuke Suzuki <Basuke.Suzuki@sony.com> 2 12 -
trunk/Source/WTF/wtf/Range.h
r215565 r244745 110 110 } 111 111 112 bool contains(Type point) const 113 { 114 return m_begin <= point && point < m_end; 115 } 116 112 117 void dump(PrintStream& out) const 113 118 {
Note: See TracChangeset
for help on using the changeset viewer.