| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
| 9 #include "src/full-codegen.h" | 9 #include "src/full-codegen.h" |
| 10 #include "src/heap/mark-compact.h" | 10 #include "src/heap/mark-compact.h" |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 | 86 |
| 87 // ----------------------------------------------------------------------------- | 87 // ----------------------------------------------------------------------------- |
| 88 // CodeRange | 88 // CodeRange |
| 89 | 89 |
| 90 | 90 |
| 91 CodeRange::CodeRange(Isolate* isolate) | 91 CodeRange::CodeRange(Isolate* isolate) |
| 92 : isolate_(isolate), | 92 : isolate_(isolate), |
| 93 code_range_(NULL), | 93 code_range_(NULL), |
| 94 free_list_(0), | 94 free_list_(0), |
| 95 allocation_list_(0), | 95 allocation_list_(0), |
| 96 current_allocation_block_index_(0) {} | 96 current_allocation_block_index_(0), |
| 97 emergency_block_() {} |
| 97 | 98 |
| 98 | 99 |
| 99 bool CodeRange::SetUp(size_t requested) { | 100 bool CodeRange::SetUp(size_t requested) { |
| 100 DCHECK(code_range_ == NULL); | 101 DCHECK(code_range_ == NULL); |
| 101 | 102 |
| 102 if (requested == 0) { | 103 if (requested == 0) { |
| 103 // When a target requires the code range feature, we put all code objects | 104 // When a target requires the code range feature, we put all code objects |
| 104 // in a kMaximalCodeRangeSize range of virtual address space, so that | 105 // in a kMaximalCodeRangeSize range of virtual address space, so that |
| 105 // they can call each other with near calls. | 106 // they can call each other with near calls. |
| 106 if (kRequiresCodeRange) { | 107 if (kRequiresCodeRange) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 current_allocation_block_index_ = 0; | 196 current_allocation_block_index_ = 0; |
| 196 // Code range is full or too fragmented. | 197 // Code range is full or too fragmented. |
| 197 return false; | 198 return false; |
| 198 } | 199 } |
| 199 | 200 |
| 200 | 201 |
| 201 Address CodeRange::AllocateRawMemory(const size_t requested_size, | 202 Address CodeRange::AllocateRawMemory(const size_t requested_size, |
| 202 const size_t commit_size, | 203 const size_t commit_size, |
| 203 size_t* allocated) { | 204 size_t* allocated) { |
| 204 DCHECK(commit_size <= requested_size); | 205 DCHECK(commit_size <= requested_size); |
| 205 DCHECK(allocation_list_.length() == 0 || | 206 FreeBlock current; |
| 206 current_allocation_block_index_ < allocation_list_.length()); | 207 if (!ReserveBlock(requested_size, ¤t)) { |
| 207 if (allocation_list_.length() == 0 || | 208 *allocated = 0; |
| 208 requested_size > allocation_list_[current_allocation_block_index_].size) { | 209 return NULL; |
| 209 // Find an allocation block large enough. | |
| 210 if (!GetNextAllocationBlock(requested_size)) return NULL; | |
| 211 } | 210 } |
| 212 // Commit the requested memory at the start of the current allocation block. | 211 *allocated = current.size; |
| 213 size_t aligned_requested = RoundUp(requested_size, MemoryChunk::kAlignment); | |
| 214 FreeBlock current = allocation_list_[current_allocation_block_index_]; | |
| 215 if (aligned_requested >= (current.size - Page::kPageSize)) { | |
| 216 // Don't leave a small free block, useless for a large object or chunk. | |
| 217 *allocated = current.size; | |
| 218 } else { | |
| 219 *allocated = aligned_requested; | |
| 220 } | |
| 221 DCHECK(*allocated <= current.size); | 212 DCHECK(*allocated <= current.size); |
| 222 DCHECK(IsAddressAligned(current.start, MemoryChunk::kAlignment)); | 213 DCHECK(IsAddressAligned(current.start, MemoryChunk::kAlignment)); |
| 223 if (!isolate_->memory_allocator()->CommitExecutableMemory( | 214 if (!isolate_->memory_allocator()->CommitExecutableMemory( |
| 224 code_range_, current.start, commit_size, *allocated)) { | 215 code_range_, current.start, commit_size, *allocated)) { |
| 225 *allocated = 0; | 216 *allocated = 0; |
| 217 ReleaseBlock(¤t); |
| 226 return NULL; | 218 return NULL; |
| 227 } | 219 } |
| 228 allocation_list_[current_allocation_block_index_].start += *allocated; | |
| 229 allocation_list_[current_allocation_block_index_].size -= *allocated; | |
| 230 if (*allocated == current.size) { | |
| 231 // This block is used up, get the next one. | |
| 232 GetNextAllocationBlock(0); | |
| 233 } | |
| 234 return current.start; | 220 return current.start; |
| 235 } | 221 } |
| 236 | 222 |
| 237 | 223 |
| 238 bool CodeRange::CommitRawMemory(Address start, size_t length) { | 224 bool CodeRange::CommitRawMemory(Address start, size_t length) { |
| 239 return isolate_->memory_allocator()->CommitMemory(start, length, EXECUTABLE); | 225 return isolate_->memory_allocator()->CommitMemory(start, length, EXECUTABLE); |
| 240 } | 226 } |
| 241 | 227 |
| 242 | 228 |
| 243 bool CodeRange::UncommitRawMemory(Address start, size_t length) { | 229 bool CodeRange::UncommitRawMemory(Address start, size_t length) { |
| 244 return code_range_->Uncommit(start, length); | 230 return code_range_->Uncommit(start, length); |
| 245 } | 231 } |
| 246 | 232 |
| 247 | 233 |
| 248 void CodeRange::FreeRawMemory(Address address, size_t length) { | 234 void CodeRange::FreeRawMemory(Address address, size_t length) { |
| 249 DCHECK(IsAddressAligned(address, MemoryChunk::kAlignment)); | 235 DCHECK(IsAddressAligned(address, MemoryChunk::kAlignment)); |
| 250 free_list_.Add(FreeBlock(address, length)); | 236 free_list_.Add(FreeBlock(address, length)); |
| 251 code_range_->Uncommit(address, length); | 237 code_range_->Uncommit(address, length); |
| 252 } | 238 } |
| 253 | 239 |
| 254 | 240 |
| 255 void CodeRange::TearDown() { | 241 void CodeRange::TearDown() { |
| 256 delete code_range_; // Frees all memory in the virtual memory range. | 242 delete code_range_; // Frees all memory in the virtual memory range. |
| 257 code_range_ = NULL; | 243 code_range_ = NULL; |
| 258 free_list_.Free(); | 244 free_list_.Free(); |
| 259 allocation_list_.Free(); | 245 allocation_list_.Free(); |
| 260 } | 246 } |
| 261 | 247 |
| 262 | 248 |
| 249 bool CodeRange::ReserveBlock(const size_t requested_size, FreeBlock* block) { |
| 250 DCHECK(allocation_list_.length() == 0 || |
| 251 current_allocation_block_index_ < allocation_list_.length()); |
| 252 if (allocation_list_.length() == 0 || |
| 253 requested_size > allocation_list_[current_allocation_block_index_].size) { |
| 254 // Find an allocation block large enough. |
| 255 if (!GetNextAllocationBlock(requested_size)) return false; |
| 256 } |
| 257 // Commit the requested memory at the start of the current allocation block. |
| 258 size_t aligned_requested = RoundUp(requested_size, MemoryChunk::kAlignment); |
| 259 *block = allocation_list_[current_allocation_block_index_]; |
| 260 // Don't leave a small free block, useless for a large object or chunk. |
| 261 if (aligned_requested < (block->size - Page::kPageSize)) { |
| 262 block->size = aligned_requested; |
| 263 } |
| 264 DCHECK(IsAddressAligned(block->start, MemoryChunk::kAlignment)); |
| 265 allocation_list_[current_allocation_block_index_].start += block->size; |
| 266 allocation_list_[current_allocation_block_index_].size -= block->size; |
| 267 return true; |
| 268 } |
| 269 |
| 270 |
| 271 void CodeRange::ReleaseBlock(const FreeBlock* block) { free_list_.Add(*block); } |
| 272 |
| 273 |
| 274 void CodeRange::ReserveEmergencyBlock() { |
| 275 const size_t requested_size = MemoryAllocator::CodePageAreaSize(); |
| 276 if (emergency_block_.size == 0) { |
| 277 ReserveBlock(requested_size, &emergency_block_); |
| 278 } else { |
| 279 DCHECK(emergency_block_.size >= requested_size); |
| 280 } |
| 281 } |
| 282 |
| 283 |
| 284 void CodeRange::ReleaseEmergencyBlock() { |
| 285 if (emergency_block_.size != 0) { |
| 286 ReleaseBlock(&emergency_block_); |
| 287 emergency_block_.size = 0; |
| 288 } |
| 289 } |
| 290 |
| 291 |
| 263 // ----------------------------------------------------------------------------- | 292 // ----------------------------------------------------------------------------- |
| 264 // MemoryAllocator | 293 // MemoryAllocator |
| 265 // | 294 // |
| 266 | 295 |
| 267 MemoryAllocator::MemoryAllocator(Isolate* isolate) | 296 MemoryAllocator::MemoryAllocator(Isolate* isolate) |
| 268 : isolate_(isolate), | 297 : isolate_(isolate), |
| 269 capacity_(0), | 298 capacity_(0), |
| 270 capacity_executable_(0), | 299 capacity_executable_(0), |
| 271 size_(0), | 300 size_(0), |
| 272 size_executable_(0), | 301 size_executable_(0), |
| (...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1099 } else { | 1128 } else { |
| 1100 heap()->QueueMemoryChunkForFree(page); | 1129 heap()->QueueMemoryChunkForFree(page); |
| 1101 } | 1130 } |
| 1102 | 1131 |
| 1103 DCHECK(Capacity() > 0); | 1132 DCHECK(Capacity() > 0); |
| 1104 accounting_stats_.ShrinkSpace(AreaSize()); | 1133 accounting_stats_.ShrinkSpace(AreaSize()); |
| 1105 } | 1134 } |
| 1106 | 1135 |
| 1107 | 1136 |
| 1108 void PagedSpace::CreateEmergencyMemory() { | 1137 void PagedSpace::CreateEmergencyMemory() { |
| 1138 if (identity() == CODE_SPACE) { |
| 1139 // Make the emergency block available to the allocator. |
| 1140 heap()->isolate()->code_range()->ReleaseEmergencyBlock(); |
| 1141 DCHECK(MemoryAllocator::CodePageAreaSize() == AreaSize()); |
| 1142 } |
| 1109 emergency_memory_ = heap()->isolate()->memory_allocator()->AllocateChunk( | 1143 emergency_memory_ = heap()->isolate()->memory_allocator()->AllocateChunk( |
| 1110 AreaSize(), AreaSize(), executable(), this); | 1144 AreaSize(), AreaSize(), executable(), this); |
| 1111 } | 1145 } |
| 1112 | 1146 |
| 1113 | 1147 |
| 1114 void PagedSpace::FreeEmergencyMemory() { | 1148 void PagedSpace::FreeEmergencyMemory() { |
| 1115 Page* page = static_cast<Page*>(emergency_memory_); | 1149 Page* page = static_cast<Page*>(emergency_memory_); |
| 1116 DCHECK(page->LiveBytes() == 0); | 1150 DCHECK(page->LiveBytes() == 0); |
| 1117 DCHECK(AreaSize() == page->area_size()); | 1151 DCHECK(AreaSize() == page->area_size()); |
| 1118 DCHECK(!free_list_.ContainsPageFreeListItems(page)); | 1152 DCHECK(!free_list_.ContainsPageFreeListItems(page)); |
| (...skipping 2047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3166 object->ShortPrint(); | 3200 object->ShortPrint(); |
| 3167 PrintF("\n"); | 3201 PrintF("\n"); |
| 3168 } | 3202 } |
| 3169 printf(" --------------------------------------\n"); | 3203 printf(" --------------------------------------\n"); |
| 3170 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3204 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3171 } | 3205 } |
| 3172 | 3206 |
| 3173 #endif // DEBUG | 3207 #endif // DEBUG |
| 3174 } | 3208 } |
| 3175 } // namespace v8::internal | 3209 } // namespace v8::internal |
| OLD | NEW |