| 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 |