Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(307)

Side by Side Diff: src/spaces.cc

Issue 6685088: Merge isolates to bleeding_edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/spaces.h ('k') | src/spaces-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 24 matching lines...) Expand all
35 namespace v8 { 35 namespace v8 {
36 namespace internal { 36 namespace internal {
37 37
38 // For contiguous spaces, top should be in the space (or at the end) and limit 38 // For contiguous spaces, top should be in the space (or at the end) and limit
39 // should be the end of the space. 39 // should be the end of the space.
40 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ 40 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \
41 ASSERT((space).low() <= (info).top \ 41 ASSERT((space).low() <= (info).top \
42 && (info).top <= (space).high() \ 42 && (info).top <= (space).high() \
43 && (info).limit == (space).high()) 43 && (info).limit == (space).high())
44 44
45 intptr_t Page::watermark_invalidated_mark_ = 1 << Page::WATERMARK_INVALIDATED;
46
47 // ---------------------------------------------------------------------------- 45 // ----------------------------------------------------------------------------
48 // HeapObjectIterator 46 // HeapObjectIterator
49 47
50 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) { 48 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) {
51 Initialize(space->bottom(), space->top(), NULL); 49 Initialize(space->bottom(), space->top(), NULL);
52 } 50 }
53 51
54 52
55 HeapObjectIterator::HeapObjectIterator(PagedSpace* space, 53 HeapObjectIterator::HeapObjectIterator(PagedSpace* space,
56 HeapObjectCallback size_func) { 54 HeapObjectCallback size_func) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 #endif 140 #endif
143 stop_page_ = space->last_page_; 141 stop_page_ = space->last_page_;
144 break; 142 break;
145 } 143 }
146 } 144 }
147 145
148 146
149 // ----------------------------------------------------------------------------- 147 // -----------------------------------------------------------------------------
150 // CodeRange 148 // CodeRange
151 149
152 List<CodeRange::FreeBlock> CodeRange::free_list_(0); 150
153 List<CodeRange::FreeBlock> CodeRange::allocation_list_(0); 151 CodeRange::CodeRange()
154 int CodeRange::current_allocation_block_index_ = 0; 152 : code_range_(NULL),
155 VirtualMemory* CodeRange::code_range_ = NULL; 153 free_list_(0),
154 allocation_list_(0),
155 current_allocation_block_index_(0),
156 isolate_(NULL) {
157 }
156 158
157 159
158 bool CodeRange::Setup(const size_t requested) { 160 bool CodeRange::Setup(const size_t requested) {
159 ASSERT(code_range_ == NULL); 161 ASSERT(code_range_ == NULL);
160 162
161 code_range_ = new VirtualMemory(requested); 163 code_range_ = new VirtualMemory(requested);
162 CHECK(code_range_ != NULL); 164 CHECK(code_range_ != NULL);
163 if (!code_range_->IsReserved()) { 165 if (!code_range_->IsReserved()) {
164 delete code_range_; 166 delete code_range_;
165 code_range_ = NULL; 167 code_range_ = NULL;
166 return false; 168 return false;
167 } 169 }
168 170
169 // We are sure that we have mapped a block of requested addresses. 171 // We are sure that we have mapped a block of requested addresses.
170 ASSERT(code_range_->size() == requested); 172 ASSERT(code_range_->size() == requested);
171 LOG(NewEvent("CodeRange", code_range_->address(), requested)); 173 LOG(isolate_, NewEvent("CodeRange", code_range_->address(), requested));
172 allocation_list_.Add(FreeBlock(code_range_->address(), code_range_->size())); 174 allocation_list_.Add(FreeBlock(code_range_->address(), code_range_->size()));
173 current_allocation_block_index_ = 0; 175 current_allocation_block_index_ = 0;
174 return true; 176 return true;
175 } 177 }
176 178
177 179
178 int CodeRange::CompareFreeBlockAddress(const FreeBlock* left, 180 int CodeRange::CompareFreeBlockAddress(const FreeBlock* left,
179 const FreeBlock* right) { 181 const FreeBlock* right) {
180 // The entire point of CodeRange is that the difference between two 182 // The entire point of CodeRange is that the difference between two
181 // addresses in the range can be represented as a signed 32-bit int, 183 // addresses in the range can be represented as a signed 32-bit int,
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 delete code_range_; // Frees all memory in the virtual memory range. 266 delete code_range_; // Frees all memory in the virtual memory range.
265 code_range_ = NULL; 267 code_range_ = NULL;
266 free_list_.Free(); 268 free_list_.Free();
267 allocation_list_.Free(); 269 allocation_list_.Free();
268 } 270 }
269 271
270 272
271 // ----------------------------------------------------------------------------- 273 // -----------------------------------------------------------------------------
272 // MemoryAllocator 274 // MemoryAllocator
273 // 275 //
274 intptr_t MemoryAllocator::capacity_ = 0;
275 intptr_t MemoryAllocator::capacity_executable_ = 0;
276 intptr_t MemoryAllocator::size_ = 0;
277 intptr_t MemoryAllocator::size_executable_ = 0;
278
279 List<MemoryAllocator::MemoryAllocationCallbackRegistration>
280 MemoryAllocator::memory_allocation_callbacks_;
281
282 VirtualMemory* MemoryAllocator::initial_chunk_ = NULL;
283 276
284 // 270 is an estimate based on the static default heap size of a pair of 256K 277 // 270 is an estimate based on the static default heap size of a pair of 256K
285 // semispaces and a 64M old generation. 278 // semispaces and a 64M old generation.
286 const int kEstimatedNumberOfChunks = 270; 279 const int kEstimatedNumberOfChunks = 270;
287 List<MemoryAllocator::ChunkInfo> MemoryAllocator::chunks_( 280
288 kEstimatedNumberOfChunks); 281
289 List<int> MemoryAllocator::free_chunk_ids_(kEstimatedNumberOfChunks); 282 MemoryAllocator::MemoryAllocator()
290 int MemoryAllocator::max_nof_chunks_ = 0; 283 : capacity_(0),
291 int MemoryAllocator::top_ = 0; 284 capacity_executable_(0),
285 size_(0),
286 size_executable_(0),
287 initial_chunk_(NULL),
288 chunks_(kEstimatedNumberOfChunks),
289 free_chunk_ids_(kEstimatedNumberOfChunks),
290 max_nof_chunks_(0),
291 top_(0),
292 isolate_(NULL) {
293 }
292 294
293 295
294 void MemoryAllocator::Push(int free_chunk_id) { 296 void MemoryAllocator::Push(int free_chunk_id) {
295 ASSERT(max_nof_chunks_ > 0); 297 ASSERT(max_nof_chunks_ > 0);
296 ASSERT(top_ < max_nof_chunks_); 298 ASSERT(top_ < max_nof_chunks_);
297 free_chunk_ids_[top_++] = free_chunk_id; 299 free_chunk_ids_[top_++] = free_chunk_id;
298 } 300 }
299 301
300 302
301 int MemoryAllocator::Pop() { 303 int MemoryAllocator::Pop() {
(...skipping 25 matching lines...) Expand all
327 ChunkInfo info; // uninitialized element. 329 ChunkInfo info; // uninitialized element.
328 for (int i = max_nof_chunks_ - 1; i >= 0; i--) { 330 for (int i = max_nof_chunks_ - 1; i >= 0; i--) {
329 chunks_.Add(info); 331 chunks_.Add(info);
330 free_chunk_ids_.Add(i); 332 free_chunk_ids_.Add(i);
331 } 333 }
332 top_ = max_nof_chunks_; 334 top_ = max_nof_chunks_;
333 return true; 335 return true;
334 } 336 }
335 337
336 338
337 bool MemoryAllocator::SafeIsInAPageChunk(Address addr) {
338 return InInitialChunk(addr) || InAllocatedChunks(addr);
339 }
340
341
342 void MemoryAllocator::TearDown() { 339 void MemoryAllocator::TearDown() {
343 for (int i = 0; i < max_nof_chunks_; i++) { 340 for (int i = 0; i < max_nof_chunks_; i++) {
344 if (chunks_[i].address() != NULL) DeleteChunk(i); 341 if (chunks_[i].address() != NULL) DeleteChunk(i);
345 } 342 }
346 chunks_.Clear(); 343 chunks_.Clear();
347 free_chunk_ids_.Clear(); 344 free_chunk_ids_.Clear();
348 345
349 if (initial_chunk_ != NULL) { 346 if (initial_chunk_ != NULL) {
350 LOG(DeleteEvent("InitialChunk", initial_chunk_->address())); 347 LOG(isolate_, DeleteEvent("InitialChunk", initial_chunk_->address()));
351 delete initial_chunk_; 348 delete initial_chunk_;
352 initial_chunk_ = NULL; 349 initial_chunk_ = NULL;
353 } 350 }
354 351
355 FreeChunkTables(&chunk_table_[0],
356 kChunkTableTopLevelEntries,
357 kChunkTableLevels);
358
359 ASSERT(top_ == max_nof_chunks_); // all chunks are free 352 ASSERT(top_ == max_nof_chunks_); // all chunks are free
360 top_ = 0; 353 top_ = 0;
361 capacity_ = 0; 354 capacity_ = 0;
362 capacity_executable_ = 0; 355 capacity_executable_ = 0;
363 size_ = 0; 356 size_ = 0;
364 max_nof_chunks_ = 0; 357 max_nof_chunks_ = 0;
365 } 358 }
366 359
367 360
368 void MemoryAllocator::FreeChunkTables(uintptr_t* array, int len, int level) {
369 for (int i = 0; i < len; i++) {
370 if (array[i] != kUnusedChunkTableEntry) {
371 uintptr_t* subarray = reinterpret_cast<uintptr_t*>(array[i]);
372 if (level > 1) {
373 array[i] = kUnusedChunkTableEntry;
374 FreeChunkTables(subarray, 1 << kChunkTableBitsPerLevel, level - 1);
375 } else {
376 array[i] = kUnusedChunkTableEntry;
377 }
378 delete[] subarray;
379 }
380 }
381 }
382
383
384 void* MemoryAllocator::AllocateRawMemory(const size_t requested, 361 void* MemoryAllocator::AllocateRawMemory(const size_t requested,
385 size_t* allocated, 362 size_t* allocated,
386 Executability executable) { 363 Executability executable) {
387 if (size_ + static_cast<size_t>(requested) > static_cast<size_t>(capacity_)) { 364 if (size_ + static_cast<size_t>(requested) > static_cast<size_t>(capacity_)) {
388 return NULL; 365 return NULL;
389 } 366 }
390 367
391 void* mem; 368 void* mem;
392 if (executable == EXECUTABLE) { 369 if (executable == EXECUTABLE) {
393 // Check executable memory limit. 370 // Check executable memory limit.
394 if (size_executable_ + requested > 371 if (size_executable_ + requested >
395 static_cast<size_t>(capacity_executable_)) { 372 static_cast<size_t>(capacity_executable_)) {
396 LOG(StringEvent("MemoryAllocator::AllocateRawMemory", 373 LOG(isolate_,
374 StringEvent("MemoryAllocator::AllocateRawMemory",
397 "V8 Executable Allocation capacity exceeded")); 375 "V8 Executable Allocation capacity exceeded"));
398 return NULL; 376 return NULL;
399 } 377 }
400 // Allocate executable memory either from code range or from the 378 // Allocate executable memory either from code range or from the
401 // OS. 379 // OS.
402 if (CodeRange::exists()) { 380 if (isolate_->code_range()->exists()) {
403 mem = CodeRange::AllocateRawMemory(requested, allocated); 381 mem = isolate_->code_range()->AllocateRawMemory(requested, allocated);
404 } else { 382 } else {
405 mem = OS::Allocate(requested, allocated, true); 383 mem = OS::Allocate(requested, allocated, true);
406 } 384 }
407 // Update executable memory size. 385 // Update executable memory size.
408 size_executable_ += static_cast<int>(*allocated); 386 size_executable_ += static_cast<int>(*allocated);
409 } else { 387 } else {
410 mem = OS::Allocate(requested, allocated, false); 388 mem = OS::Allocate(requested, allocated, false);
411 } 389 }
412 int alloced = static_cast<int>(*allocated); 390 int alloced = static_cast<int>(*allocated);
413 size_ += alloced; 391 size_ += alloced;
414 392
415 #ifdef DEBUG 393 #ifdef DEBUG
416 ZapBlock(reinterpret_cast<Address>(mem), alloced); 394 ZapBlock(reinterpret_cast<Address>(mem), alloced);
417 #endif 395 #endif
418 Counters::memory_allocated.Increment(alloced); 396 COUNTERS->memory_allocated()->Increment(alloced);
419 return mem; 397 return mem;
420 } 398 }
421 399
422 400
423 void MemoryAllocator::FreeRawMemory(void* mem, 401 void MemoryAllocator::FreeRawMemory(void* mem,
424 size_t length, 402 size_t length,
425 Executability executable) { 403 Executability executable) {
426 #ifdef DEBUG 404 #ifdef DEBUG
427 ZapBlock(reinterpret_cast<Address>(mem), length); 405 ZapBlock(reinterpret_cast<Address>(mem), length);
428 #endif 406 #endif
429 if (CodeRange::contains(static_cast<Address>(mem))) { 407 if (isolate_->code_range()->contains(static_cast<Address>(mem))) {
430 CodeRange::FreeRawMemory(mem, length); 408 isolate_->code_range()->FreeRawMemory(mem, length);
431 } else { 409 } else {
432 OS::Free(mem, length); 410 OS::Free(mem, length);
433 } 411 }
434 Counters::memory_allocated.Decrement(static_cast<int>(length)); 412 COUNTERS->memory_allocated()->Decrement(static_cast<int>(length));
435 size_ -= static_cast<int>(length); 413 size_ -= static_cast<int>(length);
436 if (executable == EXECUTABLE) size_executable_ -= static_cast<int>(length); 414 if (executable == EXECUTABLE) size_executable_ -= static_cast<int>(length);
437 415
438 ASSERT(size_ >= 0); 416 ASSERT(size_ >= 0);
439 ASSERT(size_executable_ >= 0); 417 ASSERT(size_executable_ >= 0);
440 } 418 }
441 419
442 420
443 void MemoryAllocator::PerformAllocationCallback(ObjectSpace space, 421 void MemoryAllocator::PerformAllocationCallback(ObjectSpace space,
444 AllocationAction action, 422 AllocationAction action,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 initial_chunk_ = new VirtualMemory(requested); 469 initial_chunk_ = new VirtualMemory(requested);
492 CHECK(initial_chunk_ != NULL); 470 CHECK(initial_chunk_ != NULL);
493 if (!initial_chunk_->IsReserved()) { 471 if (!initial_chunk_->IsReserved()) {
494 delete initial_chunk_; 472 delete initial_chunk_;
495 initial_chunk_ = NULL; 473 initial_chunk_ = NULL;
496 return NULL; 474 return NULL;
497 } 475 }
498 476
499 // We are sure that we have mapped a block of requested addresses. 477 // We are sure that we have mapped a block of requested addresses.
500 ASSERT(initial_chunk_->size() == requested); 478 ASSERT(initial_chunk_->size() == requested);
501 LOG(NewEvent("InitialChunk", initial_chunk_->address(), requested)); 479 LOG(isolate_,
480 NewEvent("InitialChunk", initial_chunk_->address(), requested));
502 size_ += static_cast<int>(requested); 481 size_ += static_cast<int>(requested);
503 return initial_chunk_->address(); 482 return initial_chunk_->address();
504 } 483 }
505 484
506 485
507 static int PagesInChunk(Address start, size_t size) { 486 static int PagesInChunk(Address start, size_t size) {
508 // The first page starts on the first page-aligned address from start onward 487 // The first page starts on the first page-aligned address from start onward
509 // and the last page ends on the last page-aligned address before 488 // and the last page ends on the last page-aligned address before
510 // start+size. Page::kPageSize is a power of two so we can divide by 489 // start+size. Page::kPageSize is a power of two so we can divide by
511 // shifting. 490 // shifting.
512 return static_cast<int>((RoundDown(start + size, Page::kPageSize) 491 return static_cast<int>((RoundDown(start + size, Page::kPageSize)
513 - RoundUp(start, Page::kPageSize)) >> kPageSizeBits); 492 - RoundUp(start, Page::kPageSize)) >> kPageSizeBits);
514 } 493 }
515 494
516 495
517 Page* MemoryAllocator::AllocatePages(int requested_pages, 496 Page* MemoryAllocator::AllocatePages(int requested_pages,
518 int* allocated_pages, 497 int* allocated_pages,
519 PagedSpace* owner) { 498 PagedSpace* owner) {
520 if (requested_pages <= 0) return Page::FromAddress(NULL); 499 if (requested_pages <= 0) return Page::FromAddress(NULL);
521 size_t chunk_size = requested_pages * Page::kPageSize; 500 size_t chunk_size = requested_pages * Page::kPageSize;
522 501
523 void* chunk = AllocateRawMemory(chunk_size, &chunk_size, owner->executable()); 502 void* chunk = AllocateRawMemory(chunk_size, &chunk_size, owner->executable());
524 if (chunk == NULL) return Page::FromAddress(NULL); 503 if (chunk == NULL) return Page::FromAddress(NULL);
525 LOG(NewEvent("PagedChunk", chunk, chunk_size)); 504 LOG(isolate_, NewEvent("PagedChunk", chunk, chunk_size));
526 505
527 *allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size); 506 *allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size);
528 // We may 'lose' a page due to alignment. 507 // We may 'lose' a page due to alignment.
529 ASSERT(*allocated_pages >= kPagesPerChunk - 1); 508 ASSERT(*allocated_pages >= kPagesPerChunk - 1);
530 if (*allocated_pages == 0) { 509 if (*allocated_pages == 0) {
531 FreeRawMemory(chunk, chunk_size, owner->executable()); 510 FreeRawMemory(chunk, chunk_size, owner->executable());
532 LOG(DeleteEvent("PagedChunk", chunk)); 511 LOG(isolate_, DeleteEvent("PagedChunk", chunk));
533 return Page::FromAddress(NULL); 512 return Page::FromAddress(NULL);
534 } 513 }
535 514
536 int chunk_id = Pop(); 515 int chunk_id = Pop();
537 chunks_[chunk_id].init(static_cast<Address>(chunk), chunk_size, owner); 516 chunks_[chunk_id].init(static_cast<Address>(chunk), chunk_size, owner);
538 517
539 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity()); 518 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity());
540 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); 519 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size);
541 Page* new_pages = InitializePagesInChunk(chunk_id, *allocated_pages, owner); 520 Page* new_pages = InitializePagesInChunk(chunk_id, *allocated_pages, owner);
542 521
543 AddToAllocatedChunks(static_cast<Address>(chunk), chunk_size);
544
545 return new_pages; 522 return new_pages;
546 } 523 }
547 524
548 525
549 Page* MemoryAllocator::CommitPages(Address start, size_t size, 526 Page* MemoryAllocator::CommitPages(Address start, size_t size,
550 PagedSpace* owner, int* num_pages) { 527 PagedSpace* owner, int* num_pages) {
551 ASSERT(start != NULL); 528 ASSERT(start != NULL);
552 *num_pages = PagesInChunk(start, size); 529 *num_pages = PagesInChunk(start, size);
553 ASSERT(*num_pages > 0); 530 ASSERT(*num_pages > 0);
554 ASSERT(initial_chunk_ != NULL); 531 ASSERT(initial_chunk_ != NULL);
555 ASSERT(InInitialChunk(start)); 532 ASSERT(InInitialChunk(start));
556 ASSERT(InInitialChunk(start + size - 1)); 533 ASSERT(InInitialChunk(start + size - 1));
557 if (!initial_chunk_->Commit(start, size, owner->executable() == EXECUTABLE)) { 534 if (!initial_chunk_->Commit(start, size, owner->executable() == EXECUTABLE)) {
558 return Page::FromAddress(NULL); 535 return Page::FromAddress(NULL);
559 } 536 }
560 #ifdef DEBUG 537 #ifdef DEBUG
561 ZapBlock(start, size); 538 ZapBlock(start, size);
562 #endif 539 #endif
563 Counters::memory_allocated.Increment(static_cast<int>(size)); 540 COUNTERS->memory_allocated()->Increment(static_cast<int>(size));
564 541
565 // So long as we correctly overestimated the number of chunks we should not 542 // So long as we correctly overestimated the number of chunks we should not
566 // run out of chunk ids. 543 // run out of chunk ids.
567 CHECK(!OutOfChunkIds()); 544 CHECK(!OutOfChunkIds());
568 int chunk_id = Pop(); 545 int chunk_id = Pop();
569 chunks_[chunk_id].init(start, size, owner); 546 chunks_[chunk_id].init(start, size, owner);
570 return InitializePagesInChunk(chunk_id, *num_pages, owner); 547 return InitializePagesInChunk(chunk_id, *num_pages, owner);
571 } 548 }
572 549
573 550
574 bool MemoryAllocator::CommitBlock(Address start, 551 bool MemoryAllocator::CommitBlock(Address start,
575 size_t size, 552 size_t size,
576 Executability executable) { 553 Executability executable) {
577 ASSERT(start != NULL); 554 ASSERT(start != NULL);
578 ASSERT(size > 0); 555 ASSERT(size > 0);
579 ASSERT(initial_chunk_ != NULL); 556 ASSERT(initial_chunk_ != NULL);
580 ASSERT(InInitialChunk(start)); 557 ASSERT(InInitialChunk(start));
581 ASSERT(InInitialChunk(start + size - 1)); 558 ASSERT(InInitialChunk(start + size - 1));
582 559
583 if (!initial_chunk_->Commit(start, size, executable)) return false; 560 if (!initial_chunk_->Commit(start, size, executable)) return false;
584 #ifdef DEBUG 561 #ifdef DEBUG
585 ZapBlock(start, size); 562 ZapBlock(start, size);
586 #endif 563 #endif
587 Counters::memory_allocated.Increment(static_cast<int>(size)); 564 COUNTERS->memory_allocated()->Increment(static_cast<int>(size));
588 return true; 565 return true;
589 } 566 }
590 567
591 568
592 bool MemoryAllocator::UncommitBlock(Address start, size_t size) { 569 bool MemoryAllocator::UncommitBlock(Address start, size_t size) {
593 ASSERT(start != NULL); 570 ASSERT(start != NULL);
594 ASSERT(size > 0); 571 ASSERT(size > 0);
595 ASSERT(initial_chunk_ != NULL); 572 ASSERT(initial_chunk_ != NULL);
596 ASSERT(InInitialChunk(start)); 573 ASSERT(InInitialChunk(start));
597 ASSERT(InInitialChunk(start + size - 1)); 574 ASSERT(InInitialChunk(start + size - 1));
598 575
599 if (!initial_chunk_->Uncommit(start, size)) return false; 576 if (!initial_chunk_->Uncommit(start, size)) return false;
600 Counters::memory_allocated.Decrement(static_cast<int>(size)); 577 COUNTERS->memory_allocated()->Decrement(static_cast<int>(size));
601 return true; 578 return true;
602 } 579 }
603 580
604 581
605 void MemoryAllocator::ZapBlock(Address start, size_t size) { 582 void MemoryAllocator::ZapBlock(Address start, size_t size) {
606 for (size_t s = 0; s + kPointerSize <= size; s += kPointerSize) { 583 for (size_t s = 0; s + kPointerSize <= size; s += kPointerSize) {
607 Memory::Address_at(start + s) = kZapValue; 584 Memory::Address_at(start + s) = kZapValue;
608 } 585 }
609 } 586 }
610 587
(...skipping 10 matching lines...) Expand all
621 #ifdef DEBUG 598 #ifdef DEBUG
622 size_t chunk_size = chunks_[chunk_id].size(); 599 size_t chunk_size = chunks_[chunk_id].size();
623 Address high = RoundDown(chunk_start + chunk_size, Page::kPageSize); 600 Address high = RoundDown(chunk_start + chunk_size, Page::kPageSize);
624 ASSERT(pages_in_chunk <= 601 ASSERT(pages_in_chunk <=
625 ((OffsetFrom(high) - OffsetFrom(low)) / Page::kPageSize)); 602 ((OffsetFrom(high) - OffsetFrom(low)) / Page::kPageSize));
626 #endif 603 #endif
627 604
628 Address page_addr = low; 605 Address page_addr = low;
629 for (int i = 0; i < pages_in_chunk; i++) { 606 for (int i = 0; i < pages_in_chunk; i++) {
630 Page* p = Page::FromAddress(page_addr); 607 Page* p = Page::FromAddress(page_addr);
608 p->heap_ = owner->heap();
631 p->opaque_header = OffsetFrom(page_addr + Page::kPageSize) | chunk_id; 609 p->opaque_header = OffsetFrom(page_addr + Page::kPageSize) | chunk_id;
632 p->InvalidateWatermark(true); 610 p->InvalidateWatermark(true);
633 p->SetIsLargeObjectPage(false); 611 p->SetIsLargeObjectPage(false);
634 p->SetAllocationWatermark(p->ObjectAreaStart()); 612 p->SetAllocationWatermark(p->ObjectAreaStart());
635 p->SetCachedAllocationWatermark(p->ObjectAreaStart()); 613 p->SetCachedAllocationWatermark(p->ObjectAreaStart());
636 page_addr += Page::kPageSize; 614 page_addr += Page::kPageSize;
637 } 615 }
638 616
639 // Set the next page of the last page to 0. 617 // Set the next page of the last page to 0.
640 Page* last_page = Page::FromAddress(page_addr - Page::kPageSize); 618 Page* last_page = Page::FromAddress(page_addr - Page::kPageSize);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 668
691 ChunkInfo& c = chunks_[chunk_id]; 669 ChunkInfo& c = chunks_[chunk_id];
692 670
693 // We cannot free a chunk contained in the initial chunk because it was not 671 // We cannot free a chunk contained in the initial chunk because it was not
694 // allocated with AllocateRawMemory. Instead we uncommit the virtual 672 // allocated with AllocateRawMemory. Instead we uncommit the virtual
695 // memory. 673 // memory.
696 if (InInitialChunk(c.address())) { 674 if (InInitialChunk(c.address())) {
697 // TODO(1240712): VirtualMemory::Uncommit has a return value which 675 // TODO(1240712): VirtualMemory::Uncommit has a return value which
698 // is ignored here. 676 // is ignored here.
699 initial_chunk_->Uncommit(c.address(), c.size()); 677 initial_chunk_->Uncommit(c.address(), c.size());
700 Counters::memory_allocated.Decrement(static_cast<int>(c.size())); 678 COUNTERS->memory_allocated()->Decrement(static_cast<int>(c.size()));
701 } else { 679 } else {
702 RemoveFromAllocatedChunks(c.address(), c.size()); 680 LOG(isolate_, DeleteEvent("PagedChunk", c.address()));
703 LOG(DeleteEvent("PagedChunk", c.address())); 681 ObjectSpace space = static_cast<ObjectSpace>(1 << c.owner_identity());
704 ObjectSpace space = static_cast<ObjectSpace>(1 << c.owner()->identity());
705 size_t size = c.size(); 682 size_t size = c.size();
706 FreeRawMemory(c.address(), size, c.executable()); 683 FreeRawMemory(c.address(), size, c.executable());
707 PerformAllocationCallback(space, kAllocationActionFree, size); 684 PerformAllocationCallback(space, kAllocationActionFree, size);
708 } 685 }
709 c.init(NULL, 0, NULL); 686 c.init(NULL, 0, NULL);
710 Push(chunk_id); 687 Push(chunk_id);
711 } 688 }
712 689
713 690
714 Page* MemoryAllocator::FindFirstPageInSameChunk(Page* p) { 691 Page* MemoryAllocator::FindFirstPageInSameChunk(Page* p) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 last_page->opaque_header = OffsetFrom(0) | chunk_id; 783 last_page->opaque_header = OffsetFrom(0) | chunk_id;
807 784
808 if (last_page->WasInUseBeforeMC()) { 785 if (last_page->WasInUseBeforeMC()) {
809 *last_page_in_use = last_page; 786 *last_page_in_use = last_page;
810 } 787 }
811 788
812 return last_page; 789 return last_page;
813 } 790 }
814 791
815 792
816 void MemoryAllocator::AddToAllocatedChunks(Address addr, intptr_t size) {
817 ASSERT(size == kChunkSize);
818 uintptr_t int_address = reinterpret_cast<uintptr_t>(addr);
819 AddChunkUsingAddress(int_address, int_address);
820 AddChunkUsingAddress(int_address, int_address + size - 1);
821 }
822
823
824 void MemoryAllocator::AddChunkUsingAddress(uintptr_t chunk_start,
825 uintptr_t chunk_index_base) {
826 uintptr_t* fine_grained = AllocatedChunksFinder(
827 chunk_table_,
828 chunk_index_base,
829 kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
830 kCreateTablesAsNeeded);
831 int index = FineGrainedIndexForAddress(chunk_index_base);
832 if (fine_grained[index] != kUnusedChunkTableEntry) index++;
833 ASSERT(fine_grained[index] == kUnusedChunkTableEntry);
834 fine_grained[index] = chunk_start;
835 }
836
837
838 void MemoryAllocator::RemoveFromAllocatedChunks(Address addr, intptr_t size) {
839 ASSERT(size == kChunkSize);
840 uintptr_t int_address = reinterpret_cast<uintptr_t>(addr);
841 RemoveChunkFoundUsingAddress(int_address, int_address);
842 RemoveChunkFoundUsingAddress(int_address, int_address + size - 1);
843 }
844
845
846 void MemoryAllocator::RemoveChunkFoundUsingAddress(
847 uintptr_t chunk_start,
848 uintptr_t chunk_index_base) {
849 uintptr_t* fine_grained = AllocatedChunksFinder(
850 chunk_table_,
851 chunk_index_base,
852 kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
853 kDontCreateTables);
854 // Can't remove an entry that's not there.
855 ASSERT(fine_grained != kUnusedChunkTableEntry);
856 int index = FineGrainedIndexForAddress(chunk_index_base);
857 ASSERT(fine_grained[index] != kUnusedChunkTableEntry);
858 if (fine_grained[index] != chunk_start) {
859 index++;
860 ASSERT(fine_grained[index] == chunk_start);
861 fine_grained[index] = kUnusedChunkTableEntry;
862 } else {
863 // If only one of the entries is used it must be the first, since
864 // InAllocatedChunks relies on that. Move things around so that this is
865 // the case.
866 fine_grained[index] = fine_grained[index + 1];
867 fine_grained[index + 1] = kUnusedChunkTableEntry;
868 }
869 }
870
871
872 bool MemoryAllocator::InAllocatedChunks(Address addr) {
873 uintptr_t int_address = reinterpret_cast<uintptr_t>(addr);
874 uintptr_t* fine_grained = AllocatedChunksFinder(
875 chunk_table_,
876 int_address,
877 kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
878 kDontCreateTables);
879 if (fine_grained == NULL) return false;
880 int index = FineGrainedIndexForAddress(int_address);
881 if (fine_grained[index] == kUnusedChunkTableEntry) return false;
882 uintptr_t entry = fine_grained[index];
883 if (entry <= int_address && entry + kChunkSize > int_address) return true;
884 index++;
885 if (fine_grained[index] == kUnusedChunkTableEntry) return false;
886 entry = fine_grained[index];
887 if (entry <= int_address && entry + kChunkSize > int_address) return true;
888 return false;
889 }
890
891
892 uintptr_t* MemoryAllocator::AllocatedChunksFinder(
893 uintptr_t* table,
894 uintptr_t address,
895 int bit_position,
896 CreateTables create_as_needed) {
897 if (bit_position == kChunkSizeLog2) {
898 return table;
899 }
900 ASSERT(bit_position >= kChunkSizeLog2 + kChunkTableBitsPerLevel);
901 int index =
902 ((address >> bit_position) &
903 ((V8_INTPTR_C(1) << kChunkTableBitsPerLevel) - 1));
904 uintptr_t more_fine_grained_address =
905 address & ((V8_INTPTR_C(1) << bit_position) - 1);
906 ASSERT((table == chunk_table_ && index < kChunkTableTopLevelEntries) ||
907 (table != chunk_table_ && index < 1 << kChunkTableBitsPerLevel));
908 uintptr_t* more_fine_grained_table =
909 reinterpret_cast<uintptr_t*>(table[index]);
910 if (more_fine_grained_table == kUnusedChunkTableEntry) {
911 if (create_as_needed == kDontCreateTables) return NULL;
912 int words_needed = 1 << kChunkTableBitsPerLevel;
913 if (bit_position == kChunkTableBitsPerLevel + kChunkSizeLog2) {
914 words_needed =
915 (1 << kChunkTableBitsPerLevel) * kChunkTableFineGrainedWordsPerEntry;
916 }
917 more_fine_grained_table = new uintptr_t[words_needed];
918 for (int i = 0; i < words_needed; i++) {
919 more_fine_grained_table[i] = kUnusedChunkTableEntry;
920 }
921 table[index] = reinterpret_cast<uintptr_t>(more_fine_grained_table);
922 }
923 return AllocatedChunksFinder(
924 more_fine_grained_table,
925 more_fine_grained_address,
926 bit_position - kChunkTableBitsPerLevel,
927 create_as_needed);
928 }
929
930
931 uintptr_t MemoryAllocator::chunk_table_[kChunkTableTopLevelEntries];
932
933
934 // ----------------------------------------------------------------------------- 793 // -----------------------------------------------------------------------------
935 // PagedSpace implementation 794 // PagedSpace implementation
936 795
937 PagedSpace::PagedSpace(intptr_t max_capacity, 796 PagedSpace::PagedSpace(Heap* heap,
797 intptr_t max_capacity,
938 AllocationSpace id, 798 AllocationSpace id,
939 Executability executable) 799 Executability executable)
940 : Space(id, executable) { 800 : Space(heap, id, executable) {
941 max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) 801 max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize)
942 * Page::kObjectAreaSize; 802 * Page::kObjectAreaSize;
943 accounting_stats_.Clear(); 803 accounting_stats_.Clear();
944 804
945 allocation_info_.top = NULL; 805 allocation_info_.top = NULL;
946 allocation_info_.limit = NULL; 806 allocation_info_.limit = NULL;
947 807
948 mc_forwarding_info_.top = NULL; 808 mc_forwarding_info_.top = NULL;
949 mc_forwarding_info_.limit = NULL; 809 mc_forwarding_info_.limit = NULL;
950 } 810 }
951 811
952 812
953 bool PagedSpace::Setup(Address start, size_t size) { 813 bool PagedSpace::Setup(Address start, size_t size) {
954 if (HasBeenSetup()) return false; 814 if (HasBeenSetup()) return false;
955 815
956 int num_pages = 0; 816 int num_pages = 0;
957 // Try to use the virtual memory range passed to us. If it is too small to 817 // Try to use the virtual memory range passed to us. If it is too small to
958 // contain at least one page, ignore it and allocate instead. 818 // contain at least one page, ignore it and allocate instead.
959 int pages_in_chunk = PagesInChunk(start, size); 819 int pages_in_chunk = PagesInChunk(start, size);
960 if (pages_in_chunk > 0) { 820 if (pages_in_chunk > 0) {
961 first_page_ = MemoryAllocator::CommitPages(RoundUp(start, Page::kPageSize), 821 first_page_ = Isolate::Current()->memory_allocator()->CommitPages(
962 Page::kPageSize * pages_in_chunk, 822 RoundUp(start, Page::kPageSize),
963 this, &num_pages); 823 Page::kPageSize * pages_in_chunk,
824 this, &num_pages);
964 } else { 825 } else {
965 int requested_pages = 826 int requested_pages =
966 Min(MemoryAllocator::kPagesPerChunk, 827 Min(MemoryAllocator::kPagesPerChunk,
967 static_cast<int>(max_capacity_ / Page::kObjectAreaSize)); 828 static_cast<int>(max_capacity_ / Page::kObjectAreaSize));
968 first_page_ = 829 first_page_ =
969 MemoryAllocator::AllocatePages(requested_pages, &num_pages, this); 830 Isolate::Current()->memory_allocator()->AllocatePages(
831 requested_pages, &num_pages, this);
970 if (!first_page_->is_valid()) return false; 832 if (!first_page_->is_valid()) return false;
971 } 833 }
972 834
973 // We are sure that the first page is valid and that we have at least one 835 // We are sure that the first page is valid and that we have at least one
974 // page. 836 // page.
975 ASSERT(first_page_->is_valid()); 837 ASSERT(first_page_->is_valid());
976 ASSERT(num_pages > 0); 838 ASSERT(num_pages > 0);
977 accounting_stats_.ExpandSpace(num_pages * Page::kObjectAreaSize); 839 accounting_stats_.ExpandSpace(num_pages * Page::kObjectAreaSize);
978 ASSERT(Capacity() <= max_capacity_); 840 ASSERT(Capacity() <= max_capacity_);
979 841
(...skipping 12 matching lines...) Expand all
992 return true; 854 return true;
993 } 855 }
994 856
995 857
996 bool PagedSpace::HasBeenSetup() { 858 bool PagedSpace::HasBeenSetup() {
997 return (Capacity() > 0); 859 return (Capacity() > 0);
998 } 860 }
999 861
1000 862
1001 void PagedSpace::TearDown() { 863 void PagedSpace::TearDown() {
1002 MemoryAllocator::FreeAllPages(this); 864 Isolate::Current()->memory_allocator()->FreeAllPages(this);
1003 first_page_ = NULL; 865 first_page_ = NULL;
1004 accounting_stats_.Clear(); 866 accounting_stats_.Clear();
1005 } 867 }
1006 868
1007 869
1008 #ifdef ENABLE_HEAP_PROTECTION 870 #ifdef ENABLE_HEAP_PROTECTION
1009 871
1010 void PagedSpace::Protect() { 872 void PagedSpace::Protect() {
1011 Page* page = first_page_; 873 Page* page = first_page_;
1012 while (page->is_valid()) { 874 while (page->is_valid()) {
1013 MemoryAllocator::ProtectChunkFromPage(page); 875 Isolate::Current()->memory_allocator()->ProtectChunkFromPage(page);
1014 page = MemoryAllocator::FindLastPageInSameChunk(page)->next_page(); 876 page = Isolate::Current()->memory_allocator()->
877 FindLastPageInSameChunk(page)->next_page();
1015 } 878 }
1016 } 879 }
1017 880
1018 881
1019 void PagedSpace::Unprotect() { 882 void PagedSpace::Unprotect() {
1020 Page* page = first_page_; 883 Page* page = first_page_;
1021 while (page->is_valid()) { 884 while (page->is_valid()) {
1022 MemoryAllocator::UnprotectChunkFromPage(page); 885 Isolate::Current()->memory_allocator()->UnprotectChunkFromPage(page);
1023 page = MemoryAllocator::FindLastPageInSameChunk(page)->next_page(); 886 page = Isolate::Current()->memory_allocator()->
887 FindLastPageInSameChunk(page)->next_page();
1024 } 888 }
1025 } 889 }
1026 890
1027 #endif 891 #endif
1028 892
1029 893
1030 void PagedSpace::MarkAllPagesClean() { 894 void PagedSpace::MarkAllPagesClean() {
1031 PageIterator it(this, PageIterator::ALL_PAGES); 895 PageIterator it(this, PageIterator::ALL_PAGES);
1032 while (it.has_next()) { 896 while (it.has_next()) {
1033 it.next()->SetRegionMarks(Page::kAllRegionsCleanMarks); 897 it.next()->SetRegionMarks(Page::kAllRegionsCleanMarks);
1034 } 898 }
1035 } 899 }
1036 900
1037 901
1038 MaybeObject* PagedSpace::FindObject(Address addr) { 902 MaybeObject* PagedSpace::FindObject(Address addr) {
1039 // Note: this function can only be called before or after mark-compact GC 903 // Note: this function can only be called before or after mark-compact GC
1040 // because it accesses map pointers. 904 // because it accesses map pointers.
1041 ASSERT(!MarkCompactCollector::in_use()); 905 ASSERT(!heap()->mark_compact_collector()->in_use());
1042 906
1043 if (!Contains(addr)) return Failure::Exception(); 907 if (!Contains(addr)) return Failure::Exception();
1044 908
1045 Page* p = Page::FromAddress(addr); 909 Page* p = Page::FromAddress(addr);
1046 ASSERT(IsUsed(p)); 910 ASSERT(IsUsed(p));
1047 Address cur = p->ObjectAreaStart(); 911 Address cur = p->ObjectAreaStart();
1048 Address end = p->AllocationTop(); 912 Address end = p->AllocationTop();
1049 while (cur < end) { 913 while (cur < end) {
1050 HeapObject* obj = HeapObject::FromAddress(cur); 914 HeapObject* obj = HeapObject::FromAddress(cur);
1051 Address next = cur + obj->Size(); 915 Address next = cur + obj->Size();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 ASSERT(last_page->is_valid() && !last_page->next_page()->is_valid()); 1015 ASSERT(last_page->is_valid() && !last_page->next_page()->is_valid());
1152 1016
1153 int available_pages = 1017 int available_pages =
1154 static_cast<int>((max_capacity_ - Capacity()) / Page::kObjectAreaSize); 1018 static_cast<int>((max_capacity_ - Capacity()) / Page::kObjectAreaSize);
1155 // We don't want to have to handle small chunks near the end so if there are 1019 // We don't want to have to handle small chunks near the end so if there are
1156 // not kPagesPerChunk pages available without exceeding the max capacity then 1020 // not kPagesPerChunk pages available without exceeding the max capacity then
1157 // act as if memory has run out. 1021 // act as if memory has run out.
1158 if (available_pages < MemoryAllocator::kPagesPerChunk) return false; 1022 if (available_pages < MemoryAllocator::kPagesPerChunk) return false;
1159 1023
1160 int desired_pages = Min(available_pages, MemoryAllocator::kPagesPerChunk); 1024 int desired_pages = Min(available_pages, MemoryAllocator::kPagesPerChunk);
1161 Page* p = MemoryAllocator::AllocatePages(desired_pages, &desired_pages, this); 1025 Page* p = heap()->isolate()->memory_allocator()->AllocatePages(
1026 desired_pages, &desired_pages, this);
1162 if (!p->is_valid()) return false; 1027 if (!p->is_valid()) return false;
1163 1028
1164 accounting_stats_.ExpandSpace(desired_pages * Page::kObjectAreaSize); 1029 accounting_stats_.ExpandSpace(desired_pages * Page::kObjectAreaSize);
1165 ASSERT(Capacity() <= max_capacity_); 1030 ASSERT(Capacity() <= max_capacity_);
1166 1031
1167 MemoryAllocator::SetNextPage(last_page, p); 1032 heap()->isolate()->memory_allocator()->SetNextPage(last_page, p);
1168 1033
1169 // Sequentially clear region marks of new pages and and cache the 1034 // Sequentially clear region marks of new pages and and cache the
1170 // new last page in the space. 1035 // new last page in the space.
1171 while (p->is_valid()) { 1036 while (p->is_valid()) {
1172 p->SetRegionMarks(Page::kAllRegionsCleanMarks); 1037 p->SetRegionMarks(Page::kAllRegionsCleanMarks);
1173 last_page_ = p; 1038 last_page_ = p;
1174 p = p->next_page(); 1039 p = p->next_page();
1175 } 1040 }
1176 1041
1177 return true; 1042 return true;
(...skipping 22 matching lines...) Expand all
1200 Page* top_page = AllocationTopPage(); 1065 Page* top_page = AllocationTopPage();
1201 ASSERT(top_page->is_valid()); 1066 ASSERT(top_page->is_valid());
1202 1067
1203 // Count the number of pages we would like to free. 1068 // Count the number of pages we would like to free.
1204 int pages_to_free = 0; 1069 int pages_to_free = 0;
1205 for (Page* p = top_page->next_page(); p->is_valid(); p = p->next_page()) { 1070 for (Page* p = top_page->next_page(); p->is_valid(); p = p->next_page()) {
1206 pages_to_free++; 1071 pages_to_free++;
1207 } 1072 }
1208 1073
1209 // Free pages after top_page. 1074 // Free pages after top_page.
1210 Page* p = MemoryAllocator::FreePages(top_page->next_page()); 1075 Page* p = heap()->isolate()->memory_allocator()->
1211 MemoryAllocator::SetNextPage(top_page, p); 1076 FreePages(top_page->next_page());
1077 heap()->isolate()->memory_allocator()->SetNextPage(top_page, p);
1212 1078
1213 // Find out how many pages we failed to free and update last_page_. 1079 // Find out how many pages we failed to free and update last_page_.
1214 // Please note pages can only be freed in whole chunks. 1080 // Please note pages can only be freed in whole chunks.
1215 last_page_ = top_page; 1081 last_page_ = top_page;
1216 for (Page* p = top_page->next_page(); p->is_valid(); p = p->next_page()) { 1082 for (Page* p = top_page->next_page(); p->is_valid(); p = p->next_page()) {
1217 pages_to_free--; 1083 pages_to_free--;
1218 last_page_ = p; 1084 last_page_ = p;
1219 } 1085 }
1220 1086
1221 accounting_stats_.ShrinkSpace(pages_to_free * Page::kObjectAreaSize); 1087 accounting_stats_.ShrinkSpace(pages_to_free * Page::kObjectAreaSize);
1222 ASSERT(Capacity() == CountTotalPages() * Page::kObjectAreaSize); 1088 ASSERT(Capacity() == CountTotalPages() * Page::kObjectAreaSize);
1223 } 1089 }
1224 1090
1225 1091
1226 bool PagedSpace::EnsureCapacity(int capacity) { 1092 bool PagedSpace::EnsureCapacity(int capacity) {
1227 if (Capacity() >= capacity) return true; 1093 if (Capacity() >= capacity) return true;
1228 1094
1229 // Start from the allocation top and loop to the last page in the space. 1095 // Start from the allocation top and loop to the last page in the space.
1230 Page* last_page = AllocationTopPage(); 1096 Page* last_page = AllocationTopPage();
1231 Page* next_page = last_page->next_page(); 1097 Page* next_page = last_page->next_page();
1232 while (next_page->is_valid()) { 1098 while (next_page->is_valid()) {
1233 last_page = MemoryAllocator::FindLastPageInSameChunk(next_page); 1099 last_page = heap()->isolate()->memory_allocator()->
1100 FindLastPageInSameChunk(next_page);
1234 next_page = last_page->next_page(); 1101 next_page = last_page->next_page();
1235 } 1102 }
1236 1103
1237 // Expand the space until it has the required capacity or expansion fails. 1104 // Expand the space until it has the required capacity or expansion fails.
1238 do { 1105 do {
1239 if (!Expand(last_page)) return false; 1106 if (!Expand(last_page)) return false;
1240 ASSERT(last_page->next_page()->is_valid()); 1107 ASSERT(last_page->next_page()->is_valid());
1241 last_page = 1108 last_page =
1242 MemoryAllocator::FindLastPageInSameChunk(last_page->next_page()); 1109 heap()->isolate()->memory_allocator()->FindLastPageInSameChunk(
1110 last_page->next_page());
1243 } while (Capacity() < capacity); 1111 } while (Capacity() < capacity);
1244 1112
1245 return true; 1113 return true;
1246 } 1114 }
1247 1115
1248 1116
1249 #ifdef DEBUG 1117 #ifdef DEBUG
1250 void PagedSpace::Print() { } 1118 void PagedSpace::Print() { }
1251 #endif 1119 #endif
1252 1120
1253 1121
1254 #ifdef DEBUG 1122 #ifdef DEBUG
1255 // We do not assume that the PageIterator works, because it depends on the 1123 // We do not assume that the PageIterator works, because it depends on the
1256 // invariants we are checking during verification. 1124 // invariants we are checking during verification.
1257 void PagedSpace::Verify(ObjectVisitor* visitor) { 1125 void PagedSpace::Verify(ObjectVisitor* visitor) {
1258 // The allocation pointer should be valid, and it should be in a page in the 1126 // The allocation pointer should be valid, and it should be in a page in the
1259 // space. 1127 // space.
1260 ASSERT(allocation_info_.VerifyPagedAllocation()); 1128 ASSERT(allocation_info_.VerifyPagedAllocation());
1261 Page* top_page = Page::FromAllocationTop(allocation_info_.top); 1129 Page* top_page = Page::FromAllocationTop(allocation_info_.top);
1262 ASSERT(MemoryAllocator::IsPageInSpace(top_page, this)); 1130 ASSERT(heap()->isolate()->memory_allocator()->IsPageInSpace(top_page, this));
1263 1131
1264 // Loop over all the pages. 1132 // Loop over all the pages.
1265 bool above_allocation_top = false; 1133 bool above_allocation_top = false;
1266 Page* current_page = first_page_; 1134 Page* current_page = first_page_;
1267 while (current_page->is_valid()) { 1135 while (current_page->is_valid()) {
1268 if (above_allocation_top) { 1136 if (above_allocation_top) {
1269 // We don't care what's above the allocation top. 1137 // We don't care what's above the allocation top.
1270 } else { 1138 } else {
1271 Address top = current_page->AllocationTop(); 1139 Address top = current_page->AllocationTop();
1272 if (current_page == top_page) { 1140 if (current_page == top_page) {
1273 ASSERT(top == allocation_info_.top); 1141 ASSERT(top == allocation_info_.top);
1274 // The next page will be above the allocation top. 1142 // The next page will be above the allocation top.
1275 above_allocation_top = true; 1143 above_allocation_top = true;
1276 } 1144 }
1277 1145
1278 // It should be packed with objects from the bottom to the top. 1146 // It should be packed with objects from the bottom to the top.
1279 Address current = current_page->ObjectAreaStart(); 1147 Address current = current_page->ObjectAreaStart();
1280 while (current < top) { 1148 while (current < top) {
1281 HeapObject* object = HeapObject::FromAddress(current); 1149 HeapObject* object = HeapObject::FromAddress(current);
1282 1150
1283 // The first word should be a map, and we expect all map pointers to 1151 // The first word should be a map, and we expect all map pointers to
1284 // be in map space. 1152 // be in map space.
1285 Map* map = object->map(); 1153 Map* map = object->map();
1286 ASSERT(map->IsMap()); 1154 ASSERT(map->IsMap());
1287 ASSERT(Heap::map_space()->Contains(map)); 1155 ASSERT(heap()->map_space()->Contains(map));
1288 1156
1289 // Perform space-specific object verification. 1157 // Perform space-specific object verification.
1290 VerifyObject(object); 1158 VerifyObject(object);
1291 1159
1292 // The object itself should look OK. 1160 // The object itself should look OK.
1293 object->Verify(); 1161 object->Verify();
1294 1162
1295 // All the interior pointers should be contained in the heap and 1163 // All the interior pointers should be contained in the heap and
1296 // have page regions covering intergenerational references should be 1164 // have page regions covering intergenerational references should be
1297 // marked dirty. 1165 // marked dirty.
(...skipping 15 matching lines...) Expand all
1313 1181
1314 // ----------------------------------------------------------------------------- 1182 // -----------------------------------------------------------------------------
1315 // NewSpace implementation 1183 // NewSpace implementation
1316 1184
1317 1185
1318 bool NewSpace::Setup(Address start, int size) { 1186 bool NewSpace::Setup(Address start, int size) {
1319 // Setup new space based on the preallocated memory block defined by 1187 // Setup new space based on the preallocated memory block defined by
1320 // start and size. The provided space is divided into two semi-spaces. 1188 // start and size. The provided space is divided into two semi-spaces.
1321 // To support fast containment testing in the new space, the size of 1189 // To support fast containment testing in the new space, the size of
1322 // this chunk must be a power of two and it must be aligned to its size. 1190 // this chunk must be a power of two and it must be aligned to its size.
1323 int initial_semispace_capacity = Heap::InitialSemiSpaceSize(); 1191 int initial_semispace_capacity = heap()->InitialSemiSpaceSize();
1324 int maximum_semispace_capacity = Heap::MaxSemiSpaceSize(); 1192 int maximum_semispace_capacity = heap()->MaxSemiSpaceSize();
1325 1193
1326 ASSERT(initial_semispace_capacity <= maximum_semispace_capacity); 1194 ASSERT(initial_semispace_capacity <= maximum_semispace_capacity);
1327 ASSERT(IsPowerOf2(maximum_semispace_capacity)); 1195 ASSERT(IsPowerOf2(maximum_semispace_capacity));
1328 1196
1329 // Allocate and setup the histogram arrays if necessary. 1197 // Allocate and setup the histogram arrays if necessary.
1330 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1198 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
1331 allocated_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); 1199 allocated_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1);
1332 promoted_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); 1200 promoted_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1);
1333 1201
1334 #define SET_NAME(name) allocated_histogram_[name].set_name(#name); \ 1202 #define SET_NAME(name) allocated_histogram_[name].set_name(#name); \
1335 promoted_histogram_[name].set_name(#name); 1203 promoted_histogram_[name].set_name(#name);
1336 INSTANCE_TYPE_LIST(SET_NAME) 1204 INSTANCE_TYPE_LIST(SET_NAME)
1337 #undef SET_NAME 1205 #undef SET_NAME
1338 #endif 1206 #endif
1339 1207
1340 ASSERT(size == 2 * Heap::ReservedSemiSpaceSize()); 1208 ASSERT(size == 2 * heap()->ReservedSemiSpaceSize());
1341 ASSERT(IsAddressAligned(start, size, 0)); 1209 ASSERT(IsAddressAligned(start, size, 0));
1342 1210
1343 if (!to_space_.Setup(start, 1211 if (!to_space_.Setup(start,
1344 initial_semispace_capacity, 1212 initial_semispace_capacity,
1345 maximum_semispace_capacity)) { 1213 maximum_semispace_capacity)) {
1346 return false; 1214 return false;
1347 } 1215 }
1348 if (!from_space_.Setup(start + maximum_semispace_capacity, 1216 if (!from_space_.Setup(start + maximum_semispace_capacity,
1349 initial_semispace_capacity, 1217 initial_semispace_capacity,
1350 maximum_semispace_capacity)) { 1218 maximum_semispace_capacity)) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1385 mc_forwarding_info_.limit = NULL; 1253 mc_forwarding_info_.limit = NULL;
1386 1254
1387 to_space_.TearDown(); 1255 to_space_.TearDown();
1388 from_space_.TearDown(); 1256 from_space_.TearDown();
1389 } 1257 }
1390 1258
1391 1259
1392 #ifdef ENABLE_HEAP_PROTECTION 1260 #ifdef ENABLE_HEAP_PROTECTION
1393 1261
1394 void NewSpace::Protect() { 1262 void NewSpace::Protect() {
1395 MemoryAllocator::Protect(ToSpaceLow(), Capacity()); 1263 heap()->isolate()->memory_allocator()->Protect(ToSpaceLow(), Capacity());
1396 MemoryAllocator::Protect(FromSpaceLow(), Capacity()); 1264 heap()->isolate()->memory_allocator()->Protect(FromSpaceLow(), Capacity());
1397 } 1265 }
1398 1266
1399 1267
1400 void NewSpace::Unprotect() { 1268 void NewSpace::Unprotect() {
1401 MemoryAllocator::Unprotect(ToSpaceLow(), Capacity(), 1269 heap()->isolate()->memory_allocator()->Unprotect(ToSpaceLow(), Capacity(),
1402 to_space_.executable()); 1270 to_space_.executable());
1403 MemoryAllocator::Unprotect(FromSpaceLow(), Capacity(), 1271 heap()->isolate()->memory_allocator()->Unprotect(FromSpaceLow(), Capacity(),
1404 from_space_.executable()); 1272 from_space_.executable());
1405 } 1273 }
1406 1274
1407 #endif 1275 #endif
1408 1276
1409 1277
1410 void NewSpace::Flip() { 1278 void NewSpace::Flip() {
1411 SemiSpace tmp = from_space_; 1279 SemiSpace tmp = from_space_;
1412 from_space_ = to_space_; 1280 from_space_ = to_space_;
1413 to_space_ = tmp; 1281 to_space_ = tmp;
1414 } 1282 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 // There should be objects packed in from the low address up to the 1356 // There should be objects packed in from the low address up to the
1489 // allocation pointer. 1357 // allocation pointer.
1490 Address current = to_space_.low(); 1358 Address current = to_space_.low();
1491 while (current < top()) { 1359 while (current < top()) {
1492 HeapObject* object = HeapObject::FromAddress(current); 1360 HeapObject* object = HeapObject::FromAddress(current);
1493 1361
1494 // The first word should be a map, and we expect all map pointers to 1362 // The first word should be a map, and we expect all map pointers to
1495 // be in map space. 1363 // be in map space.
1496 Map* map = object->map(); 1364 Map* map = object->map();
1497 ASSERT(map->IsMap()); 1365 ASSERT(map->IsMap());
1498 ASSERT(Heap::map_space()->Contains(map)); 1366 ASSERT(heap()->map_space()->Contains(map));
1499 1367
1500 // The object should not be code or a map. 1368 // The object should not be code or a map.
1501 ASSERT(!object->IsMap()); 1369 ASSERT(!object->IsMap());
1502 ASSERT(!object->IsCode()); 1370 ASSERT(!object->IsCode());
1503 1371
1504 // The object itself should look OK. 1372 // The object itself should look OK.
1505 object->Verify(); 1373 object->Verify();
1506 1374
1507 // All the interior pointers should be contained in the heap. 1375 // All the interior pointers should be contained in the heap.
1508 VerifyPointersVisitor visitor; 1376 VerifyPointersVisitor visitor;
1509 int size = object->Size(); 1377 int size = object->Size();
1510 object->IterateBody(map->instance_type(), size, &visitor); 1378 object->IterateBody(map->instance_type(), size, &visitor);
1511 1379
1512 current += size; 1380 current += size;
1513 } 1381 }
1514 1382
1515 // The allocation pointer should not be in the middle of an object. 1383 // The allocation pointer should not be in the middle of an object.
1516 ASSERT(current == top()); 1384 ASSERT(current == top());
1517 } 1385 }
1518 #endif 1386 #endif
1519 1387
1520 1388
1521 bool SemiSpace::Commit() { 1389 bool SemiSpace::Commit() {
1522 ASSERT(!is_committed()); 1390 ASSERT(!is_committed());
1523 if (!MemoryAllocator::CommitBlock(start_, capacity_, executable())) { 1391 if (!heap()->isolate()->memory_allocator()->CommitBlock(
1392 start_, capacity_, executable())) {
1524 return false; 1393 return false;
1525 } 1394 }
1526 committed_ = true; 1395 committed_ = true;
1527 return true; 1396 return true;
1528 } 1397 }
1529 1398
1530 1399
1531 bool SemiSpace::Uncommit() { 1400 bool SemiSpace::Uncommit() {
1532 ASSERT(is_committed()); 1401 ASSERT(is_committed());
1533 if (!MemoryAllocator::UncommitBlock(start_, capacity_)) { 1402 if (!heap()->isolate()->memory_allocator()->UncommitBlock(
1403 start_, capacity_)) {
1534 return false; 1404 return false;
1535 } 1405 }
1536 committed_ = false; 1406 committed_ = false;
1537 return true; 1407 return true;
1538 } 1408 }
1539 1409
1540 1410
1541 // ----------------------------------------------------------------------------- 1411 // -----------------------------------------------------------------------------
1542 // SemiSpace implementation 1412 // SemiSpace implementation
1543 1413
(...skipping 25 matching lines...) Expand all
1569 start_ = NULL; 1439 start_ = NULL;
1570 capacity_ = 0; 1440 capacity_ = 0;
1571 } 1441 }
1572 1442
1573 1443
1574 bool SemiSpace::Grow() { 1444 bool SemiSpace::Grow() {
1575 // Double the semispace size but only up to maximum capacity. 1445 // Double the semispace size but only up to maximum capacity.
1576 int maximum_extra = maximum_capacity_ - capacity_; 1446 int maximum_extra = maximum_capacity_ - capacity_;
1577 int extra = Min(RoundUp(capacity_, static_cast<int>(OS::AllocateAlignment())), 1447 int extra = Min(RoundUp(capacity_, static_cast<int>(OS::AllocateAlignment())),
1578 maximum_extra); 1448 maximum_extra);
1579 if (!MemoryAllocator::CommitBlock(high(), extra, executable())) { 1449 if (!heap()->isolate()->memory_allocator()->CommitBlock(
1450 high(), extra, executable())) {
1580 return false; 1451 return false;
1581 } 1452 }
1582 capacity_ += extra; 1453 capacity_ += extra;
1583 return true; 1454 return true;
1584 } 1455 }
1585 1456
1586 1457
1587 bool SemiSpace::GrowTo(int new_capacity) { 1458 bool SemiSpace::GrowTo(int new_capacity) {
1588 ASSERT(new_capacity <= maximum_capacity_); 1459 ASSERT(new_capacity <= maximum_capacity_);
1589 ASSERT(new_capacity > capacity_); 1460 ASSERT(new_capacity > capacity_);
1590 size_t delta = new_capacity - capacity_; 1461 size_t delta = new_capacity - capacity_;
1591 ASSERT(IsAligned(delta, OS::AllocateAlignment())); 1462 ASSERT(IsAligned(delta, OS::AllocateAlignment()));
1592 if (!MemoryAllocator::CommitBlock(high(), delta, executable())) { 1463 if (!heap()->isolate()->memory_allocator()->CommitBlock(
1464 high(), delta, executable())) {
1593 return false; 1465 return false;
1594 } 1466 }
1595 capacity_ = new_capacity; 1467 capacity_ = new_capacity;
1596 return true; 1468 return true;
1597 } 1469 }
1598 1470
1599 1471
1600 bool SemiSpace::ShrinkTo(int new_capacity) { 1472 bool SemiSpace::ShrinkTo(int new_capacity) {
1601 ASSERT(new_capacity >= initial_capacity_); 1473 ASSERT(new_capacity >= initial_capacity_);
1602 ASSERT(new_capacity < capacity_); 1474 ASSERT(new_capacity < capacity_);
1603 size_t delta = capacity_ - new_capacity; 1475 size_t delta = capacity_ - new_capacity;
1604 ASSERT(IsAligned(delta, OS::AllocateAlignment())); 1476 ASSERT(IsAligned(delta, OS::AllocateAlignment()));
1605 if (!MemoryAllocator::UncommitBlock(high() - delta, delta)) { 1477 if (!heap()->isolate()->memory_allocator()->UncommitBlock(
1478 high() - delta, delta)) {
1606 return false; 1479 return false;
1607 } 1480 }
1608 capacity_ = new_capacity; 1481 capacity_ = new_capacity;
1609 return true; 1482 return true;
1610 } 1483 }
1611 1484
1612 1485
1613 #ifdef DEBUG 1486 #ifdef DEBUG
1614 void SemiSpace::Print() { } 1487 void SemiSpace::Print() { }
1615 1488
(...skipping 27 matching lines...) Expand all
1643 ASSERT(space->ToSpaceLow() <= end 1516 ASSERT(space->ToSpaceLow() <= end
1644 && end <= space->ToSpaceHigh()); 1517 && end <= space->ToSpaceHigh());
1645 space_ = &space->to_space_; 1518 space_ = &space->to_space_;
1646 current_ = start; 1519 current_ = start;
1647 limit_ = end; 1520 limit_ = end;
1648 size_func_ = size_func; 1521 size_func_ = size_func;
1649 } 1522 }
1650 1523
1651 1524
1652 #ifdef DEBUG 1525 #ifdef DEBUG
1653 // A static array of histogram info for each type.
1654 static HistogramInfo heap_histograms[LAST_TYPE+1];
1655 static JSObject::SpillInformation js_spill_information;
1656
1657 // heap_histograms is shared, always clear it before using it. 1526 // heap_histograms is shared, always clear it before using it.
1658 static void ClearHistograms() { 1527 static void ClearHistograms() {
1528 Isolate* isolate = Isolate::Current();
1659 // We reset the name each time, though it hasn't changed. 1529 // We reset the name each time, though it hasn't changed.
1660 #define DEF_TYPE_NAME(name) heap_histograms[name].set_name(#name); 1530 #define DEF_TYPE_NAME(name) isolate->heap_histograms()[name].set_name(#name);
1661 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) 1531 INSTANCE_TYPE_LIST(DEF_TYPE_NAME)
1662 #undef DEF_TYPE_NAME 1532 #undef DEF_TYPE_NAME
1663 1533
1664 #define CLEAR_HISTOGRAM(name) heap_histograms[name].clear(); 1534 #define CLEAR_HISTOGRAM(name) isolate->heap_histograms()[name].clear();
1665 INSTANCE_TYPE_LIST(CLEAR_HISTOGRAM) 1535 INSTANCE_TYPE_LIST(CLEAR_HISTOGRAM)
1666 #undef CLEAR_HISTOGRAM 1536 #undef CLEAR_HISTOGRAM
1667 1537
1668 js_spill_information.Clear(); 1538 isolate->js_spill_information()->Clear();
1669 } 1539 }
1670 1540
1671 1541
1672 static int code_kind_statistics[Code::NUMBER_OF_KINDS];
1673
1674
1675 static void ClearCodeKindStatistics() { 1542 static void ClearCodeKindStatistics() {
1543 Isolate* isolate = Isolate::Current();
1676 for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) { 1544 for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) {
1677 code_kind_statistics[i] = 0; 1545 isolate->code_kind_statistics()[i] = 0;
1678 } 1546 }
1679 } 1547 }
1680 1548
1681 1549
1682 static void ReportCodeKindStatistics() { 1550 static void ReportCodeKindStatistics() {
1551 Isolate* isolate = Isolate::Current();
1683 const char* table[Code::NUMBER_OF_KINDS] = { NULL }; 1552 const char* table[Code::NUMBER_OF_KINDS] = { NULL };
1684 1553
1685 #define CASE(name) \ 1554 #define CASE(name) \
1686 case Code::name: table[Code::name] = #name; \ 1555 case Code::name: table[Code::name] = #name; \
1687 break 1556 break
1688 1557
1689 for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) { 1558 for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) {
1690 switch (static_cast<Code::Kind>(i)) { 1559 switch (static_cast<Code::Kind>(i)) {
1691 CASE(FUNCTION); 1560 CASE(FUNCTION);
1692 CASE(OPTIMIZED_FUNCTION); 1561 CASE(OPTIMIZED_FUNCTION);
(...skipping 10 matching lines...) Expand all
1703 CASE(BINARY_OP_IC); 1572 CASE(BINARY_OP_IC);
1704 CASE(TYPE_RECORDING_BINARY_OP_IC); 1573 CASE(TYPE_RECORDING_BINARY_OP_IC);
1705 CASE(COMPARE_IC); 1574 CASE(COMPARE_IC);
1706 } 1575 }
1707 } 1576 }
1708 1577
1709 #undef CASE 1578 #undef CASE
1710 1579
1711 PrintF("\n Code kind histograms: \n"); 1580 PrintF("\n Code kind histograms: \n");
1712 for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) { 1581 for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) {
1713 if (code_kind_statistics[i] > 0) { 1582 if (isolate->code_kind_statistics()[i] > 0) {
1714 PrintF(" %-20s: %10d bytes\n", table[i], code_kind_statistics[i]); 1583 PrintF(" %-20s: %10d bytes\n", table[i],
1584 isolate->code_kind_statistics()[i]);
1715 } 1585 }
1716 } 1586 }
1717 PrintF("\n"); 1587 PrintF("\n");
1718 } 1588 }
1719 1589
1720 1590
1721 static int CollectHistogramInfo(HeapObject* obj) { 1591 static int CollectHistogramInfo(HeapObject* obj) {
1592 Isolate* isolate = Isolate::Current();
1722 InstanceType type = obj->map()->instance_type(); 1593 InstanceType type = obj->map()->instance_type();
1723 ASSERT(0 <= type && type <= LAST_TYPE); 1594 ASSERT(0 <= type && type <= LAST_TYPE);
1724 ASSERT(heap_histograms[type].name() != NULL); 1595 ASSERT(isolate->heap_histograms()[type].name() != NULL);
1725 heap_histograms[type].increment_number(1); 1596 isolate->heap_histograms()[type].increment_number(1);
1726 heap_histograms[type].increment_bytes(obj->Size()); 1597 isolate->heap_histograms()[type].increment_bytes(obj->Size());
1727 1598
1728 if (FLAG_collect_heap_spill_statistics && obj->IsJSObject()) { 1599 if (FLAG_collect_heap_spill_statistics && obj->IsJSObject()) {
1729 JSObject::cast(obj)->IncrementSpillStatistics(&js_spill_information); 1600 JSObject::cast(obj)->IncrementSpillStatistics(
1601 isolate->js_spill_information());
1730 } 1602 }
1731 1603
1732 return obj->Size(); 1604 return obj->Size();
1733 } 1605 }
1734 1606
1735 1607
1736 static void ReportHistogram(bool print_spill) { 1608 static void ReportHistogram(bool print_spill) {
1609 Isolate* isolate = Isolate::Current();
1737 PrintF("\n Object Histogram:\n"); 1610 PrintF("\n Object Histogram:\n");
1738 for (int i = 0; i <= LAST_TYPE; i++) { 1611 for (int i = 0; i <= LAST_TYPE; i++) {
1739 if (heap_histograms[i].number() > 0) { 1612 if (isolate->heap_histograms()[i].number() > 0) {
1740 PrintF(" %-34s%10d (%10d bytes)\n", 1613 PrintF(" %-34s%10d (%10d bytes)\n",
1741 heap_histograms[i].name(), 1614 isolate->heap_histograms()[i].name(),
1742 heap_histograms[i].number(), 1615 isolate->heap_histograms()[i].number(),
1743 heap_histograms[i].bytes()); 1616 isolate->heap_histograms()[i].bytes());
1744 } 1617 }
1745 } 1618 }
1746 PrintF("\n"); 1619 PrintF("\n");
1747 1620
1748 // Summarize string types. 1621 // Summarize string types.
1749 int string_number = 0; 1622 int string_number = 0;
1750 int string_bytes = 0; 1623 int string_bytes = 0;
1751 #define INCREMENT(type, size, name, camel_name) \ 1624 #define INCREMENT(type, size, name, camel_name) \
1752 string_number += heap_histograms[type].number(); \ 1625 string_number += isolate->heap_histograms()[type].number(); \
1753 string_bytes += heap_histograms[type].bytes(); 1626 string_bytes += isolate->heap_histograms()[type].bytes();
1754 STRING_TYPE_LIST(INCREMENT) 1627 STRING_TYPE_LIST(INCREMENT)
1755 #undef INCREMENT 1628 #undef INCREMENT
1756 if (string_number > 0) { 1629 if (string_number > 0) {
1757 PrintF(" %-34s%10d (%10d bytes)\n\n", "STRING_TYPE", string_number, 1630 PrintF(" %-34s%10d (%10d bytes)\n\n", "STRING_TYPE", string_number,
1758 string_bytes); 1631 string_bytes);
1759 } 1632 }
1760 1633
1761 if (FLAG_collect_heap_spill_statistics && print_spill) { 1634 if (FLAG_collect_heap_spill_statistics && print_spill) {
1762 js_spill_information.Print(); 1635 isolate->js_spill_information()->Print();
1763 } 1636 }
1764 } 1637 }
1765 #endif // DEBUG 1638 #endif // DEBUG
1766 1639
1767 1640
1768 // Support for statistics gathering for --heap-stats and --log-gc. 1641 // Support for statistics gathering for --heap-stats and --log-gc.
1769 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1642 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
1770 void NewSpace::ClearHistograms() { 1643 void NewSpace::ClearHistograms() {
1771 for (int i = 0; i <= LAST_TYPE; i++) { 1644 for (int i = 0; i <= LAST_TYPE; i++) {
1772 allocated_histogram_[i].clear(); 1645 allocated_histogram_[i].clear();
1773 promoted_histogram_[i].clear(); 1646 promoted_histogram_[i].clear();
1774 } 1647 }
1775 } 1648 }
1776 1649
1777 // Because the copying collector does not touch garbage objects, we iterate 1650 // Because the copying collector does not touch garbage objects, we iterate
1778 // the new space before a collection to get a histogram of allocated objects. 1651 // the new space before a collection to get a histogram of allocated objects.
1779 // This only happens (1) when compiled with DEBUG and the --heap-stats flag is 1652 // This only happens (1) when compiled with DEBUG and the --heap-stats flag is
1780 // set, or when compiled with ENABLE_LOGGING_AND_PROFILING and the --log-gc 1653 // set, or when compiled with ENABLE_LOGGING_AND_PROFILING and the --log-gc
1781 // flag is set. 1654 // flag is set.
1782 void NewSpace::CollectStatistics() { 1655 void NewSpace::CollectStatistics() {
1783 ClearHistograms(); 1656 ClearHistograms();
1784 SemiSpaceIterator it(this); 1657 SemiSpaceIterator it(this);
1785 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) 1658 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next())
1786 RecordAllocation(obj); 1659 RecordAllocation(obj);
1787 } 1660 }
1788 1661
1789 1662
1790 #ifdef ENABLE_LOGGING_AND_PROFILING 1663 #ifdef ENABLE_LOGGING_AND_PROFILING
1791 static void DoReportStatistics(HistogramInfo* info, const char* description) { 1664 static void DoReportStatistics(Isolate* isolate,
1792 LOG(HeapSampleBeginEvent("NewSpace", description)); 1665 HistogramInfo* info, const char* description) {
1666 LOG(isolate, HeapSampleBeginEvent("NewSpace", description));
1793 // Lump all the string types together. 1667 // Lump all the string types together.
1794 int string_number = 0; 1668 int string_number = 0;
1795 int string_bytes = 0; 1669 int string_bytes = 0;
1796 #define INCREMENT(type, size, name, camel_name) \ 1670 #define INCREMENT(type, size, name, camel_name) \
1797 string_number += info[type].number(); \ 1671 string_number += info[type].number(); \
1798 string_bytes += info[type].bytes(); 1672 string_bytes += info[type].bytes();
1799 STRING_TYPE_LIST(INCREMENT) 1673 STRING_TYPE_LIST(INCREMENT)
1800 #undef INCREMENT 1674 #undef INCREMENT
1801 if (string_number > 0) { 1675 if (string_number > 0) {
1802 LOG(HeapSampleItemEvent("STRING_TYPE", string_number, string_bytes)); 1676 LOG(isolate,
1677 HeapSampleItemEvent("STRING_TYPE", string_number, string_bytes));
1803 } 1678 }
1804 1679
1805 // Then do the other types. 1680 // Then do the other types.
1806 for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) { 1681 for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) {
1807 if (info[i].number() > 0) { 1682 if (info[i].number() > 0) {
1808 LOG(HeapSampleItemEvent(info[i].name(), info[i].number(), 1683 LOG(isolate,
1684 HeapSampleItemEvent(info[i].name(), info[i].number(),
1809 info[i].bytes())); 1685 info[i].bytes()));
1810 } 1686 }
1811 } 1687 }
1812 LOG(HeapSampleEndEvent("NewSpace", description)); 1688 LOG(isolate, HeapSampleEndEvent("NewSpace", description));
1813 } 1689 }
1814 #endif // ENABLE_LOGGING_AND_PROFILING 1690 #endif // ENABLE_LOGGING_AND_PROFILING
1815 1691
1816 1692
1817 void NewSpace::ReportStatistics() { 1693 void NewSpace::ReportStatistics() {
1818 #ifdef DEBUG 1694 #ifdef DEBUG
1819 if (FLAG_heap_stats) { 1695 if (FLAG_heap_stats) {
1820 float pct = static_cast<float>(Available()) / Capacity(); 1696 float pct = static_cast<float>(Available()) / Capacity();
1821 PrintF(" capacity: %" V8_PTR_PREFIX "d" 1697 PrintF(" capacity: %" V8_PTR_PREFIX "d"
1822 ", available: %" V8_PTR_PREFIX "d, %%%d\n", 1698 ", available: %" V8_PTR_PREFIX "d, %%%d\n",
1823 Capacity(), Available(), static_cast<int>(pct*100)); 1699 Capacity(), Available(), static_cast<int>(pct*100));
1824 PrintF("\n Object Histogram:\n"); 1700 PrintF("\n Object Histogram:\n");
1825 for (int i = 0; i <= LAST_TYPE; i++) { 1701 for (int i = 0; i <= LAST_TYPE; i++) {
1826 if (allocated_histogram_[i].number() > 0) { 1702 if (allocated_histogram_[i].number() > 0) {
1827 PrintF(" %-34s%10d (%10d bytes)\n", 1703 PrintF(" %-34s%10d (%10d bytes)\n",
1828 allocated_histogram_[i].name(), 1704 allocated_histogram_[i].name(),
1829 allocated_histogram_[i].number(), 1705 allocated_histogram_[i].number(),
1830 allocated_histogram_[i].bytes()); 1706 allocated_histogram_[i].bytes());
1831 } 1707 }
1832 } 1708 }
1833 PrintF("\n"); 1709 PrintF("\n");
1834 } 1710 }
1835 #endif // DEBUG 1711 #endif // DEBUG
1836 1712
1837 #ifdef ENABLE_LOGGING_AND_PROFILING 1713 #ifdef ENABLE_LOGGING_AND_PROFILING
1838 if (FLAG_log_gc) { 1714 if (FLAG_log_gc) {
1839 DoReportStatistics(allocated_histogram_, "allocated"); 1715 Isolate* isolate = ISOLATE;
1840 DoReportStatistics(promoted_histogram_, "promoted"); 1716 DoReportStatistics(isolate, allocated_histogram_, "allocated");
1717 DoReportStatistics(isolate, promoted_histogram_, "promoted");
1841 } 1718 }
1842 #endif // ENABLE_LOGGING_AND_PROFILING 1719 #endif // ENABLE_LOGGING_AND_PROFILING
1843 } 1720 }
1844 1721
1845 1722
1846 void NewSpace::RecordAllocation(HeapObject* obj) { 1723 void NewSpace::RecordAllocation(HeapObject* obj) {
1847 InstanceType type = obj->map()->instance_type(); 1724 InstanceType type = obj->map()->instance_type();
1848 ASSERT(0 <= type && type <= LAST_TYPE); 1725 ASSERT(0 <= type && type <= LAST_TYPE);
1849 allocated_histogram_[type].increment_number(1); 1726 allocated_histogram_[type].increment_number(1);
1850 allocated_histogram_[type].increment_bytes(obj->Size()); 1727 allocated_histogram_[type].increment_bytes(obj->Size());
(...skipping 17 matching lines...) Expand all
1868 ASSERT(IsAligned(size_in_bytes, kPointerSize)); 1745 ASSERT(IsAligned(size_in_bytes, kPointerSize));
1869 1746
1870 // We write a map and possibly size information to the block. If the block 1747 // We write a map and possibly size information to the block. If the block
1871 // is big enough to be a ByteArray with at least one extra word (the next 1748 // is big enough to be a ByteArray with at least one extra word (the next
1872 // pointer), we set its map to be the byte array map and its size to an 1749 // pointer), we set its map to be the byte array map and its size to an
1873 // appropriate array length for the desired size from HeapObject::Size(). 1750 // appropriate array length for the desired size from HeapObject::Size().
1874 // If the block is too small (eg, one or two words), to hold both a size 1751 // If the block is too small (eg, one or two words), to hold both a size
1875 // field and a next pointer, we give it a filler map that gives it the 1752 // field and a next pointer, we give it a filler map that gives it the
1876 // correct size. 1753 // correct size.
1877 if (size_in_bytes > ByteArray::kHeaderSize) { 1754 if (size_in_bytes > ByteArray::kHeaderSize) {
1878 set_map(Heap::raw_unchecked_byte_array_map()); 1755 set_map(HEAP->raw_unchecked_byte_array_map());
1879 // Can't use ByteArray::cast because it fails during deserialization. 1756 // Can't use ByteArray::cast because it fails during deserialization.
1880 ByteArray* this_as_byte_array = reinterpret_cast<ByteArray*>(this); 1757 ByteArray* this_as_byte_array = reinterpret_cast<ByteArray*>(this);
1881 this_as_byte_array->set_length(ByteArray::LengthFor(size_in_bytes)); 1758 this_as_byte_array->set_length(ByteArray::LengthFor(size_in_bytes));
1882 } else if (size_in_bytes == kPointerSize) { 1759 } else if (size_in_bytes == kPointerSize) {
1883 set_map(Heap::raw_unchecked_one_pointer_filler_map()); 1760 set_map(HEAP->raw_unchecked_one_pointer_filler_map());
1884 } else if (size_in_bytes == 2 * kPointerSize) { 1761 } else if (size_in_bytes == 2 * kPointerSize) {
1885 set_map(Heap::raw_unchecked_two_pointer_filler_map()); 1762 set_map(HEAP->raw_unchecked_two_pointer_filler_map());
1886 } else { 1763 } else {
1887 UNREACHABLE(); 1764 UNREACHABLE();
1888 } 1765 }
1889 // We would like to ASSERT(Size() == size_in_bytes) but this would fail during 1766 // We would like to ASSERT(Size() == size_in_bytes) but this would fail during
1890 // deserialization because the byte array map is not done yet. 1767 // deserialization because the byte array map is not done yet.
1891 } 1768 }
1892 1769
1893 1770
1894 Address FreeListNode::next() { 1771 Address FreeListNode::next() {
1895 ASSERT(IsFreeListNode(this)); 1772 ASSERT(IsFreeListNode(this));
1896 if (map() == Heap::raw_unchecked_byte_array_map()) { 1773 if (map() == HEAP->raw_unchecked_byte_array_map()) {
1897 ASSERT(Size() >= kNextOffset + kPointerSize); 1774 ASSERT(Size() >= kNextOffset + kPointerSize);
1898 return Memory::Address_at(address() + kNextOffset); 1775 return Memory::Address_at(address() + kNextOffset);
1899 } else { 1776 } else {
1900 return Memory::Address_at(address() + kPointerSize); 1777 return Memory::Address_at(address() + kPointerSize);
1901 } 1778 }
1902 } 1779 }
1903 1780
1904 1781
1905 void FreeListNode::set_next(Address next) { 1782 void FreeListNode::set_next(Address next) {
1906 ASSERT(IsFreeListNode(this)); 1783 ASSERT(IsFreeListNode(this));
1907 if (map() == Heap::raw_unchecked_byte_array_map()) { 1784 if (map() == HEAP->raw_unchecked_byte_array_map()) {
1908 ASSERT(Size() >= kNextOffset + kPointerSize); 1785 ASSERT(Size() >= kNextOffset + kPointerSize);
1909 Memory::Address_at(address() + kNextOffset) = next; 1786 Memory::Address_at(address() + kNextOffset) = next;
1910 } else { 1787 } else {
1911 Memory::Address_at(address() + kPointerSize) = next; 1788 Memory::Address_at(address() + kPointerSize) = next;
1912 } 1789 }
1913 } 1790 }
1914 1791
1915 1792
1916 OldSpaceFreeList::OldSpaceFreeList(AllocationSpace owner) : owner_(owner) { 1793 OldSpaceFreeList::OldSpaceFreeList(AllocationSpace owner) : owner_(owner) {
1917 Reset(); 1794 Reset();
(...skipping 20 matching lines...) Expand all
1938 cur = i; 1815 cur = i;
1939 } 1816 }
1940 } 1817 }
1941 free_[cur].next_size_ = kEnd; 1818 free_[cur].next_size_ = kEnd;
1942 needs_rebuild_ = false; 1819 needs_rebuild_ = false;
1943 } 1820 }
1944 1821
1945 1822
1946 int OldSpaceFreeList::Free(Address start, int size_in_bytes) { 1823 int OldSpaceFreeList::Free(Address start, int size_in_bytes) {
1947 #ifdef DEBUG 1824 #ifdef DEBUG
1948 MemoryAllocator::ZapBlock(start, size_in_bytes); 1825 Isolate::Current()->memory_allocator()->ZapBlock(start, size_in_bytes);
1949 #endif 1826 #endif
1950 FreeListNode* node = FreeListNode::FromAddress(start); 1827 FreeListNode* node = FreeListNode::FromAddress(start);
1951 node->set_size(size_in_bytes); 1828 node->set_size(size_in_bytes);
1952 1829
1953 // We don't use the freelists in compacting mode. This makes it more like a 1830 // We don't use the freelists in compacting mode. This makes it more like a
1954 // GC that only has mark-sweep-compact and doesn't have a mark-sweep 1831 // GC that only has mark-sweep-compact and doesn't have a mark-sweep
1955 // collector. 1832 // collector.
1956 if (FLAG_always_compact) { 1833 if (FLAG_always_compact) {
1957 return size_in_bytes; 1834 return size_in_bytes;
1958 } 1835 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
2082 1959
2083 1960
2084 void FixedSizeFreeList::Reset() { 1961 void FixedSizeFreeList::Reset() {
2085 available_ = 0; 1962 available_ = 0;
2086 head_ = tail_ = NULL; 1963 head_ = tail_ = NULL;
2087 } 1964 }
2088 1965
2089 1966
2090 void FixedSizeFreeList::Free(Address start) { 1967 void FixedSizeFreeList::Free(Address start) {
2091 #ifdef DEBUG 1968 #ifdef DEBUG
2092 MemoryAllocator::ZapBlock(start, object_size_); 1969 Isolate::Current()->memory_allocator()->ZapBlock(start, object_size_);
2093 #endif 1970 #endif
2094 // We only use the freelists with mark-sweep. 1971 // We only use the freelists with mark-sweep.
2095 ASSERT(!MarkCompactCollector::IsCompacting()); 1972 ASSERT(!HEAP->mark_compact_collector()->IsCompacting());
2096 FreeListNode* node = FreeListNode::FromAddress(start); 1973 FreeListNode* node = FreeListNode::FromAddress(start);
2097 node->set_size(object_size_); 1974 node->set_size(object_size_);
2098 node->set_next(NULL); 1975 node->set_next(NULL);
2099 if (head_ == NULL) { 1976 if (head_ == NULL) {
2100 tail_ = head_ = node->address(); 1977 tail_ = head_ = node->address();
2101 } else { 1978 } else {
2102 FreeListNode::FromAddress(tail_)->set_next(node->address()); 1979 FreeListNode::FromAddress(tail_)->set_next(node->address());
2103 tail_ = node->address(); 1980 tail_ = node->address();
2104 } 1981 }
2105 available_ += object_size_; 1982 available_ += object_size_;
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
2212 } 2089 }
2213 2090
2214 Page* first = NULL; 2091 Page* first = NULL;
2215 2092
2216 // Remove pages from the list. 2093 // Remove pages from the list.
2217 if (prev == NULL) { 2094 if (prev == NULL) {
2218 first = first_page_; 2095 first = first_page_;
2219 first_page_ = last->next_page(); 2096 first_page_ = last->next_page();
2220 } else { 2097 } else {
2221 first = prev->next_page(); 2098 first = prev->next_page();
2222 MemoryAllocator::SetNextPage(prev, last->next_page()); 2099 heap()->isolate()->memory_allocator()->SetNextPage(
2100 prev, last->next_page());
2223 } 2101 }
2224 2102
2225 // Attach it after the last page. 2103 // Attach it after the last page.
2226 MemoryAllocator::SetNextPage(last_page_, first); 2104 heap()->isolate()->memory_allocator()->SetNextPage(last_page_, first);
2227 last_page_ = last; 2105 last_page_ = last;
2228 MemoryAllocator::SetNextPage(last, NULL); 2106 heap()->isolate()->memory_allocator()->SetNextPage(last, NULL);
2229 2107
2230 // Clean them up. 2108 // Clean them up.
2231 do { 2109 do {
2232 first->InvalidateWatermark(true); 2110 first->InvalidateWatermark(true);
2233 first->SetAllocationWatermark(first->ObjectAreaStart()); 2111 first->SetAllocationWatermark(first->ObjectAreaStart());
2234 first->SetCachedAllocationWatermark(first->ObjectAreaStart()); 2112 first->SetCachedAllocationWatermark(first->ObjectAreaStart());
2235 first->SetRegionMarks(Page::kAllRegionsCleanMarks); 2113 first->SetRegionMarks(Page::kAllRegionsCleanMarks);
2236 first = first->next_page(); 2114 first = first->next_page();
2237 } while (first != NULL); 2115 } while (first != NULL);
2238 2116
(...skipping 18 matching lines...) Expand all
2257 if (p == last_in_use) { 2135 if (p == last_in_use) {
2258 // We passed a page containing allocation top. All consequent 2136 // We passed a page containing allocation top. All consequent
2259 // pages are not used. 2137 // pages are not used.
2260 in_use = false; 2138 in_use = false;
2261 } 2139 }
2262 } 2140 }
2263 2141
2264 if (page_list_is_chunk_ordered_) return; 2142 if (page_list_is_chunk_ordered_) return;
2265 2143
2266 Page* new_last_in_use = Page::FromAddress(NULL); 2144 Page* new_last_in_use = Page::FromAddress(NULL);
2267 MemoryAllocator::RelinkPageListInChunkOrder(this, 2145 heap()->isolate()->memory_allocator()->RelinkPageListInChunkOrder(
2268 &first_page_, 2146 this, &first_page_, &last_page_, &new_last_in_use);
2269 &last_page_,
2270 &new_last_in_use);
2271 ASSERT(new_last_in_use->is_valid()); 2147 ASSERT(new_last_in_use->is_valid());
2272 2148
2273 if (new_last_in_use != last_in_use) { 2149 if (new_last_in_use != last_in_use) {
2274 // Current allocation top points to a page which is now in the middle 2150 // Current allocation top points to a page which is now in the middle
2275 // of page list. We should move allocation top forward to the new last 2151 // of page list. We should move allocation top forward to the new last
2276 // used page so various object iterators will continue to work properly. 2152 // used page so various object iterators will continue to work properly.
2277 int size_in_bytes = static_cast<int>(PageAllocationLimit(last_in_use) - 2153 int size_in_bytes = static_cast<int>(PageAllocationLimit(last_in_use) -
2278 last_in_use->AllocationTop()); 2154 last_in_use->AllocationTop());
2279 2155
2280 last_in_use->SetAllocationWatermark(last_in_use->AllocationTop()); 2156 last_in_use->SetAllocationWatermark(last_in_use->AllocationTop());
2281 if (size_in_bytes > 0) { 2157 if (size_in_bytes > 0) {
2282 Address start = last_in_use->AllocationTop(); 2158 Address start = last_in_use->AllocationTop();
2283 if (deallocate_blocks) { 2159 if (deallocate_blocks) {
2284 accounting_stats_.AllocateBytes(size_in_bytes); 2160 accounting_stats_.AllocateBytes(size_in_bytes);
2285 DeallocateBlock(start, size_in_bytes, add_to_freelist); 2161 DeallocateBlock(start, size_in_bytes, add_to_freelist);
2286 } else { 2162 } else {
2287 Heap::CreateFillerObjectAt(start, size_in_bytes); 2163 heap()->CreateFillerObjectAt(start, size_in_bytes);
2288 } 2164 }
2289 } 2165 }
2290 2166
2291 // New last in use page was in the middle of the list before 2167 // New last in use page was in the middle of the list before
2292 // sorting so it full. 2168 // sorting so it full.
2293 SetTop(new_last_in_use->AllocationTop()); 2169 SetTop(new_last_in_use->AllocationTop());
2294 2170
2295 ASSERT(AllocationTopPage() == new_last_in_use); 2171 ASSERT(AllocationTopPage() == new_last_in_use);
2296 ASSERT(AllocationTopPage()->WasInUseBeforeMC()); 2172 ASSERT(AllocationTopPage()->WasInUseBeforeMC());
2297 } 2173 }
2298 2174
2299 PageIterator pages_in_use_iterator(this, PageIterator::PAGES_IN_USE); 2175 PageIterator pages_in_use_iterator(this, PageIterator::PAGES_IN_USE);
2300 while (pages_in_use_iterator.has_next()) { 2176 while (pages_in_use_iterator.has_next()) {
2301 Page* p = pages_in_use_iterator.next(); 2177 Page* p = pages_in_use_iterator.next();
2302 if (!p->WasInUseBeforeMC()) { 2178 if (!p->WasInUseBeforeMC()) {
2303 // Empty page is in the middle of a sequence of used pages. 2179 // Empty page is in the middle of a sequence of used pages.
2304 // Allocate it as a whole and deallocate immediately. 2180 // Allocate it as a whole and deallocate immediately.
2305 int size_in_bytes = static_cast<int>(PageAllocationLimit(p) - 2181 int size_in_bytes = static_cast<int>(PageAllocationLimit(p) -
2306 p->ObjectAreaStart()); 2182 p->ObjectAreaStart());
2307 2183
2308 p->SetAllocationWatermark(p->ObjectAreaStart()); 2184 p->SetAllocationWatermark(p->ObjectAreaStart());
2309 Address start = p->ObjectAreaStart(); 2185 Address start = p->ObjectAreaStart();
2310 if (deallocate_blocks) { 2186 if (deallocate_blocks) {
2311 accounting_stats_.AllocateBytes(size_in_bytes); 2187 accounting_stats_.AllocateBytes(size_in_bytes);
2312 DeallocateBlock(start, size_in_bytes, add_to_freelist); 2188 DeallocateBlock(start, size_in_bytes, add_to_freelist);
2313 } else { 2189 } else {
2314 Heap::CreateFillerObjectAt(start, size_in_bytes); 2190 heap()->CreateFillerObjectAt(start, size_in_bytes);
2315 } 2191 }
2316 } 2192 }
2317 } 2193 }
2318 2194
2319 page_list_is_chunk_ordered_ = true; 2195 page_list_is_chunk_ordered_ = true;
2320 } 2196 }
2321 2197
2322 2198
2323 void PagedSpace::PrepareForMarkCompact(bool will_compact) { 2199 void PagedSpace::PrepareForMarkCompact(bool will_compact) {
2324 if (will_compact) { 2200 if (will_compact) {
2325 RelinkPageListInChunkOrder(false); 2201 RelinkPageListInChunkOrder(false);
2326 } 2202 }
2327 } 2203 }
2328 2204
2329 2205
2330 bool PagedSpace::ReserveSpace(int bytes) { 2206 bool PagedSpace::ReserveSpace(int bytes) {
2331 Address limit = allocation_info_.limit; 2207 Address limit = allocation_info_.limit;
2332 Address top = allocation_info_.top; 2208 Address top = allocation_info_.top;
2333 if (limit - top >= bytes) return true; 2209 if (limit - top >= bytes) return true;
2334 2210
2335 // There wasn't enough space in the current page. Lets put the rest 2211 // There wasn't enough space in the current page. Lets put the rest
2336 // of the page on the free list and start a fresh page. 2212 // of the page on the free list and start a fresh page.
2337 PutRestOfCurrentPageOnFreeList(TopPageOf(allocation_info_)); 2213 PutRestOfCurrentPageOnFreeList(TopPageOf(allocation_info_));
2338 2214
2339 Page* reserved_page = TopPageOf(allocation_info_); 2215 Page* reserved_page = TopPageOf(allocation_info_);
2340 int bytes_left_to_reserve = bytes; 2216 int bytes_left_to_reserve = bytes;
2341 while (bytes_left_to_reserve > 0) { 2217 while (bytes_left_to_reserve > 0) {
2342 if (!reserved_page->next_page()->is_valid()) { 2218 if (!reserved_page->next_page()->is_valid()) {
2343 if (Heap::OldGenerationAllocationLimitReached()) return false; 2219 if (heap()->OldGenerationAllocationLimitReached()) return false;
2344 Expand(reserved_page); 2220 Expand(reserved_page);
2345 } 2221 }
2346 bytes_left_to_reserve -= Page::kPageSize; 2222 bytes_left_to_reserve -= Page::kPageSize;
2347 reserved_page = reserved_page->next_page(); 2223 reserved_page = reserved_page->next_page();
2348 if (!reserved_page->is_valid()) return false; 2224 if (!reserved_page->is_valid()) return false;
2349 } 2225 }
2350 ASSERT(TopPageOf(allocation_info_)->next_page()->is_valid()); 2226 ASSERT(TopPageOf(allocation_info_)->next_page()->is_valid());
2351 TopPageOf(allocation_info_)->next_page()->InvalidateWatermark(true); 2227 TopPageOf(allocation_info_)->next_page()->InvalidateWatermark(true);
2352 SetAllocationInfo(&allocation_info_, 2228 SetAllocationInfo(&allocation_info_,
2353 TopPageOf(allocation_info_)->next_page()); 2229 TopPageOf(allocation_info_)->next_page());
2354 return true; 2230 return true;
2355 } 2231 }
2356 2232
2357 2233
2358 // You have to call this last, since the implementation from PagedSpace 2234 // You have to call this last, since the implementation from PagedSpace
2359 // doesn't know that memory was 'promised' to large object space. 2235 // doesn't know that memory was 'promised' to large object space.
2360 bool LargeObjectSpace::ReserveSpace(int bytes) { 2236 bool LargeObjectSpace::ReserveSpace(int bytes) {
2361 return Heap::OldGenerationSpaceAvailable() >= bytes; 2237 return heap()->OldGenerationSpaceAvailable() >= bytes;
2362 } 2238 }
2363 2239
2364 2240
2365 // Slow case for normal allocation. Try in order: (1) allocate in the next 2241 // Slow case for normal allocation. Try in order: (1) allocate in the next
2366 // page in the space, (2) allocate off the space's free list, (3) expand the 2242 // page in the space, (2) allocate off the space's free list, (3) expand the
2367 // space, (4) fail. 2243 // space, (4) fail.
2368 HeapObject* OldSpace::SlowAllocateRaw(int size_in_bytes) { 2244 HeapObject* OldSpace::SlowAllocateRaw(int size_in_bytes) {
2369 // Linear allocation in this space has failed. If there is another page 2245 // Linear allocation in this space has failed. If there is another page
2370 // in the space, move to that page and allocate there. This allocation 2246 // in the space, move to that page and allocate there. This allocation
2371 // should succeed (size_in_bytes should not be greater than a page's 2247 // should succeed (size_in_bytes should not be greater than a page's
2372 // object area size). 2248 // object area size).
2373 Page* current_page = TopPageOf(allocation_info_); 2249 Page* current_page = TopPageOf(allocation_info_);
2374 if (current_page->next_page()->is_valid()) { 2250 if (current_page->next_page()->is_valid()) {
2375 return AllocateInNextPage(current_page, size_in_bytes); 2251 return AllocateInNextPage(current_page, size_in_bytes);
2376 } 2252 }
2377 2253
2378 // There is no next page in this space. Try free list allocation unless that 2254 // There is no next page in this space. Try free list allocation unless that
2379 // is currently forbidden. 2255 // is currently forbidden.
2380 if (!Heap::linear_allocation()) { 2256 if (!heap()->linear_allocation()) {
2381 int wasted_bytes; 2257 int wasted_bytes;
2382 Object* result; 2258 Object* result;
2383 MaybeObject* maybe = free_list_.Allocate(size_in_bytes, &wasted_bytes); 2259 MaybeObject* maybe = free_list_.Allocate(size_in_bytes, &wasted_bytes);
2384 accounting_stats_.WasteBytes(wasted_bytes); 2260 accounting_stats_.WasteBytes(wasted_bytes);
2385 if (maybe->ToObject(&result)) { 2261 if (maybe->ToObject(&result)) {
2386 accounting_stats_.AllocateBytes(size_in_bytes); 2262 accounting_stats_.AllocateBytes(size_in_bytes);
2387 2263
2388 HeapObject* obj = HeapObject::cast(result); 2264 HeapObject* obj = HeapObject::cast(result);
2389 Page* p = Page::FromAddress(obj->address()); 2265 Page* p = Page::FromAddress(obj->address());
2390 2266
2391 if (obj->address() >= p->AllocationWatermark()) { 2267 if (obj->address() >= p->AllocationWatermark()) {
2392 // There should be no hole between the allocation watermark 2268 // There should be no hole between the allocation watermark
2393 // and allocated object address. 2269 // and allocated object address.
2394 // Memory above the allocation watermark was not swept and 2270 // Memory above the allocation watermark was not swept and
2395 // might contain garbage pointers to new space. 2271 // might contain garbage pointers to new space.
2396 ASSERT(obj->address() == p->AllocationWatermark()); 2272 ASSERT(obj->address() == p->AllocationWatermark());
2397 p->SetAllocationWatermark(obj->address() + size_in_bytes); 2273 p->SetAllocationWatermark(obj->address() + size_in_bytes);
2398 } 2274 }
2399 2275
2400 return obj; 2276 return obj;
2401 } 2277 }
2402 } 2278 }
2403 2279
2404 // Free list allocation failed and there is no next page. Fail if we have 2280 // Free list allocation failed and there is no next page. Fail if we have
2405 // hit the old generation size limit that should cause a garbage 2281 // hit the old generation size limit that should cause a garbage
2406 // collection. 2282 // collection.
2407 if (!Heap::always_allocate() && Heap::OldGenerationAllocationLimitReached()) { 2283 if (!heap()->always_allocate() &&
2284 heap()->OldGenerationAllocationLimitReached()) {
2408 return NULL; 2285 return NULL;
2409 } 2286 }
2410 2287
2411 // Try to expand the space and allocate in the new next page. 2288 // Try to expand the space and allocate in the new next page.
2412 ASSERT(!current_page->next_page()->is_valid()); 2289 ASSERT(!current_page->next_page()->is_valid());
2413 if (Expand(current_page)) { 2290 if (Expand(current_page)) {
2414 return AllocateInNextPage(current_page, size_in_bytes); 2291 return AllocateInNextPage(current_page, size_in_bytes);
2415 } 2292 }
2416 2293
2417 // Finally, fail. 2294 // Finally, fail.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2460 2337
2461 2338
2462 void OldSpace::DeallocateBlock(Address start, 2339 void OldSpace::DeallocateBlock(Address start,
2463 int size_in_bytes, 2340 int size_in_bytes,
2464 bool add_to_freelist) { 2341 bool add_to_freelist) {
2465 Free(start, size_in_bytes, add_to_freelist); 2342 Free(start, size_in_bytes, add_to_freelist);
2466 } 2343 }
2467 2344
2468 2345
2469 #ifdef DEBUG 2346 #ifdef DEBUG
2470 struct CommentStatistic {
2471 const char* comment;
2472 int size;
2473 int count;
2474 void Clear() {
2475 comment = NULL;
2476 size = 0;
2477 count = 0;
2478 }
2479 };
2480
2481
2482 // must be small, since an iteration is used for lookup
2483 const int kMaxComments = 64;
2484 static CommentStatistic comments_statistics[kMaxComments+1];
2485
2486
2487 void PagedSpace::ReportCodeStatistics() { 2347 void PagedSpace::ReportCodeStatistics() {
2348 Isolate* isolate = Isolate::Current();
2349 CommentStatistic* comments_statistics =
2350 isolate->paged_space_comments_statistics();
2488 ReportCodeKindStatistics(); 2351 ReportCodeKindStatistics();
2489 PrintF("Code comment statistics (\" [ comment-txt : size/ " 2352 PrintF("Code comment statistics (\" [ comment-txt : size/ "
2490 "count (average)\"):\n"); 2353 "count (average)\"):\n");
2491 for (int i = 0; i <= kMaxComments; i++) { 2354 for (int i = 0; i <= CommentStatistic::kMaxComments; i++) {
2492 const CommentStatistic& cs = comments_statistics[i]; 2355 const CommentStatistic& cs = comments_statistics[i];
2493 if (cs.size > 0) { 2356 if (cs.size > 0) {
2494 PrintF(" %-30s: %10d/%6d (%d)\n", cs.comment, cs.size, cs.count, 2357 PrintF(" %-30s: %10d/%6d (%d)\n", cs.comment, cs.size, cs.count,
2495 cs.size/cs.count); 2358 cs.size/cs.count);
2496 } 2359 }
2497 } 2360 }
2498 PrintF("\n"); 2361 PrintF("\n");
2499 } 2362 }
2500 2363
2501 2364
2502 void PagedSpace::ResetCodeStatistics() { 2365 void PagedSpace::ResetCodeStatistics() {
2366 Isolate* isolate = Isolate::Current();
2367 CommentStatistic* comments_statistics =
2368 isolate->paged_space_comments_statistics();
2503 ClearCodeKindStatistics(); 2369 ClearCodeKindStatistics();
2504 for (int i = 0; i < kMaxComments; i++) comments_statistics[i].Clear(); 2370 for (int i = 0; i < CommentStatistic::kMaxComments; i++) {
2505 comments_statistics[kMaxComments].comment = "Unknown"; 2371 comments_statistics[i].Clear();
2506 comments_statistics[kMaxComments].size = 0; 2372 }
2507 comments_statistics[kMaxComments].count = 0; 2373 comments_statistics[CommentStatistic::kMaxComments].comment = "Unknown";
2374 comments_statistics[CommentStatistic::kMaxComments].size = 0;
2375 comments_statistics[CommentStatistic::kMaxComments].count = 0;
2508 } 2376 }
2509 2377
2510 2378
2511 // Adds comment to 'comment_statistics' table. Performance OK sa long as 2379 // Adds comment to 'comment_statistics' table. Performance OK as long as
2512 // 'kMaxComments' is small 2380 // 'kMaxComments' is small
2513 static void EnterComment(const char* comment, int delta) { 2381 static void EnterComment(Isolate* isolate, const char* comment, int delta) {
2382 CommentStatistic* comments_statistics =
2383 isolate->paged_space_comments_statistics();
2514 // Do not count empty comments 2384 // Do not count empty comments
2515 if (delta <= 0) return; 2385 if (delta <= 0) return;
2516 CommentStatistic* cs = &comments_statistics[kMaxComments]; 2386 CommentStatistic* cs = &comments_statistics[CommentStatistic::kMaxComments];
2517 // Search for a free or matching entry in 'comments_statistics': 'cs' 2387 // Search for a free or matching entry in 'comments_statistics': 'cs'
2518 // points to result. 2388 // points to result.
2519 for (int i = 0; i < kMaxComments; i++) { 2389 for (int i = 0; i < CommentStatistic::kMaxComments; i++) {
2520 if (comments_statistics[i].comment == NULL) { 2390 if (comments_statistics[i].comment == NULL) {
2521 cs = &comments_statistics[i]; 2391 cs = &comments_statistics[i];
2522 cs->comment = comment; 2392 cs->comment = comment;
2523 break; 2393 break;
2524 } else if (strcmp(comments_statistics[i].comment, comment) == 0) { 2394 } else if (strcmp(comments_statistics[i].comment, comment) == 0) {
2525 cs = &comments_statistics[i]; 2395 cs = &comments_statistics[i];
2526 break; 2396 break;
2527 } 2397 }
2528 } 2398 }
2529 // Update entry for 'comment' 2399 // Update entry for 'comment'
2530 cs->size += delta; 2400 cs->size += delta;
2531 cs->count += 1; 2401 cs->count += 1;
2532 } 2402 }
2533 2403
2534 2404
2535 // Call for each nested comment start (start marked with '[ xxx', end marked 2405 // Call for each nested comment start (start marked with '[ xxx', end marked
2536 // with ']'. RelocIterator 'it' must point to a comment reloc info. 2406 // with ']'. RelocIterator 'it' must point to a comment reloc info.
2537 static void CollectCommentStatistics(RelocIterator* it) { 2407 static void CollectCommentStatistics(Isolate* isolate, RelocIterator* it) {
2538 ASSERT(!it->done()); 2408 ASSERT(!it->done());
2539 ASSERT(it->rinfo()->rmode() == RelocInfo::COMMENT); 2409 ASSERT(it->rinfo()->rmode() == RelocInfo::COMMENT);
2540 const char* tmp = reinterpret_cast<const char*>(it->rinfo()->data()); 2410 const char* tmp = reinterpret_cast<const char*>(it->rinfo()->data());
2541 if (tmp[0] != '[') { 2411 if (tmp[0] != '[') {
2542 // Not a nested comment; skip 2412 // Not a nested comment; skip
2543 return; 2413 return;
2544 } 2414 }
2545 2415
2546 // Search for end of nested comment or a new nested comment 2416 // Search for end of nested comment or a new nested comment
2547 const char* const comment_txt = 2417 const char* const comment_txt =
2548 reinterpret_cast<const char*>(it->rinfo()->data()); 2418 reinterpret_cast<const char*>(it->rinfo()->data());
2549 const byte* prev_pc = it->rinfo()->pc(); 2419 const byte* prev_pc = it->rinfo()->pc();
2550 int flat_delta = 0; 2420 int flat_delta = 0;
2551 it->next(); 2421 it->next();
2552 while (true) { 2422 while (true) {
2553 // All nested comments must be terminated properly, and therefore exit 2423 // All nested comments must be terminated properly, and therefore exit
2554 // from loop. 2424 // from loop.
2555 ASSERT(!it->done()); 2425 ASSERT(!it->done());
2556 if (it->rinfo()->rmode() == RelocInfo::COMMENT) { 2426 if (it->rinfo()->rmode() == RelocInfo::COMMENT) {
2557 const char* const txt = 2427 const char* const txt =
2558 reinterpret_cast<const char*>(it->rinfo()->data()); 2428 reinterpret_cast<const char*>(it->rinfo()->data());
2559 flat_delta += static_cast<int>(it->rinfo()->pc() - prev_pc); 2429 flat_delta += static_cast<int>(it->rinfo()->pc() - prev_pc);
2560 if (txt[0] == ']') break; // End of nested comment 2430 if (txt[0] == ']') break; // End of nested comment
2561 // A new comment 2431 // A new comment
2562 CollectCommentStatistics(it); 2432 CollectCommentStatistics(isolate, it);
2563 // Skip code that was covered with previous comment 2433 // Skip code that was covered with previous comment
2564 prev_pc = it->rinfo()->pc(); 2434 prev_pc = it->rinfo()->pc();
2565 } 2435 }
2566 it->next(); 2436 it->next();
2567 } 2437 }
2568 EnterComment(comment_txt, flat_delta); 2438 EnterComment(isolate, comment_txt, flat_delta);
2569 } 2439 }
2570 2440
2571 2441
2572 // Collects code size statistics: 2442 // Collects code size statistics:
2573 // - by code kind 2443 // - by code kind
2574 // - by code comment 2444 // - by code comment
2575 void PagedSpace::CollectCodeStatistics() { 2445 void PagedSpace::CollectCodeStatistics() {
2446 Isolate* isolate = heap()->isolate();
2576 HeapObjectIterator obj_it(this); 2447 HeapObjectIterator obj_it(this);
2577 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) { 2448 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) {
2578 if (obj->IsCode()) { 2449 if (obj->IsCode()) {
2579 Code* code = Code::cast(obj); 2450 Code* code = Code::cast(obj);
2580 code_kind_statistics[code->kind()] += code->Size(); 2451 isolate->code_kind_statistics()[code->kind()] += code->Size();
2581 RelocIterator it(code); 2452 RelocIterator it(code);
2582 int delta = 0; 2453 int delta = 0;
2583 const byte* prev_pc = code->instruction_start(); 2454 const byte* prev_pc = code->instruction_start();
2584 while (!it.done()) { 2455 while (!it.done()) {
2585 if (it.rinfo()->rmode() == RelocInfo::COMMENT) { 2456 if (it.rinfo()->rmode() == RelocInfo::COMMENT) {
2586 delta += static_cast<int>(it.rinfo()->pc() - prev_pc); 2457 delta += static_cast<int>(it.rinfo()->pc() - prev_pc);
2587 CollectCommentStatistics(&it); 2458 CollectCommentStatistics(isolate, &it);
2588 prev_pc = it.rinfo()->pc(); 2459 prev_pc = it.rinfo()->pc();
2589 } 2460 }
2590 it.next(); 2461 it.next();
2591 } 2462 }
2592 2463
2593 ASSERT(code->instruction_start() <= prev_pc && 2464 ASSERT(code->instruction_start() <= prev_pc &&
2594 prev_pc <= code->instruction_end()); 2465 prev_pc <= code->instruction_end());
2595 delta += static_cast<int>(code->instruction_end() - prev_pc); 2466 delta += static_cast<int>(code->instruction_end() - prev_pc);
2596 EnterComment("NoComment", delta); 2467 EnterComment(isolate, "NoComment", delta);
2597 } 2468 }
2598 } 2469 }
2599 } 2470 }
2600 2471
2601 2472
2602 void OldSpace::ReportStatistics() { 2473 void OldSpace::ReportStatistics() {
2603 int pct = static_cast<int>(Available() * 100 / Capacity()); 2474 int pct = static_cast<int>(Available() * 100 / Capacity());
2604 PrintF(" capacity: %" V8_PTR_PREFIX "d" 2475 PrintF(" capacity: %" V8_PTR_PREFIX "d"
2605 ", waste: %" V8_PTR_PREFIX "d" 2476 ", waste: %" V8_PTR_PREFIX "d"
2606 ", available: %" V8_PTR_PREFIX "d, %%%d\n", 2477 ", available: %" V8_PTR_PREFIX "d, %%%d\n",
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2680 // in the space, move to that page and allocate there. This allocation 2551 // in the space, move to that page and allocate there. This allocation
2681 // should succeed. 2552 // should succeed.
2682 Page* current_page = TopPageOf(allocation_info_); 2553 Page* current_page = TopPageOf(allocation_info_);
2683 if (current_page->next_page()->is_valid()) { 2554 if (current_page->next_page()->is_valid()) {
2684 return AllocateInNextPage(current_page, size_in_bytes); 2555 return AllocateInNextPage(current_page, size_in_bytes);
2685 } 2556 }
2686 2557
2687 // There is no next page in this space. Try free list allocation unless 2558 // There is no next page in this space. Try free list allocation unless
2688 // that is currently forbidden. The fixed space free list implicitly assumes 2559 // that is currently forbidden. The fixed space free list implicitly assumes
2689 // that all free blocks are of the fixed size. 2560 // that all free blocks are of the fixed size.
2690 if (!Heap::linear_allocation()) { 2561 if (!heap()->linear_allocation()) {
2691 Object* result; 2562 Object* result;
2692 MaybeObject* maybe = free_list_.Allocate(); 2563 MaybeObject* maybe = free_list_.Allocate();
2693 if (maybe->ToObject(&result)) { 2564 if (maybe->ToObject(&result)) {
2694 accounting_stats_.AllocateBytes(size_in_bytes); 2565 accounting_stats_.AllocateBytes(size_in_bytes);
2695 HeapObject* obj = HeapObject::cast(result); 2566 HeapObject* obj = HeapObject::cast(result);
2696 Page* p = Page::FromAddress(obj->address()); 2567 Page* p = Page::FromAddress(obj->address());
2697 2568
2698 if (obj->address() >= p->AllocationWatermark()) { 2569 if (obj->address() >= p->AllocationWatermark()) {
2699 // There should be no hole between the allocation watermark 2570 // There should be no hole between the allocation watermark
2700 // and allocated object address. 2571 // and allocated object address.
2701 // Memory above the allocation watermark was not swept and 2572 // Memory above the allocation watermark was not swept and
2702 // might contain garbage pointers to new space. 2573 // might contain garbage pointers to new space.
2703 ASSERT(obj->address() == p->AllocationWatermark()); 2574 ASSERT(obj->address() == p->AllocationWatermark());
2704 p->SetAllocationWatermark(obj->address() + size_in_bytes); 2575 p->SetAllocationWatermark(obj->address() + size_in_bytes);
2705 } 2576 }
2706 2577
2707 return obj; 2578 return obj;
2708 } 2579 }
2709 } 2580 }
2710 2581
2711 // Free list allocation failed and there is no next page. Fail if we have 2582 // Free list allocation failed and there is no next page. Fail if we have
2712 // hit the old generation size limit that should cause a garbage 2583 // hit the old generation size limit that should cause a garbage
2713 // collection. 2584 // collection.
2714 if (!Heap::always_allocate() && Heap::OldGenerationAllocationLimitReached()) { 2585 if (!heap()->always_allocate() &&
2586 heap()->OldGenerationAllocationLimitReached()) {
2715 return NULL; 2587 return NULL;
2716 } 2588 }
2717 2589
2718 // Try to expand the space and allocate in the new next page. 2590 // Try to expand the space and allocate in the new next page.
2719 ASSERT(!current_page->next_page()->is_valid()); 2591 ASSERT(!current_page->next_page()->is_valid());
2720 if (Expand(current_page)) { 2592 if (Expand(current_page)) {
2721 return AllocateInNextPage(current_page, size_in_bytes); 2593 return AllocateInNextPage(current_page, size_in_bytes);
2722 } 2594 }
2723 2595
2724 // Finally, fail. 2596 // Finally, fail.
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2806 #endif 2678 #endif
2807 2679
2808 2680
2809 // ----------------------------------------------------------------------------- 2681 // -----------------------------------------------------------------------------
2810 // GlobalPropertyCellSpace implementation 2682 // GlobalPropertyCellSpace implementation
2811 2683
2812 #ifdef DEBUG 2684 #ifdef DEBUG
2813 void CellSpace::VerifyObject(HeapObject* object) { 2685 void CellSpace::VerifyObject(HeapObject* object) {
2814 // The object should be a global object property cell or a free-list node. 2686 // The object should be a global object property cell or a free-list node.
2815 ASSERT(object->IsJSGlobalPropertyCell() || 2687 ASSERT(object->IsJSGlobalPropertyCell() ||
2816 object->map() == Heap::two_pointer_filler_map()); 2688 object->map() == heap()->two_pointer_filler_map());
2817 } 2689 }
2818 #endif 2690 #endif
2819 2691
2820 2692
2821 // ----------------------------------------------------------------------------- 2693 // -----------------------------------------------------------------------------
2822 // LargeObjectIterator 2694 // LargeObjectIterator
2823 2695
2824 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) { 2696 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) {
2825 current_ = space->first_chunk_; 2697 current_ = space->first_chunk_;
2826 size_func_ = NULL; 2698 size_func_ = NULL;
(...skipping 16 matching lines...) Expand all
2843 } 2715 }
2844 2716
2845 2717
2846 // ----------------------------------------------------------------------------- 2718 // -----------------------------------------------------------------------------
2847 // LargeObjectChunk 2719 // LargeObjectChunk
2848 2720
2849 LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes, 2721 LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes,
2850 Executability executable) { 2722 Executability executable) {
2851 size_t requested = ChunkSizeFor(size_in_bytes); 2723 size_t requested = ChunkSizeFor(size_in_bytes);
2852 size_t size; 2724 size_t size;
2853 void* mem = MemoryAllocator::AllocateRawMemory(requested, &size, executable); 2725 Isolate* isolate = Isolate::Current();
2726 void* mem = isolate->memory_allocator()->AllocateRawMemory(
2727 requested, &size, executable);
2854 if (mem == NULL) return NULL; 2728 if (mem == NULL) return NULL;
2855 2729
2856 // The start of the chunk may be overlayed with a page so we have to 2730 // The start of the chunk may be overlayed with a page so we have to
2857 // make sure that the page flags fit in the size field. 2731 // make sure that the page flags fit in the size field.
2858 ASSERT((size & Page::kPageFlagMask) == 0); 2732 ASSERT((size & Page::kPageFlagMask) == 0);
2859 2733
2860 LOG(NewEvent("LargeObjectChunk", mem, size)); 2734 LOG(isolate, NewEvent("LargeObjectChunk", mem, size));
2861 if (size < requested) { 2735 if (size < requested) {
2862 MemoryAllocator::FreeRawMemory(mem, size, executable); 2736 isolate->memory_allocator()->FreeRawMemory(
2863 LOG(DeleteEvent("LargeObjectChunk", mem)); 2737 mem, size, executable);
2738 LOG(isolate, DeleteEvent("LargeObjectChunk", mem));
2864 return NULL; 2739 return NULL;
2865 } 2740 }
2866 2741
2867 ObjectSpace space = (executable == EXECUTABLE) 2742 ObjectSpace space = (executable == EXECUTABLE)
2868 ? kObjectSpaceCodeSpace 2743 ? kObjectSpaceCodeSpace
2869 : kObjectSpaceLoSpace; 2744 : kObjectSpaceLoSpace;
2870 MemoryAllocator::PerformAllocationCallback( 2745 isolate->memory_allocator()->PerformAllocationCallback(
2871 space, kAllocationActionAllocate, size); 2746 space, kAllocationActionAllocate, size);
2872 2747
2873 LargeObjectChunk* chunk = reinterpret_cast<LargeObjectChunk*>(mem); 2748 LargeObjectChunk* chunk = reinterpret_cast<LargeObjectChunk*>(mem);
2874 chunk->size_ = size; 2749 chunk->size_ = size;
2750 Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize));
2751 page->heap_ = Isolate::Current()->heap();
2875 return chunk; 2752 return chunk;
2876 } 2753 }
2877 2754
2878 2755
2879 int LargeObjectChunk::ChunkSizeFor(int size_in_bytes) { 2756 int LargeObjectChunk::ChunkSizeFor(int size_in_bytes) {
2880 int os_alignment = static_cast<int>(OS::AllocateAlignment()); 2757 int os_alignment = static_cast<int>(OS::AllocateAlignment());
2881 if (os_alignment < Page::kPageSize) { 2758 if (os_alignment < Page::kPageSize) {
2882 size_in_bytes += (Page::kPageSize - os_alignment); 2759 size_in_bytes += (Page::kPageSize - os_alignment);
2883 } 2760 }
2884 return size_in_bytes + Page::kObjectStartOffset; 2761 return size_in_bytes + Page::kObjectStartOffset;
2885 } 2762 }
2886 2763
2887 // ----------------------------------------------------------------------------- 2764 // -----------------------------------------------------------------------------
2888 // LargeObjectSpace 2765 // LargeObjectSpace
2889 2766
2890 LargeObjectSpace::LargeObjectSpace(AllocationSpace id) 2767 LargeObjectSpace::LargeObjectSpace(Heap* heap, AllocationSpace id)
2891 : Space(id, NOT_EXECUTABLE), // Managed on a per-allocation basis 2768 : Space(heap, id, NOT_EXECUTABLE), // Managed on a per-allocation basis
2892 first_chunk_(NULL), 2769 first_chunk_(NULL),
2893 size_(0), 2770 size_(0),
2894 page_count_(0), 2771 page_count_(0),
2895 objects_size_(0) {} 2772 objects_size_(0) {}
2896 2773
2897 2774
2898 bool LargeObjectSpace::Setup() { 2775 bool LargeObjectSpace::Setup() {
2899 first_chunk_ = NULL; 2776 first_chunk_ = NULL;
2900 size_ = 0; 2777 size_ = 0;
2901 page_count_ = 0; 2778 page_count_ = 0;
2902 objects_size_ = 0; 2779 objects_size_ = 0;
2903 return true; 2780 return true;
2904 } 2781 }
2905 2782
2906 2783
2907 void LargeObjectSpace::TearDown() { 2784 void LargeObjectSpace::TearDown() {
2908 while (first_chunk_ != NULL) { 2785 while (first_chunk_ != NULL) {
2909 LargeObjectChunk* chunk = first_chunk_; 2786 LargeObjectChunk* chunk = first_chunk_;
2910 first_chunk_ = first_chunk_->next(); 2787 first_chunk_ = first_chunk_->next();
2911 LOG(DeleteEvent("LargeObjectChunk", chunk->address())); 2788 LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk->address()));
2912 Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize)); 2789 Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize));
2913 Executability executable = 2790 Executability executable =
2914 page->IsPageExecutable() ? EXECUTABLE : NOT_EXECUTABLE; 2791 page->IsPageExecutable() ? EXECUTABLE : NOT_EXECUTABLE;
2915 ObjectSpace space = kObjectSpaceLoSpace; 2792 ObjectSpace space = kObjectSpaceLoSpace;
2916 if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace; 2793 if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace;
2917 size_t size = chunk->size(); 2794 size_t size = chunk->size();
2918 MemoryAllocator::FreeRawMemory(chunk->address(), size, executable); 2795 heap()->isolate()->memory_allocator()->FreeRawMemory(chunk->address(),
2919 MemoryAllocator::PerformAllocationCallback( 2796 size,
2797 executable);
2798 heap()->isolate()->memory_allocator()->PerformAllocationCallback(
2920 space, kAllocationActionFree, size); 2799 space, kAllocationActionFree, size);
2921 } 2800 }
2922 2801
2923 size_ = 0; 2802 size_ = 0;
2924 page_count_ = 0; 2803 page_count_ = 0;
2925 objects_size_ = 0; 2804 objects_size_ = 0;
2926 } 2805 }
2927 2806
2928 2807
2929 #ifdef ENABLE_HEAP_PROTECTION 2808 #ifdef ENABLE_HEAP_PROTECTION
2930 2809
2931 void LargeObjectSpace::Protect() { 2810 void LargeObjectSpace::Protect() {
2932 LargeObjectChunk* chunk = first_chunk_; 2811 LargeObjectChunk* chunk = first_chunk_;
2933 while (chunk != NULL) { 2812 while (chunk != NULL) {
2934 MemoryAllocator::Protect(chunk->address(), chunk->size()); 2813 heap()->isolate()->memory_allocator()->Protect(chunk->address(),
2814 chunk->size());
2935 chunk = chunk->next(); 2815 chunk = chunk->next();
2936 } 2816 }
2937 } 2817 }
2938 2818
2939 2819
2940 void LargeObjectSpace::Unprotect() { 2820 void LargeObjectSpace::Unprotect() {
2941 LargeObjectChunk* chunk = first_chunk_; 2821 LargeObjectChunk* chunk = first_chunk_;
2942 while (chunk != NULL) { 2822 while (chunk != NULL) {
2943 bool is_code = chunk->GetObject()->IsCode(); 2823 bool is_code = chunk->GetObject()->IsCode();
2944 MemoryAllocator::Unprotect(chunk->address(), chunk->size(), 2824 heap()->isolate()->memory_allocator()->Unprotect(chunk->address(),
2945 is_code ? EXECUTABLE : NOT_EXECUTABLE); 2825 chunk->size(), is_code ? EXECUTABLE : NOT_EXECUTABLE);
2946 chunk = chunk->next(); 2826 chunk = chunk->next();
2947 } 2827 }
2948 } 2828 }
2949 2829
2950 #endif 2830 #endif
2951 2831
2952 2832
2953 MaybeObject* LargeObjectSpace::AllocateRawInternal(int requested_size, 2833 MaybeObject* LargeObjectSpace::AllocateRawInternal(int requested_size,
2954 int object_size, 2834 int object_size,
2955 Executability executable) { 2835 Executability executable) {
2956 ASSERT(0 < object_size && object_size <= requested_size); 2836 ASSERT(0 < object_size && object_size <= requested_size);
2957 2837
2958 // Check if we want to force a GC before growing the old space further. 2838 // Check if we want to force a GC before growing the old space further.
2959 // If so, fail the allocation. 2839 // If so, fail the allocation.
2960 if (!Heap::always_allocate() && Heap::OldGenerationAllocationLimitReached()) { 2840 if (!heap()->always_allocate() &&
2841 heap()->OldGenerationAllocationLimitReached()) {
2961 return Failure::RetryAfterGC(identity()); 2842 return Failure::RetryAfterGC(identity());
2962 } 2843 }
2963 2844
2964 LargeObjectChunk* chunk = LargeObjectChunk::New(requested_size, executable); 2845 LargeObjectChunk* chunk = LargeObjectChunk::New(requested_size, executable);
2965 if (chunk == NULL) { 2846 if (chunk == NULL) {
2966 return Failure::RetryAfterGC(identity()); 2847 return Failure::RetryAfterGC(identity());
2967 } 2848 }
2968 2849
2969 size_ += static_cast<int>(chunk->size()); 2850 size_ += static_cast<int>(chunk->size());
2970 objects_size_ += requested_size; 2851 objects_size_ += requested_size;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
3055 // regions (modulo 32). So we treat a large page as a sequence of 2936 // regions (modulo 32). So we treat a large page as a sequence of
3056 // normal pages of size Page::kPageSize having same dirty marks 2937 // normal pages of size Page::kPageSize having same dirty marks
3057 // and subsequently iterate dirty regions on each of these pages. 2938 // and subsequently iterate dirty regions on each of these pages.
3058 Address start = object->address(); 2939 Address start = object->address();
3059 Address end = page->ObjectAreaEnd(); 2940 Address end = page->ObjectAreaEnd();
3060 Address object_end = start + object->Size(); 2941 Address object_end = start + object->Size();
3061 2942
3062 // Iterate regions of the first normal page covering object. 2943 // Iterate regions of the first normal page covering object.
3063 uint32_t first_region_number = page->GetRegionNumberForAddress(start); 2944 uint32_t first_region_number = page->GetRegionNumberForAddress(start);
3064 newmarks |= 2945 newmarks |=
3065 Heap::IterateDirtyRegions(marks >> first_region_number, 2946 heap()->IterateDirtyRegions(marks >> first_region_number,
3066 start, 2947 start,
3067 end, 2948 end,
3068 &Heap::IteratePointersInDirtyRegion, 2949 &Heap::IteratePointersInDirtyRegion,
3069 copy_object) << first_region_number; 2950 copy_object) << first_region_number;
3070 2951
3071 start = end; 2952 start = end;
3072 end = start + Page::kPageSize; 2953 end = start + Page::kPageSize;
3073 while (end <= object_end) { 2954 while (end <= object_end) {
3074 // Iterate next 32 regions. 2955 // Iterate next 32 regions.
3075 newmarks |= 2956 newmarks |=
3076 Heap::IterateDirtyRegions(marks, 2957 heap()->IterateDirtyRegions(marks,
3077 start, 2958 start,
3078 end, 2959 end,
3079 &Heap::IteratePointersInDirtyRegion, 2960 &Heap::IteratePointersInDirtyRegion,
3080 copy_object); 2961 copy_object);
3081 start = end; 2962 start = end;
3082 end = start + Page::kPageSize; 2963 end = start + Page::kPageSize;
3083 } 2964 }
3084 2965
3085 if (start != object_end) { 2966 if (start != object_end) {
3086 // Iterate the last piece of an object which is less than 2967 // Iterate the last piece of an object which is less than
3087 // Page::kPageSize. 2968 // Page::kPageSize.
3088 newmarks |= 2969 newmarks |=
3089 Heap::IterateDirtyRegions(marks, 2970 heap()->IterateDirtyRegions(marks,
3090 start, 2971 start,
3091 object_end, 2972 object_end,
3092 &Heap::IteratePointersInDirtyRegion, 2973 &Heap::IteratePointersInDirtyRegion,
3093 copy_object); 2974 copy_object);
3094 } 2975 }
3095 2976
3096 page->SetRegionMarks(newmarks); 2977 page->SetRegionMarks(newmarks);
3097 } 2978 }
3098 } 2979 }
3099 } 2980 }
3100 } 2981 }
3101 2982
3102 2983
3103 void LargeObjectSpace::FreeUnmarkedObjects() { 2984 void LargeObjectSpace::FreeUnmarkedObjects() {
3104 LargeObjectChunk* previous = NULL; 2985 LargeObjectChunk* previous = NULL;
3105 LargeObjectChunk* current = first_chunk_; 2986 LargeObjectChunk* current = first_chunk_;
3106 while (current != NULL) { 2987 while (current != NULL) {
3107 HeapObject* object = current->GetObject(); 2988 HeapObject* object = current->GetObject();
3108 if (object->IsMarked()) { 2989 if (object->IsMarked()) {
3109 object->ClearMark(); 2990 object->ClearMark();
3110 MarkCompactCollector::tracer()->decrement_marked_count(); 2991 heap()->mark_compact_collector()->tracer()->decrement_marked_count();
3111 previous = current; 2992 previous = current;
3112 current = current->next(); 2993 current = current->next();
3113 } else { 2994 } else {
3114 Page* page = Page::FromAddress(RoundUp(current->address(), 2995 Page* page = Page::FromAddress(RoundUp(current->address(),
3115 Page::kPageSize)); 2996 Page::kPageSize));
3116 Executability executable = 2997 Executability executable =
3117 page->IsPageExecutable() ? EXECUTABLE : NOT_EXECUTABLE; 2998 page->IsPageExecutable() ? EXECUTABLE : NOT_EXECUTABLE;
3118 Address chunk_address = current->address(); 2999 Address chunk_address = current->address();
3119 size_t chunk_size = current->size(); 3000 size_t chunk_size = current->size();
3120 3001
3121 // Cut the chunk out from the chunk list. 3002 // Cut the chunk out from the chunk list.
3122 current = current->next(); 3003 current = current->next();
3123 if (previous == NULL) { 3004 if (previous == NULL) {
3124 first_chunk_ = current; 3005 first_chunk_ = current;
3125 } else { 3006 } else {
3126 previous->set_next(current); 3007 previous->set_next(current);
3127 } 3008 }
3128 3009
3129 // Free the chunk. 3010 // Free the chunk.
3130 MarkCompactCollector::ReportDeleteIfNeeded(object); 3011 heap()->mark_compact_collector()->ReportDeleteIfNeeded(object);
3131 LiveObjectList::ProcessNonLive(object); 3012 LiveObjectList::ProcessNonLive(object);
3132 3013
3133 size_ -= static_cast<int>(chunk_size); 3014 size_ -= static_cast<int>(chunk_size);
3134 objects_size_ -= object->Size(); 3015 objects_size_ -= object->Size();
3135 page_count_--; 3016 page_count_--;
3136 ObjectSpace space = kObjectSpaceLoSpace; 3017 ObjectSpace space = kObjectSpaceLoSpace;
3137 if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace; 3018 if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace;
3138 MemoryAllocator::FreeRawMemory(chunk_address, chunk_size, executable); 3019 heap()->isolate()->memory_allocator()->FreeRawMemory(chunk_address,
3139 MemoryAllocator::PerformAllocationCallback(space, kAllocationActionFree, 3020 chunk_size,
3140 size_); 3021 executable);
3141 LOG(DeleteEvent("LargeObjectChunk", chunk_address)); 3022 heap()->isolate()->memory_allocator()->PerformAllocationCallback(
3023 space, kAllocationActionFree, size_);
3024 LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk_address));
3142 } 3025 }
3143 } 3026 }
3144 } 3027 }
3145 3028
3146 3029
3147 bool LargeObjectSpace::Contains(HeapObject* object) { 3030 bool LargeObjectSpace::Contains(HeapObject* object) {
3148 Address address = object->address(); 3031 Address address = object->address();
3149 if (Heap::new_space()->Contains(address)) { 3032 if (heap()->new_space()->Contains(address)) {
3150 return false; 3033 return false;
3151 } 3034 }
3152 Page* page = Page::FromAddress(address); 3035 Page* page = Page::FromAddress(address);
3153 3036
3154 SLOW_ASSERT(!page->IsLargeObjectPage() 3037 SLOW_ASSERT(!page->IsLargeObjectPage()
3155 || !FindObject(address)->IsFailure()); 3038 || !FindObject(address)->IsFailure());
3156 3039
3157 return page->IsLargeObjectPage(); 3040 return page->IsLargeObjectPage();
3158 } 3041 }
3159 3042
3160 3043
3161 #ifdef DEBUG 3044 #ifdef DEBUG
3162 // We do not assume that the large object iterator works, because it depends 3045 // We do not assume that the large object iterator works, because it depends
3163 // on the invariants we are checking during verification. 3046 // on the invariants we are checking during verification.
3164 void LargeObjectSpace::Verify() { 3047 void LargeObjectSpace::Verify() {
3165 for (LargeObjectChunk* chunk = first_chunk_; 3048 for (LargeObjectChunk* chunk = first_chunk_;
3166 chunk != NULL; 3049 chunk != NULL;
3167 chunk = chunk->next()) { 3050 chunk = chunk->next()) {
3168 // Each chunk contains an object that starts at the large object page's 3051 // Each chunk contains an object that starts at the large object page's
3169 // object area start. 3052 // object area start.
3170 HeapObject* object = chunk->GetObject(); 3053 HeapObject* object = chunk->GetObject();
3171 Page* page = Page::FromAddress(object->address()); 3054 Page* page = Page::FromAddress(object->address());
3172 ASSERT(object->address() == page->ObjectAreaStart()); 3055 ASSERT(object->address() == page->ObjectAreaStart());
3173 3056
3174 // The first word should be a map, and we expect all map pointers to be 3057 // The first word should be a map, and we expect all map pointers to be
3175 // in map space. 3058 // in map space.
3176 Map* map = object->map(); 3059 Map* map = object->map();
3177 ASSERT(map->IsMap()); 3060 ASSERT(map->IsMap());
3178 ASSERT(Heap::map_space()->Contains(map)); 3061 ASSERT(heap()->map_space()->Contains(map));
3179 3062
3180 // We have only code, sequential strings, external strings 3063 // We have only code, sequential strings, external strings
3181 // (sequential strings that have been morphed into external 3064 // (sequential strings that have been morphed into external
3182 // strings), fixed arrays, and byte arrays in large object space. 3065 // strings), fixed arrays, and byte arrays in large object space.
3183 ASSERT(object->IsCode() || object->IsSeqString() || 3066 ASSERT(object->IsCode() || object->IsSeqString() ||
3184 object->IsExternalString() || object->IsFixedArray() || 3067 object->IsExternalString() || object->IsFixedArray() ||
3185 object->IsByteArray()); 3068 object->IsByteArray());
3186 3069
3187 // The object itself should look OK. 3070 // The object itself should look OK.
3188 object->Verify(); 3071 object->Verify();
3189 3072
3190 // Byte arrays and strings don't have interior pointers. 3073 // Byte arrays and strings don't have interior pointers.
3191 if (object->IsCode()) { 3074 if (object->IsCode()) {
3192 VerifyPointersVisitor code_visitor; 3075 VerifyPointersVisitor code_visitor;
3193 object->IterateBody(map->instance_type(), 3076 object->IterateBody(map->instance_type(),
3194 object->Size(), 3077 object->Size(),
3195 &code_visitor); 3078 &code_visitor);
3196 } else if (object->IsFixedArray()) { 3079 } else if (object->IsFixedArray()) {
3197 // We loop over fixed arrays ourselves, rather then using the visitor, 3080 // We loop over fixed arrays ourselves, rather then using the visitor,
3198 // because the visitor doesn't support the start/offset iteration 3081 // because the visitor doesn't support the start/offset iteration
3199 // needed for IsRegionDirty. 3082 // needed for IsRegionDirty.
3200 FixedArray* array = FixedArray::cast(object); 3083 FixedArray* array = FixedArray::cast(object);
3201 for (int j = 0; j < array->length(); j++) { 3084 for (int j = 0; j < array->length(); j++) {
3202 Object* element = array->get(j); 3085 Object* element = array->get(j);
3203 if (element->IsHeapObject()) { 3086 if (element->IsHeapObject()) {
3204 HeapObject* element_object = HeapObject::cast(element); 3087 HeapObject* element_object = HeapObject::cast(element);
3205 ASSERT(Heap::Contains(element_object)); 3088 ASSERT(heap()->Contains(element_object));
3206 ASSERT(element_object->map()->IsMap()); 3089 ASSERT(element_object->map()->IsMap());
3207 if (Heap::InNewSpace(element_object)) { 3090 if (heap()->InNewSpace(element_object)) {
3208 Address array_addr = object->address(); 3091 Address array_addr = object->address();
3209 Address element_addr = array_addr + FixedArray::kHeaderSize + 3092 Address element_addr = array_addr + FixedArray::kHeaderSize +
3210 j * kPointerSize; 3093 j * kPointerSize;
3211 3094
3212 ASSERT(Page::FromAddress(array_addr)->IsRegionDirty(element_addr)); 3095 ASSERT(Page::FromAddress(array_addr)->IsRegionDirty(element_addr));
3213 } 3096 }
3214 } 3097 }
3215 } 3098 }
3216 } 3099 }
3217 } 3100 }
(...skipping 18 matching lines...) Expand all
3236 CollectHistogramInfo(obj); 3119 CollectHistogramInfo(obj);
3237 } 3120 }
3238 3121
3239 PrintF(" number of objects %d, " 3122 PrintF(" number of objects %d, "
3240 "size of objects %" V8_PTR_PREFIX "d\n", num_objects, objects_size_); 3123 "size of objects %" V8_PTR_PREFIX "d\n", num_objects, objects_size_);
3241 if (num_objects > 0) ReportHistogram(false); 3124 if (num_objects > 0) ReportHistogram(false);
3242 } 3125 }
3243 3126
3244 3127
3245 void LargeObjectSpace::CollectCodeStatistics() { 3128 void LargeObjectSpace::CollectCodeStatistics() {
3129 Isolate* isolate = heap()->isolate();
3246 LargeObjectIterator obj_it(this); 3130 LargeObjectIterator obj_it(this);
3247 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) { 3131 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) {
3248 if (obj->IsCode()) { 3132 if (obj->IsCode()) {
3249 Code* code = Code::cast(obj); 3133 Code* code = Code::cast(obj);
3250 code_kind_statistics[code->kind()] += code->Size(); 3134 isolate->code_kind_statistics()[code->kind()] += code->Size();
3251 } 3135 }
3252 } 3136 }
3253 } 3137 }
3254 #endif // DEBUG 3138 #endif // DEBUG
3255 3139
3256 } } // namespace v8::internal 3140 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/spaces.h ('k') | src/spaces-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698