Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
Alfredo Di Napoli
GHC
Commits
30c01e42
Commit
30c01e42
authored
Jul 16, 2019
by
Daniel Gröber (dxld)
Committed by
Marge Bot
Feb 17, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rts: TraverseHeap: Move "flip" bit into traverseState struct
parent
d7bbaf5d
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
67 additions
and
57 deletions
+67
-57
rts/ProfHeap.c
rts/ProfHeap.c
+2
-2
rts/RetainerProfile.c
rts/RetainerProfile.c
+8
-3
rts/RetainerProfile.h
rts/RetainerProfile.h
+2
-0
rts/TraverseHeap.c
rts/TraverseHeap.c
+15
-47
rts/TraverseHeap.h
rts/TraverseHeap.h
+39
-4
rts/sm/GC.c
rts/sm/GC.c
+1
-1
No files found.
rts/ProfHeap.c
View file @
30c01e42
...
...
@@ -215,7 +215,7 @@ closureIdentity( const StgClosure *p )
case
HEAP_BY_RETAINER
:
// AFAIK, the only closures in the heap which might not have a
// valid retainer set are DEAD_WEAK closures.
if
(
is
TravData
Valid
(
p
))
if
(
is
RetainerSet
Valid
(
p
))
return
retainerSetOf
(
p
);
else
return
NULL
;
...
...
@@ -739,7 +739,7 @@ closureSatisfiesConstraints( const StgClosure* p )
// reason it might not be valid is if this closure is a
// a newly deceased weak pointer (i.e. a DEAD_WEAK), since
// these aren't reached by the retainer profiler's traversal.
if
(
is
TravData
Valid
((
StgClosure
*
)
p
))
{
if
(
is
RetainerSet
Valid
((
StgClosure
*
)
p
))
{
rs
=
retainerSetOf
((
StgClosure
*
)
p
);
if
(
rs
!=
NULL
)
{
for
(
i
=
0
;
i
<
rs
->
num
;
i
++
)
{
...
...
rts/RetainerProfile.c
View file @
30c01e42
...
...
@@ -251,13 +251,18 @@ associate( StgClosure *c, RetainerSet *s )
{
// StgWord has the same size as pointers, so the following type
// casting is okay.
setTravData
(
c
,
(
StgWord
)
s
);
setTravData
(
&
g_retainerTraverseState
,
c
,
(
StgWord
)
s
);
}
bool
isRetainerSetValid
(
const
StgClosure
*
c
)
{
return
isTravDataValid
(
&
g_retainerTraverseState
,
c
);
}
inline
RetainerSet
*
retainerSetOf
(
const
StgClosure
*
c
)
{
ASSERT
(
is
TravData
Valid
(
c
));
ASSERT
(
is
RetainerSet
Valid
(
c
));
return
(
RetainerSet
*
)
getTravData
(
c
);
}
...
...
@@ -355,7 +360,7 @@ retainRoot(void *user, StgClosure **tl)
// be a root.
c
=
UNTAG_CLOSURE
(
*
tl
);
traverseMaybeInitClosureData
(
c
);
traverseMaybeInitClosureData
(
&
g_retainerTraverseState
,
c
);
if
(
c
!=
&
stg_END_TSO_QUEUE_closure
&&
isRetainer
(
c
))
{
traversePushRoot
(
ts
,
c
,
c
,
(
stackData
)
getRetainerFrom
(
c
));
}
else
{
...
...
rts/RetainerProfile.h
View file @
30c01e42
...
...
@@ -20,10 +20,12 @@ void initRetainerProfiling ( void );
void
endRetainerProfiling
(
void
);
void
retainerProfile
(
void
);
bool
isRetainerSetValid
(
const
StgClosure
*
c
);
RetainerSet
*
retainerSetOf
(
const
StgClosure
*
c
);
// Used by GC.c
W_
retainerStackBlocks
(
void
);
extern
traverseState
g_retainerTraverseState
;
#include "EndPrivate.h"
...
...
rts/TraverseHeap.c
View file @
30c01e42
...
...
@@ -16,52 +16,20 @@
#include "TraverseHeap.h"
/** Note [Profiling heap traversal visited bit]
*
* If the RTS is compiled with profiling enabled StgProfHeader can be used by
* profiling code to store per-heap object information. Specifically the
* 'hp_hdr' field is used to store heap profiling information.
*
* The generic heap traversal code reserves the least significant bit of the
* heap profiling word to decide whether we've already visited a given closure
* in the current pass or not. The rest of the field is free to be used by the
* calling profiler.
*
* By doing things this way we implicitly assume that the LSB is not used by the
* user. This is true at least for the word aligned pointers which the retainer
* profiler currently stores there and should be maintained by new users for
* example by shifting the real data up by one bit.
*
* Since we don't want to have to scan the entire heap a second time just to
* reset the per-object visitied bit before/after the real traversal we make the
* interpretation of this bit dependent on the value of a global variable,
* 'flip'.
*
* When the 'trav' bit is equal to the value of 'flip' the closure data is
* valid otherwise not (see isTravDataValid). We then invert the value of 'flip'
* on each heap traversal (see traverseWorkStack), in effect marking all
* closure's data as invalid at once.
*
* There are some complications with this approach, namely: static objects and
* mutable data. There we do just go over all existing objects to reset the bit
* manually. See 'resetStaticObjectForProfiling' and 'resetMutableObjects'.
*/
static
StgWord
flip
=
0
;
StgWord
getTravData
(
const
StgClosure
*
c
)
{
const
StgWord
hp_hdr
=
c
->
header
.
prof
.
hp
.
trav
;
return
hp_hdr
&
(
STG_WORD_MAX
^
1
);
}
void
setTravData
(
StgClosure
*
c
,
StgWord
w
)
void
setTravData
(
const
traverseState
*
ts
,
StgClosure
*
c
,
StgWord
w
)
{
c
->
header
.
prof
.
hp
.
trav
=
w
|
flip
;
c
->
header
.
prof
.
hp
.
trav
=
w
|
ts
->
flip
;
}
bool
isTravDataValid
(
const
StgClosure
*
c
)
bool
isTravDataValid
(
const
traverseState
*
ts
,
const
StgClosure
*
c
)
{
return
(
(
c
->
header
.
prof
.
hp
.
trav
&
1
)
^
flip
)
==
0
;
return
(
c
->
header
.
prof
.
hp
.
trav
&
1
)
==
ts
->
flip
;
}
typedef
enum
{
...
...
@@ -959,10 +927,10 @@ out:
* See Note [Profiling heap traversal visited bit].
*/
bool
traverseMaybeInitClosureData
(
StgClosure
*
c
)
traverseMaybeInitClosureData
(
const
traverseState
*
ts
,
StgClosure
*
c
)
{
if
(
!
isTravDataValid
(
c
))
{
setTravData
(
c
,
0
);
if
(
!
isTravDataValid
(
ts
,
c
))
{
setTravData
(
ts
,
c
,
0
);
return
true
;
}
return
false
;
...
...
@@ -1176,7 +1144,7 @@ traversePAP (traverseState *ts,
}
static
void
resetMutableObjects
(
void
)
resetMutableObjects
(
traverseState
*
ts
)
{
uint32_t
g
,
n
;
bdescr
*
bd
;
...
...
@@ -1195,7 +1163,7 @@ resetMutableObjects(void)
for
(
bd
=
capabilities
[
n
]
->
mut_lists
[
g
];
bd
!=
NULL
;
bd
=
bd
->
link
)
{
for
(
ml
=
bd
->
start
;
ml
<
bd
->
free
;
ml
++
)
{
traverseMaybeInitClosureData
((
StgClosure
*
)
*
ml
);
traverseMaybeInitClosureData
(
ts
,
(
StgClosure
*
)
*
ml
);
}
}
}
...
...
@@ -1219,7 +1187,7 @@ traverseWorkStack(traverseState *ts, visitClosure_cb visit_cb)
bool
other_children
;
// Now we flip the flip bit.
flip
=
flip
^
1
;
ts
->
flip
=
ts
->
flip
^
1
;
// c = Current closure (possibly tagged)
// cp = Current closure's Parent (NOT tagged)
...
...
@@ -1231,7 +1199,7 @@ loop:
if
(
c
==
NULL
)
{
debug
(
"maxStackSize= %d
\n
"
,
ts
->
maxStackSize
);
resetMutableObjects
();
resetMutableObjects
(
ts
);
return
;
}
...
...
@@ -1309,7 +1277,7 @@ inner_loop:
stackAccum
accum
=
{};
// If this is the first visit to c, initialize its data.
bool
first_visit
=
traverseMaybeInitClosureData
(
c
);
bool
first_visit
=
traverseMaybeInitClosureData
(
ts
,
c
);
bool
traverse_children
=
visit_cb
(
c
,
cp
,
data
,
first_visit
,
&
accum
,
&
child_data
);
if
(
!
traverse_children
)
...
...
@@ -1458,7 +1426,7 @@ inner_loop:
* encountering.
*/
void
resetStaticObjectForProfiling
(
StgClosure
*
static_objects
)
resetStaticObjectForProfiling
(
const
traverseState
*
ts
,
StgClosure
*
static_objects
)
{
uint32_t
count
=
0
;
StgClosure
*
p
;
...
...
@@ -1476,7 +1444,7 @@ resetStaticObjectForProfiling( StgClosure *static_objects )
p
=
(
StgClosure
*
)
*
IND_STATIC_LINK
(
p
);
break
;
case
THUNK_STATIC
:
traverseMaybeInitClosureData
(
p
);
traverseMaybeInitClosureData
(
ts
,
p
);
p
=
(
StgClosure
*
)
*
THUNK_STATIC_LINK
(
p
);
break
;
case
FUN_STATIC
:
...
...
@@ -1485,7 +1453,7 @@ resetStaticObjectForProfiling( StgClosure *static_objects )
case
CONSTR_2_0
:
case
CONSTR_1_1
:
case
CONSTR_NOCAF
:
traverseMaybeInitClosureData
(
p
);
traverseMaybeInitClosureData
(
ts
,
p
);
p
=
(
StgClosure
*
)
*
STATIC_LINK
(
get_itbl
(
p
),
p
);
break
;
default:
...
...
rts/TraverseHeap.h
View file @
30c01e42
...
...
@@ -16,7 +16,6 @@
#include "BeginPrivate.h"
void
resetStaticObjectForProfiling
(
StgClosure
*
static_objects
);
typedef
struct
traverseState_
traverseState
;
...
...
@@ -34,6 +33,40 @@ typedef union stackAccum_ {
typedef
struct
stackElement_
stackElement
;
typedef
struct
traverseState_
{
/** Note [Profiling heap traversal visited bit]
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* If the RTS is compiled with profiling enabled StgProfHeader can be used
* by profiling code to store per-heap object information. Specifically the
* 'hp_hdr' field is used to store heap profiling information.
*
* The generic heap traversal code reserves the least significant bit of the
* heap profiling word to decide whether we've already visited a given
* closure in the current pass or not. The rest of the field is free to be
* used by the calling profiler.
*
* By doing things this way we implicitly assume that the LSB is not used by
* the user. This is true at least for the word aligned pointers which the
* retainer profiler currently stores there and should be maintained by new
* users for example by shifting the real data up by one bit.
*
* Since we don't want to have to scan the entire heap a second time just to
* reset the per-object visitied bit before/after the real traversal we make
* the interpretation of this bit dependent on the value of a global
* variable, 'flip' and "flip" this variable when we want to invalidate all
* objects.
*
* When the visited bit is equal to the value of 'flip' the closure data
* is valid otherwise not (see isTravDataValid). We then invert the value of
* 'flip' after each each profiling run (see traverseWorkStack).
*
* There are some complications with this approach, namely: static objects
* and mutable data. There we do just go over all existing objects to reset
* the bit manually. See 'resetStaticObjectForProfiling' and
* 'resetMutableObjects'.
*/
StgWord
flip
;
/**
* Invariants:
*
...
...
@@ -123,18 +156,20 @@ typedef bool (*visitClosure_cb) (
stackData
*
child_data
);
StgWord
getTravData
(
const
StgClosure
*
c
);
void
setTravData
(
StgClosure
*
c
,
StgWord
w
);
bool
isTravDataValid
(
const
StgClosure
*
c
);
void
setTravData
(
const
traverseState
*
ts
,
StgClosure
*
c
,
StgWord
w
);
bool
isTravDataValid
(
const
traverseState
*
ts
,
const
StgClosure
*
c
);
void
traverseWorkStack
(
traverseState
*
ts
,
visitClosure_cb
visit_cb
);
void
traversePushRoot
(
traverseState
*
ts
,
StgClosure
*
c
,
StgClosure
*
cp
,
stackData
data
);
bool
traverseMaybeInitClosureData
(
StgClosure
*
c
);
bool
traverseMaybeInitClosureData
(
const
traverseState
*
ts
,
StgClosure
*
c
);
void
initializeTraverseStack
(
traverseState
*
ts
);
void
closeTraverseStack
(
traverseState
*
ts
);
int
getTraverseStackMaxSize
(
traverseState
*
ts
);
// for GC.c
W_
traverseWorkStackBlocks
(
traverseState
*
ts
);
void
resetStaticObjectForProfiling
(
const
traverseState
*
ts
,
StgClosure
*
static_objects
);
#include "EndPrivate.h"
...
...
rts/sm/GC.c
View file @
30c01e42
...
...
@@ -916,7 +916,7 @@ GarbageCollect (uint32_t collect_gen,
// zeroing below.
// ToDo: fix the gct->scavenged_static_objects below
resetStaticObjectForProfiling
(
gct
->
scavenged_static_objects
);
resetStaticObjectForProfiling
(
&
g_retainerTraverseState
,
gct
->
scavenged_static_objects
);
#endif
// Start any pending finalizers. Must be after
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment