diff --git a/common.gypi b/common.gypi index 23ac7205baa36b..11b5d3b7aeb11d 100644 --- a/common.gypi +++ b/common.gypi @@ -37,7 +37,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.13', + 'v8_embedder_string': '-node.16', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/include/v8-internal.h b/deps/v8/include/v8-internal.h index 5cc62f3e726f7c..8e700a4d4d401b 100644 --- a/deps/v8/include/v8-internal.h +++ b/deps/v8/include/v8-internal.h @@ -7,6 +7,7 @@ #include #include +#include #include #include "v8-version.h" // NOLINT(build/include) @@ -164,7 +165,6 @@ class Internals { static const int kNodeStateMask = 0x7; static const int kNodeStateIsWeakValue = 2; static const int kNodeStateIsPendingValue = 3; - static const int kNodeStateIsNearDeathValue = 4; static const int kNodeIsIndependentShift = 3; static const int kNodeIsActiveShift = 4; @@ -275,6 +275,17 @@ class Internals { V8_INLINE static T ReadRawField(internal::Address heap_object_ptr, int offset) { internal::Address addr = heap_object_ptr + offset - kHeapObjectTag; +#ifdef V8_COMPRESS_POINTERS + if (sizeof(T) > kApiTaggedSize) { + // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size + // fields (external pointers, doubles and BigInt data) are only + // kTaggedSize aligned so we have to use unaligned pointer friendly way of + // accessing them in order to avoid undefined behavior in C++ code. + T r; + memcpy(&r, reinterpret_cast(addr), sizeof(T)); + return r; + } +#endif return *reinterpret_cast(addr); } diff --git a/deps/v8/include/v8-util.h b/deps/v8/include/v8-util.h index 466b99fd6b717e..24962607076f78 100644 --- a/deps/v8/include/v8-util.h +++ b/deps/v8/include/v8-util.h @@ -198,7 +198,7 @@ class PersistentValueMapBase { * Call V8::RegisterExternallyReferencedObject with the map value for given * key. */ - V8_DEPRECATE_SOON( + V8_DEPRECATED( "Used TracedGlobal and EmbedderHeapTracer::RegisterEmbedderReference", inline void RegisterExternallyReferencedObject(K& key)); diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 5635bd21b10693..7e48cd422db289 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -118,6 +118,7 @@ class Arguments; class DeferredHandles; class Heap; class HeapObject; +class ExternalString; class Isolate; class LocalEmbedderHeapTracer; class MicrotaskQueue; @@ -549,7 +550,7 @@ template class PersistentBase { * is alive. Only allowed when the embedder is asked to trace its heap by * EmbedderHeapTracer. */ - V8_DEPRECATE_SOON( + V8_DEPRECATED( "Used TracedGlobal and EmbedderHeapTracer::RegisterEmbedderReference", V8_INLINE void RegisterExternalReference(Isolate* isolate) const); @@ -572,14 +573,10 @@ template class PersistentBase { * * This bit is cleared after the each garbage collection pass. */ - V8_DEPRECATE_SOON("Use TracedGlobal.", V8_INLINE void MarkActive()); + V8_DEPRECATED("Use TracedGlobal.", V8_INLINE void MarkActive()); V8_DEPRECATED("See MarkIndependent.", V8_INLINE bool IsIndependent() const); - /** Checks if the handle holds the only reference to an object. */ - V8_DEPRECATED("Garbage collection internal state should not be relied on.", - V8_INLINE bool IsNearDeath() const); - /** Returns true if the handle's reference is weak. */ V8_INLINE bool IsWeak() const; @@ -2801,7 +2798,7 @@ class V8_EXPORT String : public Name { void operator=(const ExternalStringResourceBase&) = delete; private: - friend class internal::Heap; + friend class internal::ExternalString; friend class v8::String; friend class internal::ScopedExternalStringLock; }; @@ -8519,17 +8516,6 @@ class V8_EXPORT Isolate { */ void VisitHandlesWithClassIds(PersistentHandleVisitor* visitor); - /** - * Iterates through all the persistent handles in the current isolate's heap - * that have class_ids and are candidates to be marked as partially dependent - * handles. This will visit handles to young objects created since the last - * garbage collection but is free to visit an arbitrary superset of these - * objects. - */ - V8_DEPRECATED( - "Use VisitHandlesWithClassIds", - void VisitHandlesForPartialDependence(PersistentHandleVisitor* visitor)); - /** * Iterates through all the persistent handles in the current isolate's heap * that have class_ids and are weak to be marked as inactive if there is no @@ -9783,17 +9769,6 @@ bool PersistentBase::IsIndependent() const { I::kNodeIsIndependentShift); } -template -bool PersistentBase::IsNearDeath() const { - typedef internal::Internals I; - if (this->IsEmpty()) return false; - uint8_t node_state = - I::GetNodeState(reinterpret_cast(this->val_)); - return node_state == I::kNodeStateIsNearDeathValue || - node_state == I::kNodeStateIsPendingValue; -} - - template bool PersistentBase::IsWeak() const { typedef internal::Internals I; diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 360bb7840757e6..eae3fd27921d45 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -8876,15 +8876,6 @@ void Isolate::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) { isolate->global_handles()->IterateAllRootsWithClassIds(visitor); } - -void Isolate::VisitHandlesForPartialDependence( - PersistentHandleVisitor* visitor) { - i::Isolate* isolate = reinterpret_cast(this); - i::DisallowHeapAllocation no_allocation; - isolate->global_handles()->IterateAllYoungRootsWithClassIds(visitor); -} - - void Isolate::VisitWeakHandles(PersistentHandleVisitor* visitor) { i::Isolate* isolate = reinterpret_cast(this); i::DisallowHeapAllocation no_allocation; diff --git a/deps/v8/src/global-handles.cc b/deps/v8/src/global-handles.cc index 5eb3d93f142ea4..350380b23ce6f4 100644 --- a/deps/v8/src/global-handles.cc +++ b/deps/v8/src/global-handles.cc @@ -379,7 +379,6 @@ class GlobalHandles::Node final : public NodeBase { Internals::kNodeStateMask); STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue); STATIC_ASSERT(PENDING == Internals::kNodeStateIsPendingValue); - STATIC_ASSERT(NEAR_DEATH == Internals::kNodeStateIsNearDeathValue); STATIC_ASSERT(static_cast(IsIndependent::kShift) == Internals::kNodeIsIndependentShift); STATIC_ASSERT(static_cast(IsActive::kShift) == @@ -427,11 +426,6 @@ class GlobalHandles::Node final : public NodeBase { flags_ = NodeWeaknessType::update(flags_, weakness_type); } - bool IsNearDeath() const { - // Check for PENDING to ensure correct answer when processing callbacks. - return state() == PENDING || state() == NEAR_DEATH; - } - bool IsWeak() const { return state() == WEAK; } bool IsInUse() const { return state() != FREE; } @@ -819,10 +813,6 @@ void GlobalHandles::AnnotateStrongRetainer(Address* location, Node::FromLocation(location)->AnnotateStrongRetainer(label); } -bool GlobalHandles::IsNearDeath(Address* location) { - return Node::FromLocation(location)->IsNearDeath(); -} - bool GlobalHandles::IsWeak(Address* location) { return Node::FromLocation(location)->IsWeak(); } diff --git a/deps/v8/src/global-handles.h b/deps/v8/src/global-handles.h index 3604af1d28e5a8..8caa3c33ce7226 100644 --- a/deps/v8/src/global-handles.h +++ b/deps/v8/src/global-handles.h @@ -73,9 +73,6 @@ class GlobalHandles final { // Clear the weakness of a global handle. static void* ClearWeakness(Address* location); - // Tells whether global handle is near death. - static bool IsNearDeath(Address* location); - // Tells whether global handle is weak. static bool IsWeak(Address* location); diff --git a/deps/v8/src/heap/heap-inl.h b/deps/v8/src/heap/heap-inl.h index b143a33af5d8b1..26717e2ba13b9c 100644 --- a/deps/v8/src/heap/heap-inl.h +++ b/deps/v8/src/heap/heap-inl.h @@ -300,15 +300,7 @@ void Heap::FinalizeExternalString(String string) { ExternalBackingStoreType::kExternalString, ext_string->ExternalPayloadSize()); - v8::String::ExternalStringResourceBase** resource_addr = - reinterpret_cast( - string->address() + ExternalString::kResourceOffset); - - // Dispose of the C++ object if it has not already been disposed. - if (*resource_addr != nullptr) { - (*resource_addr)->Dispose(); - *resource_addr = nullptr; - } + ext_string->DisposeResource(); } Address Heap::NewSpaceTop() { return new_space_->top(); } diff --git a/deps/v8/src/objects/bigint.cc b/deps/v8/src/objects/bigint.cc index fb69d5847a4dcb..7c886a7b1d5799 100644 --- a/deps/v8/src/objects/bigint.cc +++ b/deps/v8/src/objects/bigint.cc @@ -205,8 +205,7 @@ class MutableBigInt : public FreshlyAllocatedBigInt { } inline void set_digit(int n, digit_t value) { SLOW_DCHECK(0 <= n && n < length()); - Address address = FIELD_ADDR(*this, kDigitsOffset + n * kDigitSize); - (*reinterpret_cast(address)) = value; + WRITE_UINTPTR_FIELD(*this, kDigitsOffset + n * kDigitSize, value); } void set_64_bits(uint64_t bits); diff --git a/deps/v8/src/objects/bigint.h b/deps/v8/src/objects/bigint.h index ae1ffe6866136a..4ddb57a5b22b19 100644 --- a/deps/v8/src/objects/bigint.h +++ b/deps/v8/src/objects/bigint.h @@ -87,8 +87,7 @@ class BigIntBase : public HeapObject { inline digit_t digit(int n) const { SLOW_DCHECK(0 <= n && n < length()); - Address address = FIELD_ADDR(*this, kDigitsOffset + n * kDigitSize); - return *reinterpret_cast(address); + return READ_UINTPTR_FIELD(*this, kDigitsOffset + n * kDigitSize); } bool is_zero() const { return length() == 0; } diff --git a/deps/v8/src/objects/embedder-data-slot-inl.h b/deps/v8/src/objects/embedder-data-slot-inl.h index 7762479cf9ce44..b87f31ac7d303d 100644 --- a/deps/v8/src/objects/embedder-data-slot-inl.h +++ b/deps/v8/src/objects/embedder-data-slot-inl.h @@ -11,6 +11,7 @@ #include "src/objects-inl.h" #include "src/objects/embedder-data-array.h" #include "src/objects/js-objects-inl.h" +#include "src/v8memory.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -71,7 +72,15 @@ bool EmbedderDataSlot::ToAlignedPointer(void** out_pointer) const { // are accessed this way only from the main thread via API during "mutator" // phase which is propely synched with GC (concurrent marker may still look // at the tagged part of the embedder slot but read-only access is ok). +#ifdef V8_COMPRESS_POINTERS + // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size + // fields (external pointers, doubles and BigInt data) are only kTaggedSize + // aligned so we have to use unaligned pointer friendly way of accessing them + // in order to avoid undefined behavior in C++ code. + Address raw_value = ReadUnalignedValue
(address()); +#else Address raw_value = *location(); +#endif *out_pointer = reinterpret_cast(raw_value); return HAS_SMI_TAG(raw_value); } @@ -89,7 +98,15 @@ EmbedderDataSlot::RawData EmbedderDataSlot::load_raw( // are accessed this way only by serializer from the main thread when // GC is not active (concurrent marker may still look at the tagged part // of the embedder slot but read-only access is ok). +#ifdef V8_COMPRESS_POINTERS + // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size + // fields (external pointers, doubles and BigInt data) are only kTaggedSize + // aligned so we have to use unaligned pointer friendly way of accessing them + // in order to avoid undefined behavior in C++ code. + return ReadUnalignedValue
(address()); +#else return *location(); +#endif } void EmbedderDataSlot::store_raw(EmbedderDataSlot::RawData data, diff --git a/deps/v8/src/objects/fixed-array-inl.h b/deps/v8/src/objects/fixed-array-inl.h index dfb34102ddf20b..9aa65a8de6be6c 100644 --- a/deps/v8/src/objects/fixed-array-inl.h +++ b/deps/v8/src/objects/fixed-array-inl.h @@ -653,7 +653,17 @@ typename Traits::ElementType FixedTypedArray::get_scalar_from_data_ptr( // JavaScript memory model to have tear-free reads of overlapping accesses, // and using relaxed atomics may introduce overhead. TSAN_ANNOTATE_IGNORE_READS_BEGIN; - auto result = ptr[index]; + ElementType result; + if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) { + // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size + // fields (external pointers, doubles and BigInt data) are only kTaggedSize + // aligned so we have to use unaligned pointer friendly way of accessing + // them in order to avoid undefined behavior in C++ code. + result = ReadUnalignedValue(reinterpret_cast
(ptr) + + index * sizeof(ElementType)); + } else { + result = ptr[index]; + } TSAN_ANNOTATE_IGNORE_READS_END; return result; } @@ -664,7 +674,16 @@ void FixedTypedArray::set(int index, ElementType value) { // See the comment in FixedTypedArray::get_scalar. auto* ptr = reinterpret_cast(DataPtr()); TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; - ptr[index] = value; + if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) { + // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size + // fields (external pointers, doubles and BigInt data) are only kTaggedSize + // aligned so we have to use unaligned pointer friendly way of accessing + // them in order to avoid undefined behavior in C++ code. + WriteUnalignedValue( + reinterpret_cast
(ptr) + index * sizeof(ElementType), value); + } else { + ptr[index] = value; + } TSAN_ANNOTATE_IGNORE_WRITES_END; } diff --git a/deps/v8/src/objects/object-macros-undef.h b/deps/v8/src/objects/object-macros-undef.h index 6f243eb19fcffe..b5d076564ddc8b 100644 --- a/deps/v8/src/objects/object-macros-undef.h +++ b/deps/v8/src/objects/object-macros-undef.h @@ -15,6 +15,7 @@ #undef DECL_INT_ACCESSORS #undef DECL_INT32_ACCESSORS #undef DECL_UINT16_ACCESSORS +#undef DECL_INT16_ACCESSORS #undef DECL_UINT8_ACCESSORS #undef DECL_ACCESSORS #undef DECL_CAST @@ -42,6 +43,7 @@ #undef BIT_FIELD_ACCESSORS #undef INSTANCE_TYPE_CHECKER #undef TYPE_CHECKER +#undef RELAXED_INT16_ACCESSORS #undef FIELD_ADDR #undef READ_FIELD #undef READ_WEAK_FIELD @@ -52,6 +54,7 @@ #undef WRITE_WEAK_FIELD #undef RELEASE_WRITE_FIELD #undef RELAXED_WRITE_FIELD +#undef RELAXED_WRITE_WEAK_FIELD #undef WRITE_BARRIER #undef WEAK_WRITE_BARRIER #undef CONDITIONAL_WRITE_BARRIER @@ -60,14 +63,7 @@ #undef WRITE_DOUBLE_FIELD #undef READ_INT_FIELD #undef WRITE_INT_FIELD -#undef ACQUIRE_READ_INTPTR_FIELD -#undef RELAXED_READ_INTPTR_FIELD -#undef READ_INTPTR_FIELD -#undef RELEASE_WRITE_INTPTR_FIELD -#undef RELAXED_WRITE_INTPTR_FIELD -#undef WRITE_INTPTR_FIELD -#undef READ_UINTPTR_FIELD -#undef WRITE_UINTPTR_FIELD +#undef ACQUIRE_READ_INT32_FIELD #undef READ_UINT8_FIELD #undef WRITE_UINT8_FIELD #undef RELAXED_WRITE_INT8_FIELD @@ -78,18 +74,25 @@ #undef WRITE_UINT16_FIELD #undef READ_INT16_FIELD #undef WRITE_INT16_FIELD +#undef RELAXED_READ_INT16_FIELD +#undef RELAXED_WRITE_INT16_FIELD #undef READ_UINT32_FIELD +#undef RELAXED_READ_UINT32_FIELD #undef WRITE_UINT32_FIELD +#undef RELAXED_WRITE_UINT32_FIELD #undef READ_INT32_FIELD #undef RELAXED_READ_INT32_FIELD #undef WRITE_INT32_FIELD +#undef RELEASE_WRITE_INT32_FIELD #undef RELAXED_WRITE_INT32_FIELD #undef READ_FLOAT_FIELD #undef WRITE_FLOAT_FIELD +#undef READ_INTPTR_FIELD +#undef WRITE_INTPTR_FIELD +#undef READ_UINTPTR_FIELD +#undef WRITE_UINTPTR_FIELD #undef READ_UINT64_FIELD #undef WRITE_UINT64_FIELD -#undef READ_INT64_FIELD -#undef WRITE_INT64_FIELD #undef READ_BYTE_FIELD #undef RELAXED_READ_BYTE_FIELD #undef WRITE_BYTE_FIELD diff --git a/deps/v8/src/objects/object-macros.h b/deps/v8/src/objects/object-macros.h index 3b15d63e095be2..941c68a6a29e1e 100644 --- a/deps/v8/src/objects/object-macros.h +++ b/deps/v8/src/objects/object-macros.h @@ -323,40 +323,10 @@ #define WRITE_INT_FIELD(p, offset, value) \ (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) -#define ACQUIRE_READ_INTPTR_FIELD(p, offset) \ - static_cast(base::Acquire_Load( \ - reinterpret_cast(FIELD_ADDR(p, offset)))) - #define ACQUIRE_READ_INT32_FIELD(p, offset) \ static_cast(base::Acquire_Load( \ reinterpret_cast(FIELD_ADDR(p, offset)))) -#define RELAXED_READ_INTPTR_FIELD(p, offset) \ - static_cast(base::Relaxed_Load( \ - reinterpret_cast(FIELD_ADDR(p, offset)))) - -#define READ_INTPTR_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR(p, offset))) - -#define RELEASE_WRITE_INTPTR_FIELD(p, offset, value) \ - base::Release_Store( \ - reinterpret_cast(FIELD_ADDR(p, offset)), \ - static_cast(value)); - -#define RELAXED_WRITE_INTPTR_FIELD(p, offset, value) \ - base::Relaxed_Store( \ - reinterpret_cast(FIELD_ADDR(p, offset)), \ - static_cast(value)); - -#define WRITE_INTPTR_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_UINTPTR_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR(p, offset))) - -#define WRITE_UINTPTR_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - #define READ_UINT8_FIELD(p, offset) \ (*reinterpret_cast(FIELD_ADDR(p, offset))) @@ -439,17 +409,51 @@ #define WRITE_FLOAT_FIELD(p, offset, value) \ (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) +// TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size fields +// (external pointers, doubles and BigInt data) are only kTaggedSize aligned so +// we have to use unaligned pointer friendly way of accessing them in order to +// avoid undefined behavior in C++ code. +#ifdef V8_COMPRESS_POINTERS + +#define READ_INTPTR_FIELD(p, offset) \ + ReadUnalignedValue(FIELD_ADDR(p, offset)) + +#define WRITE_INTPTR_FIELD(p, offset, value) \ + WriteUnalignedValue(FIELD_ADDR(p, offset), value) + +#define READ_UINTPTR_FIELD(p, offset) \ + ReadUnalignedValue(FIELD_ADDR(p, offset)) + +#define WRITE_UINTPTR_FIELD(p, offset, value) \ + WriteUnalignedValue(FIELD_ADDR(p, offset), value) + +#define READ_UINT64_FIELD(p, offset) \ + ReadUnalignedValue(FIELD_ADDR(p, offset)) + +#define WRITE_UINT64_FIELD(p, offset, value) \ + WriteUnalignedValue(FIELD_ADDR(p, offset), value) + +#else // V8_COMPRESS_POINTERS + +#define READ_INTPTR_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR(p, offset))) + +#define WRITE_INTPTR_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_UINTPTR_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR(p, offset))) + +#define WRITE_UINTPTR_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + #define READ_UINT64_FIELD(p, offset) \ (*reinterpret_cast(FIELD_ADDR(p, offset))) #define WRITE_UINT64_FIELD(p, offset, value) \ (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) -#define READ_INT64_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR(p, offset))) - -#define WRITE_INT64_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) +#endif // V8_COMPRESS_POINTERS #define READ_BYTE_FIELD(p, offset) \ (*reinterpret_cast(FIELD_ADDR(p, offset))) diff --git a/deps/v8/src/objects/string-inl.h b/deps/v8/src/objects/string-inl.h index 8ae2ad405c0d17..440266ced19da6 100644 --- a/deps/v8/src/objects/string-inl.h +++ b/deps/v8/src/objects/string-inl.h @@ -553,11 +553,11 @@ bool ExternalString::is_uncached() const { } Address ExternalString::resource_as_address() { - return *reinterpret_cast(FIELD_ADDR(*this, kResourceOffset)); + return READ_UINTPTR_FIELD(*this, kResourceOffset); } void ExternalString::set_address_as_resource(Address address) { - *reinterpret_cast(FIELD_ADDR(*this, kResourceOffset)) = address; + WRITE_UINTPTR_FIELD(*this, kResourceOffset, address); if (IsExternalOneByteString()) { ExternalOneByteString::cast(*this)->update_data_cache(); } else { @@ -566,27 +566,36 @@ void ExternalString::set_address_as_resource(Address address) { } uint32_t ExternalString::resource_as_uint32() { - return static_cast( - *reinterpret_cast(FIELD_ADDR(*this, kResourceOffset))); + return static_cast(READ_UINTPTR_FIELD(*this, kResourceOffset)); } void ExternalString::set_uint32_as_resource(uint32_t value) { - *reinterpret_cast(FIELD_ADDR(*this, kResourceOffset)) = value; + WRITE_UINTPTR_FIELD(*this, kResourceOffset, value); if (is_uncached()) return; - const char** data_field = - reinterpret_cast(FIELD_ADDR(*this, kResourceDataOffset)); - *data_field = nullptr; + WRITE_UINTPTR_FIELD(*this, kResourceDataOffset, kNullAddress); +} + +void ExternalString::DisposeResource() { + v8::String::ExternalStringResourceBase* resource = + reinterpret_cast( + READ_UINTPTR_FIELD(*this, ExternalString::kResourceOffset)); + + // Dispose of the C++ object if it has not already been disposed. + if (resource != nullptr) { + resource->Dispose(); + WRITE_UINTPTR_FIELD(*this, ExternalString::kResourceOffset, kNullAddress); + } } const ExternalOneByteString::Resource* ExternalOneByteString::resource() { - return *reinterpret_cast(FIELD_ADDR(*this, kResourceOffset)); + return reinterpret_cast( + READ_UINTPTR_FIELD(*this, kResourceOffset)); } void ExternalOneByteString::update_data_cache() { if (is_uncached()) return; - const char** data_field = - reinterpret_cast(FIELD_ADDR(*this, kResourceDataOffset)); - *data_field = resource()->data(); + WRITE_UINTPTR_FIELD(*this, kResourceDataOffset, + reinterpret_cast
(resource()->data())); } void ExternalOneByteString::SetResource( @@ -600,8 +609,8 @@ void ExternalOneByteString::SetResource( void ExternalOneByteString::set_resource( const ExternalOneByteString::Resource* resource) { - *reinterpret_cast(FIELD_ADDR(*this, kResourceOffset)) = - resource; + WRITE_UINTPTR_FIELD(*this, kResourceOffset, + reinterpret_cast
(resource)); if (resource != nullptr) update_data_cache(); } @@ -615,14 +624,14 @@ uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) { } const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() { - return *reinterpret_cast(FIELD_ADDR(*this, kResourceOffset)); + return reinterpret_cast( + READ_UINTPTR_FIELD(*this, kResourceOffset)); } void ExternalTwoByteString::update_data_cache() { if (is_uncached()) return; - const uint16_t** data_field = reinterpret_cast( - FIELD_ADDR(*this, kResourceDataOffset)); - *data_field = resource()->data(); + WRITE_UINTPTR_FIELD(*this, kResourceDataOffset, + reinterpret_cast
(resource()->data())); } void ExternalTwoByteString::SetResource( @@ -636,8 +645,8 @@ void ExternalTwoByteString::SetResource( void ExternalTwoByteString::set_resource( const ExternalTwoByteString::Resource* resource) { - *reinterpret_cast(FIELD_ADDR(*this, kResourceOffset)) = - resource; + WRITE_UINTPTR_FIELD(*this, kResourceOffset, + reinterpret_cast
(resource)); if (resource != nullptr) update_data_cache(); } diff --git a/deps/v8/src/objects/string.h b/deps/v8/src/objects/string.h index e0b34f7a0e4575..e91f913c2b252b 100644 --- a/deps/v8/src/objects/string.h +++ b/deps/v8/src/objects/string.h @@ -736,6 +736,9 @@ class ExternalString : public String { inline uint32_t resource_as_uint32(); inline void set_uint32_as_resource(uint32_t value); + // Disposes string's resource object if it has not already been disposed. + inline void DisposeResource(); + STATIC_ASSERT(kResourceOffset == Internals::kStringResourceOffset); OBJECT_CONSTRUCTORS(ExternalString, String); diff --git a/deps/v8/src/snapshot/serializer.cc b/deps/v8/src/snapshot/serializer.cc index e5b371ef285c95..660d2ce04ab403 100644 --- a/deps/v8/src/snapshot/serializer.cc +++ b/deps/v8/src/snapshot/serializer.cc @@ -710,8 +710,8 @@ void Serializer::ObjectSerializer::VisitEmbeddedPointer(Code host, void Serializer::ObjectSerializer::VisitExternalReference(Foreign host, Address* p) { - Address target = *p; - auto encoded_reference = serializer_->EncodeExternalReference(target); + auto encoded_reference = + serializer_->EncodeExternalReference(host->foreign_address()); if (encoded_reference.is_from_api()) { sink_->Put(kApiReference, "ApiRef"); } else { diff --git a/deps/v8/src/wasm/wasm-objects-inl.h b/deps/v8/src/wasm/wasm-objects-inl.h index 9a25995203c13f..b5180804cf32b2 100644 --- a/deps/v8/src/wasm/wasm-objects-inl.h +++ b/deps/v8/src/wasm/wasm-objects-inl.h @@ -57,18 +57,30 @@ CAST_ACCESSOR(AsmWasmData) } \ ACCESSORS(holder, name, type, offset) -#define READ_PRIMITIVE_FIELD(p, type, offset) \ - (*reinterpret_cast(FIELD_ADDR(p, offset))) - -#define WRITE_PRIMITIVE_FIELD(p, type, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define PRIMITIVE_ACCESSORS(holder, name, type, offset) \ - type holder::name() const { \ - return READ_PRIMITIVE_FIELD(*this, type, offset); \ - } \ - void holder::set_##name(type value) { \ - WRITE_PRIMITIVE_FIELD(*this, type, offset, value); \ +#define PRIMITIVE_ACCESSORS(holder, name, type, offset) \ + type holder::name() const { \ + if (COMPRESS_POINTERS_BOOL && alignof(type) > kTaggedSize) { \ + /* TODO(ishell, v8:8875): When pointer compression is enabled 8-byte */ \ + /* size fields (external pointers, doubles and BigInt data) are only */ \ + /* kTaggedSize aligned so we have to use unaligned pointer friendly */ \ + /* way of accessing them in order to avoid undefined behavior in C++ */ \ + /* code. */ \ + return ReadUnalignedValue(FIELD_ADDR(*this, offset)); \ + } else { \ + return *reinterpret_cast(FIELD_ADDR(*this, offset)); \ + } \ + } \ + void holder::set_##name(type value) { \ + if (COMPRESS_POINTERS_BOOL && alignof(type) > kTaggedSize) { \ + /* TODO(ishell, v8:8875): When pointer compression is enabled 8-byte */ \ + /* size fields (external pointers, doubles and BigInt data) are only */ \ + /* kTaggedSize aligned so we have to use unaligned pointer friendly */ \ + /* way of accessing them in order to avoid undefined behavior in C++ */ \ + /* code. */ \ + WriteUnalignedValue(FIELD_ADDR(*this, offset), value); \ + } else { \ + *reinterpret_cast(FIELD_ADDR(*this, offset)) = value; \ + } \ } // WasmModuleObject diff --git a/deps/v8/test/cctest/heap/test-heap.cc b/deps/v8/test/cctest/heap/test-heap.cc index f12ba109795451..1d06f460869e81 100644 --- a/deps/v8/test/cctest/heap/test-heap.cc +++ b/deps/v8/test/cctest/heap/test-heap.cc @@ -531,14 +531,9 @@ TEST(WeakGlobalHandlesScavenge) { // Scavenge treats weak pointers as normal roots. CcTest::CollectGarbage(NEW_SPACE); - CHECK((*h1)->IsString()); CHECK((*h2)->IsHeapNumber()); - CHECK(!WeakPointerCleared); - CHECK(!global_handles->IsNearDeath(h2.location())); - CHECK(!global_handles->IsNearDeath(h1.location())); - GlobalHandles::Destroy(h1.location()); GlobalHandles::Destroy(h2.location()); } @@ -576,11 +571,8 @@ TEST(WeakGlobalUnmodifiedApiHandlesScavenge) { &TestWeakGlobalHandleCallback, v8::WeakCallbackType::kParameter); CcTest::CollectGarbage(NEW_SPACE); - CHECK((*h1)->IsHeapNumber()); CHECK(WeakPointerCleared); - CHECK(!global_handles->IsNearDeath(h1.location())); - GlobalHandles::Destroy(h1.location()); } @@ -617,10 +609,7 @@ TEST(WeakGlobalApiHandleModifiedMapScavenge) { &TestWeakGlobalHandleCallback, v8::WeakCallbackType::kParameter); CcTest::CollectGarbage(NEW_SPACE); - CHECK(!WeakPointerCleared); - CHECK(!global_handles->IsNearDeath(h1.location())); - GlobalHandles::Destroy(h1.location()); } @@ -661,10 +650,7 @@ TEST(WeakGlobalApiHandleWithElementsScavenge) { &TestWeakGlobalHandleCallback, v8::WeakCallbackType::kParameter); CcTest::CollectGarbage(NEW_SPACE); - CHECK(!WeakPointerCleared); - CHECK(!global_handles->IsNearDeath(h1.location())); - GlobalHandles::Destroy(h1.location()); } @@ -699,17 +685,11 @@ TEST(WeakGlobalHandlesMark) { GlobalHandles::MakeWeak( h2.location(), reinterpret_cast(&handle_and_id), &TestWeakGlobalHandleCallback, v8::WeakCallbackType::kParameter); - CHECK(!GlobalHandles::IsNearDeath(h1.location())); - CHECK(!GlobalHandles::IsNearDeath(h2.location())); // Incremental marking potentially marked handles before they turned weak. CcTest::CollectAllGarbage(); - CHECK((*h1)->IsString()); - CHECK(WeakPointerCleared); - CHECK(!GlobalHandles::IsNearDeath(h1.location())); - GlobalHandles::Destroy(h1.location()); } diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index aae1b3674e5771..2edc5b50029d26 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -20545,43 +20545,6 @@ TEST(WrapperClassId) { object.Reset(); } - -TEST(PersistentHandleInNewSpaceVisitor) { - LocalContext context; - v8::Isolate* isolate = context->GetIsolate(); - v8::HandleScope scope(isolate); - v8::Persistent object1(isolate, v8::Object::New(isolate)); - CHECK_EQ(0, object1.WrapperClassId()); - object1.SetWrapperClassId(42); - CHECK_EQ(42, object1.WrapperClassId()); - - CcTest::CollectAllGarbage(); - CcTest::CollectAllGarbage(); - - v8::Persistent object2(isolate, v8::Object::New(isolate)); - CHECK_EQ(0, object2.WrapperClassId()); - object2.SetWrapperClassId(42); - CHECK_EQ(42, object2.WrapperClassId()); - - Visitor42 visitor(&object2); -#if __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated" -#endif - // VisitHandlesForPartialDependence is marked deprecated. This test will be - // removed with the API method. - isolate->VisitHandlesForPartialDependence(&visitor); -#if __clang__ -#pragma clang diagnostic pop -#endif - - CHECK_EQ(1, visitor.counter_); - - object1.Reset(); - object2.Reset(); -} - - TEST(RegExp) { LocalContext context; v8::HandleScope scope(context->GetIsolate());