WebKit Bugzilla
Attachment 368408 Details for
Bug 186732
: JITStubRoutineSet wastes 180KB of HashTable capacity on can.com
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-186732-20190427115940.patch (text/plain), 9.41 KB, created by
Yusuke Suzuki
on 2019-04-27 11:59:41 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2019-04-27 11:59:41 PDT
Size:
9.41 KB
patch
obsolete
>Subversion Revision: 244721 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 28aeca460ca65580a9ae60e98de7e15fada6d41b..d2711aa512ac26cfd0f20482d79cecd26b3c5b4e 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,37 @@ >+2019-04-27 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ JITStubRoutineSet wastes 180KB of HashTable capacity on can.com >+ https://bugs.webkit.org/show_bug.cgi?id=186732 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Our current mechanism of JITStubRoutineSet is too memory consuming. Basically we have HashMap<uintptr_t, StubRoutine*> and register >+ each executable address by 16 byte to this entry. So if your StubRoutine has 128bytes, it just adds 8 entries to this hash table. >+ In Gmail, we see ~2MB table size. >+ >+ Instead, this patch uses Vector<pair<uintptr_t, StubRoutine*>> and performs binary search onto this sorted vector. Before conservative >+ scanning, we sort this vector. And doing binary search with the sorted vector to find executing stub routines from the conservative roots. >+ This vector includes uintptr_t startAddress to make binary searching fast. >+ >+ 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 >+ performance bots say. >+ >+ * heap/Heap.cpp: >+ (JSC::Heap::addCoreConstraints): >+ * heap/JITStubRoutineSet.cpp: >+ (JSC::JITStubRoutineSet::~JITStubRoutineSet): >+ (JSC::JITStubRoutineSet::add): >+ (JSC::JITStubRoutineSet::prepareForConservativeScan): >+ (JSC::JITStubRoutineSet::clearMarks): >+ (JSC::JITStubRoutineSet::markSlow): >+ (JSC::JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines): >+ (JSC::JITStubRoutineSet::traceMarkedStubRoutines): >+ * heap/JITStubRoutineSet.h: >+ (JSC::JITStubRoutineSet::mark): >+ (JSC::JITStubRoutineSet::prepareForConservativeScan): >+ (JSC::JITStubRoutineSet::size const): Deleted. >+ (JSC::JITStubRoutineSet::at const): Deleted. >+ > 2019-04-26 Keith Rollin <krollin@apple.com> > > Enable new build rule for post-processing headers when using XCBuild >diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp >index 4953ac259223f32a1a0ad6e96182ffbc16aaa522..8d92313977d332bbebe3dcd7cebbe6336fa6073f 100644 >--- a/Source/JavaScriptCore/heap/Heap.cpp >+++ b/Source/JavaScriptCore/heap/Heap.cpp >@@ -2687,6 +2687,7 @@ void Heap::addCoreConstraints() > > TimingScope preConvergenceTimingScope(*this, "Constraint: conservative scan"); > m_objectSpace.prepareForConservativeScan(); >+ m_jitStubRoutines->prepareForConservativeScan(); > > { > ConservativeRoots conservativeRoots(*this); >diff --git a/Source/JavaScriptCore/heap/JITStubRoutineSet.cpp b/Source/JavaScriptCore/heap/JITStubRoutineSet.cpp >index ae80595326e8ca99badc5736a99f1c0c01474b87..85fa63fbd8e58b02426ff441a487e2aa93613457 100644 >--- a/Source/JavaScriptCore/heap/JITStubRoutineSet.cpp >+++ b/Source/JavaScriptCore/heap/JITStubRoutineSet.cpp >@@ -37,9 +37,8 @@ namespace JSC { > JITStubRoutineSet::JITStubRoutineSet() { } > JITStubRoutineSet::~JITStubRoutineSet() > { >- for (size_t i = m_listOfRoutines.size(); i--;) { >- GCAwareJITStubRoutine* routine = m_listOfRoutines[i]; >- >+ for (auto& current : m_routines) { >+ GCAwareJITStubRoutine* routine = current.routine; > routine->m_mayBeExecuting = false; > > if (!routine->m_isJettisoned) { >@@ -57,62 +56,83 @@ void JITStubRoutineSet::add(GCAwareJITStubRoutine* routine) > { > ASSERT(!routine->m_isJettisoned); > >- m_listOfRoutines.append(routine); >- >- uintptr_t start = routine->startAddress(); >- uintptr_t end = routine->endAddress(); >- uintptr_t step = JITStubRoutine::addressStep(); >- for (uintptr_t iter = start; iter < end; iter += step) { >- ASSERT(m_addressToRoutineMap.find(iter) == m_addressToRoutineMap.end()); >- m_addressToRoutineMap.add(iter, routine); >+ m_routines.append(Routine { >+ routine->startAddress(), >+ routine, >+ }); >+} >+ >+void JITStubRoutineSet::prepareForConservativeScan() >+{ >+ if (m_routines.isEmpty()) { >+ m_startOfRange = 0; >+ m_endOfRange = 0; >+ return; > } >+ std::sort( >+ m_routines.begin(), m_routines.end(), >+ [&] (const Routine& a, const Routine& b) { >+ return a.startAddress < b.startAddress; >+ }); >+ m_startOfRange = m_routines.first().startAddress; >+ m_endOfRange = m_routines.last().routine->endAddress(); > } > > void JITStubRoutineSet::clearMarks() > { >- for (size_t i = m_listOfRoutines.size(); i--;) >- m_listOfRoutines[i]->m_mayBeExecuting = false; >+ for (auto& routine : m_routines) >+ routine.routine->m_mayBeExecuting = false; > } > > void JITStubRoutineSet::markSlow(uintptr_t address) > { >- HashMap<uintptr_t, GCAwareJITStubRoutine*>::iterator iter = >- m_addressToRoutineMap.find(address & ~(JITStubRoutine::addressStep() - 1)); >- >- if (iter == m_addressToRoutineMap.end()) >- return; >- >- iter->value->m_mayBeExecuting = true; >+ ASSERT(!isJITPC(bitwise_cast<void*>(address))); >+ ASSERT(!m_routines.isEmpty()); >+ >+ Routine* result = approximateBinarySearch<Routine>( >+ m_routines.begin(), m_routines.size(), address, >+ [] (const Routine* routine) -> uintptr_t { return routine->startAddress; }); >+ if (result) { >+ auto markIfContained = [&] (const Routine& routine, uintptr_t address) { >+ if (routine.startAddress <= address && address < routine.routine->endAddress()) { >+ routine.routine->m_mayBeExecuting = true; >+ return true; >+ } >+ return false; >+ }; >+ >+ if (result > m_routines.begin()) { >+ if (markIfContained(result[-1], address)) >+ return; >+ } >+ if (markIfContained(result[0], address)) >+ return; >+ if (result + 1 < m_routines.end()) { >+ if (markIfContained(result[1], address)) >+ return; >+ } >+ } > } > > void JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines() > { >- for (size_t i = 0; i < m_listOfRoutines.size(); i++) { >- GCAwareJITStubRoutine* routine = m_listOfRoutines[i]; >- if (!routine->m_isJettisoned || routine->m_mayBeExecuting) >+ unsigned srcIndex = 0; >+ unsigned dstIndex = srcIndex; >+ while (srcIndex < m_routines.size()) { >+ Routine routine = m_routines[srcIndex++]; >+ if (!routine.routine->m_isJettisoned || routine.routine->m_mayBeExecuting) { >+ m_routines[dstIndex++] = routine; > continue; >- >- uintptr_t start = routine->startAddress(); >- uintptr_t end = routine->endAddress(); >- uintptr_t step = JITStubRoutine::addressStep(); >- for (uintptr_t iter = start; iter < end; iter += step) { >- ASSERT(m_addressToRoutineMap.find(iter) != m_addressToRoutineMap.end()); >- ASSERT(m_addressToRoutineMap.find(iter)->value == routine); >- m_addressToRoutineMap.remove(iter); > } >- >- routine->deleteFromGC(); >- >- m_listOfRoutines[i] = m_listOfRoutines.last(); >- m_listOfRoutines.removeLast(); >- i--; >+ routine.routine->deleteFromGC(); > } >+ m_routines.shrink(dstIndex); > } > > void JITStubRoutineSet::traceMarkedStubRoutines(SlotVisitor& visitor) > { >- for (size_t i = m_listOfRoutines.size(); i--;) { >- GCAwareJITStubRoutine* routine = m_listOfRoutines[i]; >+ for (size_t i = m_routines.size(); i--;) { >+ GCAwareJITStubRoutine* routine = m_routines[i].routine; > if (!routine->m_mayBeExecuting) > continue; > >diff --git a/Source/JavaScriptCore/heap/JITStubRoutineSet.h b/Source/JavaScriptCore/heap/JITStubRoutineSet.h >index 44a393fecbdad7d351b3b42d73830acfcbbb4722..763281e96964267659d4eb0f7564498b4931d009 100644 >--- a/Source/JavaScriptCore/heap/JITStubRoutineSet.h >+++ b/Source/JavaScriptCore/heap/JITStubRoutineSet.h >@@ -52,24 +52,27 @@ class JITStubRoutineSet { > void mark(void* candidateAddress) > { > uintptr_t address = removeCodePtrTag<uintptr_t>(candidateAddress); >- if (!JITStubRoutine::passesFilter(address)) >+ if (m_startOfRange > address || address >= m_endOfRange) > return; >- > markSlow(address); > } >+ >+ void prepareForConservativeScan(); > > void deleteUnmarkedJettisonedStubRoutines(); > > void traceMarkedStubRoutines(SlotVisitor&); > >- unsigned size() const { return m_listOfRoutines.size(); } >- GCAwareJITStubRoutine* at(unsigned i) const { return m_listOfRoutines[i]; } >- > private: > void markSlow(uintptr_t address); > >- HashMap<uintptr_t, GCAwareJITStubRoutine*> m_addressToRoutineMap; >- Vector<GCAwareJITStubRoutine*> m_listOfRoutines; >+ struct Routine { >+ uintptr_t startAddress; >+ GCAwareJITStubRoutine* routine; >+ }; >+ Vector<Routine> m_routines; >+ uintptr_t m_startOfRange { 0 }; >+ uintptr_t m_endOfRange { 0 }; > }; > > #else // !ENABLE(JIT) >@@ -85,6 +88,7 @@ class JITStubRoutineSet { > void add(GCAwareJITStubRoutine*) { } > void clearMarks() { } > void mark(void*) { } >+ void prepareForConservativeScan() { } > void deleteUnmarkedJettisonedStubRoutines() { } > void traceMarkedStubRoutines(SlotVisitor&) { } > };
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186732
:
368393
|
368406
|
368408
|
368410
|
368411
|
368420
|
368421
|
368422
|
368443