OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 // three areas: the first two words are used for bookkeeping, the next 248 | 92 // three areas: the first two words are used for bookkeeping, the next 248 |
93 // bytes are used as remembered set, and the rest of the page is the object | 93 // bytes are used as remembered set, and the rest of the page is the object |
94 // area. | 94 // area. |
95 // | 95 // |
96 // Pointers are aligned to the pointer size (4), only 1 bit is needed | 96 // Pointers are aligned to the pointer size (4), only 1 bit is needed |
97 // for a pointer in the remembered set. Given an address, its remembered set | 97 // for a pointer in the remembered set. Given an address, its remembered set |
98 // bit position (offset from the start of the page) is calculated by dividing | 98 // bit position (offset from the start of the page) is calculated by dividing |
99 // its page offset by 32. Therefore, the object area in a page starts at the | 99 // its page offset by 32. Therefore, the object area in a page starts at the |
100 // 256th byte (8K/32). Bytes 0 to 255 do not need the remembered set, so that | 100 // 256th byte (8K/32). Bytes 0 to 255 do not need the remembered set, so that |
101 // the first two words (64 bits) in a page can be used for other purposes. | 101 // the first two words (64 bits) in a page can be used for other purposes. |
102 // TODO(X64): This description only represents the 32-bit layout. | 102 // |
103 // On the 64-bit platform, we add an offset to the start of the remembered set. | 103 // On the 64-bit platform, we add an offset to the start of the remembered set, |
| 104 // and pointers are aligned to 8-byte pointer size. This means that we need |
| 105 // only 128 bytes for the RSet, and only get two bytes free in the RSet's RSet. |
| 106 // For this reason we add an offset to get room for the Page data at the start. |
104 // | 107 // |
105 // The mark-compact collector transforms a map pointer into a page index and a | 108 // The mark-compact collector transforms a map pointer into a page index and a |
106 // page offset. The map space can have up to 1024 pages, and 8M bytes (1024 * | 109 // page offset. The map space can have up to 1024 pages, and 8M bytes (1024 * |
107 // 8K) in total. Because a map pointer is aligned to the pointer size (4 | 110 // 8K) in total. Because a map pointer is aligned to the pointer size (4 |
108 // bytes), 11 bits are enough to encode the page offset. 21 bits (10 for the | 111 // bytes), 11 bits are enough to encode the page offset. 21 bits (10 for the |
109 // page index + 11 for the offset in the page) are required to encode a map | 112 // page index + 11 for the offset in the page) are required to encode a map |
110 // pointer. | 113 // pointer. |
111 // | 114 // |
112 // The only way to get a page pointer is by calling factory methods: | 115 // The only way to get a page pointer is by calling factory methods: |
113 // Page* p = Page::FromAddress(addr); or | 116 // Page* p = Page::FromAddress(addr); or |
114 // Page* p = Page::FromAllocationTop(top); | 117 // Page* p = Page::FromAllocationTop(top); |
115 class Page { | 118 class Page { |
116 public: | 119 public: |
117 // Returns the page containing a given address. The address ranges | 120 // Returns the page containing a given address. The address ranges |
118 // from [page_addr .. page_addr + kPageSize[ | 121 // from [page_addr .. page_addr + kPageSize[ |
119 // | 122 // |
120 // Note that this function only works for addresses in normal paged | 123 // Note that this function only works for addresses in normal paged |
121 // spaces and addresses in the first 8K of large object pages (ie, | 124 // spaces and addresses in the first 8K of large object pages (i.e., |
122 // the start of large objects but not necessarily derived pointers | 125 // the start of large objects but not necessarily derived pointers |
123 // within them). | 126 // within them). |
124 INLINE(static Page* FromAddress(Address a)) { | 127 INLINE(static Page* FromAddress(Address a)) { |
125 return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask); | 128 return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask); |
126 } | 129 } |
127 | 130 |
128 // Returns the page containing an allocation top. Because an allocation | 131 // Returns the page containing an allocation top. Because an allocation |
129 // top address can be the upper bound of the page, we need to subtract | 132 // top address can be the upper bound of the page, we need to subtract |
130 // it with kPointerSize first. The address ranges from | 133 // it with kPointerSize first. The address ranges from |
131 // [page_addr + kObjectStartOffset .. page_addr + kPageSize]. | 134 // [page_addr + kObjectStartOffset .. page_addr + kPageSize]. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 | 214 |
212 // 8K bytes per page. | 215 // 8K bytes per page. |
213 static const int kPageSizeBits = 13; | 216 static const int kPageSizeBits = 13; |
214 | 217 |
215 // Page size in bytes. This must be a multiple of the OS page size. | 218 // Page size in bytes. This must be a multiple of the OS page size. |
216 static const int kPageSize = 1 << kPageSizeBits; | 219 static const int kPageSize = 1 << kPageSizeBits; |
217 | 220 |
218 // Page size mask. | 221 // Page size mask. |
219 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; | 222 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; |
220 | 223 |
221 // The offset of the remembered set in a page, in addition to the empty words | 224 // The offset of the remembered set in a page, in addition to the empty bytes |
222 // formed as the remembered bits of the remembered set itself. | 225 // formed as the remembered bits of the remembered set itself. |
223 #ifdef V8_TARGET_ARCH_X64 | 226 #ifdef V8_TARGET_ARCH_X64 |
224 static const int kRSetOffset = 4 * kPointerSize; // Room for four pointers. | 227 static const int kRSetOffset = 4 * kPointerSize; // Room for four pointers. |
225 #else | 228 #else |
226 static const int kRSetOffset = 0; | 229 static const int kRSetOffset = 0; |
227 #endif | 230 #endif |
228 // The end offset of the remembered set in a page | 231 // The end offset of the remembered set in a page |
229 // (heaps are aligned to pointer size). | 232 // (heaps are aligned to pointer size). |
230 static const int kRSetEndOffset = kRSetOffset + kPageSize / kBitsPerPointer; | 233 static const int kRSetEndOffset = kRSetOffset + kPageSize / kBitsPerPointer; |
231 | 234 |
232 // The start offset of the object area in a page. | 235 // The start offset of the object area in a page. |
233 // This needs to be at least (bits per uint32_t) * kBitsPerPointer, | 236 // This needs to be at least (bits per uint32_t) * kBitsPerPointer, |
234 // to align start of rset to a uint32_t address. | 237 // to align start of rset to a uint32_t address. |
235 static const int kObjectStartOffset = 256; | 238 static const int kObjectStartOffset = 256; |
236 | 239 |
237 // The start offset of the remembered set in a page. | 240 // The start offset of the used part of the remembered set in a page. |
238 static const int kRSetStartOffset = kRSetOffset + | 241 static const int kRSetStartOffset = kRSetOffset + |
239 kObjectStartOffset / kBitsPerPointer; | 242 kObjectStartOffset / kBitsPerPointer; |
240 | 243 |
241 // Object area size in bytes. | 244 // Object area size in bytes. |
242 static const int kObjectAreaSize = kPageSize - kObjectStartOffset; | 245 static const int kObjectAreaSize = kPageSize - kObjectStartOffset; |
243 | 246 |
244 // Maximum object size that fits in a page. | 247 // Maximum object size that fits in a page. |
245 static const int kMaxHeapObjectSize = kObjectAreaSize; | 248 static const int kMaxHeapObjectSize = kObjectAreaSize; |
246 | 249 |
247 //--------------------------------------------------------------------------- | 250 //--------------------------------------------------------------------------- |
248 // Page header description. | 251 // Page header description. |
249 // | 252 // |
250 // If a page is not in the large object space, the first word, | 253 // If a page is not in the large object space, the first word, |
251 // opaque_header, encodes the next page address (aligned to kPageSize 8K) | 254 // opaque_header, encodes the next page address (aligned to kPageSize 8K) |
252 // and the chunk number (0 ~ 8K-1). Only MemoryAllocator should use | 255 // and the chunk number (0 ~ 8K-1). Only MemoryAllocator should use |
253 // opaque_header. The value range of the opaque_header is [0..kPageSize[, | 256 // opaque_header. The value range of the opaque_header is [0..kPageSize[, |
254 // or [next_page_start, next_page_end[. It cannot point to a valid address | 257 // or [next_page_start, next_page_end[. It cannot point to a valid address |
255 // in the current page. If a page is in the large object space, the first | 258 // in the current page. If a page is in the large object space, the first |
256 // word *may* (if the page start and large object chunk start are the | 259 // word *may* (if the page start and large object chunk start are the |
257 // same) contain the address of the next large object chunk. | 260 // same) contain the address of the next large object chunk. |
258 intptr_t opaque_header; | 261 intptr_t opaque_header; |
259 | 262 |
260 // If the page is not in the large object space, the low-order bit of the | 263 // If the page is not in the large object space, the low-order bit of the |
261 // second word is set. If the page is in the large object space, the | 264 // second word is set. If the page is in the large object space, the |
262 // second word *may* (if the page start and large object chunk start are | 265 // second word *may* (if the page start and large object chunk start are |
263 // the same) contain the large object chunk size. In either case, the | 266 // the same) contain the large object chunk size. In either case, the |
264 // low-order bit for large object pages will be cleared. | 267 // low-order bit for large object pages will be cleared. |
265 int is_normal_page; | 268 int is_normal_page; |
266 | 269 |
267 // The following fields overlap with remembered set, they can only | 270 // The following fields may overlap with remembered set, they can only |
268 // be used in the mark-compact collector when remembered set is not | 271 // be used in the mark-compact collector when remembered set is not |
269 // used. | 272 // used. |
270 | 273 |
| 274 // The index of the page in its owner space. |
| 275 int mc_page_index; |
| 276 |
271 // The allocation pointer after relocating objects to this page. | 277 // The allocation pointer after relocating objects to this page. |
272 Address mc_relocation_top; | 278 Address mc_relocation_top; |
273 | 279 |
274 // The index of the page in its owner space. | |
275 int mc_page_index; | |
276 | |
277 // The forwarding address of the first live object in this page. | 280 // The forwarding address of the first live object in this page. |
278 Address mc_first_forwarded; | 281 Address mc_first_forwarded; |
279 | 282 |
280 #ifdef DEBUG | 283 #ifdef DEBUG |
281 private: | 284 private: |
282 static RSetState rset_state_; // state of the remembered set | 285 static RSetState rset_state_; // state of the remembered set |
283 #endif | 286 #endif |
284 }; | 287 }; |
285 | 288 |
286 | 289 |
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 Address bottom() { return to_space_.low(); } | 1161 Address bottom() { return to_space_.low(); } |
1159 | 1162 |
1160 // Get the age mark of the inactive semispace. | 1163 // Get the age mark of the inactive semispace. |
1161 Address age_mark() { return from_space_.age_mark(); } | 1164 Address age_mark() { return from_space_.age_mark(); } |
1162 // Set the age mark in the active semispace. | 1165 // Set the age mark in the active semispace. |
1163 void set_age_mark(Address mark) { to_space_.set_age_mark(mark); } | 1166 void set_age_mark(Address mark) { to_space_.set_age_mark(mark); } |
1164 | 1167 |
1165 // The start address of the space and a bit mask. Anding an address in the | 1168 // The start address of the space and a bit mask. Anding an address in the |
1166 // new space with the mask will result in the start address. | 1169 // new space with the mask will result in the start address. |
1167 Address start() { return start_; } | 1170 Address start() { return start_; } |
1168 uint32_t mask() { return address_mask_; } | 1171 uintptr_t mask() { return address_mask_; } |
1169 | 1172 |
1170 // The allocation top and limit addresses. | 1173 // The allocation top and limit addresses. |
1171 Address* allocation_top_address() { return &allocation_info_.top; } | 1174 Address* allocation_top_address() { return &allocation_info_.top; } |
1172 Address* allocation_limit_address() { return &allocation_info_.limit; } | 1175 Address* allocation_limit_address() { return &allocation_info_.limit; } |
1173 | 1176 |
1174 Object* AllocateRaw(int size_in_bytes) { | 1177 Object* AllocateRaw(int size_in_bytes) { |
1175 return AllocateRawInternal(size_in_bytes, &allocation_info_); | 1178 return AllocateRawInternal(size_in_bytes, &allocation_info_); |
1176 } | 1179 } |
1177 | 1180 |
1178 // Allocate the requested number of bytes for relocation during mark-compact | 1181 // Allocate the requested number of bytes for relocation during mark-compact |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1806 | 1809 |
1807 private: | 1810 private: |
1808 LargeObjectChunk* current_; | 1811 LargeObjectChunk* current_; |
1809 HeapObjectCallback size_func_; | 1812 HeapObjectCallback size_func_; |
1810 }; | 1813 }; |
1811 | 1814 |
1812 | 1815 |
1813 } } // namespace v8::internal | 1816 } } // namespace v8::internal |
1814 | 1817 |
1815 #endif // V8_SPACES_H_ | 1818 #endif // V8_SPACES_H_ |
OLD | NEW |