Commit 317462be authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[compiler] Make BigInts bg-serialized

BigInts are immutable after initialization, thus an acquire-release
synchronization point is sufficient to read safely from the background
thread. This CL introduces the `length` field as that sync point.

Bug: v8:7790
Change-Id: I977f30836b311c3851896dd29e708f78a090f547
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2854745
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74245}
parent bbe0c56a
......@@ -1098,14 +1098,17 @@ class AllocationSiteData : public HeapObjectData {
class BigIntData : public HeapObjectData {
public:
BigIntData(JSHeapBroker* broker, ObjectData** storage, Handle<BigInt> object,
ObjectDataKind kind = ObjectDataKind::kSerializedHeapObject)
: HeapObjectData(broker, storage, object, kind),
as_uint64_(object->AsUint64(nullptr)) {}
ObjectDataKind kind)
: HeapObjectData(broker, storage, object, kind) {
// Read length first as an artificial synchronization point.
object->synchronized_length();
as_uint64_ = object->AsUint64(nullptr);
}
uint64_t AsUint64() const { return as_uint64_; }
private:
const uint64_t as_uint64_;
uint64_t as_uint64_;
};
// Only used in JSNativeContextSpecialization.
......
......@@ -110,7 +110,7 @@ enum class RefSerializationKind {
V(AccessorInfo, RefSerializationKind::kNeverSerialized) \
V(AllocationSite, RefSerializationKind::kSerialized) \
V(ArrayBoilerplateDescription, RefSerializationKind::kNeverSerialized) \
V(BigInt, RefSerializationKind::kPossiblyBackgroundSerialized) \
V(BigInt, RefSerializationKind::kBackgroundSerialized) \
V(CallHandlerInfo, RefSerializationKind::kNeverSerialized) \
V(Cell, RefSerializationKind::kNeverSerialized) \
V(Code, RefSerializationKind::kNeverSerialized) \
......
......@@ -418,7 +418,6 @@ void MutableBigInt::Canonicalize(MutableBigInt result) {
// of the object changed significantly.
heap->CreateFillerObjectAt(new_end, size_delta, ClearRecordedSlots::kNo);
}
result.synchronized_set_length(new_length);
// Canonicalize -0n.
if (new_length == 0) {
......@@ -426,6 +425,11 @@ void MutableBigInt::Canonicalize(MutableBigInt result) {
// TODO(jkummerow): If we cache a canonical 0n, return that here.
}
}
// This is the synchronization point which safely allows concurrent reads of
// BigInt instances. It *must* be reached on every path that results in a
// published BigInt. No writes to the BigInt instance are allowed after this
// point.
result.synchronized_set_length(new_length);
DCHECK_IMPLIES(result.length() > 0,
result.digit(result.length() - 1) != 0); // MSD is non-zero.
}
......
......@@ -32,12 +32,17 @@ class ValueSerializer;
// Most code should be using BigInts instead.
class BigIntBase : public PrimitiveHeapObject {
public:
// The `length` field (or rather its underlying storage location) is the
// synchronization point that allows concurrent interactions with BigInt
// instances. The invariants are:
// - Instances are immutable after initialization, see MakeImmutable.
// - The last write to an instance is a release-store of `length`.
inline int length() const {
int32_t bitfield = RELAXED_READ_INT32_FIELD(*this, kBitfieldOffset);
return LengthBits::decode(static_cast<uint32_t>(bitfield));
}
// For use by the GC.
// For use by the GC and Turbofan.
inline int synchronized_length() const {
int32_t bitfield = ACQUIRE_READ_INT32_FIELD(*this, kBitfieldOffset);
return LengthBits::decode(static_cast<uint32_t>(bitfield));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment