OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 #endif | 188 #endif |
189 | 189 |
190 ASSERT(gcInfoIndex < GCInfoTable::maxIndex); | 190 ASSERT(gcInfoIndex < GCInfoTable::maxIndex); |
191 ASSERT(size < nonLargeObjectPageSizeMax); | 191 ASSERT(size < nonLargeObjectPageSizeMax); |
192 ASSERT(!(size & allocationMask)); | 192 ASSERT(!(size & allocationMask)); |
193 m_encoded = static_cast<uint32_t>( | 193 m_encoded = static_cast<uint32_t>( |
194 (gcInfoIndex << headerGCInfoIndexShift) | size | | 194 (gcInfoIndex << headerGCInfoIndexShift) | size | |
195 (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0)); | 195 (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0)); |
196 } | 196 } |
197 | 197 |
198 NO_SANITIZE_ADDRESS | 198 NO_SANITIZE_ADDRESS bool isFree() const { |
199 bool isFree() const { return m_encoded & headerFreedBitMask; } | 199 return m_encoded & headerFreedBitMask; |
200 NO_SANITIZE_ADDRESS | 200 } |
201 bool isPromptlyFreed() const { | 201 |
| 202 NO_SANITIZE_ADDRESS bool isPromptlyFreed() const { |
202 return (m_encoded & headerPromptlyFreedBitMask) == | 203 return (m_encoded & headerPromptlyFreedBitMask) == |
203 headerPromptlyFreedBitMask; | 204 headerPromptlyFreedBitMask; |
204 } | 205 } |
205 NO_SANITIZE_ADDRESS | 206 |
206 void markPromptlyFreed() { m_encoded |= headerPromptlyFreedBitMask; } | 207 NO_SANITIZE_ADDRESS void markPromptlyFreed() { |
| 208 m_encoded |= headerPromptlyFreedBitMask; |
| 209 } |
| 210 |
207 size_t size() const; | 211 size_t size() const; |
208 | 212 |
209 NO_SANITIZE_ADDRESS | 213 NO_SANITIZE_ADDRESS size_t gcInfoIndex() const { |
210 size_t gcInfoIndex() const { | |
211 return (m_encoded & headerGCInfoIndexMask) >> headerGCInfoIndexShift; | 214 return (m_encoded & headerGCInfoIndexMask) >> headerGCInfoIndexShift; |
212 } | 215 } |
213 NO_SANITIZE_ADDRESS | 216 |
214 void setSize(size_t size) { | 217 NO_SANITIZE_ADDRESS void setSize(size_t size) { |
215 ASSERT(size < nonLargeObjectPageSizeMax); | 218 ASSERT(size < nonLargeObjectPageSizeMax); |
| 219 checkHeader(); |
216 m_encoded = static_cast<uint32_t>(size) | (m_encoded & ~headerSizeMask); | 220 m_encoded = static_cast<uint32_t>(size) | (m_encoded & ~headerSizeMask); |
217 } | 221 } |
| 222 |
218 bool isWrapperHeaderMarked() const; | 223 bool isWrapperHeaderMarked() const; |
219 void markWrapperHeader(); | 224 void markWrapperHeader(); |
220 void unmarkWrapperHeader(); | 225 void unmarkWrapperHeader(); |
221 bool isMarked() const; | 226 bool isMarked() const; |
222 void mark(); | 227 void mark(); |
223 void unmark(); | 228 void unmark(); |
224 | 229 |
225 Address payload(); | 230 Address payload(); |
226 size_t payloadSize(); | 231 size_t payloadSize(); |
227 Address payloadEnd(); | 232 Address payloadEnd(); |
228 | 233 |
229 // TODO(633030): Make |checkHeader| and |zapMagic| private. This class should | 234 void finalize(Address, size_t); |
230 // manage its integrity on its own, without requiring outside callers to | 235 static HeapObjectHeader* fromPayload(const void*); |
231 // explicitly check. | |
232 void checkHeader() const; | |
233 | 236 |
| 237 // Some callers formerly called |fromPayload| only for its side-effect of |
| 238 // calling |checkHeader| (which is now private). This function does that, but |
| 239 // its explanatory name makes the intention at the call sites easier to |
| 240 // understand, and is public. |
| 241 static void checkFromPayload(const void*); |
| 242 |
| 243 static const uint32_t zappedMagic = 0xDEAD4321; |
| 244 |
| 245 protected: |
234 #if DCHECK_IS_ON() && CPU(64BIT) | 246 #if DCHECK_IS_ON() && CPU(64BIT) |
235 // Zap |m_magic| with a new magic number that means there was once an object | 247 // Zap |m_magic| with a new magic number that means there was once an object |
236 // allocated here, but it was freed because nobody marked it during GC. | 248 // allocated here, but it was freed because nobody marked it during GC. |
237 void zapMagic(); | 249 void zapMagic(); |
238 #endif | 250 #endif |
239 | 251 |
240 void finalize(Address, size_t); | 252 private: |
241 static HeapObjectHeader* fromPayload(const void*); | 253 void checkHeader() const; |
242 | 254 |
243 static const uint32_t zappedMagic = 0xDEAD4321; | |
244 | |
245 private: | |
246 #if CPU(64BIT) | 255 #if CPU(64BIT) |
247 // Returns a random value. | 256 // Returns a random value. |
248 // | 257 // |
249 // The implementation gets its randomness from the locations of 2 independent | 258 // The implementation gets its randomness from the locations of 2 independent |
250 // sources of address space layout randomization: a function in a Chrome | 259 // sources of address space layout randomization: a function in a Chrome |
251 // executable image, and a function in an external DLL/so. This implementation | 260 // executable image, and a function in an external DLL/so. This implementation |
252 // should be fast and small, and should have the benefit of requiring | 261 // should be fast and small, and should have the benefit of requiring |
253 // attackers to discover and use 2 independent weak infoleak bugs, or 1 | 262 // attackers to discover and use 2 independent weak infoleak bugs, or 1 |
254 // arbitrary infoleak bug (used twice). | 263 // arbitrary infoleak bug (used twice). |
255 uint32_t getMagic() const; | 264 uint32_t getMagic() const; |
256 uint32_t m_magic; | 265 uint32_t m_magic; |
257 #endif | 266 #endif // CPU(64BIT) |
258 | 267 |
259 uint32_t m_encoded; | 268 uint32_t m_encoded; |
260 }; | 269 }; |
261 | 270 |
262 class FreeListEntry final : public HeapObjectHeader { | 271 class FreeListEntry final : public HeapObjectHeader { |
263 public: | 272 public: |
264 NO_SANITIZE_ADDRESS | 273 NO_SANITIZE_ADDRESS |
265 explicit FreeListEntry(size_t size) | 274 explicit FreeListEntry(size_t size) |
266 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { | 275 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { |
267 #if DCHECK_IS_ON() && CPU(64BIT) | 276 #if DCHECK_IS_ON() && CPU(64BIT) |
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 size_t result = m_encoded & headerSizeMask; | 842 size_t result = m_encoded & headerSizeMask; |
834 // Large objects should not refer to header->size(). The actual size of a | 843 // Large objects should not refer to header->size(). The actual size of a |
835 // large object is stored in |LargeObjectPage::m_payloadSize|. | 844 // large object is stored in |LargeObjectPage::m_payloadSize|. |
836 ASSERT(result != largeObjectSizeInHeader); | 845 ASSERT(result != largeObjectSizeInHeader); |
837 ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 846 ASSERT(!pageFromObject(this)->isLargeObjectPage()); |
838 return result; | 847 return result; |
839 } | 848 } |
840 | 849 |
841 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::checkHeader() const { | 850 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::checkHeader() const { |
842 #if CPU(64BIT) | 851 #if CPU(64BIT) |
843 const bool good = getMagic() == m_magic; | 852 const bool goodMagic = getMagic() == m_magic; |
844 DCHECK(good); | 853 DCHECK(goodMagic); |
845 #endif | 854 #endif |
846 } | 855 } |
847 | 856 |
848 inline Address HeapObjectHeader::payload() { | 857 inline Address HeapObjectHeader::payload() { |
849 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); | 858 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); |
850 } | 859 } |
851 | 860 |
852 inline Address HeapObjectHeader::payloadEnd() { | 861 inline Address HeapObjectHeader::payloadEnd() { |
853 return reinterpret_cast<Address>(this) + size(); | 862 return reinterpret_cast<Address>(this) + size(); |
854 } | 863 } |
855 | 864 |
856 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { | 865 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { |
| 866 checkHeader(); |
857 size_t size = m_encoded & headerSizeMask; | 867 size_t size = m_encoded & headerSizeMask; |
858 if (UNLIKELY(size == largeObjectSizeInHeader)) { | 868 if (UNLIKELY(size == largeObjectSizeInHeader)) { |
859 ASSERT(pageFromObject(this)->isLargeObjectPage()); | 869 ASSERT(pageFromObject(this)->isLargeObjectPage()); |
860 return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize(); | 870 return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize(); |
861 } | 871 } |
862 ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 872 ASSERT(!pageFromObject(this)->isLargeObjectPage()); |
863 return size - sizeof(HeapObjectHeader); | 873 return size - sizeof(HeapObjectHeader); |
864 } | 874 } |
865 | 875 |
866 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { | 876 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { |
867 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); | 877 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); |
868 HeapObjectHeader* header = | 878 HeapObjectHeader* header = |
869 reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader)); | 879 reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader)); |
870 header->checkHeader(); | 880 header->checkHeader(); |
871 return header; | 881 return header; |
872 } | 882 } |
873 | 883 |
| 884 inline void HeapObjectHeader::checkFromPayload(const void* payload) { |
| 885 (void)fromPayload(payload); |
| 886 } |
| 887 |
874 #if CPU(64BIT) | 888 #if CPU(64BIT) |
875 ALWAYS_INLINE uint32_t RotateLeft16(uint32_t x) { | 889 ALWAYS_INLINE uint32_t RotateLeft16(uint32_t x) { |
876 #if COMPILER(MSVC) | 890 #if COMPILER(MSVC) |
877 return _lrotr(x, 16); | 891 return _lrotr(x, 16); |
878 #else | 892 #else |
879 // http://blog.regehr.org/archives/1063 | 893 // http://blog.regehr.org/archives/1063 |
880 return (x << 16) | (x >> (-16 & 31)); | 894 return (x << 16) | (x >> (-16 & 31)); |
881 #endif | 895 #endif |
882 } | 896 } |
883 | 897 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
978 return outOfLineAllocate(allocationSize, gcInfoIndex); | 992 return outOfLineAllocate(allocationSize, gcInfoIndex); |
979 } | 993 } |
980 | 994 |
981 inline NormalPageArena* NormalPage::arenaForNormalPage() const { | 995 inline NormalPageArena* NormalPage::arenaForNormalPage() const { |
982 return static_cast<NormalPageArena*>(arena()); | 996 return static_cast<NormalPageArena*>(arena()); |
983 } | 997 } |
984 | 998 |
985 } // namespace blink | 999 } // namespace blink |
986 | 1000 |
987 #endif // HeapPage_h | 1001 #endif // HeapPage_h |
OLD | NEW |