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 static const uint32_t zappedMagic = 0xDEAD4321; | |
238 | |
239 protected: | |
234 #if DCHECK_IS_ON() && CPU(64BIT) | 240 #if DCHECK_IS_ON() && CPU(64BIT) |
235 // Zap |m_magic| with a new magic number that means there was once an object | 241 // 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. | 242 // allocated here, but it was freed because nobody marked it during GC. |
237 void zapMagic(); | 243 void zapMagic(); |
238 #endif | 244 #endif |
239 | 245 |
240 void finalize(Address, size_t); | 246 private: |
241 static HeapObjectHeader* fromPayload(const void*); | 247 void checkHeader() const; |
242 | 248 |
243 static const uint32_t zappedMagic = 0xDEAD4321; | |
244 | |
245 private: | |
246 #if CPU(64BIT) | 249 #if CPU(64BIT) |
247 // Returns a random value. | 250 // Returns a random value. |
248 // | 251 // |
249 // The implementation gets its randomness from the locations of 2 independent | 252 // The implementation gets its randomness from the locations of 2 independent |
250 // sources of address space layout randomization: a function in a Chrome | 253 // sources of address space layout randomization: a function in a Chrome |
251 // executable image, and a function in an external DLL/so. This implementation | 254 // 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 | 255 // 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 | 256 // attackers to discover and use 2 independent weak infoleak bugs, or 1 |
254 // arbitrary infoleak bug (used twice). | 257 // arbitrary infoleak bug (used twice). |
255 uint32_t getMagic() const; | 258 uint32_t getMagic() const; |
256 uint32_t m_magic; | 259 uint32_t m_magic; |
257 #endif | 260 #endif // CPU(64BIT) |
258 | 261 |
259 uint32_t m_encoded; | 262 uint32_t m_encoded; |
260 }; | 263 }; |
261 | 264 |
262 class FreeListEntry final : public HeapObjectHeader { | 265 class FreeListEntry final : public HeapObjectHeader { |
263 public: | 266 public: |
264 NO_SANITIZE_ADDRESS | 267 NO_SANITIZE_ADDRESS |
265 explicit FreeListEntry(size_t size) | 268 explicit FreeListEntry(size_t size) |
266 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { | 269 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { |
267 #if DCHECK_IS_ON() && CPU(64BIT) | 270 #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; | 836 size_t result = m_encoded & headerSizeMask; |
834 // Large objects should not refer to header->size(). The actual size of a | 837 // Large objects should not refer to header->size(). The actual size of a |
835 // large object is stored in |LargeObjectPage::m_payloadSize|. | 838 // large object is stored in |LargeObjectPage::m_payloadSize|. |
836 ASSERT(result != largeObjectSizeInHeader); | 839 ASSERT(result != largeObjectSizeInHeader); |
837 ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 840 ASSERT(!pageFromObject(this)->isLargeObjectPage()); |
838 return result; | 841 return result; |
839 } | 842 } |
840 | 843 |
841 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::checkHeader() const { | 844 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::checkHeader() const { |
842 #if CPU(64BIT) | 845 #if CPU(64BIT) |
843 const bool good = getMagic() == m_magic; | 846 const bool goodMagic = getMagic() == m_magic; |
844 DCHECK(good); | 847 CHECK(goodMagic); |
haraken
2017/03/30 14:12:46
What's a performance implication for the DCHECK =>
| |
845 #endif | 848 #endif |
846 } | 849 } |
847 | 850 |
848 inline Address HeapObjectHeader::payload() { | 851 inline Address HeapObjectHeader::payload() { |
849 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); | 852 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); |
850 } | 853 } |
851 | 854 |
852 inline Address HeapObjectHeader::payloadEnd() { | 855 inline Address HeapObjectHeader::payloadEnd() { |
853 return reinterpret_cast<Address>(this) + size(); | 856 return reinterpret_cast<Address>(this) + size(); |
854 } | 857 } |
855 | 858 |
856 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { | 859 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { |
860 checkHeader(); | |
857 size_t size = m_encoded & headerSizeMask; | 861 size_t size = m_encoded & headerSizeMask; |
858 if (UNLIKELY(size == largeObjectSizeInHeader)) { | 862 if (UNLIKELY(size == largeObjectSizeInHeader)) { |
859 ASSERT(pageFromObject(this)->isLargeObjectPage()); | 863 ASSERT(pageFromObject(this)->isLargeObjectPage()); |
860 return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize(); | 864 return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize(); |
861 } | 865 } |
862 ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 866 ASSERT(!pageFromObject(this)->isLargeObjectPage()); |
863 return size - sizeof(HeapObjectHeader); | 867 return size - sizeof(HeapObjectHeader); |
864 } | 868 } |
865 | 869 |
866 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { | 870 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
978 return outOfLineAllocate(allocationSize, gcInfoIndex); | 982 return outOfLineAllocate(allocationSize, gcInfoIndex); |
979 } | 983 } |
980 | 984 |
981 inline NormalPageArena* NormalPage::arenaForNormalPage() const { | 985 inline NormalPageArena* NormalPage::arenaForNormalPage() const { |
982 return static_cast<NormalPageArena*>(arena()); | 986 return static_cast<NormalPageArena*>(arena()); |
983 } | 987 } |
984 | 988 |
985 } // namespace blink | 989 } // namespace blink |
986 | 990 |
987 #endif // HeapPage_h | 991 #endif // HeapPage_h |
OLD | NEW |