// the garbage collector could follow a pointer to x,
// but see uninitialized memory or stale heap bits.
publicationBarrier()
- // As x and the heap bits are initialized, update
- // freeIndexForScan now so x is seen by the GC
- // (including conservative scan) as an allocated object.
- // While this pointer can't escape into user code as a
- // _live_ pointer until we return, conservative scanning
- // may find a dead pointer that happens to point into this
- // object. Delaying this update until now ensures that
- // conservative scanning considers this pointer dead until
- // this point.
- span.freeIndexForScan = span.freeindex
-
- // Allocate black during GC.
- // All slots hold nil so no scanning is needed.
- // This may be racing with GC so do it atomically if there can be
- // a race marking the bit.
+
if writeBarrier.enabled {
+ // Allocate black during GC.
+ // All slots hold nil so no scanning is needed.
+ // This may be racing with GC so do it atomically if there can be
+ // a race marking the bit.
gcmarknewobject(span, uintptr(x))
+ } else {
+ // Track the last free index before the mark phase. This field
+ // is only used by the garbage collector. During the mark phase
+ // this is used by the conservative scanner to filter out objects
+ // that are both free and recently-allocated. It's safe to do that
+ // because we allocate-black if the GC is enabled. The conservative
+ // scanner produces pointers out of thin air, so without additional
+ // synchronization it might otherwise observe a partially-initialized
+ // object, which could crash the program.
+ span.freeIndexForScan = span.freeindex
}
// Note cache c only valid while m acquired; see #47302
// the garbage collector could follow a pointer to x,
// but see uninitialized memory or stale heap bits.
publicationBarrier()
- // As x and the heap bits are initialized, update
- // freeIndexForScan now so x is seen by the GC
- // (including conservative scan) as an allocated object.
- // While this pointer can't escape into user code as a
- // _live_ pointer until we return, conservative scanning
- // may find a dead pointer that happens to point into this
- // object. Delaying this update until now ensures that
- // conservative scanning considers this pointer dead until
- // this point.
- span.freeIndexForScan = span.freeindex
-
- // Allocate black during GC.
- // All slots hold nil so no scanning is needed.
- // This may be racing with GC so do it atomically if there can be
- // a race marking the bit.
+
if writeBarrier.enabled {
+ // Allocate black during GC.
+ // All slots hold nil so no scanning is needed.
+ // This may be racing with GC so do it atomically if there can be
+ // a race marking the bit.
gcmarknewobject(span, uintptr(x))
+ } else {
+ // Track the last free index before the mark phase. This field
+ // is only used by the garbage collector. During the mark phase
+ // this is used by the conservative scanner to filter out objects
+ // that are both free and recently-allocated. It's safe to do that
+ // because we allocate-black if the GC is enabled. The conservative
+ // scanner produces pointers out of thin air, so without additional
+ // synchronization it might otherwise observe a partially-initialized
+ // object, which could crash the program.
+ span.freeIndexForScan = span.freeindex
}
// Note cache c only valid while m acquired; see #47302
// the garbage collector could follow a pointer to x,
// but see uninitialized memory or stale heap bits.
publicationBarrier()
- // As x and the heap bits are initialized, update
- // freeIndexForScan now so x is seen by the GC
- // (including conservative scan) as an allocated object.
- // While this pointer can't escape into user code as a
- // _live_ pointer until we return, conservative scanning
- // may find a dead pointer that happens to point into this
- // object. Delaying this update until now ensures that
- // conservative scanning considers this pointer dead until
- // this point.
- span.freeIndexForScan = span.freeindex
-
- // Allocate black during GC.
- // All slots hold nil so no scanning is needed.
- // This may be racing with GC so do it atomically if there can be
- // a race marking the bit.
+
if writeBarrier.enabled {
+ // Allocate black during GC.
+ // All slots hold nil so no scanning is needed.
+ // This may be racing with GC so do it atomically if there can be
+ // a race marking the bit.
gcmarknewobject(span, uintptr(x))
+ } else {
+ // Track the last free index before the mark phase. This field
+ // is only used by the garbage collector. During the mark phase
+ // this is used by the conservative scanner to filter out objects
+ // that are both free and recently-allocated. It's safe to do that
+ // because we allocate-black if the GC is enabled. The conservative
+ // scanner produces pointers out of thin air, so without additional
+ // synchronization it might otherwise observe a partially-initialized
+ // object, which could crash the program.
+ span.freeIndexForScan = span.freeindex
}
// Note cache c only valid while m acquired; see #47302
// the garbage collector could follow a pointer to x,
// but see uninitialized memory or stale heap bits.
publicationBarrier()
- // As x and the heap bits are initialized, update
- // freeIndexForScan now so x is seen by the GC
- // (including conservative scan) as an allocated object.
- // While this pointer can't escape into user code as a
- // _live_ pointer until we return, conservative scanning
- // may find a dead pointer that happens to point into this
- // object. Delaying this update until now ensures that
- // conservative scanning considers this pointer dead until
- // this point.
- span.freeIndexForScan = span.freeindex
-
- // Allocate black during GC.
- // All slots hold nil so no scanning is needed.
- // This may be racing with GC so do it atomically if there can be
- // a race marking the bit.
+
if writeBarrier.enabled {
+ // Allocate black during GC.
+ // All slots hold nil so no scanning is needed.
+ // This may be racing with GC so do it atomically if there can be
+ // a race marking the bit.
gcmarknewobject(span, uintptr(x))
+ } else {
+ // Track the last free index before the mark phase. This field
+ // is only used by the garbage collector. During the mark phase
+ // this is used by the conservative scanner to filter out objects
+ // that are both free and recently-allocated. It's safe to do that
+ // because we allocate-black if the GC is enabled. The conservative
+ // scanner produces pointers out of thin air, so without additional
+ // synchronization it might otherwise observe a partially-initialized
+ // object, which could crash the program.
+ span.freeIndexForScan = span.freeindex
}
// Note cache c only valid while m acquired; see #47302
// the garbage collector could follow a pointer to x,
// but see uninitialized memory or stale heap bits.
publicationBarrier()
- // As x and the heap bits are initialized, update
- // freeIndexForScan now so x is seen by the GC
- // (including conservative scan) as an allocated object.
- // While this pointer can't escape into user code as a
- // _live_ pointer until we return, conservative scanning
- // may find a dead pointer that happens to point into this
- // object. Delaying this update until now ensures that
- // conservative scanning considers this pointer dead until
- // this point.
- span.freeIndexForScan = span.freeindex
-
- // Allocate black during GC.
- // All slots hold nil so no scanning is needed.
- // This may be racing with GC so do it atomically if there can be
- // a race marking the bit.
+
if writeBarrier.enabled {
+ // Allocate black during GC.
+ // All slots hold nil so no scanning is needed.
+ // This may be racing with GC so do it atomically if there can be
+ // a race marking the bit.
gcmarknewobject(span, uintptr(x))
+ } else {
+ // Track the last free index before the mark phase. This field
+ // is only used by the garbage collector. During the mark phase
+ // this is used by the conservative scanner to filter out objects
+ // that are both free and recently-allocated. It's safe to do that
+ // because we allocate-black if the GC is enabled. The conservative
+ // scanner produces pointers out of thin air, so without additional
+ // synchronization it might otherwise observe a partially-initialized
+ // object, which could crash the program.
+ span.freeIndexForScan = span.freeindex
}
// Note cache c only valid while m acquired; see #47302