Commit d693117f authored by Igor Sheludko's avatar Igor Sheludko Committed by V8 LUCI CQ

[ext-code-space] Fix two more TSAN issues

1) add relaxed version of Code::main_cage_base accessors and use them
   from in those cases where they can be called from backround thread,
2) pass the main cage base value to IsCode() predicate to avoid
   accessing non-acomic Heap pointer value in page headers from
   background compilation thread.

Drive-by cleanup: use MarkingVerifier::cage_base() instead of
Code::main_cage_base().

Bug: v8:11880, v8:12611
Change-Id: I9fd28c1a3babb862d08fec09f6cfc369beaad231
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3494238Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79313}
parent f41ba08c
...@@ -66,14 +66,14 @@ enum ObjectDataKind { ...@@ -66,14 +66,14 @@ enum ObjectDataKind {
namespace { namespace {
bool IsReadOnlyHeapObjectForCompiler(HeapObject object) { bool IsReadOnlyHeapObjectForCompiler(PtrComprCageBase cage_base,
HeapObject object) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
// TODO(jgruber): Remove this compiler-specific predicate and use the plain // TODO(jgruber): Remove this compiler-specific predicate and use the plain
// heap predicate instead. This would involve removing the special cases for // heap predicate instead. This would involve removing the special cases for
// builtins. // builtins.
return (object.IsCode() && Code::cast(object).is_builtin()) || return (object.IsCode(cage_base) && Code::cast(object).is_builtin()) ||
(object.IsHeapObject() && ReadOnlyHeap::Contains(object);
ReadOnlyHeap::Contains(HeapObject::cast(object)));
} }
} // namespace } // namespace
...@@ -103,17 +103,18 @@ class ObjectData : public ZoneObject { ...@@ -103,17 +103,18 @@ class ObjectData : public ZoneObject {
// handles from read only root table or builtins table which is what // handles from read only root table or builtins table which is what
// canonical scope uses as well. For all other objects we should have // canonical scope uses as well. For all other objects we should have
// created ObjectData in canonical handle scope on the main thread. // created ObjectData in canonical handle scope on the main thread.
CHECK_IMPLIES( Isolate* isolate = broker->isolate();
broker->mode() == JSHeapBroker::kDisabled || CHECK_IMPLIES(broker->mode() == JSHeapBroker::kDisabled ||
broker->mode() == JSHeapBroker::kSerializing, broker->mode() == JSHeapBroker::kSerializing,
broker->isolate()->handle_scope_data()->canonical_scope != nullptr); isolate->handle_scope_data()->canonical_scope != nullptr);
CHECK_IMPLIES(broker->mode() == JSHeapBroker::kSerialized, CHECK_IMPLIES(broker->mode() == JSHeapBroker::kSerialized,
kind == kUnserializedReadOnlyHeapObject || kind == kSmi || kind == kUnserializedReadOnlyHeapObject || kind == kSmi ||
kind == kNeverSerializedHeapObject || kind == kNeverSerializedHeapObject ||
kind == kBackgroundSerializedHeapObject); kind == kBackgroundSerializedHeapObject);
CHECK_IMPLIES(kind == kUnserializedReadOnlyHeapObject, CHECK_IMPLIES(
object->IsHeapObject() && IsReadOnlyHeapObjectForCompiler( kind == kUnserializedReadOnlyHeapObject,
HeapObject::cast(*object))); object->IsHeapObject() && IsReadOnlyHeapObjectForCompiler(
isolate, HeapObject::cast(*object)));
} }
#define DECLARE_IS(Name) bool Is##Name() const; #define DECLARE_IS(Name) bool Is##Name() const;
...@@ -1005,7 +1006,7 @@ ObjectData* JSHeapBroker::TryGetOrCreateData(Handle<Object> object, ...@@ -1005,7 +1006,7 @@ ObjectData* JSHeapBroker::TryGetOrCreateData(Handle<Object> object,
return nullptr; return nullptr;
} }
if (IsReadOnlyHeapObjectForCompiler(HeapObject::cast(*object))) { if (IsReadOnlyHeapObjectForCompiler(isolate(), HeapObject::cast(*object))) {
entry = refs_->LookupOrInsert(object.address()); entry = refs_->LookupOrInsert(object.address());
return zone()->New<ObjectData>(this, &entry->value, object, return zone()->New<ObjectData>(this, &entry->value, object,
kUnserializedReadOnlyHeapObject); kUnserializedReadOnlyHeapObject);
......
...@@ -231,7 +231,7 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal( ...@@ -231,7 +231,7 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
raw_code.clear_padding(); raw_code.clear_padding();
if (V8_EXTERNAL_CODE_SPACE_BOOL) { if (V8_EXTERNAL_CODE_SPACE_BOOL) {
raw_code.set_main_cage_base(isolate_->cage_base()); raw_code.set_main_cage_base(isolate_->cage_base(), kRelaxedStore);
data_container->SetCodeAndEntryPoint(isolate_, raw_code); data_container->SetCodeAndEntryPoint(isolate_, raw_code);
} }
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
......
...@@ -4909,8 +4909,7 @@ class YoungGenerationMarkingVerifier : public MarkingVerifier { ...@@ -4909,8 +4909,7 @@ class YoungGenerationMarkingVerifier : public MarkingVerifier {
VerifyHeapObjectImpl(target); VerifyHeapObjectImpl(target);
} }
void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) override { void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) override {
PtrComprCageBase cage_base = host.main_cage_base(); VerifyHeapObjectImpl(rinfo->target_object(cage_base()));
VerifyHeapObjectImpl(rinfo->target_object(cage_base));
} }
void VerifyRootPointers(FullObjectSlot start, FullObjectSlot end) override { void VerifyRootPointers(FullObjectSlot start, FullObjectSlot end) override {
VerifyPointersImpl(start, end); VerifyPointersImpl(start, end);
......
...@@ -171,11 +171,11 @@ INT32_ACCESSORS(Code, unwinding_info_offset, kUnwindingInfoOffsetOffset) ...@@ -171,11 +171,11 @@ INT32_ACCESSORS(Code, unwinding_info_offset, kUnwindingInfoOffsetOffset)
} }
// Same as RELEASE_ACQUIRE_ACCESSORS_CHECKED2 macro but with Code as a host and // Same as RELEASE_ACQUIRE_ACCESSORS_CHECKED2 macro but with Code as a host and
// using main_cage_base() for computing the base. // using main_cage_base(kRelaxedLoad) for computing the base.
#define RELEASE_ACQUIRE_CODE_ACCESSORS_CHECKED2(name, type, offset, \ #define RELEASE_ACQUIRE_CODE_ACCESSORS_CHECKED2(name, type, offset, \
get_condition, set_condition) \ get_condition, set_condition) \
type Code::name(AcquireLoadTag tag) const { \ type Code::name(AcquireLoadTag tag) const { \
PtrComprCageBase cage_base = main_cage_base(); \ PtrComprCageBase cage_base = main_cage_base(kRelaxedLoad); \
return Code::name(cage_base, tag); \ return Code::name(cage_base, tag); \
} \ } \
type Code::name(PtrComprCageBase cage_base, AcquireLoadTag) const { \ type Code::name(PtrComprCageBase cage_base, AcquireLoadTag) const { \
...@@ -236,17 +236,27 @@ PtrComprCageBase Code::main_cage_base() const { ...@@ -236,17 +236,27 @@ PtrComprCageBase Code::main_cage_base() const {
#endif #endif
} }
void Code::set_main_cage_base(Address cage_base) { PtrComprCageBase Code::main_cage_base(RelaxedLoadTag) const {
#ifdef V8_EXTERNAL_CODE_SPACE
Address cage_base_hi =
Relaxed_ReadField<Tagged_t>(kMainCageBaseUpper32BitsOffset);
return PtrComprCageBase(cage_base_hi << 32);
#else
return GetPtrComprCageBase(*this);
#endif
}
void Code::set_main_cage_base(Address cage_base, RelaxedStoreTag) {
#ifdef V8_EXTERNAL_CODE_SPACE #ifdef V8_EXTERNAL_CODE_SPACE
Tagged_t cage_base_hi = static_cast<Tagged_t>(cage_base >> 32); Tagged_t cage_base_hi = static_cast<Tagged_t>(cage_base >> 32);
WriteField<Tagged_t>(kMainCageBaseUpper32BitsOffset, cage_base_hi); Relaxed_WriteField<Tagged_t>(kMainCageBaseUpper32BitsOffset, cage_base_hi);
#else #else
UNREACHABLE(); UNREACHABLE();
#endif #endif
} }
CodeDataContainer Code::GCSafeCodeDataContainer(AcquireLoadTag) const { CodeDataContainer Code::GCSafeCodeDataContainer(AcquireLoadTag) const {
PtrComprCageBase cage_base = main_cage_base(); PtrComprCageBase cage_base = main_cage_base(kRelaxedLoad);
HeapObject object = HeapObject object =
TaggedField<HeapObject, kCodeDataContainerOffset>::Acquire_Load(cage_base, TaggedField<HeapObject, kCodeDataContainerOffset>::Acquire_Load(cage_base,
*this); *this);
...@@ -318,7 +328,7 @@ void Code::WipeOutHeader() { ...@@ -318,7 +328,7 @@ void Code::WipeOutHeader() {
WRITE_FIELD(*this, kPositionTableOffset, Smi::FromInt(0)); WRITE_FIELD(*this, kPositionTableOffset, Smi::FromInt(0));
WRITE_FIELD(*this, kCodeDataContainerOffset, Smi::FromInt(0)); WRITE_FIELD(*this, kCodeDataContainerOffset, Smi::FromInt(0));
if (V8_EXTERNAL_CODE_SPACE_BOOL) { if (V8_EXTERNAL_CODE_SPACE_BOOL) {
set_main_cage_base(kNullAddress); set_main_cage_base(kNullAddress, kRelaxedStore);
} }
} }
......
...@@ -508,7 +508,8 @@ class Code : public HeapObject { ...@@ -508,7 +508,8 @@ class Code : public HeapObject {
// This field contains cage base value which is used for decompressing // This field contains cage base value which is used for decompressing
// the references to non-Code objects (map, deoptimization_data, etc.). // the references to non-Code objects (map, deoptimization_data, etc.).
inline PtrComprCageBase main_cage_base() const; inline PtrComprCageBase main_cage_base() const;
inline void set_main_cage_base(Address cage_base); inline PtrComprCageBase main_cage_base(RelaxedLoadTag) const;
inline void set_main_cage_base(Address cage_base, RelaxedStoreTag);
// Clear uninitialized padding space. This ensures that the snapshot content // Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic. Depending on the V8 build mode there could be no padding. // is deterministic. Depending on the V8 build mode there could be no padding.
......
...@@ -1140,7 +1140,7 @@ int Deserializer<IsolateT>::ReadSingleBytecodeData(byte data, ...@@ -1140,7 +1140,7 @@ int Deserializer<IsolateT>::ReadSingleBytecodeData(byte data,
Code code = Code::cast(*slot_accessor.object()); Code code = Code::cast(*slot_accessor.object());
if (V8_EXTERNAL_CODE_SPACE_BOOL) { if (V8_EXTERNAL_CODE_SPACE_BOOL) {
code.set_main_cage_base(isolate()->cage_base()); code.set_main_cage_base(isolate()->cage_base(), kRelaxedStore);
} }
DeserializerRelocInfoVisitor visitor(this, &preserialized_objects); DeserializerRelocInfoVisitor visitor(this, &preserialized_objects);
for (RelocIterator it(code, Code::BodyDescriptor::kRelocModeMask); for (RelocIterator it(code, Code::BodyDescriptor::kRelocModeMask);
......
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