diff --git a/BUILD.bazel b/BUILD.bazel index f45ec37ba2..7ff94a17cd 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1146,6 +1146,7 @@ filegroup( "src/common/high-allocation-throughput-scope.h", "src/common/message-template.h", "src/common/ptr-compr-inl.h", + "src/common/ptr-compr.h", "src/compiler-dispatcher/lazy-compile-dispatcher.cc", "src/compiler-dispatcher/lazy-compile-dispatcher.h", "src/compiler-dispatcher/optimizing-compile-dispatcher.cc", diff --git a/BUILD.gn b/BUILD.gn index bec411cf23..f6034b204a 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -2735,6 +2735,7 @@ v8_header_set("v8_internal_headers") { "src/common/high-allocation-throughput-scope.h", "src/common/message-template.h", "src/common/ptr-compr-inl.h", + "src/common/ptr-compr.h", "src/compiler-dispatcher/lazy-compile-dispatcher.h", "src/compiler-dispatcher/optimizing-compile-dispatcher.h", "src/compiler/access-builder.h", diff --git a/src/common/ptr-compr.h b/src/common/ptr-compr.h new file mode 100644 index 0000000000..58d1460290 --- /dev/null +++ b/src/common/ptr-compr.h @@ -0,0 +1,55 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_COMMON_PTR_COMPR_H_ +#define V8_COMMON_PTR_COMPR_H_ + +#include "src/base/memory.h" +#include "src/common/globals.h" + +namespace v8 { +namespace internal { + +// Accessors for fields that may be unaligned due to pointer compression. + +template +static inline V ReadMaybeUnalignedValue(Address p) { + // Pointer compression causes types larger than kTaggedSize to be unaligned. +#ifdef V8_COMPRESS_POINTERS + constexpr bool v8_pointer_compression_unaligned = sizeof(V) > kTaggedSize; +#else + constexpr bool v8_pointer_compression_unaligned = false; +#endif + // Bug(v8:8875) Double fields may be unaligned. + constexpr bool unaligned_double_field = + std::is_same::value && kDoubleSize > kTaggedSize; + if (unaligned_double_field || v8_pointer_compression_unaligned) { + return base::ReadUnalignedValue(p); + } else { + return base::Memory(p); + } +} + +template +static inline void WriteMaybeUnalignedValue(Address p, V value) { + // Pointer compression causes types larger than kTaggedSize to be unaligned. +#ifdef V8_COMPRESS_POINTERS + constexpr bool v8_pointer_compression_unaligned = sizeof(V) > kTaggedSize; +#else + constexpr bool v8_pointer_compression_unaligned = false; +#endif + // Bug(v8:8875) Double fields may be unaligned. + constexpr bool unaligned_double_field = + std::is_same::value && kDoubleSize > kTaggedSize; + if (unaligned_double_field || v8_pointer_compression_unaligned) { + base::WriteUnalignedValue(p, value); + } else { + base::Memory(p) = value; + } +} + +} // namespace internal +} // namespace v8 + +#endif // V8_COMMON_PTR_COMPR_H_ diff --git a/src/objects/objects.h b/src/objects/objects.h index 499d5a9d1c..53f18bff80 100644 --- a/src/objects/objects.h +++ b/src/objects/objects.h @@ -19,6 +19,7 @@ #include "src/common/assert-scope.h" #include "src/common/checks.h" #include "src/common/message-template.h" +#include "src/common/ptr-compr.h" #include "src/flags/flags.h" #include "src/objects/elements-kind.h" #include "src/objects/field-index.h" @@ -669,18 +670,7 @@ class Object : public TaggedImpl { std::is_enum::value, int>::type = 0> inline T ReadField(size_t offset) const { - // Pointer compression causes types larger than kTaggedSize to be unaligned. -#ifdef V8_COMPRESS_POINTERS - constexpr bool v8_pointer_compression_unaligned = sizeof(T) > kTaggedSize; -#else - constexpr bool v8_pointer_compression_unaligned = false; -#endif - if (std::is_same::value || v8_pointer_compression_unaligned) { - // Bug(v8:8875) Double fields may be unaligned. - return base::ReadUnalignedValue(field_address(offset)); - } else { - return base::Memory(field_address(offset)); - } + return ReadMaybeUnalignedValue(field_address(offset)); } // Atomically reads a field using relaxed memory ordering. Can only be used @@ -696,18 +686,7 @@ class Object : public TaggedImpl { std::is_enum::value, int>::type = 0> inline void WriteField(size_t offset, T value) const { - // Pointer compression causes types larger than kTaggedSize to be unaligned. -#ifdef V8_COMPRESS_POINTERS - constexpr bool v8_pointer_compression_unaligned = sizeof(T) > kTaggedSize; -#else - constexpr bool v8_pointer_compression_unaligned = false; -#endif - if (std::is_same::value || v8_pointer_compression_unaligned) { - // Bug(v8:8875) Double fields may be unaligned. - base::WriteUnalignedValue(field_address(offset), value); - } else { - base::Memory(field_address(offset)) = value; - } + return WriteMaybeUnalignedValue(field_address(offset), value); } // diff --git a/src/sandbox/sandboxed-pointer-inl.h b/src/sandbox/sandboxed-pointer-inl.h index b19e2c6f75..3682be6974 100644 --- a/src/sandbox/sandboxed-pointer-inl.h +++ b/src/sandbox/sandboxed-pointer-inl.h @@ -6,6 +6,7 @@ #define V8_SANDBOX_SANDBOXED_POINTER_INL_H_ #include "include/v8-internal.h" +#include "src/common/ptr-compr.h" #include "src/execution/isolate.h" #include "src/sandbox/sandboxed-pointer.h" @@ -22,7 +23,7 @@ V8_INLINE Address ReadSandboxedPointerField(Address field_address, Address pointer = cage_base.address() + offset; return pointer; #else - return base::ReadUnalignedValue
(field_address); + return ReadMaybeUnalignedValue
(field_address); #endif } @@ -38,7 +39,7 @@ V8_INLINE void WriteSandboxedPointerField(Address field_address, base::WriteUnalignedValue(field_address, sandboxed_pointer); #else - base::WriteUnalignedValue
(field_address, pointer); + WriteMaybeUnalignedValue
(field_address, pointer); #endif } diff --git a/src/wasm/wasm-objects-inl.h b/src/wasm/wasm-objects-inl.h index 1067332e9b..d151fe8a1a 100644 --- a/src/wasm/wasm-objects-inl.h +++ b/src/wasm/wasm-objects-inl.h @@ -12,6 +12,7 @@ #include #include "src/base/memory.h" +#include "src/common/ptr-compr.h" #include "src/heap/heap-write-barrier-inl.h" #include "src/objects/contexts-inl.h" #include "src/objects/foreign.h" @@ -66,30 +67,12 @@ CAST_ACCESSOR(WasmInstanceObject) ACCESSORS_CHECKED2(holder, name, type, offset, \ !value.IsUndefined(GetReadOnlyRoots(cage_base)), true) -#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 base::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. */ \ - base::WriteUnalignedValue(FIELD_ADDR(*this, offset), value); \ - } else { \ - *reinterpret_cast(FIELD_ADDR(*this, offset)) = value; \ - } \ +#define PRIMITIVE_ACCESSORS(holder, name, type, offset) \ + type holder::name() const { \ + return ReadMaybeUnalignedValue(FIELD_ADDR(*this, offset)); \ + } \ + void holder::set_##name(type value) { \ + WriteMaybeUnalignedValue(FIELD_ADDR(*this, offset), value); \ } #define SANDBOXED_POINTER_ACCESSORS(holder, name, type, offset) \