Skip to content

Commit 31f2a4b

Browse files
d-nettokpamnany
authored andcommitted
correctly track element pointer in heap snapshot (#90)
Backports JuliaLang#51592.
1 parent 41e06e4 commit 31f2a4b

File tree

1 file changed

+42
-10
lines changed

1 file changed

+42
-10
lines changed

src/gc.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,7 +2061,8 @@ STATIC_INLINE void gc_mark_objarray(jl_ptls_t ptls, jl_value_t *obj_parent, jl_v
20612061
// the first young object before starting this chunk
20622062
// (this also would be valid for young objects, but probably less beneficial)
20632063
for (; obj_begin < obj_end; obj_begin += step) {
2064-
new_obj = *obj_begin;
2064+
jl_value_t **slot = obj_begin;
2065+
new_obj = *slot;
20652066
if (new_obj != NULL) {
20662067
verify_parent2("obj array", obj_parent, obj_begin, "elem(%d)",
20672068
gc_slot_to_arrayidx(obj_parent, obj_begin));
@@ -2070,7 +2071,7 @@ STATIC_INLINE void gc_mark_objarray(jl_ptls_t ptls, jl_value_t *obj_parent, jl_v
20702071
nptr |= 1;
20712072
if (!gc_marked(o->header))
20722073
break;
2073-
gc_heap_snapshot_record_array_edge(obj_parent, &new_obj);
2074+
gc_heap_snapshot_record_array_edge(obj_parent, slot);
20742075
}
20752076
}
20762077
}
@@ -2092,12 +2093,13 @@ STATIC_INLINE void gc_mark_objarray(jl_ptls_t ptls, jl_value_t *obj_parent, jl_v
20922093
}
20932094
}
20942095
for (; obj_begin < scan_end; obj_begin += step) {
2096+
jl_value_t **slot = obj_begin;
20952097
new_obj = *obj_begin;
20962098
if (new_obj != NULL) {
20972099
verify_parent2("obj array", obj_parent, obj_begin, "elem(%d)",
20982100
gc_slot_to_arrayidx(obj_parent, obj_begin));
20992101
gc_try_claim_and_push(mq, new_obj, &nptr);
2100-
gc_heap_snapshot_record_array_edge(obj_parent, &new_obj);
2102+
gc_heap_snapshot_record_array_edge(obj_parent, slot);
21012103
}
21022104
}
21032105
if (too_big) {
@@ -2128,7 +2130,8 @@ STATIC_INLINE void gc_mark_array8(jl_ptls_t ptls, jl_value_t *ary8_parent, jl_va
21282130
for (; ary8_begin < ary8_end; ary8_begin += elsize) {
21292131
int early_end = 0;
21302132
for (uint8_t *pindex = elem_begin; pindex < elem_end; pindex++) {
2131-
new_obj = ary8_begin[*pindex];
2133+
jl_value_t **slot = &ary8_begin[*pindex];
2134+
new_obj = *slot;
21322135
if (new_obj != NULL) {
21332136
verify_parent2("array", ary8_parent, &new_obj, "elem(%d)",
21342137
gc_slot_to_arrayidx(ary8_parent, ary8_begin));
@@ -2139,7 +2142,7 @@ STATIC_INLINE void gc_mark_array8(jl_ptls_t ptls, jl_value_t *ary8_parent, jl_va
21392142
early_end = 1;
21402143
break;
21412144
}
2142-
gc_heap_snapshot_record_array_edge(ary8_parent, &new_obj);
2145+
gc_heap_snapshot_record_array_edge(ary8_parent, slot);
21432146
}
21442147
}
21452148
if (early_end)
@@ -2165,12 +2168,13 @@ STATIC_INLINE void gc_mark_array8(jl_ptls_t ptls, jl_value_t *ary8_parent, jl_va
21652168
}
21662169
for (; ary8_begin < ary8_end; ary8_begin += elsize) {
21672170
for (uint8_t *pindex = elem_begin; pindex < elem_end; pindex++) {
2168-
new_obj = ary8_begin[*pindex];
2171+
jl_value_t **slot = &ary8_begin[*pindex];
2172+
new_obj = *slot;
21692173
if (new_obj != NULL) {
21702174
verify_parent2("array", ary8_parent, &new_obj, "elem(%d)",
21712175
gc_slot_to_arrayidx(ary8_parent, ary8_begin));
21722176
gc_try_claim_and_push(mq, new_obj, &nptr);
2173-
gc_heap_snapshot_record_array_edge(ary8_parent, &new_obj);
2177+
gc_heap_snapshot_record_array_edge(ary8_parent, slot);
21742178
}
21752179
}
21762180
}
@@ -2193,7 +2197,34 @@ STATIC_INLINE void gc_mark_array16(jl_ptls_t ptls, jl_value_t *ary16_parent, jl_
21932197
jl_gc_markqueue_t *mq = &ptls->mark_queue;
21942198
jl_value_t *new_obj;
21952199
size_t elsize = ((jl_array_t *)ary16_parent)->elsize / sizeof(jl_value_t *);
2196-
// Decide whether need to chunk ary16
2200+
assert(elsize > 0);
2201+
// Decide whether need to chunk objary
2202+
if ((nptr & 0x2) == 0x2) {
2203+
// pre-scan this object: most of this object should be old, so look for
2204+
// the first young object before starting this chunk
2205+
// (this also would be valid for young objects, but probably less beneficial)
2206+
for (; ary16_begin < ary16_end; ary16_begin += elsize) {
2207+
int early_end = 0;
2208+
for (uint16_t *pindex = elem_begin; pindex < elem_end; pindex++) {
2209+
jl_value_t **slot = &ary16_begin[*pindex];
2210+
new_obj = *slot;
2211+
if (new_obj != NULL) {
2212+
verify_parent2("array", ary16_parent, &new_obj, "elem(%d)",
2213+
gc_slot_to_arrayidx(ary16_parent, ary16_begin));
2214+
jl_taggedvalue_t *o = jl_astaggedvalue(new_obj);
2215+
if (!gc_old(o->header))
2216+
nptr |= 1;
2217+
if (!gc_marked(o->header)){
2218+
early_end = 1;
2219+
break;
2220+
}
2221+
gc_heap_snapshot_record_array_edge(ary16_parent, slot);
2222+
}
2223+
}
2224+
if (early_end)
2225+
break;
2226+
}
2227+
}
21972228
size_t too_big = (ary16_end - ary16_begin) / GC_CHUNK_BATCH_SIZE > elsize; // use this order of operations to avoid idiv
21982229
jl_value_t **scan_end = ary16_end;
21992230
int pushed_chunk = 0;
@@ -2213,12 +2244,13 @@ STATIC_INLINE void gc_mark_array16(jl_ptls_t ptls, jl_value_t *ary16_parent, jl_
22132244
}
22142245
for (; ary16_begin < scan_end; ary16_begin += elsize) {
22152246
for (uint16_t *pindex = elem_begin; pindex < elem_end; pindex++) {
2216-
new_obj = ary16_begin[*pindex];
2247+
jl_value_t **slot = &ary16_begin[*pindex];
2248+
new_obj = *slot;
22172249
if (new_obj != NULL) {
22182250
verify_parent2("array", ary16_parent, &new_obj, "elem(%d)",
22192251
gc_slot_to_arrayidx(ary16_parent, ary16_begin));
22202252
gc_try_claim_and_push(mq, new_obj, &nptr);
2221-
gc_heap_snapshot_record_array_edge(ary16_parent, &new_obj);
2253+
gc_heap_snapshot_record_array_edge(ary16_parent, slot);
22222254
}
22232255
}
22242256
}

0 commit comments

Comments
 (0)