1 // Copyright 2020 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_ZONE_ZONE_COMPRESSION_H_ 6 #define V8_ZONE_ZONE_COMPRESSION_H_ 7 8 #include "src/base/bits.h" 9 #include "src/common/globals.h" 10 11 namespace v8 { 12 namespace internal { 13 14 // This struct provides untyped implementation of zone compression scheme. 15 // 16 // The compression scheme relies on the following assumptions: 17 // 1) all zones containing compressed pointers are allocated in the same "zone 18 // cage" of kReservationSize size and kReservationAlignment-aligned. 19 // Attempt to compress pointer to an object stored outside of the "cage" 20 // will silently succeed but it will later produce wrong result after 21 // decompression. 22 // 2) compression is just a masking away bits above kReservationAlignment. 23 // 3) nullptr is compressed to 0, thus there must be no valid objects allocated 24 // at the beginning of the "zone cage". Ideally, the first page of the cage 25 // should be unmapped in order to catch attempts to use decompressed nullptr 26 // value earlier. 27 // 4) decompression requires "zone cage" address value, which is computed on 28 // the fly from an arbitrary address pointing somewhere to the "zone cage". 29 // 5) decompression requires special casing for nullptr. 30 struct ZoneCompression { 31 static const size_t kReservationSize = size_t{2} * GB; 32 static const size_t kReservationAlignment = 33 COMPRESS_ZONES_BOOL ? size_t{4} * GB : 1; 34 35 static_assert(base::bits::IsPowerOfTwo(kReservationAlignment), 36 "Bad zone alignment"); 37 38 static const size_t kOffsetMask = kReservationAlignment - 1; 39 base_ofZoneCompression40 inline static Address base_of(const void* zone_pointer) { 41 return reinterpret_cast<Address>(zone_pointer) & ~kOffsetMask; 42 } 43 CheckSameBaseZoneCompression44 inline static bool CheckSameBase(const void* p1, const void* p2) { 45 if (p1 == nullptr || p2 == nullptr) return true; 46 CHECK_EQ(base_of(p1), base_of(p2)); 47 return true; 48 } 49 CompressZoneCompression50 inline static uint32_t Compress(const void* value) { 51 Address raw_value = reinterpret_cast<Address>(value); 52 uint32_t compressed_value = static_cast<uint32_t>(raw_value & kOffsetMask); 53 DCHECK_IMPLIES(compressed_value == 0, value == nullptr); 54 DCHECK_LT(compressed_value, kReservationSize); 55 return compressed_value; 56 } 57 DecompressZoneCompression58 inline static Address Decompress(const void* zone_pointer, 59 uint32_t compressed_value) { 60 if (compressed_value == 0) return kNullAddress; 61 return base_of(zone_pointer) + compressed_value; 62 } 63 }; 64 65 } // namespace internal 66 } // namespace v8 67 68 #endif // V8_ZONE_ZONE_COMPRESSION_H_ 69