From 5b8434eebceb7a60062bbebc03cdf83d520c6bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sat, 30 Mar 2019 15:21:31 +0100 Subject: [PATCH] deps: V8: cherry-pick 0188634 Original commit message: [ptr-compr][ubsan] Use [Read/Write]UnalignedValue for unaligned fields When pointer compression is enabled the [u]intptr_t and double fields are only kTaggedSize aligned so in order to avoid undefined behavior in C++ code we have to access these values in an unaligned pointer friendly way although both x64 and arm64 architectures (where pointer compression is supported) allow unaligned access. These changes will be removed once v8:8875 is fixed and all the kSystemPointerSize fields are properly aligned. Bug: v8:7703 Change-Id: I4df477cbdeab806303bb4f675d52b61c06342c8e Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1528996 Commit-Queue: Igor Sheludko Reviewed-by: Ulan Degenbaev Reviewed-by: Jakob Gruber Reviewed-by: Clemens Hammacher Cr-Commit-Position: refs/heads/master@{#60321} Refs: https://github.com/v8/v8/commit/0188634ee523aef39ba71732b1ab9d422f449825 PR-URL: https://github.com/nodejs/node/pull/27013 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: Ruben Bridgewater Reviewed-By: Ben Noordhuis --- common.gypi | 2 +- deps/v8/include/v8-internal.h | 12 ++++ deps/v8/include/v8.h | 3 +- deps/v8/src/heap/heap-inl.h | 10 +-- deps/v8/src/objects/bigint.cc | 3 +- deps/v8/src/objects/bigint.h | 3 +- deps/v8/src/objects/embedder-data-slot-inl.h | 17 +++++ deps/v8/src/objects/fixed-array-inl.h | 23 +++++- deps/v8/src/objects/object-macros-undef.h | 23 +++--- deps/v8/src/objects/object-macros.h | 74 +++++++++++--------- deps/v8/src/objects/string-inl.h | 49 +++++++------ deps/v8/src/objects/string.h | 3 + deps/v8/src/snapshot/serializer.cc | 4 +- deps/v8/src/wasm/wasm-objects-inl.h | 36 ++++++---- 14 files changed, 166 insertions(+), 96 deletions(-) diff --git a/common.gypi b/common.gypi index 8d00e6864a52ba..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.15', + '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 a0d0bfb959c9a3..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) @@ -274,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.h b/deps/v8/include/v8.h index 7346e0bbbc74c2..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; @@ -2797,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; }; 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