Skip to content
This repository was archived by the owner on Jun 24, 2022. It is now read-only.

Commit c3b0b2b

Browse files
GC timers should carry on gracefully when Heap claims it grew from GC.
<https://webkit.org/b/151521> Reviewed by Mark Lam. TL;DR the Heap "extra memory" reporting APIs are hard to use 100% correctly and GC scheduling shouldn't break if someone makes a mistake with it. The JSC::Heap allows you to report an extra memory cost for any GC object. This is reported first when allocating the memory, and then each time the object is visited during the marking phase. When reporting an allocation, it's added to the Heap's "bytes allocated in this cycle" counter. This contributes to the computed heap size at the start of a collection. When visiting a GC object that reports extra memory, it's added to the Heap's "extra memory visited in this collection" counter. This contributes to the computed heap size at the end of a collection. As you can see, this means that visiting more memory than we said we allocated can lead to the Heap thinking it's bigger after a collection than it was before. Clients of this API do some sketchy things to compute costs, for instance StringImpl cost is determined by dividing the number of bytes used for the characters, and dividing it by the StringImpl's ref count. Since a JSString could be backed by any StringImpl, any code that modifies a StringImpl's ref count during collection will change the extra memory reported by all JSString objects that wrap that StringImpl. So anyways... The object death rate, which is the basis for when to schedule the next collection is computed like so: deathRate = (sizeBeforeGC - sizeAfterGC) / sizeBeforeGC This patch adds a safety mechanism that returns a zero death rate when the Heap claims it grew from collection. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::deathRate): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::deathRate): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@192721 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 9476af1 commit c3b0b2b

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

Source/JavaScriptCore/ChangeLog

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,50 @@
1+
2015-11-20 Andreas Kling <[email protected]>
2+
3+
GC timers should carry on gracefully when Heap claims it grew from GC.
4+
<https://webkit.org/b/151521>
5+
6+
Reviewed by Mark Lam.
7+
8+
TL;DR the Heap "extra memory" reporting APIs are hard to use 100% correctly
9+
and GC scheduling shouldn't break if someone makes a mistake with it.
10+
11+
The JSC::Heap allows you to report an extra memory cost for any GC object.
12+
This is reported first when allocating the memory, and then each time the
13+
object is visited during the marking phase.
14+
15+
When reporting an allocation, it's added to the Heap's "bytes allocated in
16+
this cycle" counter. This contributes to the computed heap size at the start
17+
of a collection.
18+
19+
When visiting a GC object that reports extra memory, it's added to the Heap's
20+
"extra memory visited in this collection" counter. This contributes to the
21+
computed heap size at the end of a collection.
22+
23+
As you can see, this means that visiting more memory than we said we allocated
24+
can lead to the Heap thinking it's bigger after a collection than it was before.
25+
26+
Clients of this API do some sketchy things to compute costs, for instance
27+
StringImpl cost is determined by dividing the number of bytes used for the
28+
characters, and dividing it by the StringImpl's ref count. Since a JSString
29+
could be backed by any StringImpl, any code that modifies a StringImpl's
30+
ref count during collection will change the extra memory reported by all
31+
JSString objects that wrap that StringImpl.
32+
33+
So anyways...
34+
35+
The object death rate, which is the basis for when to schedule the next
36+
collection is computed like so:
37+
38+
deathRate = (sizeBeforeGC - sizeAfterGC) / sizeBeforeGC
39+
40+
This patch adds a safety mechanism that returns a zero death rate when the Heap
41+
claims it grew from collection.
42+
43+
* heap/EdenGCActivityCallback.cpp:
44+
(JSC::EdenGCActivityCallback::deathRate):
45+
* heap/FullGCActivityCallback.cpp:
46+
(JSC::FullGCActivityCallback::deathRate):
47+
148
2015-11-20 Mark Lam <[email protected]>
249

350
New JSC tests introduced in r192664 fail on ARM.

Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ double EdenGCActivityCallback::deathRate()
5454
size_t sizeAfter = heap->sizeAfterLastEdenCollection();
5555
if (!sizeBefore)
5656
return 1.0;
57+
if (sizeAfter > sizeBefore) {
58+
// GC caused the heap to grow(!)
59+
// This could happen if the we visited more extra memory than was reported allocated.
60+
// We don't return a negative death rate, since that would schedule the next GC in the past.
61+
return 0;
62+
}
5763
return static_cast<double>(sizeBefore - sizeAfter) / static_cast<double>(sizeBefore);
5864
}
5965

Source/JavaScriptCore/heap/FullGCActivityCallback.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ double FullGCActivityCallback::deathRate()
7070
size_t sizeAfter = heap->sizeAfterLastFullCollection();
7171
if (!sizeBefore)
7272
return 1.0;
73+
if (sizeAfter > sizeBefore) {
74+
// GC caused the heap to grow(!)
75+
// This could happen if the we visited more extra memory than was reported allocated.
76+
// We don't return a negative death rate, since that would schedule the next GC in the past.
77+
return 0;
78+
}
7379
return static_cast<double>(sizeBefore - sizeAfter) / static_cast<double>(sizeBefore);
7480
}
7581

0 commit comments

Comments
 (0)