| OLD | NEW |
| 1 // Copyright 2006-2010 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2010 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 prev_page_ = (prev_page_ == NULL) | 48 prev_page_ = (prev_page_ == NULL) |
| 49 ? space_->first_page_ | 49 ? space_->first_page_ |
| 50 : prev_page_->next_page(); | 50 : prev_page_->next_page(); |
| 51 return prev_page_; | 51 return prev_page_; |
| 52 } | 52 } |
| 53 | 53 |
| 54 | 54 |
| 55 // ----------------------------------------------------------------------------- | 55 // ----------------------------------------------------------------------------- |
| 56 // Page | 56 // Page |
| 57 | 57 |
| 58 Page* Page::next_page() { | |
| 59 return MemoryAllocator::GetNextPage(this); | |
| 60 } | |
| 61 | |
| 62 | 58 |
| 63 Address Page::AllocationTop() { | 59 Address Page::AllocationTop() { |
| 64 PagedSpace* owner = MemoryAllocator::PageOwner(this); | 60 return static_cast<PagedSpace*>(owner())->PageAllocationTop(this); |
| 65 return owner->PageAllocationTop(this); | |
| 66 } | 61 } |
| 67 | 62 |
| 68 | 63 |
| 69 Address Page::AllocationWatermark() { | 64 Address Page::AllocationWatermark() { |
| 70 PagedSpace* owner = MemoryAllocator::PageOwner(this); | 65 if (this == static_cast<PagedSpace*>(owner())->AllocationTopPage()) { |
| 71 if (this == owner->AllocationTopPage()) { | 66 return static_cast<PagedSpace*>(owner())->top(); |
| 72 return owner->top(); | |
| 73 } | 67 } |
| 74 return address() + AllocationWatermarkOffset(); | 68 return address() + AllocationWatermarkOffset(); |
| 75 } | 69 } |
| 76 | 70 |
| 77 | 71 |
| 78 uint32_t Page::AllocationWatermarkOffset() { | 72 uint32_t Page::AllocationWatermarkOffset() { |
| 79 return static_cast<uint32_t>((flags_ & kAllocationWatermarkOffsetMask) >> | 73 return static_cast<uint32_t>((flags_ & kAllocationWatermarkOffsetMask) >> |
| 80 kAllocationWatermarkOffsetShift); | 74 kAllocationWatermarkOffsetShift); |
| 81 } | 75 } |
| 82 | 76 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 97 } | 91 } |
| 98 | 92 |
| 99 flags_ = (flags_ & kFlagsMask) | | 93 flags_ = (flags_ & kFlagsMask) | |
| 100 Offset(allocation_watermark) << kAllocationWatermarkOffsetShift; | 94 Offset(allocation_watermark) << kAllocationWatermarkOffsetShift; |
| 101 ASSERT(AllocationWatermarkOffset() | 95 ASSERT(AllocationWatermarkOffset() |
| 102 == static_cast<uint32_t>(Offset(allocation_watermark))); | 96 == static_cast<uint32_t>(Offset(allocation_watermark))); |
| 103 } | 97 } |
| 104 | 98 |
| 105 | 99 |
| 106 void Page::SetCachedAllocationWatermark(Address allocation_watermark) { | 100 void Page::SetCachedAllocationWatermark(Address allocation_watermark) { |
| 107 mc_first_forwarded = allocation_watermark; | 101 allocation_watermark_ = allocation_watermark; |
| 108 } | 102 } |
| 109 | 103 |
| 110 | 104 |
| 111 Address Page::CachedAllocationWatermark() { | 105 Address Page::CachedAllocationWatermark() { |
| 112 return mc_first_forwarded; | 106 return allocation_watermark_; |
| 113 } | 107 } |
| 114 | 108 |
| 115 | 109 |
| 116 uint32_t Page::GetRegionMarks() { | 110 uint32_t Page::GetRegionMarks() { |
| 117 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | 111 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 118 return dirty_regions_; | 112 return dirty_regions_; |
| 119 #else | 113 #else |
| 120 return kAllRegionsDirtyMarks; | 114 return kAllRegionsDirtyMarks; |
| 121 #endif | 115 #endif |
| 122 } | 116 } |
| 123 | 117 |
| 124 | 118 |
| 125 void Page::SetRegionMarks(uint32_t marks) { | 119 void Page::SetRegionMarks(uint32_t marks) { |
| 126 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | 120 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 127 dirty_regions_ = marks; | 121 dirty_regions_ = marks; |
| 128 #endif | 122 #endif |
| 129 } | 123 } |
| 130 | 124 |
| 131 | 125 |
| 132 int Page::GetRegionNumberForAddress(Address addr) { | 126 int Page::GetRegionNumberForAddress(Address addr) { |
| 127 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 133 // Each page is divided into 256 byte regions. Each region has a corresponding | 128 // Each page is divided into 256 byte regions. Each region has a corresponding |
| 134 // dirty mark bit in the page header. Region can contain intergenerational | 129 // dirty mark bit in the page header. Region can contain intergenerational |
| 135 // references iff its dirty mark is set. | 130 // references iff its dirty mark is set. |
| 136 // A normal 8K page contains exactly 32 regions so all region marks fit | 131 // A normal 8K page contains exactly 32 regions so all region marks fit |
| 137 // into 32-bit integer field. To calculate a region number we just divide | 132 // into 32-bit integer field. To calculate a region number we just divide |
| 138 // offset inside page by region size. | 133 // offset inside page by region size. |
| 139 // A large page can contain more then 32 regions. But we want to avoid | 134 // A large page can contain more then 32 regions. But we want to avoid |
| 140 // additional write barrier code for distinguishing between large and normal | 135 // additional write barrier code for distinguishing between large and normal |
| 141 // pages so we just ignore the fact that addr points into a large page and | 136 // pages so we just ignore the fact that addr points into a large page and |
| 142 // calculate region number as if addr pointed into a normal 8K page. This way | 137 // calculate region number as if addr pointed into a normal 8K page. This way |
| 143 // we get a region number modulo 32 so for large pages several regions might | 138 // we get a region number modulo 32 so for large pages several regions might |
| 144 // be mapped to a single dirty mark. | 139 // be mapped to a single dirty mark. |
| 145 ASSERT_PAGE_ALIGNED(this->address()); | 140 ASSERT_PAGE_ALIGNED(this->address()); |
| 146 STATIC_ASSERT((kPageAlignmentMask >> kRegionSizeLog2) < kBitsPerInt); | 141 STATIC_ASSERT((kPageAlignmentMask >> kRegionSizeLog2) < kBitsPerInt); |
| 147 | 142 |
| 148 // We are using masking with kPageAlignmentMask instead of Page::Offset() | 143 // We are using masking with kPageAlignmentMask instead of Page::Offset() |
| 149 // to get an offset to the beginning of 8K page containing addr not to the | 144 // to get an offset to the beginning of 8K page containing addr not to the |
| 150 // beginning of actual page which can be bigger then 8K. | 145 // beginning of actual page which can be bigger then 8K. |
| 151 intptr_t offset_inside_normal_page = OffsetFrom(addr) & kPageAlignmentMask; | 146 intptr_t offset_inside_normal_page = OffsetFrom(addr) & kPageAlignmentMask; |
| 152 return static_cast<int>(offset_inside_normal_page >> kRegionSizeLog2); | 147 return static_cast<int>(offset_inside_normal_page >> kRegionSizeLog2); |
| 148 #else |
| 149 return 0; |
| 150 #endif |
| 153 } | 151 } |
| 154 | 152 |
| 155 | 153 |
| 156 uint32_t Page::GetRegionMaskForAddress(Address addr) { | 154 uint32_t Page::GetRegionMaskForAddress(Address addr) { |
| 157 return 1 << GetRegionNumberForAddress(addr); | 155 return 1 << GetRegionNumberForAddress(addr); |
| 158 } | 156 } |
| 159 | 157 |
| 160 | 158 |
| 161 uint32_t Page::GetRegionMaskForSpan(Address start, int length_in_bytes) { | 159 uint32_t Page::GetRegionMaskForSpan(Address start, int length_in_bytes) { |
| 160 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 162 uint32_t result = 0; | 161 uint32_t result = 0; |
| 163 if (length_in_bytes >= kPageSize) { | 162 if (length_in_bytes >= kPageSize) { |
| 164 result = kAllRegionsDirtyMarks; | 163 result = kAllRegionsDirtyMarks; |
| 165 } else if (length_in_bytes > 0) { | 164 } else if (length_in_bytes > 0) { |
| 166 int start_region = GetRegionNumberForAddress(start); | 165 int start_region = GetRegionNumberForAddress(start); |
| 167 int end_region = | 166 int end_region = |
| 168 GetRegionNumberForAddress(start + length_in_bytes - kPointerSize); | 167 GetRegionNumberForAddress(start + length_in_bytes - kPointerSize); |
| 169 uint32_t start_mask = (~0) << start_region; | 168 uint32_t start_mask = (~0) << start_region; |
| 170 uint32_t end_mask = ~((~1) << end_region); | 169 uint32_t end_mask = ~((~1) << end_region); |
| 171 result = start_mask & end_mask; | 170 result = start_mask & end_mask; |
| 172 // if end_region < start_region, the mask is ored. | 171 // if end_region < start_region, the mask is ored. |
| 173 if (result == 0) result = start_mask | end_mask; | 172 if (result == 0) result = start_mask | end_mask; |
| 174 } | 173 } |
| 175 #ifdef DEBUG | 174 #ifdef DEBUG |
| 176 if (FLAG_enable_slow_asserts) { | 175 if (FLAG_enable_slow_asserts) { |
| 177 uint32_t expected = 0; | 176 uint32_t expected = 0; |
| 178 for (Address a = start; a < start + length_in_bytes; a += kPointerSize) { | 177 for (Address a = start; a < start + length_in_bytes; a += kPointerSize) { |
| 179 expected |= GetRegionMaskForAddress(a); | 178 expected |= GetRegionMaskForAddress(a); |
| 180 } | 179 } |
| 181 ASSERT(expected == result); | 180 ASSERT(expected == result); |
| 182 } | 181 } |
| 183 #endif | 182 #endif |
| 184 return result; | 183 return result; |
| 184 #else |
| 185 return Page::kAllRegionsDirtyMarks; |
| 186 #endif |
| 185 } | 187 } |
| 186 | 188 |
| 187 | 189 |
| 188 void Page::MarkRegionDirty(Address address) { | 190 void Page::MarkRegionDirty(Address address) { |
| 189 SetRegionMarks(GetRegionMarks() | GetRegionMaskForAddress(address)); | 191 SetRegionMarks(GetRegionMarks() | GetRegionMaskForAddress(address)); |
| 190 } | 192 } |
| 191 | 193 |
| 192 | 194 |
| 193 bool Page::IsRegionDirty(Address address) { | 195 bool Page::IsRegionDirty(Address address) { |
| 194 return GetRegionMarks() & GetRegionMaskForAddress(address); | 196 return GetRegionMarks() & GetRegionMaskForAddress(address); |
| 195 } | 197 } |
| 196 | 198 |
| 197 | 199 |
| 198 void Page::ClearRegionMarks(Address start, Address end, bool reaches_limit) { | 200 void Page::ClearRegionMarks(Address start, Address end, bool reaches_limit) { |
| 201 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 199 int rstart = GetRegionNumberForAddress(start); | 202 int rstart = GetRegionNumberForAddress(start); |
| 200 int rend = GetRegionNumberForAddress(end); | 203 int rend = GetRegionNumberForAddress(end); |
| 201 | 204 |
| 202 if (reaches_limit) { | 205 if (reaches_limit) { |
| 203 end += 1; | 206 end += 1; |
| 204 } | 207 } |
| 205 | 208 |
| 206 if ((rend - rstart) == 0) { | 209 if ((rend - rstart) == 0) { |
| 207 return; | 210 return; |
| 208 } | 211 } |
| 209 | 212 |
| 210 uint32_t bitmask = 0; | 213 uint32_t bitmask = 0; |
| 211 | 214 |
| 212 if ((OffsetFrom(start) & kRegionAlignmentMask) == 0 | 215 if ((OffsetFrom(start) & kRegionAlignmentMask) == 0 |
| 213 || (start == ObjectAreaStart())) { | 216 || (start == ObjectAreaStart())) { |
| 214 // First region is fully covered | 217 // First region is fully covered |
| 215 bitmask = 1 << rstart; | 218 bitmask = 1 << rstart; |
| 216 } | 219 } |
| 217 | 220 |
| 218 while (++rstart < rend) { | 221 while (++rstart < rend) { |
| 219 bitmask |= 1 << rstart; | 222 bitmask |= 1 << rstart; |
| 220 } | 223 } |
| 221 | 224 |
| 222 if (bitmask) { | 225 if (bitmask) { |
| 223 SetRegionMarks(GetRegionMarks() & ~bitmask); | 226 SetRegionMarks(GetRegionMarks() & ~bitmask); |
| 224 } | 227 } |
| 228 #endif |
| 225 } | 229 } |
| 226 | 230 |
| 227 | 231 |
| 228 void Page::FlipMeaningOfInvalidatedWatermarkFlag() { | 232 void Page::FlipMeaningOfInvalidatedWatermarkFlag() { |
| 229 watermark_invalidated_mark_ ^= 1 << WATERMARK_INVALIDATED; | 233 watermark_invalidated_mark_ ^= 1 << WATERMARK_INVALIDATED; |
| 230 } | 234 } |
| 231 | 235 |
| 232 | 236 |
| 233 bool Page::IsWatermarkValid() { | 237 bool Page::IsWatermarkValid() { |
| 234 return (flags_ & (1 << WATERMARK_INVALIDATED)) != watermark_invalidated_mark_; | 238 return (flags_ & (1 << WATERMARK_INVALIDATED)) != watermark_invalidated_mark_; |
| 235 } | 239 } |
| 236 | 240 |
| 237 | 241 |
| 238 void Page::InvalidateWatermark(bool value) { | 242 void Page::InvalidateWatermark(bool value) { |
| 239 if (value) { | 243 if (value) { |
| 240 flags_ = (flags_ & ~(1 << WATERMARK_INVALIDATED)) | | 244 flags_ = (flags_ & ~(1 << WATERMARK_INVALIDATED)) | |
| 241 watermark_invalidated_mark_; | 245 watermark_invalidated_mark_; |
| 242 } else { | 246 } else { |
| 243 flags_ = (flags_ & ~(1 << WATERMARK_INVALIDATED)) | | 247 flags_ = (flags_ & ~(1 << WATERMARK_INVALIDATED)) | |
| 244 (watermark_invalidated_mark_ ^ (1 << WATERMARK_INVALIDATED)); | 248 (watermark_invalidated_mark_ ^ (1 << WATERMARK_INVALIDATED)); |
| 245 } | 249 } |
| 246 | 250 |
| 247 ASSERT(IsWatermarkValid() == !value); | 251 ASSERT(IsWatermarkValid() == !value); |
| 248 } | 252 } |
| 249 | 253 |
| 250 | 254 |
| 251 bool Page::GetPageFlag(PageFlag flag) { | |
| 252 return (flags_ & static_cast<intptr_t>(1 << flag)) != 0; | |
| 253 } | |
| 254 | |
| 255 | |
| 256 void Page::SetPageFlag(PageFlag flag, bool value) { | |
| 257 if (value) { | |
| 258 flags_ |= static_cast<intptr_t>(1 << flag); | |
| 259 } else { | |
| 260 flags_ &= ~static_cast<intptr_t>(1 << flag); | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 | |
| 265 void Page::ClearPageFlags() { | |
| 266 flags_ = 0; | |
| 267 } | |
| 268 | |
| 269 | |
| 270 void Page::ClearGCFields() { | 255 void Page::ClearGCFields() { |
| 271 InvalidateWatermark(true); | 256 InvalidateWatermark(true); |
| 272 SetAllocationWatermark(ObjectAreaStart()); | 257 SetAllocationWatermark(ObjectAreaStart()); |
| 273 if (Heap::gc_state() == Heap::SCAVENGE) { | 258 if (Heap::gc_state() == Heap::SCAVENGE) { |
| 274 SetCachedAllocationWatermark(ObjectAreaStart()); | 259 SetCachedAllocationWatermark(ObjectAreaStart()); |
| 275 } | 260 } |
| 276 SetRegionMarks(kAllRegionsCleanMarks); | 261 SetRegionMarks(kAllRegionsCleanMarks); |
| 277 } | 262 } |
| 278 | 263 |
| 279 | 264 |
| 280 bool Page::WasInUseBeforeMC() { | |
| 281 return GetPageFlag(WAS_IN_USE_BEFORE_MC); | |
| 282 } | |
| 283 | |
| 284 | |
| 285 void Page::SetWasInUseBeforeMC(bool was_in_use) { | |
| 286 SetPageFlag(WAS_IN_USE_BEFORE_MC, was_in_use); | |
| 287 } | |
| 288 | |
| 289 | |
| 290 bool Page::IsLargeObjectPage() { | |
| 291 return !GetPageFlag(IS_NORMAL_PAGE); | |
| 292 } | |
| 293 | |
| 294 | |
| 295 void Page::SetIsLargeObjectPage(bool is_large_object_page) { | |
| 296 SetPageFlag(IS_NORMAL_PAGE, !is_large_object_page); | |
| 297 } | |
| 298 | |
| 299 bool Page::IsPageExecutable() { | |
| 300 return GetPageFlag(IS_EXECUTABLE); | |
| 301 } | |
| 302 | |
| 303 | |
| 304 void Page::SetIsPageExecutable(bool is_page_executable) { | |
| 305 SetPageFlag(IS_EXECUTABLE, is_page_executable); | |
| 306 } | |
| 307 | |
| 308 | |
| 309 // ----------------------------------------------------------------------------- | 265 // ----------------------------------------------------------------------------- |
| 310 // MemoryAllocator | 266 // MemoryAllocator |
| 311 | 267 |
| 312 void MemoryAllocator::ChunkInfo::init(Address a, size_t s, PagedSpace* o) { | |
| 313 address_ = a; | |
| 314 size_ = s; | |
| 315 owner_ = o; | |
| 316 executable_ = (o == NULL) ? NOT_EXECUTABLE : o->executable(); | |
| 317 } | |
| 318 | |
| 319 | |
| 320 bool MemoryAllocator::IsValidChunk(int chunk_id) { | |
| 321 if (!IsValidChunkId(chunk_id)) return false; | |
| 322 | |
| 323 ChunkInfo& c = chunks_[chunk_id]; | |
| 324 return (c.address() != NULL) && (c.size() != 0) && (c.owner() != NULL); | |
| 325 } | |
| 326 | |
| 327 | |
| 328 bool MemoryAllocator::IsValidChunkId(int chunk_id) { | |
| 329 return (0 <= chunk_id) && (chunk_id < max_nof_chunks_); | |
| 330 } | |
| 331 | |
| 332 | |
| 333 bool MemoryAllocator::IsPageInSpace(Page* p, PagedSpace* space) { | |
| 334 ASSERT(p->is_valid()); | |
| 335 | |
| 336 int chunk_id = GetChunkId(p); | |
| 337 if (!IsValidChunkId(chunk_id)) return false; | |
| 338 | |
| 339 ChunkInfo& c = chunks_[chunk_id]; | |
| 340 return (c.address() <= p->address()) && | |
| 341 (p->address() < c.address() + c.size()) && | |
| 342 (space == c.owner()); | |
| 343 } | |
| 344 | |
| 345 | |
| 346 Page* MemoryAllocator::GetNextPage(Page* p) { | |
| 347 ASSERT(p->is_valid()); | |
| 348 intptr_t raw_addr = p->opaque_header & ~Page::kPageAlignmentMask; | |
| 349 return Page::FromAddress(AddressFrom<Address>(raw_addr)); | |
| 350 } | |
| 351 | |
| 352 | |
| 353 int MemoryAllocator::GetChunkId(Page* p) { | |
| 354 ASSERT(p->is_valid()); | |
| 355 return static_cast<int>(p->opaque_header & Page::kPageAlignmentMask); | |
| 356 } | |
| 357 | |
| 358 | |
| 359 void MemoryAllocator::SetNextPage(Page* prev, Page* next) { | |
| 360 ASSERT(prev->is_valid()); | |
| 361 int chunk_id = GetChunkId(prev); | |
| 362 ASSERT_PAGE_ALIGNED(next->address()); | |
| 363 prev->opaque_header = OffsetFrom(next->address()) | chunk_id; | |
| 364 } | |
| 365 | |
| 366 | |
| 367 PagedSpace* MemoryAllocator::PageOwner(Page* page) { | |
| 368 int chunk_id = GetChunkId(page); | |
| 369 ASSERT(IsValidChunk(chunk_id)); | |
| 370 return chunks_[chunk_id].owner(); | |
| 371 } | |
| 372 | |
| 373 | |
| 374 bool MemoryAllocator::InInitialChunk(Address address) { | |
| 375 if (initial_chunk_ == NULL) return false; | |
| 376 | |
| 377 Address start = static_cast<Address>(initial_chunk_->address()); | |
| 378 return (start <= address) && (address < start + initial_chunk_->size()); | |
| 379 } | |
| 380 | |
| 381 | |
| 382 #ifdef ENABLE_HEAP_PROTECTION | 268 #ifdef ENABLE_HEAP_PROTECTION |
| 383 | 269 |
| 384 void MemoryAllocator::Protect(Address start, size_t size) { | 270 void MemoryAllocator::Protect(Address start, size_t size) { |
| 385 OS::Protect(start, size); | 271 OS::Protect(start, size); |
| 386 } | 272 } |
| 387 | 273 |
| 388 | 274 |
| 389 void MemoryAllocator::Unprotect(Address start, | 275 void MemoryAllocator::Unprotect(Address start, |
| 390 size_t size, | 276 size_t size, |
| 391 Executability executable) { | 277 Executability executable) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 407 | 293 |
| 408 #endif | 294 #endif |
| 409 | 295 |
| 410 | 296 |
| 411 // -------------------------------------------------------------------------- | 297 // -------------------------------------------------------------------------- |
| 412 // PagedSpace | 298 // PagedSpace |
| 413 | 299 |
| 414 bool PagedSpace::Contains(Address addr) { | 300 bool PagedSpace::Contains(Address addr) { |
| 415 Page* p = Page::FromAddress(addr); | 301 Page* p = Page::FromAddress(addr); |
| 416 if (!p->is_valid()) return false; | 302 if (!p->is_valid()) return false; |
| 417 return MemoryAllocator::IsPageInSpace(p, this); | 303 return p->owner() == this; |
| 418 } | 304 } |
| 419 | 305 |
| 420 | 306 |
| 421 bool PagedSpace::SafeContains(Address addr) { | |
| 422 if (!MemoryAllocator::SafeIsInAPageChunk(addr)) return false; | |
| 423 Page* p = Page::FromAddress(addr); | |
| 424 if (!p->is_valid()) return false; | |
| 425 return MemoryAllocator::IsPageInSpace(p, this); | |
| 426 } | |
| 427 | |
| 428 | |
| 429 // Try linear allocation in the page of alloc_info's allocation top. Does | 307 // Try linear allocation in the page of alloc_info's allocation top. Does |
| 430 // not contain slow case logic (eg, move to the next page or try free list | 308 // not contain slow case logic (eg, move to the next page or try free list |
| 431 // allocation) so it can be used by all the allocation functions and for all | 309 // allocation) so it can be used by all the allocation functions and for all |
| 432 // the paged spaces. | 310 // the paged spaces. |
| 433 HeapObject* PagedSpace::AllocateLinearly(AllocationInfo* alloc_info, | 311 HeapObject* PagedSpace::AllocateLinearly(AllocationInfo* alloc_info, |
| 434 int size_in_bytes) { | 312 int size_in_bytes) { |
| 435 Address current_top = alloc_info->top; | 313 Address current_top = alloc_info->top; |
| 436 Address new_top = current_top + size_in_bytes; | 314 Address new_top = current_top + size_in_bytes; |
| 437 if (new_top > alloc_info->limit) return NULL; | 315 if (new_top > alloc_info->limit) return NULL; |
| 438 | 316 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 450 HeapObject* object = AllocateLinearly(&allocation_info_, size_in_bytes); | 328 HeapObject* object = AllocateLinearly(&allocation_info_, size_in_bytes); |
| 451 if (object != NULL) return object; | 329 if (object != NULL) return object; |
| 452 | 330 |
| 453 object = SlowAllocateRaw(size_in_bytes); | 331 object = SlowAllocateRaw(size_in_bytes); |
| 454 if (object != NULL) return object; | 332 if (object != NULL) return object; |
| 455 | 333 |
| 456 return Failure::RetryAfterGC(identity()); | 334 return Failure::RetryAfterGC(identity()); |
| 457 } | 335 } |
| 458 | 336 |
| 459 | 337 |
| 460 // Reallocating (and promoting) objects during a compacting collection. | |
| 461 MaybeObject* PagedSpace::MCAllocateRaw(int size_in_bytes) { | |
| 462 ASSERT(HasBeenSetup()); | |
| 463 ASSERT_OBJECT_SIZE(size_in_bytes); | |
| 464 HeapObject* object = AllocateLinearly(&mc_forwarding_info_, size_in_bytes); | |
| 465 if (object != NULL) return object; | |
| 466 | |
| 467 object = SlowMCAllocateRaw(size_in_bytes); | |
| 468 if (object != NULL) return object; | |
| 469 | |
| 470 return Failure::RetryAfterGC(identity()); | |
| 471 } | |
| 472 | |
| 473 | |
| 474 // ----------------------------------------------------------------------------- | 338 // ----------------------------------------------------------------------------- |
| 475 // LargeObjectChunk | |
| 476 | |
| 477 Address LargeObjectChunk::GetStartAddress() { | |
| 478 // Round the chunk address up to the nearest page-aligned address | |
| 479 // and return the heap object in that page. | |
| 480 Page* page = Page::FromAddress(RoundUp(address(), Page::kPageSize)); | |
| 481 return page->ObjectAreaStart(); | |
| 482 } | |
| 483 | |
| 484 | |
| 485 void LargeObjectChunk::Free(Executability executable) { | |
| 486 MemoryAllocator::FreeRawMemory(address(), size(), executable); | |
| 487 } | |
| 488 | |
| 489 // ----------------------------------------------------------------------------- | |
| 490 // NewSpace | 339 // NewSpace |
| 491 | 340 |
| 492 MaybeObject* NewSpace::AllocateRawInternal(int size_in_bytes, | 341 MaybeObject* NewSpace::AllocateRawInternal(int size_in_bytes, |
| 493 AllocationInfo* alloc_info) { | 342 AllocationInfo* alloc_info) { |
| 494 Address new_top = alloc_info->top + size_in_bytes; | 343 Address new_top = alloc_info->top + size_in_bytes; |
| 495 if (new_top > alloc_info->limit) return Failure::RetryAfterGC(); | 344 if (new_top > alloc_info->limit) return Failure::RetryAfterGC(); |
| 496 | 345 |
| 497 Object* obj = HeapObject::FromAddress(alloc_info->top); | 346 Object* obj = HeapObject::FromAddress(alloc_info->top); |
| 498 alloc_info->top = new_top; | 347 alloc_info->top = new_top; |
| 499 #ifdef DEBUG | 348 #ifdef DEBUG |
| (...skipping 21 matching lines...) Expand all Loading... |
| 521 | 370 |
| 522 bool FreeListNode::IsFreeListNode(HeapObject* object) { | 371 bool FreeListNode::IsFreeListNode(HeapObject* object) { |
| 523 return object->map() == Heap::raw_unchecked_byte_array_map() | 372 return object->map() == Heap::raw_unchecked_byte_array_map() |
| 524 || object->map() == Heap::raw_unchecked_one_pointer_filler_map() | 373 || object->map() == Heap::raw_unchecked_one_pointer_filler_map() |
| 525 || object->map() == Heap::raw_unchecked_two_pointer_filler_map(); | 374 || object->map() == Heap::raw_unchecked_two_pointer_filler_map(); |
| 526 } | 375 } |
| 527 | 376 |
| 528 } } // namespace v8::internal | 377 } } // namespace v8::internal |
| 529 | 378 |
| 530 #endif // V8_SPACES_INL_H_ | 379 #endif // V8_SPACES_INL_H_ |
| OLD | NEW |