1 // Copyright 2009 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include "v8.h" 29 30 #include "accessors.h" 31 #include "api.h" 32 #include "bootstrapper.h" 33 #include "codegen-inl.h" 34 #include "compilation-cache.h" 35 #include "debug.h" 36 #include "heap-profiler.h" 37 #include "global-handles.h" 38 #include "mark-compact.h" 39 #include "natives.h" 40 #include "scanner.h" 41 #include "scopeinfo.h" 42 #include "snapshot.h" 43 #include "v8threads.h" 44 #if V8_TARGET_ARCH_ARM && V8_NATIVE_REGEXP 45 #include "regexp-macro-assembler.h" 46 #include "arm/regexp-macro-assembler-arm.h" 47 #endif 48 49 namespace v8 { 50 namespace internal { 51 52 53 String* Heap::hidden_symbol_; 54 Object* Heap::roots_[Heap::kRootListLength]; 55 56 57 NewSpace Heap::new_space_; 58 OldSpace* Heap::old_pointer_space_ = NULL; 59 OldSpace* Heap::old_data_space_ = NULL; 60 OldSpace* Heap::code_space_ = NULL; 61 MapSpace* Heap::map_space_ = NULL; 62 CellSpace* Heap::cell_space_ = NULL; 63 LargeObjectSpace* Heap::lo_space_ = NULL; 64 65 static const int kMinimumPromotionLimit = 2*MB; 66 static const int kMinimumAllocationLimit = 8*MB; 67 68 int Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit; 69 int Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit; 70 71 int Heap::old_gen_exhausted_ = false; 72 73 int Heap::amount_of_external_allocated_memory_ = 0; 74 int Heap::amount_of_external_allocated_memory_at_last_global_gc_ = 0; 75 76 // semispace_size_ should be a power of 2 and old_generation_size_ should be 77 // a multiple of Page::kPageSize. 78 #if defined(ANDROID) 79 int Heap::max_semispace_size_ = 2*MB; 80 int Heap::max_old_generation_size_ = 192*MB; 81 int Heap::initial_semispace_size_ = 128*KB; 82 size_t Heap::code_range_size_ = 0; 83 #elif defined(V8_TARGET_ARCH_X64) 84 int Heap::max_semispace_size_ = 16*MB; 85 int Heap::max_old_generation_size_ = 1*GB; 86 int Heap::initial_semispace_size_ = 1*MB; 87 size_t Heap::code_range_size_ = 512*MB; 88 #else 89 int Heap::max_semispace_size_ = 8*MB; 90 int Heap::max_old_generation_size_ = 512*MB; 91 int Heap::initial_semispace_size_ = 512*KB; 92 size_t Heap::code_range_size_ = 0; 93 #endif 94 95 // The snapshot semispace size will be the default semispace size if 96 // snapshotting is used and will be the requested semispace size as 97 // set up by ConfigureHeap otherwise. 98 int Heap::reserved_semispace_size_ = Heap::max_semispace_size_; 99 100 GCCallback Heap::global_gc_prologue_callback_ = NULL; 101 GCCallback Heap::global_gc_epilogue_callback_ = NULL; 102 103 // Variables set based on semispace_size_ and old_generation_size_ in 104 // ConfigureHeap. 105 106 // Will be 4 * reserved_semispace_size_ to ensure that young 107 // generation can be aligned to its size. 108 int Heap::survived_since_last_expansion_ = 0; 109 int Heap::external_allocation_limit_ = 0; 110 111 Heap::HeapState Heap::gc_state_ = NOT_IN_GC; 112 113 int Heap::mc_count_ = 0; 114 int Heap::gc_count_ = 0; 115 116 int Heap::always_allocate_scope_depth_ = 0; 117 int Heap::linear_allocation_scope_depth_ = 0; 118 bool Heap::context_disposed_pending_ = false; 119 120 #ifdef DEBUG 121 bool Heap::allocation_allowed_ = true; 122 123 int Heap::allocation_timeout_ = 0; 124 bool Heap::disallow_allocation_failure_ = false; 125 #endif // DEBUG 126 127 128 int Heap::Capacity() { 129 if (!HasBeenSetup()) return 0; 130 131 return new_space_.Capacity() + 132 old_pointer_space_->Capacity() + 133 old_data_space_->Capacity() + 134 code_space_->Capacity() + 135 map_space_->Capacity() + 136 cell_space_->Capacity(); 137 } 138 139 140 int Heap::CommittedMemory() { 141 if (!HasBeenSetup()) return 0; 142 143 return new_space_.CommittedMemory() + 144 old_pointer_space_->CommittedMemory() + 145 old_data_space_->CommittedMemory() + 146 code_space_->CommittedMemory() + 147 map_space_->CommittedMemory() + 148 cell_space_->CommittedMemory() + 149 lo_space_->Size(); 150 } 151 152 153 int Heap::Available() { 154 if (!HasBeenSetup()) return 0; 155 156 return new_space_.Available() + 157 old_pointer_space_->Available() + 158 old_data_space_->Available() + 159 code_space_->Available() + 160 map_space_->Available() + 161 cell_space_->Available(); 162 } 163 164 165 bool Heap::HasBeenSetup() { 166 return old_pointer_space_ != NULL && 167 old_data_space_ != NULL && 168 code_space_ != NULL && 169 map_space_ != NULL && 170 cell_space_ != NULL && 171 lo_space_ != NULL; 172 } 173 174 175 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) { 176 // Is global GC requested? 177 if (space != NEW_SPACE || FLAG_gc_global) { 178 Counters::gc_compactor_caused_by_request.Increment(); 179 return MARK_COMPACTOR; 180 } 181 182 // Is enough data promoted to justify a global GC? 183 if (OldGenerationPromotionLimitReached()) { 184 Counters::gc_compactor_caused_by_promoted_data.Increment(); 185 return MARK_COMPACTOR; 186 } 187 188 // Have allocation in OLD and LO failed? 189 if (old_gen_exhausted_) { 190 Counters::gc_compactor_caused_by_oldspace_exhaustion.Increment(); 191 return MARK_COMPACTOR; 192 } 193 194 // Is there enough space left in OLD to guarantee that a scavenge can 195 // succeed? 196 // 197 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available 198 // for object promotion. It counts only the bytes that the memory 199 // allocator has not yet allocated from the OS and assigned to any space, 200 // and does not count available bytes already in the old space or code 201 // space. Undercounting is safe---we may get an unrequested full GC when 202 // a scavenge would have succeeded. 203 if (MemoryAllocator::MaxAvailable() <= new_space_.Size()) { 204 Counters::gc_compactor_caused_by_oldspace_exhaustion.Increment(); 205 return MARK_COMPACTOR; 206 } 207 208 // Default 209 return SCAVENGER; 210 } 211 212 213 // TODO(1238405): Combine the infrastructure for --heap-stats and 214 // --log-gc to avoid the complicated preprocessor and flag testing. 215 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 216 void Heap::ReportStatisticsBeforeGC() { 217 // Heap::ReportHeapStatistics will also log NewSpace statistics when 218 // compiled with ENABLE_LOGGING_AND_PROFILING and --log-gc is set. The 219 // following logic is used to avoid double logging. 220 #if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING) 221 if (FLAG_heap_stats || FLAG_log_gc) new_space_.CollectStatistics(); 222 if (FLAG_heap_stats) { 223 ReportHeapStatistics("Before GC"); 224 } else if (FLAG_log_gc) { 225 new_space_.ReportStatistics(); 226 } 227 if (FLAG_heap_stats || FLAG_log_gc) new_space_.ClearHistograms(); 228 #elif defined(DEBUG) 229 if (FLAG_heap_stats) { 230 new_space_.CollectStatistics(); 231 ReportHeapStatistics("Before GC"); 232 new_space_.ClearHistograms(); 233 } 234 #elif defined(ENABLE_LOGGING_AND_PROFILING) 235 if (FLAG_log_gc) { 236 new_space_.CollectStatistics(); 237 new_space_.ReportStatistics(); 238 new_space_.ClearHistograms(); 239 } 240 #endif 241 } 242 243 244 #if defined(ENABLE_LOGGING_AND_PROFILING) 245 void Heap::PrintShortHeapStatistics() { 246 if (!FLAG_trace_gc_verbose) return; 247 PrintF("Memory allocator, used: %8d, available: %8d\n", 248 MemoryAllocator::Size(), 249 MemoryAllocator::Available()); 250 PrintF("New space, used: %8d, available: %8d\n", 251 Heap::new_space_.Size(), 252 new_space_.Available()); 253 PrintF("Old pointers, used: %8d, available: %8d, waste: %8d\n", 254 old_pointer_space_->Size(), 255 old_pointer_space_->Available(), 256 old_pointer_space_->Waste()); 257 PrintF("Old data space, used: %8d, available: %8d, waste: %8d\n", 258 old_data_space_->Size(), 259 old_data_space_->Available(), 260 old_data_space_->Waste()); 261 PrintF("Code space, used: %8d, available: %8d, waste: %8d\n", 262 code_space_->Size(), 263 code_space_->Available(), 264 code_space_->Waste()); 265 PrintF("Map space, used: %8d, available: %8d, waste: %8d\n", 266 map_space_->Size(), 267 map_space_->Available(), 268 map_space_->Waste()); 269 PrintF("Cell space, used: %8d, available: %8d, waste: %8d\n", 270 cell_space_->Size(), 271 cell_space_->Available(), 272 cell_space_->Waste()); 273 PrintF("Large object space, used: %8d, avaialble: %8d\n", 274 lo_space_->Size(), 275 lo_space_->Available()); 276 } 277 #endif 278 279 280 // TODO(1238405): Combine the infrastructure for --heap-stats and 281 // --log-gc to avoid the complicated preprocessor and flag testing. 282 void Heap::ReportStatisticsAfterGC() { 283 // Similar to the before GC, we use some complicated logic to ensure that 284 // NewSpace statistics are logged exactly once when --log-gc is turned on. 285 #if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING) 286 if (FLAG_heap_stats) { 287 new_space_.CollectStatistics(); 288 ReportHeapStatistics("After GC"); 289 } else if (FLAG_log_gc) { 290 new_space_.ReportStatistics(); 291 } 292 #elif defined(DEBUG) 293 if (FLAG_heap_stats) ReportHeapStatistics("After GC"); 294 #elif defined(ENABLE_LOGGING_AND_PROFILING) 295 if (FLAG_log_gc) new_space_.ReportStatistics(); 296 #endif 297 } 298 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 299 300 301 void Heap::GarbageCollectionPrologue() { 302 TranscendentalCache::Clear(); 303 gc_count_++; 304 #ifdef DEBUG 305 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); 306 allow_allocation(false); 307 308 if (FLAG_verify_heap) { 309 Verify(); 310 } 311 312 if (FLAG_gc_verbose) Print(); 313 314 if (FLAG_print_rset) { 315 // Not all spaces have remembered set bits that we care about. 316 old_pointer_space_->PrintRSet(); 317 map_space_->PrintRSet(); 318 lo_space_->PrintRSet(); 319 } 320 #endif 321 322 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 323 ReportStatisticsBeforeGC(); 324 #endif 325 } 326 327 int Heap::SizeOfObjects() { 328 int total = 0; 329 AllSpaces spaces; 330 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { 331 total += space->Size(); 332 } 333 return total; 334 } 335 336 void Heap::GarbageCollectionEpilogue() { 337 #ifdef DEBUG 338 allow_allocation(true); 339 ZapFromSpace(); 340 341 if (FLAG_verify_heap) { 342 Verify(); 343 } 344 345 if (FLAG_print_global_handles) GlobalHandles::Print(); 346 if (FLAG_print_handles) PrintHandles(); 347 if (FLAG_gc_verbose) Print(); 348 if (FLAG_code_stats) ReportCodeStatistics("After GC"); 349 #endif 350 351 Counters::alive_after_last_gc.Set(SizeOfObjects()); 352 353 Counters::symbol_table_capacity.Set(symbol_table()->Capacity()); 354 Counters::number_of_symbols.Set(symbol_table()->NumberOfElements()); 355 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 356 ReportStatisticsAfterGC(); 357 #endif 358 #ifdef ENABLE_DEBUGGER_SUPPORT 359 Debug::AfterGarbageCollection(); 360 #endif 361 } 362 363 364 void Heap::CollectAllGarbage(bool force_compaction) { 365 // Since we are ignoring the return value, the exact choice of space does 366 // not matter, so long as we do not specify NEW_SPACE, which would not 367 // cause a full GC. 368 MarkCompactCollector::SetForceCompaction(force_compaction); 369 CollectGarbage(0, OLD_POINTER_SPACE); 370 MarkCompactCollector::SetForceCompaction(false); 371 } 372 373 374 void Heap::CollectAllGarbageIfContextDisposed() { 375 // If the garbage collector interface is exposed through the global 376 // gc() function, we avoid being clever about forcing GCs when 377 // contexts are disposed and leave it to the embedder to make 378 // informed decisions about when to force a collection. 379 if (!FLAG_expose_gc && context_disposed_pending_) { 380 HistogramTimerScope scope(&Counters::gc_context); 381 CollectAllGarbage(false); 382 } 383 context_disposed_pending_ = false; 384 } 385 386 387 void Heap::NotifyContextDisposed() { 388 context_disposed_pending_ = true; 389 } 390 391 392 bool Heap::CollectGarbage(int requested_size, AllocationSpace space) { 393 // The VM is in the GC state until exiting this function. 394 VMState state(GC); 395 396 #ifdef DEBUG 397 // Reset the allocation timeout to the GC interval, but make sure to 398 // allow at least a few allocations after a collection. The reason 399 // for this is that we have a lot of allocation sequences and we 400 // assume that a garbage collection will allow the subsequent 401 // allocation attempts to go through. 402 allocation_timeout_ = Max(6, FLAG_gc_interval); 403 #endif 404 405 { GCTracer tracer; 406 GarbageCollectionPrologue(); 407 // The GC count was incremented in the prologue. Tell the tracer about 408 // it. 409 tracer.set_gc_count(gc_count_); 410 411 GarbageCollector collector = SelectGarbageCollector(space); 412 // Tell the tracer which collector we've selected. 413 tracer.set_collector(collector); 414 415 HistogramTimer* rate = (collector == SCAVENGER) 416 ? &Counters::gc_scavenger 417 : &Counters::gc_compactor; 418 rate->Start(); 419 PerformGarbageCollection(space, collector, &tracer); 420 rate->Stop(); 421 422 GarbageCollectionEpilogue(); 423 } 424 425 426 #ifdef ENABLE_LOGGING_AND_PROFILING 427 if (FLAG_log_gc) HeapProfiler::WriteSample(); 428 #endif 429 430 switch (space) { 431 case NEW_SPACE: 432 return new_space_.Available() >= requested_size; 433 case OLD_POINTER_SPACE: 434 return old_pointer_space_->Available() >= requested_size; 435 case OLD_DATA_SPACE: 436 return old_data_space_->Available() >= requested_size; 437 case CODE_SPACE: 438 return code_space_->Available() >= requested_size; 439 case MAP_SPACE: 440 return map_space_->Available() >= requested_size; 441 case CELL_SPACE: 442 return cell_space_->Available() >= requested_size; 443 case LO_SPACE: 444 return lo_space_->Available() >= requested_size; 445 } 446 return false; 447 } 448 449 450 void Heap::PerformScavenge() { 451 GCTracer tracer; 452 PerformGarbageCollection(NEW_SPACE, SCAVENGER, &tracer); 453 } 454 455 456 #ifdef DEBUG 457 // Helper class for verifying the symbol table. 458 class SymbolTableVerifier : public ObjectVisitor { 459 public: 460 SymbolTableVerifier() { } 461 void VisitPointers(Object** start, Object** end) { 462 // Visit all HeapObject pointers in [start, end). 463 for (Object** p = start; p < end; p++) { 464 if ((*p)->IsHeapObject()) { 465 // Check that the symbol is actually a symbol. 466 ASSERT((*p)->IsNull() || (*p)->IsUndefined() || (*p)->IsSymbol()); 467 } 468 } 469 } 470 }; 471 #endif // DEBUG 472 473 474 static void VerifySymbolTable() { 475 #ifdef DEBUG 476 SymbolTableVerifier verifier; 477 Heap::symbol_table()->IterateElements(&verifier); 478 #endif // DEBUG 479 } 480 481 482 void Heap::ReserveSpace( 483 int new_space_size, 484 int pointer_space_size, 485 int data_space_size, 486 int code_space_size, 487 int map_space_size, 488 int cell_space_size, 489 int large_object_size) { 490 NewSpace* new_space = Heap::new_space(); 491 PagedSpace* old_pointer_space = Heap::old_pointer_space(); 492 PagedSpace* old_data_space = Heap::old_data_space(); 493 PagedSpace* code_space = Heap::code_space(); 494 PagedSpace* map_space = Heap::map_space(); 495 PagedSpace* cell_space = Heap::cell_space(); 496 LargeObjectSpace* lo_space = Heap::lo_space(); 497 bool gc_performed = true; 498 while (gc_performed) { 499 gc_performed = false; 500 if (!new_space->ReserveSpace(new_space_size)) { 501 Heap::CollectGarbage(new_space_size, NEW_SPACE); 502 gc_performed = true; 503 } 504 if (!old_pointer_space->ReserveSpace(pointer_space_size)) { 505 Heap::CollectGarbage(pointer_space_size, OLD_POINTER_SPACE); 506 gc_performed = true; 507 } 508 if (!(old_data_space->ReserveSpace(data_space_size))) { 509 Heap::CollectGarbage(data_space_size, OLD_DATA_SPACE); 510 gc_performed = true; 511 } 512 if (!(code_space->ReserveSpace(code_space_size))) { 513 Heap::CollectGarbage(code_space_size, CODE_SPACE); 514 gc_performed = true; 515 } 516 if (!(map_space->ReserveSpace(map_space_size))) { 517 Heap::CollectGarbage(map_space_size, MAP_SPACE); 518 gc_performed = true; 519 } 520 if (!(cell_space->ReserveSpace(cell_space_size))) { 521 Heap::CollectGarbage(cell_space_size, CELL_SPACE); 522 gc_performed = true; 523 } 524 // We add a slack-factor of 2 in order to have space for the remembered 525 // set and a series of large-object allocations that are only just larger 526 // than the page size. 527 large_object_size *= 2; 528 // The ReserveSpace method on the large object space checks how much 529 // we can expand the old generation. This includes expansion caused by 530 // allocation in the other spaces. 531 large_object_size += cell_space_size + map_space_size + code_space_size + 532 data_space_size + pointer_space_size; 533 if (!(lo_space->ReserveSpace(large_object_size))) { 534 Heap::CollectGarbage(large_object_size, LO_SPACE); 535 gc_performed = true; 536 } 537 } 538 } 539 540 541 void Heap::EnsureFromSpaceIsCommitted() { 542 if (new_space_.CommitFromSpaceIfNeeded()) return; 543 544 // Committing memory to from space failed. 545 // Try shrinking and try again. 546 Shrink(); 547 if (new_space_.CommitFromSpaceIfNeeded()) return; 548 549 // Committing memory to from space failed again. 550 // Memory is exhausted and we will die. 551 V8::FatalProcessOutOfMemory("Committing semi space failed."); 552 } 553 554 555 void Heap::PerformGarbageCollection(AllocationSpace space, 556 GarbageCollector collector, 557 GCTracer* tracer) { 558 VerifySymbolTable(); 559 if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) { 560 ASSERT(!allocation_allowed_); 561 global_gc_prologue_callback_(); 562 } 563 EnsureFromSpaceIsCommitted(); 564 if (collector == MARK_COMPACTOR) { 565 MarkCompact(tracer); 566 567 int old_gen_size = PromotedSpaceSize(); 568 old_gen_promotion_limit_ = 569 old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3); 570 old_gen_allocation_limit_ = 571 old_gen_size + Max(kMinimumAllocationLimit, old_gen_size / 2); 572 old_gen_exhausted_ = false; 573 } 574 Scavenge(); 575 576 Counters::objs_since_last_young.Set(0); 577 578 if (collector == MARK_COMPACTOR) { 579 DisableAssertNoAllocation allow_allocation; 580 GlobalHandles::PostGarbageCollectionProcessing(); 581 } 582 583 // Update relocatables. 584 Relocatable::PostGarbageCollectionProcessing(); 585 586 if (collector == MARK_COMPACTOR) { 587 // Register the amount of external allocated memory. 588 amount_of_external_allocated_memory_at_last_global_gc_ = 589 amount_of_external_allocated_memory_; 590 } 591 592 if (collector == MARK_COMPACTOR && global_gc_epilogue_callback_) { 593 ASSERT(!allocation_allowed_); 594 global_gc_epilogue_callback_(); 595 } 596 VerifySymbolTable(); 597 } 598 599 600 void Heap::MarkCompact(GCTracer* tracer) { 601 gc_state_ = MARK_COMPACT; 602 mc_count_++; 603 tracer->set_full_gc_count(mc_count_); 604 LOG(ResourceEvent("markcompact", "begin")); 605 606 MarkCompactCollector::Prepare(tracer); 607 608 bool is_compacting = MarkCompactCollector::IsCompacting(); 609 610 MarkCompactPrologue(is_compacting); 611 612 MarkCompactCollector::CollectGarbage(); 613 614 MarkCompactEpilogue(is_compacting); 615 616 LOG(ResourceEvent("markcompact", "end")); 617 618 gc_state_ = NOT_IN_GC; 619 620 Shrink(); 621 622 Counters::objs_since_last_full.Set(0); 623 context_disposed_pending_ = false; 624 } 625 626 627 void Heap::MarkCompactPrologue(bool is_compacting) { 628 // At any old GC clear the keyed lookup cache to enable collection of unused 629 // maps. 630 KeyedLookupCache::Clear(); 631 ContextSlotCache::Clear(); 632 DescriptorLookupCache::Clear(); 633 634 CompilationCache::MarkCompactPrologue(); 635 636 Top::MarkCompactPrologue(is_compacting); 637 ThreadManager::MarkCompactPrologue(is_compacting); 638 639 if (is_compacting) FlushNumberStringCache(); 640 } 641 642 643 void Heap::MarkCompactEpilogue(bool is_compacting) { 644 Top::MarkCompactEpilogue(is_compacting); 645 ThreadManager::MarkCompactEpilogue(is_compacting); 646 } 647 648 649 Object* Heap::FindCodeObject(Address a) { 650 Object* obj = code_space_->FindObject(a); 651 if (obj->IsFailure()) { 652 obj = lo_space_->FindObject(a); 653 } 654 ASSERT(!obj->IsFailure()); 655 return obj; 656 } 657 658 659 // Helper class for copying HeapObjects 660 class ScavengeVisitor: public ObjectVisitor { 661 public: 662 663 void VisitPointer(Object** p) { ScavengePointer(p); } 664 665 void VisitPointers(Object** start, Object** end) { 666 // Copy all HeapObject pointers in [start, end) 667 for (Object** p = start; p < end; p++) ScavengePointer(p); 668 } 669 670 private: 671 void ScavengePointer(Object** p) { 672 Object* object = *p; 673 if (!Heap::InNewSpace(object)) return; 674 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), 675 reinterpret_cast<HeapObject*>(object)); 676 } 677 }; 678 679 680 // A queue of pointers and maps of to-be-promoted objects during a 681 // scavenge collection. 682 class PromotionQueue { 683 public: 684 void Initialize(Address start_address) { 685 front_ = rear_ = reinterpret_cast<HeapObject**>(start_address); 686 } 687 688 bool is_empty() { return front_ <= rear_; } 689 690 void insert(HeapObject* object, Map* map) { 691 *(--rear_) = object; 692 *(--rear_) = map; 693 // Assert no overflow into live objects. 694 ASSERT(reinterpret_cast<Address>(rear_) >= Heap::new_space()->top()); 695 } 696 697 void remove(HeapObject** object, Map** map) { 698 *object = *(--front_); 699 *map = Map::cast(*(--front_)); 700 // Assert no underflow. 701 ASSERT(front_ >= rear_); 702 } 703 704 private: 705 // The front of the queue is higher in memory than the rear. 706 HeapObject** front_; 707 HeapObject** rear_; 708 }; 709 710 711 // Shared state read by the scavenge collector and set by ScavengeObject. 712 static PromotionQueue promotion_queue; 713 714 715 #ifdef DEBUG 716 // Visitor class to verify pointers in code or data space do not point into 717 // new space. 718 class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor { 719 public: 720 void VisitPointers(Object** start, Object**end) { 721 for (Object** current = start; current < end; current++) { 722 if ((*current)->IsHeapObject()) { 723 ASSERT(!Heap::InNewSpace(HeapObject::cast(*current))); 724 } 725 } 726 } 727 }; 728 729 730 static void VerifyNonPointerSpacePointers() { 731 // Verify that there are no pointers to new space in spaces where we 732 // do not expect them. 733 VerifyNonPointerSpacePointersVisitor v; 734 HeapObjectIterator code_it(Heap::code_space()); 735 for (HeapObject* object = code_it.next(); 736 object != NULL; object = code_it.next()) 737 object->Iterate(&v); 738 739 HeapObjectIterator data_it(Heap::old_data_space()); 740 for (HeapObject* object = data_it.next(); 741 object != NULL; object = data_it.next()) 742 object->Iterate(&v); 743 } 744 #endif 745 746 747 void Heap::Scavenge() { 748 #ifdef DEBUG 749 if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers(); 750 #endif 751 752 gc_state_ = SCAVENGE; 753 754 // Implements Cheney's copying algorithm 755 LOG(ResourceEvent("scavenge", "begin")); 756 757 // Clear descriptor cache. 758 DescriptorLookupCache::Clear(); 759 760 // Used for updating survived_since_last_expansion_ at function end. 761 int survived_watermark = PromotedSpaceSize(); 762 763 if (new_space_.Capacity() < new_space_.MaximumCapacity() && 764 survived_since_last_expansion_ > new_space_.Capacity()) { 765 // Grow the size of new space if there is room to grow and enough 766 // data has survived scavenge since the last expansion. 767 new_space_.Grow(); 768 survived_since_last_expansion_ = 0; 769 } 770 771 // Flip the semispaces. After flipping, to space is empty, from space has 772 // live objects. 773 new_space_.Flip(); 774 new_space_.ResetAllocationInfo(); 775 776 // We need to sweep newly copied objects which can be either in the 777 // to space or promoted to the old generation. For to-space 778 // objects, we treat the bottom of the to space as a queue. Newly 779 // copied and unswept objects lie between a 'front' mark and the 780 // allocation pointer. 781 // 782 // Promoted objects can go into various old-generation spaces, and 783 // can be allocated internally in the spaces (from the free list). 784 // We treat the top of the to space as a queue of addresses of 785 // promoted objects. The addresses of newly promoted and unswept 786 // objects lie between a 'front' mark and a 'rear' mark that is 787 // updated as a side effect of promoting an object. 788 // 789 // There is guaranteed to be enough room at the top of the to space 790 // for the addresses of promoted objects: every object promoted 791 // frees up its size in bytes from the top of the new space, and 792 // objects are at least one pointer in size. 793 Address new_space_front = new_space_.ToSpaceLow(); 794 promotion_queue.Initialize(new_space_.ToSpaceHigh()); 795 796 ScavengeVisitor scavenge_visitor; 797 // Copy roots. 798 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); 799 800 // Copy objects reachable from the old generation. By definition, 801 // there are no intergenerational pointers in code or data spaces. 802 IterateRSet(old_pointer_space_, &ScavengePointer); 803 IterateRSet(map_space_, &ScavengePointer); 804 lo_space_->IterateRSet(&ScavengePointer); 805 806 // Copy objects reachable from cells by scavenging cell values directly. 807 HeapObjectIterator cell_iterator(cell_space_); 808 for (HeapObject* cell = cell_iterator.next(); 809 cell != NULL; cell = cell_iterator.next()) { 810 if (cell->IsJSGlobalPropertyCell()) { 811 Address value_address = 812 reinterpret_cast<Address>(cell) + 813 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); 814 scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address)); 815 } 816 } 817 818 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); 819 820 ScavengeExternalStringTable(); 821 ASSERT(new_space_front == new_space_.top()); 822 823 // Set age mark. 824 new_space_.set_age_mark(new_space_.top()); 825 826 // Update how much has survived scavenge. 827 survived_since_last_expansion_ += 828 (PromotedSpaceSize() - survived_watermark) + new_space_.Size(); 829 830 LOG(ResourceEvent("scavenge", "end")); 831 832 gc_state_ = NOT_IN_GC; 833 } 834 835 836 void Heap::ScavengeExternalStringTable() { 837 ExternalStringTable::Verify(); 838 839 if (ExternalStringTable::new_space_strings_.is_empty()) return; 840 841 Object** start = &ExternalStringTable::new_space_strings_[0]; 842 Object** end = start + ExternalStringTable::new_space_strings_.length(); 843 Object** last = start; 844 845 for (Object** p = start; p < end; ++p) { 846 ASSERT(Heap::InFromSpace(*p)); 847 MapWord first_word = HeapObject::cast(*p)->map_word(); 848 849 if (!first_word.IsForwardingAddress()) { 850 // Unreachable external string can be finalized. 851 FinalizeExternalString(String::cast(*p)); 852 continue; 853 } 854 855 // String is still reachable. 856 String* target = String::cast(first_word.ToForwardingAddress()); 857 ASSERT(target->IsExternalString()); 858 859 if (Heap::InNewSpace(target)) { 860 // String is still in new space. Update the table entry. 861 *last = target; 862 ++last; 863 } else { 864 // String got promoted. Move it to the old string list. 865 ExternalStringTable::AddOldString(target); 866 } 867 } 868 869 ASSERT(last <= end); 870 ExternalStringTable::ShrinkNewStrings(static_cast<int>(last - start)); 871 } 872 873 874 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, 875 Address new_space_front) { 876 do { 877 ASSERT(new_space_front <= new_space_.top()); 878 879 // The addresses new_space_front and new_space_.top() define a 880 // queue of unprocessed copied objects. Process them until the 881 // queue is empty. 882 while (new_space_front < new_space_.top()) { 883 HeapObject* object = HeapObject::FromAddress(new_space_front); 884 object->Iterate(scavenge_visitor); 885 new_space_front += object->Size(); 886 } 887 888 // Promote and process all the to-be-promoted objects. 889 while (!promotion_queue.is_empty()) { 890 HeapObject* source; 891 Map* map; 892 promotion_queue.remove(&source, &map); 893 // Copy the from-space object to its new location (given by the 894 // forwarding address) and fix its map. 895 HeapObject* target = source->map_word().ToForwardingAddress(); 896 CopyBlock(reinterpret_cast<Object**>(target->address()), 897 reinterpret_cast<Object**>(source->address()), 898 source->SizeFromMap(map)); 899 target->set_map(map); 900 901 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 902 // Update NewSpace stats if necessary. 903 RecordCopiedObject(target); 904 #endif 905 // Visit the newly copied object for pointers to new space. 906 target->Iterate(scavenge_visitor); 907 UpdateRSet(target); 908 } 909 910 // Take another spin if there are now unswept objects in new space 911 // (there are currently no more unswept promoted objects). 912 } while (new_space_front < new_space_.top()); 913 914 return new_space_front; 915 } 916 917 918 void Heap::ClearRSetRange(Address start, int size_in_bytes) { 919 uint32_t start_bit; 920 Address start_word_address = 921 Page::ComputeRSetBitPosition(start, 0, &start_bit); 922 uint32_t end_bit; 923 Address end_word_address = 924 Page::ComputeRSetBitPosition(start + size_in_bytes - kIntSize, 925 0, 926 &end_bit); 927 928 // We want to clear the bits in the starting word starting with the 929 // first bit, and in the ending word up to and including the last 930 // bit. Build a pair of bitmasks to do that. 931 uint32_t start_bitmask = start_bit - 1; 932 uint32_t end_bitmask = ~((end_bit << 1) - 1); 933 934 // If the start address and end address are the same, we mask that 935 // word once, otherwise mask the starting and ending word 936 // separately and all the ones in between. 937 if (start_word_address == end_word_address) { 938 Memory::uint32_at(start_word_address) &= (start_bitmask | end_bitmask); 939 } else { 940 Memory::uint32_at(start_word_address) &= start_bitmask; 941 Memory::uint32_at(end_word_address) &= end_bitmask; 942 start_word_address += kIntSize; 943 memset(start_word_address, 0, end_word_address - start_word_address); 944 } 945 } 946 947 948 class UpdateRSetVisitor: public ObjectVisitor { 949 public: 950 951 void VisitPointer(Object** p) { 952 UpdateRSet(p); 953 } 954 955 void VisitPointers(Object** start, Object** end) { 956 // Update a store into slots [start, end), used (a) to update remembered 957 // set when promoting a young object to old space or (b) to rebuild 958 // remembered sets after a mark-compact collection. 959 for (Object** p = start; p < end; p++) UpdateRSet(p); 960 } 961 private: 962 963 void UpdateRSet(Object** p) { 964 // The remembered set should not be set. It should be clear for objects 965 // newly copied to old space, and it is cleared before rebuilding in the 966 // mark-compact collector. 967 ASSERT(!Page::IsRSetSet(reinterpret_cast<Address>(p), 0)); 968 if (Heap::InNewSpace(*p)) { 969 Page::SetRSet(reinterpret_cast<Address>(p), 0); 970 } 971 } 972 }; 973 974 975 int Heap::UpdateRSet(HeapObject* obj) { 976 ASSERT(!InNewSpace(obj)); 977 // Special handling of fixed arrays to iterate the body based on the start 978 // address and offset. Just iterating the pointers as in UpdateRSetVisitor 979 // will not work because Page::SetRSet needs to have the start of the 980 // object for large object pages. 981 if (obj->IsFixedArray()) { 982 FixedArray* array = FixedArray::cast(obj); 983 int length = array->length(); 984 for (int i = 0; i < length; i++) { 985 int offset = FixedArray::kHeaderSize + i * kPointerSize; 986 ASSERT(!Page::IsRSetSet(obj->address(), offset)); 987 if (Heap::InNewSpace(array->get(i))) { 988 Page::SetRSet(obj->address(), offset); 989 } 990 } 991 } else if (!obj->IsCode()) { 992 // Skip code object, we know it does not contain inter-generational 993 // pointers. 994 UpdateRSetVisitor v; 995 obj->Iterate(&v); 996 } 997 return obj->Size(); 998 } 999 1000 1001 void Heap::RebuildRSets() { 1002 // By definition, we do not care about remembered set bits in code, 1003 // data, or cell spaces. 1004 map_space_->ClearRSet(); 1005 RebuildRSets(map_space_); 1006 1007 old_pointer_space_->ClearRSet(); 1008 RebuildRSets(old_pointer_space_); 1009 1010 Heap::lo_space_->ClearRSet(); 1011 RebuildRSets(lo_space_); 1012 } 1013 1014 1015 void Heap::RebuildRSets(PagedSpace* space) { 1016 HeapObjectIterator it(space); 1017 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) 1018 Heap::UpdateRSet(obj); 1019 } 1020 1021 1022 void Heap::RebuildRSets(LargeObjectSpace* space) { 1023 LargeObjectIterator it(space); 1024 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) 1025 Heap::UpdateRSet(obj); 1026 } 1027 1028 1029 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1030 void Heap::RecordCopiedObject(HeapObject* obj) { 1031 bool should_record = false; 1032 #ifdef DEBUG 1033 should_record = FLAG_heap_stats; 1034 #endif 1035 #ifdef ENABLE_LOGGING_AND_PROFILING 1036 should_record = should_record || FLAG_log_gc; 1037 #endif 1038 if (should_record) { 1039 if (new_space_.Contains(obj)) { 1040 new_space_.RecordAllocation(obj); 1041 } else { 1042 new_space_.RecordPromotion(obj); 1043 } 1044 } 1045 } 1046 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1047 1048 1049 1050 HeapObject* Heap::MigrateObject(HeapObject* source, 1051 HeapObject* target, 1052 int size) { 1053 // Copy the content of source to target. 1054 CopyBlock(reinterpret_cast<Object**>(target->address()), 1055 reinterpret_cast<Object**>(source->address()), 1056 size); 1057 1058 // Set the forwarding address. 1059 source->set_map_word(MapWord::FromForwardingAddress(target)); 1060 1061 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1062 // Update NewSpace stats if necessary. 1063 RecordCopiedObject(target); 1064 #endif 1065 1066 return target; 1067 } 1068 1069 1070 static inline bool IsShortcutCandidate(HeapObject* object, Map* map) { 1071 STATIC_ASSERT(kNotStringTag != 0 && kSymbolTag != 0); 1072 ASSERT(object->map() == map); 1073 InstanceType type = map->instance_type(); 1074 if ((type & kShortcutTypeMask) != kShortcutTypeTag) return false; 1075 ASSERT(object->IsString() && !object->IsSymbol()); 1076 return ConsString::cast(object)->unchecked_second() == Heap::empty_string(); 1077 } 1078 1079 1080 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { 1081 ASSERT(InFromSpace(object)); 1082 MapWord first_word = object->map_word(); 1083 ASSERT(!first_word.IsForwardingAddress()); 1084 1085 // Optimization: Bypass flattened ConsString objects. 1086 if (IsShortcutCandidate(object, first_word.ToMap())) { 1087 object = HeapObject::cast(ConsString::cast(object)->unchecked_first()); 1088 *p = object; 1089 // After patching *p we have to repeat the checks that object is in the 1090 // active semispace of the young generation and not already copied. 1091 if (!InNewSpace(object)) return; 1092 first_word = object->map_word(); 1093 if (first_word.IsForwardingAddress()) { 1094 *p = first_word.ToForwardingAddress(); 1095 return; 1096 } 1097 } 1098 1099 int object_size = object->SizeFromMap(first_word.ToMap()); 1100 // We rely on live objects in new space to be at least two pointers, 1101 // so we can store the from-space address and map pointer of promoted 1102 // objects in the to space. 1103 ASSERT(object_size >= 2 * kPointerSize); 1104 1105 // If the object should be promoted, we try to copy it to old space. 1106 if (ShouldBePromoted(object->address(), object_size)) { 1107 Object* result; 1108 if (object_size > MaxObjectSizeInPagedSpace()) { 1109 result = lo_space_->AllocateRawFixedArray(object_size); 1110 if (!result->IsFailure()) { 1111 // Save the from-space object pointer and its map pointer at the 1112 // top of the to space to be swept and copied later. Write the 1113 // forwarding address over the map word of the from-space 1114 // object. 1115 HeapObject* target = HeapObject::cast(result); 1116 promotion_queue.insert(object, first_word.ToMap()); 1117 object->set_map_word(MapWord::FromForwardingAddress(target)); 1118 1119 // Give the space allocated for the result a proper map by 1120 // treating it as a free list node (not linked into the free 1121 // list). 1122 FreeListNode* node = FreeListNode::FromAddress(target->address()); 1123 node->set_size(object_size); 1124 1125 *p = target; 1126 return; 1127 } 1128 } else { 1129 OldSpace* target_space = Heap::TargetSpace(object); 1130 ASSERT(target_space == Heap::old_pointer_space_ || 1131 target_space == Heap::old_data_space_); 1132 result = target_space->AllocateRaw(object_size); 1133 if (!result->IsFailure()) { 1134 HeapObject* target = HeapObject::cast(result); 1135 if (target_space == Heap::old_pointer_space_) { 1136 // Save the from-space object pointer and its map pointer at the 1137 // top of the to space to be swept and copied later. Write the 1138 // forwarding address over the map word of the from-space 1139 // object. 1140 promotion_queue.insert(object, first_word.ToMap()); 1141 object->set_map_word(MapWord::FromForwardingAddress(target)); 1142 1143 // Give the space allocated for the result a proper map by 1144 // treating it as a free list node (not linked into the free 1145 // list). 1146 FreeListNode* node = FreeListNode::FromAddress(target->address()); 1147 node->set_size(object_size); 1148 1149 *p = target; 1150 } else { 1151 // Objects promoted to the data space can be copied immediately 1152 // and not revisited---we will never sweep that space for 1153 // pointers and the copied objects do not contain pointers to 1154 // new space objects. 1155 *p = MigrateObject(object, target, object_size); 1156 #ifdef DEBUG 1157 VerifyNonPointerSpacePointersVisitor v; 1158 (*p)->Iterate(&v); 1159 #endif 1160 } 1161 return; 1162 } 1163 } 1164 } 1165 // The object should remain in new space or the old space allocation failed. 1166 Object* result = new_space_.AllocateRaw(object_size); 1167 // Failed allocation at this point is utterly unexpected. 1168 ASSERT(!result->IsFailure()); 1169 *p = MigrateObject(object, HeapObject::cast(result), object_size); 1170 } 1171 1172 1173 void Heap::ScavengePointer(HeapObject** p) { 1174 ScavengeObject(p, *p); 1175 } 1176 1177 1178 Object* Heap::AllocatePartialMap(InstanceType instance_type, 1179 int instance_size) { 1180 Object* result = AllocateRawMap(); 1181 if (result->IsFailure()) return result; 1182 1183 // Map::cast cannot be used due to uninitialized map field. 1184 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); 1185 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); 1186 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); 1187 reinterpret_cast<Map*>(result)->set_inobject_properties(0); 1188 reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0); 1189 reinterpret_cast<Map*>(result)->set_unused_property_fields(0); 1190 reinterpret_cast<Map*>(result)->set_bit_field(0); 1191 reinterpret_cast<Map*>(result)->set_bit_field2(0); 1192 return result; 1193 } 1194 1195 1196 Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) { 1197 Object* result = AllocateRawMap(); 1198 if (result->IsFailure()) return result; 1199 1200 Map* map = reinterpret_cast<Map*>(result); 1201 map->set_map(meta_map()); 1202 map->set_instance_type(instance_type); 1203 map->set_prototype(null_value()); 1204 map->set_constructor(null_value()); 1205 map->set_instance_size(instance_size); 1206 map->set_inobject_properties(0); 1207 map->set_pre_allocated_property_fields(0); 1208 map->set_instance_descriptors(empty_descriptor_array()); 1209 map->set_code_cache(empty_fixed_array()); 1210 map->set_unused_property_fields(0); 1211 map->set_bit_field(0); 1212 map->set_bit_field2(1 << Map::kIsExtensible); 1213 1214 // If the map object is aligned fill the padding area with Smi 0 objects. 1215 if (Map::kPadStart < Map::kSize) { 1216 memset(reinterpret_cast<byte*>(map) + Map::kPadStart - kHeapObjectTag, 1217 0, 1218 Map::kSize - Map::kPadStart); 1219 } 1220 return map; 1221 } 1222 1223 1224 const Heap::StringTypeTable Heap::string_type_table[] = { 1225 #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ 1226 {type, size, k##camel_name##MapRootIndex}, 1227 STRING_TYPE_LIST(STRING_TYPE_ELEMENT) 1228 #undef STRING_TYPE_ELEMENT 1229 }; 1230 1231 1232 const Heap::ConstantSymbolTable Heap::constant_symbol_table[] = { 1233 #define CONSTANT_SYMBOL_ELEMENT(name, contents) \ 1234 {contents, k##name##RootIndex}, 1235 SYMBOL_LIST(CONSTANT_SYMBOL_ELEMENT) 1236 #undef CONSTANT_SYMBOL_ELEMENT 1237 }; 1238 1239 1240 const Heap::StructTable Heap::struct_table[] = { 1241 #define STRUCT_TABLE_ELEMENT(NAME, Name, name) \ 1242 { NAME##_TYPE, Name::kSize, k##Name##MapRootIndex }, 1243 STRUCT_LIST(STRUCT_TABLE_ELEMENT) 1244 #undef STRUCT_TABLE_ELEMENT 1245 }; 1246 1247 1248 bool Heap::CreateInitialMaps() { 1249 Object* obj = AllocatePartialMap(MAP_TYPE, Map::kSize); 1250 if (obj->IsFailure()) return false; 1251 // Map::cast cannot be used due to uninitialized map field. 1252 Map* new_meta_map = reinterpret_cast<Map*>(obj); 1253 set_meta_map(new_meta_map); 1254 new_meta_map->set_map(new_meta_map); 1255 1256 obj = AllocatePartialMap(FIXED_ARRAY_TYPE, FixedArray::kHeaderSize); 1257 if (obj->IsFailure()) return false; 1258 set_fixed_array_map(Map::cast(obj)); 1259 1260 obj = AllocatePartialMap(ODDBALL_TYPE, Oddball::kSize); 1261 if (obj->IsFailure()) return false; 1262 set_oddball_map(Map::cast(obj)); 1263 1264 // Allocate the empty array 1265 obj = AllocateEmptyFixedArray(); 1266 if (obj->IsFailure()) return false; 1267 set_empty_fixed_array(FixedArray::cast(obj)); 1268 1269 obj = Allocate(oddball_map(), OLD_DATA_SPACE); 1270 if (obj->IsFailure()) return false; 1271 set_null_value(obj); 1272 1273 // Allocate the empty descriptor array. 1274 obj = AllocateEmptyFixedArray(); 1275 if (obj->IsFailure()) return false; 1276 set_empty_descriptor_array(DescriptorArray::cast(obj)); 1277 1278 // Fix the instance_descriptors for the existing maps. 1279 meta_map()->set_instance_descriptors(empty_descriptor_array()); 1280 meta_map()->set_code_cache(empty_fixed_array()); 1281 1282 fixed_array_map()->set_instance_descriptors(empty_descriptor_array()); 1283 fixed_array_map()->set_code_cache(empty_fixed_array()); 1284 1285 oddball_map()->set_instance_descriptors(empty_descriptor_array()); 1286 oddball_map()->set_code_cache(empty_fixed_array()); 1287 1288 // Fix prototype object for existing maps. 1289 meta_map()->set_prototype(null_value()); 1290 meta_map()->set_constructor(null_value()); 1291 1292 fixed_array_map()->set_prototype(null_value()); 1293 fixed_array_map()->set_constructor(null_value()); 1294 1295 oddball_map()->set_prototype(null_value()); 1296 oddball_map()->set_constructor(null_value()); 1297 1298 obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize); 1299 if (obj->IsFailure()) return false; 1300 set_heap_number_map(Map::cast(obj)); 1301 1302 obj = AllocateMap(PROXY_TYPE, Proxy::kSize); 1303 if (obj->IsFailure()) return false; 1304 set_proxy_map(Map::cast(obj)); 1305 1306 for (unsigned i = 0; i < ARRAY_SIZE(string_type_table); i++) { 1307 const StringTypeTable& entry = string_type_table[i]; 1308 obj = AllocateMap(entry.type, entry.size); 1309 if (obj->IsFailure()) return false; 1310 roots_[entry.index] = Map::cast(obj); 1311 } 1312 1313 obj = AllocateMap(STRING_TYPE, SeqTwoByteString::kAlignedSize); 1314 if (obj->IsFailure()) return false; 1315 set_undetectable_string_map(Map::cast(obj)); 1316 Map::cast(obj)->set_is_undetectable(); 1317 1318 obj = AllocateMap(ASCII_STRING_TYPE, SeqAsciiString::kAlignedSize); 1319 if (obj->IsFailure()) return false; 1320 set_undetectable_ascii_string_map(Map::cast(obj)); 1321 Map::cast(obj)->set_is_undetectable(); 1322 1323 obj = AllocateMap(BYTE_ARRAY_TYPE, ByteArray::kAlignedSize); 1324 if (obj->IsFailure()) return false; 1325 set_byte_array_map(Map::cast(obj)); 1326 1327 obj = AllocateMap(PIXEL_ARRAY_TYPE, PixelArray::kAlignedSize); 1328 if (obj->IsFailure()) return false; 1329 set_pixel_array_map(Map::cast(obj)); 1330 1331 obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE, 1332 ExternalArray::kAlignedSize); 1333 if (obj->IsFailure()) return false; 1334 set_external_byte_array_map(Map::cast(obj)); 1335 1336 obj = AllocateMap(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE, 1337 ExternalArray::kAlignedSize); 1338 if (obj->IsFailure()) return false; 1339 set_external_unsigned_byte_array_map(Map::cast(obj)); 1340 1341 obj = AllocateMap(EXTERNAL_SHORT_ARRAY_TYPE, 1342 ExternalArray::kAlignedSize); 1343 if (obj->IsFailure()) return false; 1344 set_external_short_array_map(Map::cast(obj)); 1345 1346 obj = AllocateMap(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE, 1347 ExternalArray::kAlignedSize); 1348 if (obj->IsFailure()) return false; 1349 set_external_unsigned_short_array_map(Map::cast(obj)); 1350 1351 obj = AllocateMap(EXTERNAL_INT_ARRAY_TYPE, 1352 ExternalArray::kAlignedSize); 1353 if (obj->IsFailure()) return false; 1354 set_external_int_array_map(Map::cast(obj)); 1355 1356 obj = AllocateMap(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE, 1357 ExternalArray::kAlignedSize); 1358 if (obj->IsFailure()) return false; 1359 set_external_unsigned_int_array_map(Map::cast(obj)); 1360 1361 obj = AllocateMap(EXTERNAL_FLOAT_ARRAY_TYPE, 1362 ExternalArray::kAlignedSize); 1363 if (obj->IsFailure()) return false; 1364 set_external_float_array_map(Map::cast(obj)); 1365 1366 obj = AllocateMap(CODE_TYPE, Code::kHeaderSize); 1367 if (obj->IsFailure()) return false; 1368 set_code_map(Map::cast(obj)); 1369 1370 obj = AllocateMap(JS_GLOBAL_PROPERTY_CELL_TYPE, 1371 JSGlobalPropertyCell::kSize); 1372 if (obj->IsFailure()) return false; 1373 set_global_property_cell_map(Map::cast(obj)); 1374 1375 obj = AllocateMap(FILLER_TYPE, kPointerSize); 1376 if (obj->IsFailure()) return false; 1377 set_one_pointer_filler_map(Map::cast(obj)); 1378 1379 obj = AllocateMap(FILLER_TYPE, 2 * kPointerSize); 1380 if (obj->IsFailure()) return false; 1381 set_two_pointer_filler_map(Map::cast(obj)); 1382 1383 for (unsigned i = 0; i < ARRAY_SIZE(struct_table); i++) { 1384 const StructTable& entry = struct_table[i]; 1385 obj = AllocateMap(entry.type, entry.size); 1386 if (obj->IsFailure()) return false; 1387 roots_[entry.index] = Map::cast(obj); 1388 } 1389 1390 obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize); 1391 if (obj->IsFailure()) return false; 1392 set_hash_table_map(Map::cast(obj)); 1393 1394 obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize); 1395 if (obj->IsFailure()) return false; 1396 set_context_map(Map::cast(obj)); 1397 1398 obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize); 1399 if (obj->IsFailure()) return false; 1400 set_catch_context_map(Map::cast(obj)); 1401 1402 obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize); 1403 if (obj->IsFailure()) return false; 1404 set_global_context_map(Map::cast(obj)); 1405 1406 obj = AllocateMap(JS_FUNCTION_TYPE, JSFunction::kSize); 1407 if (obj->IsFailure()) return false; 1408 set_boilerplate_function_map(Map::cast(obj)); 1409 1410 obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE, SharedFunctionInfo::kSize); 1411 if (obj->IsFailure()) return false; 1412 set_shared_function_info_map(Map::cast(obj)); 1413 1414 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array())); 1415 return true; 1416 } 1417 1418 1419 Object* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) { 1420 // Statically ensure that it is safe to allocate heap numbers in paged 1421 // spaces. 1422 STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize); 1423 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; 1424 1425 Object* result = AllocateRaw(HeapNumber::kSize, space, OLD_DATA_SPACE); 1426 if (result->IsFailure()) return result; 1427 1428 HeapObject::cast(result)->set_map(heap_number_map()); 1429 HeapNumber::cast(result)->set_value(value); 1430 return result; 1431 } 1432 1433 1434 Object* Heap::AllocateHeapNumber(double value) { 1435 // Use general version, if we're forced to always allocate. 1436 if (always_allocate()) return AllocateHeapNumber(value, TENURED); 1437 1438 // This version of AllocateHeapNumber is optimized for 1439 // allocation in new space. 1440 STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize); 1441 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); 1442 Object* result = new_space_.AllocateRaw(HeapNumber::kSize); 1443 if (result->IsFailure()) return result; 1444 HeapObject::cast(result)->set_map(heap_number_map()); 1445 HeapNumber::cast(result)->set_value(value); 1446 return result; 1447 } 1448 1449 1450 Object* Heap::AllocateJSGlobalPropertyCell(Object* value) { 1451 Object* result = AllocateRawCell(); 1452 if (result->IsFailure()) return result; 1453 HeapObject::cast(result)->set_map(global_property_cell_map()); 1454 JSGlobalPropertyCell::cast(result)->set_value(value); 1455 return result; 1456 } 1457 1458 1459 Object* Heap::CreateOddball(Map* map, 1460 const char* to_string, 1461 Object* to_number) { 1462 Object* result = Allocate(map, OLD_DATA_SPACE); 1463 if (result->IsFailure()) return result; 1464 return Oddball::cast(result)->Initialize(to_string, to_number); 1465 } 1466 1467 1468 bool Heap::CreateApiObjects() { 1469 Object* obj; 1470 1471 obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 1472 if (obj->IsFailure()) return false; 1473 set_neander_map(Map::cast(obj)); 1474 1475 obj = Heap::AllocateJSObjectFromMap(neander_map()); 1476 if (obj->IsFailure()) return false; 1477 Object* elements = AllocateFixedArray(2); 1478 if (elements->IsFailure()) return false; 1479 FixedArray::cast(elements)->set(0, Smi::FromInt(0)); 1480 JSObject::cast(obj)->set_elements(FixedArray::cast(elements)); 1481 set_message_listeners(JSObject::cast(obj)); 1482 1483 return true; 1484 } 1485 1486 1487 void Heap::CreateCEntryStub() { 1488 CEntryStub stub(1); 1489 set_c_entry_code(*stub.GetCode()); 1490 } 1491 1492 1493 #if V8_TARGET_ARCH_ARM && V8_NATIVE_REGEXP 1494 void Heap::CreateRegExpCEntryStub() { 1495 RegExpCEntryStub stub; 1496 set_re_c_entry_code(*stub.GetCode()); 1497 } 1498 #endif 1499 1500 1501 void Heap::CreateJSEntryStub() { 1502 JSEntryStub stub; 1503 set_js_entry_code(*stub.GetCode()); 1504 } 1505 1506 1507 void Heap::CreateJSConstructEntryStub() { 1508 JSConstructEntryStub stub; 1509 set_js_construct_entry_code(*stub.GetCode()); 1510 } 1511 1512 1513 void Heap::CreateFixedStubs() { 1514 // Here we create roots for fixed stubs. They are needed at GC 1515 // for cooking and uncooking (check out frames.cc). 1516 // The eliminates the need for doing dictionary lookup in the 1517 // stub cache for these stubs. 1518 HandleScope scope; 1519 // gcc-4.4 has problem generating correct code of following snippet: 1520 // { CEntryStub stub; 1521 // c_entry_code_ = *stub.GetCode(); 1522 // } 1523 // { DebuggerStatementStub stub; 1524 // debugger_statement_code_ = *stub.GetCode(); 1525 // } 1526 // To workaround the problem, make separate functions without inlining. 1527 Heap::CreateCEntryStub(); 1528 Heap::CreateJSEntryStub(); 1529 Heap::CreateJSConstructEntryStub(); 1530 #if V8_TARGET_ARCH_ARM && V8_NATIVE_REGEXP 1531 Heap::CreateRegExpCEntryStub(); 1532 #endif 1533 } 1534 1535 1536 bool Heap::CreateInitialObjects() { 1537 Object* obj; 1538 1539 // The -0 value must be set before NumberFromDouble works. 1540 obj = AllocateHeapNumber(-0.0, TENURED); 1541 if (obj->IsFailure()) return false; 1542 set_minus_zero_value(obj); 1543 ASSERT(signbit(minus_zero_value()->Number()) != 0); 1544 1545 obj = AllocateHeapNumber(OS::nan_value(), TENURED); 1546 if (obj->IsFailure()) return false; 1547 set_nan_value(obj); 1548 1549 obj = Allocate(oddball_map(), OLD_DATA_SPACE); 1550 if (obj->IsFailure()) return false; 1551 set_undefined_value(obj); 1552 ASSERT(!InNewSpace(undefined_value())); 1553 1554 // Allocate initial symbol table. 1555 obj = SymbolTable::Allocate(kInitialSymbolTableSize); 1556 if (obj->IsFailure()) return false; 1557 // Don't use set_symbol_table() due to asserts. 1558 roots_[kSymbolTableRootIndex] = obj; 1559 1560 // Assign the print strings for oddballs after creating symboltable. 1561 Object* symbol = LookupAsciiSymbol("undefined"); 1562 if (symbol->IsFailure()) return false; 1563 Oddball::cast(undefined_value())->set_to_string(String::cast(symbol)); 1564 Oddball::cast(undefined_value())->set_to_number(nan_value()); 1565 1566 // Assign the print strings for oddballs after creating symboltable. 1567 symbol = LookupAsciiSymbol("null"); 1568 if (symbol->IsFailure()) return false; 1569 Oddball::cast(null_value())->set_to_string(String::cast(symbol)); 1570 Oddball::cast(null_value())->set_to_number(Smi::FromInt(0)); 1571 1572 // Allocate the null_value 1573 obj = Oddball::cast(null_value())->Initialize("null", Smi::FromInt(0)); 1574 if (obj->IsFailure()) return false; 1575 1576 obj = CreateOddball(oddball_map(), "true", Smi::FromInt(1)); 1577 if (obj->IsFailure()) return false; 1578 set_true_value(obj); 1579 1580 obj = CreateOddball(oddball_map(), "false", Smi::FromInt(0)); 1581 if (obj->IsFailure()) return false; 1582 set_false_value(obj); 1583 1584 obj = CreateOddball(oddball_map(), "hole", Smi::FromInt(-1)); 1585 if (obj->IsFailure()) return false; 1586 set_the_hole_value(obj); 1587 1588 obj = CreateOddball( 1589 oddball_map(), "no_interceptor_result_sentinel", Smi::FromInt(-2)); 1590 if (obj->IsFailure()) return false; 1591 set_no_interceptor_result_sentinel(obj); 1592 1593 obj = CreateOddball(oddball_map(), "termination_exception", Smi::FromInt(-3)); 1594 if (obj->IsFailure()) return false; 1595 set_termination_exception(obj); 1596 1597 // Allocate the empty string. 1598 obj = AllocateRawAsciiString(0, TENURED); 1599 if (obj->IsFailure()) return false; 1600 set_empty_string(String::cast(obj)); 1601 1602 for (unsigned i = 0; i < ARRAY_SIZE(constant_symbol_table); i++) { 1603 obj = LookupAsciiSymbol(constant_symbol_table[i].contents); 1604 if (obj->IsFailure()) return false; 1605 roots_[constant_symbol_table[i].index] = String::cast(obj); 1606 } 1607 1608 // Allocate the hidden symbol which is used to identify the hidden properties 1609 // in JSObjects. The hash code has a special value so that it will not match 1610 // the empty string when searching for the property. It cannot be part of the 1611 // loop above because it needs to be allocated manually with the special 1612 // hash code in place. The hash code for the hidden_symbol is zero to ensure 1613 // that it will always be at the first entry in property descriptors. 1614 obj = AllocateSymbol(CStrVector(""), 0, String::kHashComputedMask); 1615 if (obj->IsFailure()) return false; 1616 hidden_symbol_ = String::cast(obj); 1617 1618 // Allocate the proxy for __proto__. 1619 obj = AllocateProxy((Address) &Accessors::ObjectPrototype); 1620 if (obj->IsFailure()) return false; 1621 set_prototype_accessors(Proxy::cast(obj)); 1622 1623 // Allocate the code_stubs dictionary. The initial size is set to avoid 1624 // expanding the dictionary during bootstrapping. 1625 obj = NumberDictionary::Allocate(128); 1626 if (obj->IsFailure()) return false; 1627 set_code_stubs(NumberDictionary::cast(obj)); 1628 1629 // Allocate the non_monomorphic_cache used in stub-cache.cc. The initial size 1630 // is set to avoid expanding the dictionary during bootstrapping. 1631 obj = NumberDictionary::Allocate(64); 1632 if (obj->IsFailure()) return false; 1633 set_non_monomorphic_cache(NumberDictionary::cast(obj)); 1634 1635 CreateFixedStubs(); 1636 1637 if (InitializeNumberStringCache()->IsFailure()) return false; 1638 1639 // Allocate cache for single character strings. 1640 obj = AllocateFixedArray(String::kMaxAsciiCharCode+1); 1641 if (obj->IsFailure()) return false; 1642 set_single_character_string_cache(FixedArray::cast(obj)); 1643 1644 // Allocate cache for external strings pointing to native source code. 1645 obj = AllocateFixedArray(Natives::GetBuiltinsCount()); 1646 if (obj->IsFailure()) return false; 1647 set_natives_source_cache(FixedArray::cast(obj)); 1648 1649 // Handling of script id generation is in Factory::NewScript. 1650 set_last_script_id(undefined_value()); 1651 1652 // Initialize keyed lookup cache. 1653 KeyedLookupCache::Clear(); 1654 1655 // Initialize context slot cache. 1656 ContextSlotCache::Clear(); 1657 1658 // Initialize descriptor cache. 1659 DescriptorLookupCache::Clear(); 1660 1661 // Initialize compilation cache. 1662 CompilationCache::Clear(); 1663 1664 return true; 1665 } 1666 1667 1668 Object* Heap::InitializeNumberStringCache() { 1669 // Compute the size of the number string cache based on the max heap size. 1670 // max_semispace_size_ == 512 KB => number_string_cache_size = 32. 1671 // max_semispace_size_ == 8 MB => number_string_cache_size = 16KB. 1672 int number_string_cache_size = max_semispace_size_ / 512; 1673 number_string_cache_size = Max(32, Min(16*KB, number_string_cache_size)); 1674 Object* obj = AllocateFixedArray(number_string_cache_size * 2); 1675 if (!obj->IsFailure()) set_number_string_cache(FixedArray::cast(obj)); 1676 return obj; 1677 } 1678 1679 1680 void Heap::FlushNumberStringCache() { 1681 // Flush the number to string cache. 1682 int len = number_string_cache()->length(); 1683 for (int i = 0; i < len; i++) { 1684 number_string_cache()->set_undefined(i); 1685 } 1686 } 1687 1688 1689 static inline int double_get_hash(double d) { 1690 DoubleRepresentation rep(d); 1691 return static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32); 1692 } 1693 1694 1695 static inline int smi_get_hash(Smi* smi) { 1696 return smi->value(); 1697 } 1698 1699 1700 Object* Heap::GetNumberStringCache(Object* number) { 1701 int hash; 1702 int mask = (number_string_cache()->length() >> 1) - 1; 1703 if (number->IsSmi()) { 1704 hash = smi_get_hash(Smi::cast(number)) & mask; 1705 } else { 1706 hash = double_get_hash(number->Number()) & mask; 1707 } 1708 Object* key = number_string_cache()->get(hash * 2); 1709 if (key == number) { 1710 return String::cast(number_string_cache()->get(hash * 2 + 1)); 1711 } else if (key->IsHeapNumber() && 1712 number->IsHeapNumber() && 1713 key->Number() == number->Number()) { 1714 return String::cast(number_string_cache()->get(hash * 2 + 1)); 1715 } 1716 return undefined_value(); 1717 } 1718 1719 1720 void Heap::SetNumberStringCache(Object* number, String* string) { 1721 int hash; 1722 int mask = (number_string_cache()->length() >> 1) - 1; 1723 if (number->IsSmi()) { 1724 hash = smi_get_hash(Smi::cast(number)) & mask; 1725 number_string_cache()->set(hash * 2, Smi::cast(number)); 1726 } else { 1727 hash = double_get_hash(number->Number()) & mask; 1728 number_string_cache()->set(hash * 2, number); 1729 } 1730 number_string_cache()->set(hash * 2 + 1, string); 1731 } 1732 1733 1734 Object* Heap::SmiOrNumberFromDouble(double value, 1735 bool new_object, 1736 PretenureFlag pretenure) { 1737 // We need to distinguish the minus zero value and this cannot be 1738 // done after conversion to int. Doing this by comparing bit 1739 // patterns is faster than using fpclassify() et al. 1740 static const DoubleRepresentation plus_zero(0.0); 1741 static const DoubleRepresentation minus_zero(-0.0); 1742 static const DoubleRepresentation nan(OS::nan_value()); 1743 ASSERT(minus_zero_value() != NULL); 1744 ASSERT(sizeof(plus_zero.value) == sizeof(plus_zero.bits)); 1745 1746 DoubleRepresentation rep(value); 1747 if (rep.bits == plus_zero.bits) return Smi::FromInt(0); // not uncommon 1748 if (rep.bits == minus_zero.bits) { 1749 return new_object ? AllocateHeapNumber(-0.0, pretenure) 1750 : minus_zero_value(); 1751 } 1752 if (rep.bits == nan.bits) { 1753 return new_object 1754 ? AllocateHeapNumber(OS::nan_value(), pretenure) 1755 : nan_value(); 1756 } 1757 1758 // Try to represent the value as a tagged small integer. 1759 int int_value = FastD2I(value); 1760 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) { 1761 return Smi::FromInt(int_value); 1762 } 1763 1764 // Materialize the value in the heap. 1765 return AllocateHeapNumber(value, pretenure); 1766 } 1767 1768 1769 Object* Heap::NumberToString(Object* number) { 1770 Counters::number_to_string_runtime.Increment(); 1771 Object* cached = GetNumberStringCache(number); 1772 if (cached != undefined_value()) { 1773 return cached; 1774 } 1775 1776 char arr[100]; 1777 Vector<char> buffer(arr, ARRAY_SIZE(arr)); 1778 const char* str; 1779 if (number->IsSmi()) { 1780 int num = Smi::cast(number)->value(); 1781 str = IntToCString(num, buffer); 1782 } else { 1783 double num = HeapNumber::cast(number)->value(); 1784 str = DoubleToCString(num, buffer); 1785 } 1786 Object* result = AllocateStringFromAscii(CStrVector(str)); 1787 1788 if (!result->IsFailure()) { 1789 SetNumberStringCache(number, String::cast(result)); 1790 } 1791 return result; 1792 } 1793 1794 1795 Map* Heap::MapForExternalArrayType(ExternalArrayType array_type) { 1796 return Map::cast(roots_[RootIndexForExternalArrayType(array_type)]); 1797 } 1798 1799 1800 Heap::RootListIndex Heap::RootIndexForExternalArrayType( 1801 ExternalArrayType array_type) { 1802 switch (array_type) { 1803 case kExternalByteArray: 1804 return kExternalByteArrayMapRootIndex; 1805 case kExternalUnsignedByteArray: 1806 return kExternalUnsignedByteArrayMapRootIndex; 1807 case kExternalShortArray: 1808 return kExternalShortArrayMapRootIndex; 1809 case kExternalUnsignedShortArray: 1810 return kExternalUnsignedShortArrayMapRootIndex; 1811 case kExternalIntArray: 1812 return kExternalIntArrayMapRootIndex; 1813 case kExternalUnsignedIntArray: 1814 return kExternalUnsignedIntArrayMapRootIndex; 1815 case kExternalFloatArray: 1816 return kExternalFloatArrayMapRootIndex; 1817 default: 1818 UNREACHABLE(); 1819 return kUndefinedValueRootIndex; 1820 } 1821 } 1822 1823 1824 Object* Heap::NewNumberFromDouble(double value, PretenureFlag pretenure) { 1825 return SmiOrNumberFromDouble(value, 1826 true /* number object must be new */, 1827 pretenure); 1828 } 1829 1830 1831 Object* Heap::NumberFromDouble(double value, PretenureFlag pretenure) { 1832 return SmiOrNumberFromDouble(value, 1833 false /* use preallocated NaN, -0.0 */, 1834 pretenure); 1835 } 1836 1837 1838 Object* Heap::AllocateProxy(Address proxy, PretenureFlag pretenure) { 1839 // Statically ensure that it is safe to allocate proxies in paged spaces. 1840 STATIC_ASSERT(Proxy::kSize <= Page::kMaxHeapObjectSize); 1841 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; 1842 Object* result = Allocate(proxy_map(), space); 1843 if (result->IsFailure()) return result; 1844 1845 Proxy::cast(result)->set_proxy(proxy); 1846 return result; 1847 } 1848 1849 1850 Object* Heap::AllocateSharedFunctionInfo(Object* name) { 1851 Object* result = Allocate(shared_function_info_map(), OLD_POINTER_SPACE); 1852 if (result->IsFailure()) return result; 1853 1854 SharedFunctionInfo* share = SharedFunctionInfo::cast(result); 1855 share->set_name(name); 1856 Code* illegal = Builtins::builtin(Builtins::Illegal); 1857 share->set_code(illegal); 1858 Code* construct_stub = Builtins::builtin(Builtins::JSConstructStubGeneric); 1859 share->set_construct_stub(construct_stub); 1860 share->set_expected_nof_properties(0); 1861 share->set_length(0); 1862 share->set_formal_parameter_count(0); 1863 share->set_instance_class_name(Object_symbol()); 1864 share->set_function_data(undefined_value()); 1865 share->set_script(undefined_value()); 1866 share->set_start_position_and_type(0); 1867 share->set_debug_info(undefined_value()); 1868 share->set_inferred_name(empty_string()); 1869 share->set_compiler_hints(0); 1870 share->set_this_property_assignments_count(0); 1871 share->set_this_property_assignments(undefined_value()); 1872 return result; 1873 } 1874 1875 1876 // Returns true for a character in a range. Both limits are inclusive. 1877 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { 1878 // This makes uses of the the unsigned wraparound. 1879 return character - from <= to - from; 1880 } 1881 1882 1883 static inline Object* MakeOrFindTwoCharacterString(uint32_t c1, uint32_t c2) { 1884 String* symbol; 1885 // Numeric strings have a different hash algorithm not known by 1886 // LookupTwoCharsSymbolIfExists, so we skip this step for such strings. 1887 if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) && 1888 Heap::symbol_table()->LookupTwoCharsSymbolIfExists(c1, c2, &symbol)) { 1889 return symbol; 1890 // Now we know the length is 2, we might as well make use of that fact 1891 // when building the new string. 1892 } else if ((c1 | c2) <= String::kMaxAsciiCharCodeU) { // We can do this 1893 ASSERT(IsPowerOf2(String::kMaxAsciiCharCodeU + 1)); // because of this. 1894 Object* result = Heap::AllocateRawAsciiString(2); 1895 if (result->IsFailure()) return result; 1896 char* dest = SeqAsciiString::cast(result)->GetChars(); 1897 dest[0] = c1; 1898 dest[1] = c2; 1899 return result; 1900 } else { 1901 Object* result = Heap::AllocateRawTwoByteString(2); 1902 if (result->IsFailure()) return result; 1903 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); 1904 dest[0] = c1; 1905 dest[1] = c2; 1906 return result; 1907 } 1908 } 1909 1910 1911 Object* Heap::AllocateConsString(String* first, String* second) { 1912 int first_length = first->length(); 1913 if (first_length == 0) { 1914 return second; 1915 } 1916 1917 int second_length = second->length(); 1918 if (second_length == 0) { 1919 return first; 1920 } 1921 1922 int length = first_length + second_length; 1923 1924 // Optimization for 2-byte strings often used as keys in a decompression 1925 // dictionary. Check whether we already have the string in the symbol 1926 // table to prevent creation of many unneccesary strings. 1927 if (length == 2) { 1928 unsigned c1 = first->Get(0); 1929 unsigned c2 = second->Get(0); 1930 return MakeOrFindTwoCharacterString(c1, c2); 1931 } 1932 1933 bool is_ascii = first->IsAsciiRepresentation() 1934 && second->IsAsciiRepresentation(); 1935 1936 // Make sure that an out of memory exception is thrown if the length 1937 // of the new cons string is too large. 1938 if (length > String::kMaxLength || length < 0) { 1939 Top::context()->mark_out_of_memory(); 1940 return Failure::OutOfMemoryException(); 1941 } 1942 1943 // If the resulting string is small make a flat string. 1944 if (length < String::kMinNonFlatLength) { 1945 ASSERT(first->IsFlat()); 1946 ASSERT(second->IsFlat()); 1947 if (is_ascii) { 1948 Object* result = AllocateRawAsciiString(length); 1949 if (result->IsFailure()) return result; 1950 // Copy the characters into the new object. 1951 char* dest = SeqAsciiString::cast(result)->GetChars(); 1952 // Copy first part. 1953 const char* src; 1954 if (first->IsExternalString()) { 1955 src = ExternalAsciiString::cast(first)->resource()->data(); 1956 } else { 1957 src = SeqAsciiString::cast(first)->GetChars(); 1958 } 1959 for (int i = 0; i < first_length; i++) *dest++ = src[i]; 1960 // Copy second part. 1961 if (second->IsExternalString()) { 1962 src = ExternalAsciiString::cast(second)->resource()->data(); 1963 } else { 1964 src = SeqAsciiString::cast(second)->GetChars(); 1965 } 1966 for (int i = 0; i < second_length; i++) *dest++ = src[i]; 1967 return result; 1968 } else { 1969 Object* result = AllocateRawTwoByteString(length); 1970 if (result->IsFailure()) return result; 1971 // Copy the characters into the new object. 1972 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); 1973 String::WriteToFlat(first, dest, 0, first_length); 1974 String::WriteToFlat(second, dest + first_length, 0, second_length); 1975 return result; 1976 } 1977 } 1978 1979 Map* map = is_ascii ? cons_ascii_string_map() : cons_string_map(); 1980 1981 Object* result = Allocate(map, NEW_SPACE); 1982 if (result->IsFailure()) return result; 1983 1984 AssertNoAllocation no_gc; 1985 ConsString* cons_string = ConsString::cast(result); 1986 WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc); 1987 cons_string->set_length(length); 1988 cons_string->set_hash_field(String::kEmptyHashField); 1989 cons_string->set_first(first, mode); 1990 cons_string->set_second(second, mode); 1991 return result; 1992 } 1993 1994 1995 Object* Heap::AllocateSubString(String* buffer, 1996 int start, 1997 int end) { 1998 int length = end - start; 1999 2000 if (length == 1) { 2001 return Heap::LookupSingleCharacterStringFromCode( 2002 buffer->Get(start)); 2003 } else if (length == 2) { 2004 // Optimization for 2-byte strings often used as keys in a decompression 2005 // dictionary. Check whether we already have the string in the symbol 2006 // table to prevent creation of many unneccesary strings. 2007 unsigned c1 = buffer->Get(start); 2008 unsigned c2 = buffer->Get(start + 1); 2009 return MakeOrFindTwoCharacterString(c1, c2); 2010 } 2011 2012 // Make an attempt to flatten the buffer to reduce access time. 2013 if (!buffer->IsFlat()) { 2014 buffer->TryFlatten(); 2015 } 2016 2017 Object* result = buffer->IsAsciiRepresentation() 2018 ? AllocateRawAsciiString(length) 2019 : AllocateRawTwoByteString(length); 2020 if (result->IsFailure()) return result; 2021 String* string_result = String::cast(result); 2022 2023 // Copy the characters into the new object. 2024 if (buffer->IsAsciiRepresentation()) { 2025 ASSERT(string_result->IsAsciiRepresentation()); 2026 char* dest = SeqAsciiString::cast(string_result)->GetChars(); 2027 String::WriteToFlat(buffer, dest, start, end); 2028 } else { 2029 ASSERT(string_result->IsTwoByteRepresentation()); 2030 uc16* dest = SeqTwoByteString::cast(string_result)->GetChars(); 2031 String::WriteToFlat(buffer, dest, start, end); 2032 } 2033 2034 return result; 2035 } 2036 2037 2038 Object* Heap::AllocateExternalStringFromAscii( 2039 ExternalAsciiString::Resource* resource) { 2040 size_t length = resource->length(); 2041 if (length > static_cast<size_t>(String::kMaxLength)) { 2042 Top::context()->mark_out_of_memory(); 2043 return Failure::OutOfMemoryException(); 2044 } 2045 2046 Map* map = external_ascii_string_map(); 2047 Object* result = Allocate(map, NEW_SPACE); 2048 if (result->IsFailure()) return result; 2049 2050 ExternalAsciiString* external_string = ExternalAsciiString::cast(result); 2051 external_string->set_length(static_cast<int>(length)); 2052 external_string->set_hash_field(String::kEmptyHashField); 2053 external_string->set_resource(resource); 2054 2055 return result; 2056 } 2057 2058 2059 Object* Heap::AllocateExternalStringFromTwoByte( 2060 ExternalTwoByteString::Resource* resource) { 2061 size_t length = resource->length(); 2062 if (length > static_cast<size_t>(String::kMaxLength)) { 2063 Top::context()->mark_out_of_memory(); 2064 return Failure::OutOfMemoryException(); 2065 } 2066 2067 Map* map = Heap::external_string_map(); 2068 Object* result = Allocate(map, NEW_SPACE); 2069 if (result->IsFailure()) return result; 2070 2071 ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result); 2072 external_string->set_length(static_cast<int>(length)); 2073 external_string->set_hash_field(String::kEmptyHashField); 2074 external_string->set_resource(resource); 2075 2076 return result; 2077 } 2078 2079 2080 Object* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { 2081 if (code <= String::kMaxAsciiCharCode) { 2082 Object* value = Heap::single_character_string_cache()->get(code); 2083 if (value != Heap::undefined_value()) return value; 2084 2085 char buffer[1]; 2086 buffer[0] = static_cast<char>(code); 2087 Object* result = LookupSymbol(Vector<const char>(buffer, 1)); 2088 2089 if (result->IsFailure()) return result; 2090 Heap::single_character_string_cache()->set(code, result); 2091 return result; 2092 } 2093 2094 Object* result = Heap::AllocateRawTwoByteString(1); 2095 if (result->IsFailure()) return result; 2096 String* answer = String::cast(result); 2097 answer->Set(0, code); 2098 return answer; 2099 } 2100 2101 2102 Object* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { 2103 if (length < 0 || length > ByteArray::kMaxLength) { 2104 return Failure::OutOfMemoryException(); 2105 } 2106 if (pretenure == NOT_TENURED) { 2107 return AllocateByteArray(length); 2108 } 2109 int size = ByteArray::SizeFor(length); 2110 Object* result = (size <= MaxObjectSizeInPagedSpace()) 2111 ? old_data_space_->AllocateRaw(size) 2112 : lo_space_->AllocateRaw(size); 2113 if (result->IsFailure()) return result; 2114 2115 reinterpret_cast<Array*>(result)->set_map(byte_array_map()); 2116 reinterpret_cast<Array*>(result)->set_length(length); 2117 return result; 2118 } 2119 2120 2121 Object* Heap::AllocateByteArray(int length) { 2122 if (length < 0 || length > ByteArray::kMaxLength) { 2123 return Failure::OutOfMemoryException(); 2124 } 2125 int size = ByteArray::SizeFor(length); 2126 AllocationSpace space = 2127 (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : NEW_SPACE; 2128 Object* result = AllocateRaw(size, space, OLD_DATA_SPACE); 2129 if (result->IsFailure()) return result; 2130 2131 reinterpret_cast<Array*>(result)->set_map(byte_array_map()); 2132 reinterpret_cast<Array*>(result)->set_length(length); 2133 return result; 2134 } 2135 2136 2137 void Heap::CreateFillerObjectAt(Address addr, int size) { 2138 if (size == 0) return; 2139 HeapObject* filler = HeapObject::FromAddress(addr); 2140 if (size == kPointerSize) { 2141 filler->set_map(Heap::one_pointer_filler_map()); 2142 } else { 2143 filler->set_map(Heap::byte_array_map()); 2144 ByteArray::cast(filler)->set_length(ByteArray::LengthFor(size)); 2145 } 2146 } 2147 2148 2149 Object* Heap::AllocatePixelArray(int length, 2150 uint8_t* external_pointer, 2151 PretenureFlag pretenure) { 2152 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; 2153 Object* result = AllocateRaw(PixelArray::kAlignedSize, space, OLD_DATA_SPACE); 2154 if (result->IsFailure()) return result; 2155 2156 reinterpret_cast<PixelArray*>(result)->set_map(pixel_array_map()); 2157 reinterpret_cast<PixelArray*>(result)->set_length(length); 2158 reinterpret_cast<PixelArray*>(result)->set_external_pointer(external_pointer); 2159 2160 return result; 2161 } 2162 2163 2164 Object* Heap::AllocateExternalArray(int length, 2165 ExternalArrayType array_type, 2166 void* external_pointer, 2167 PretenureFlag pretenure) { 2168 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; 2169 Object* result = AllocateRaw(ExternalArray::kAlignedSize, 2170 space, 2171 OLD_DATA_SPACE); 2172 if (result->IsFailure()) return result; 2173 2174 reinterpret_cast<ExternalArray*>(result)->set_map( 2175 MapForExternalArrayType(array_type)); 2176 reinterpret_cast<ExternalArray*>(result)->set_length(length); 2177 reinterpret_cast<ExternalArray*>(result)->set_external_pointer( 2178 external_pointer); 2179 2180 return result; 2181 } 2182 2183 2184 Object* Heap::CreateCode(const CodeDesc& desc, 2185 ZoneScopeInfo* sinfo, 2186 Code::Flags flags, 2187 Handle<Object> self_reference) { 2188 // Compute size 2189 int body_size = RoundUp(desc.instr_size + desc.reloc_size, kObjectAlignment); 2190 int sinfo_size = 0; 2191 if (sinfo != NULL) sinfo_size = sinfo->Serialize(NULL); 2192 int obj_size = Code::SizeFor(body_size, sinfo_size); 2193 ASSERT(IsAligned(obj_size, Code::kCodeAlignment)); 2194 Object* result; 2195 if (obj_size > MaxObjectSizeInPagedSpace()) { 2196 result = lo_space_->AllocateRawCode(obj_size); 2197 } else { 2198 result = code_space_->AllocateRaw(obj_size); 2199 } 2200 2201 if (result->IsFailure()) return result; 2202 2203 // Initialize the object 2204 HeapObject::cast(result)->set_map(code_map()); 2205 Code* code = Code::cast(result); 2206 ASSERT(!CodeRange::exists() || CodeRange::contains(code->address())); 2207 code->set_instruction_size(desc.instr_size); 2208 code->set_relocation_size(desc.reloc_size); 2209 code->set_sinfo_size(sinfo_size); 2210 code->set_flags(flags); 2211 // Allow self references to created code object by patching the handle to 2212 // point to the newly allocated Code object. 2213 if (!self_reference.is_null()) { 2214 *(self_reference.location()) = code; 2215 } 2216 // Migrate generated code. 2217 // The generated code can contain Object** values (typically from handles) 2218 // that are dereferenced during the copy to point directly to the actual heap 2219 // objects. These pointers can include references to the code object itself, 2220 // through the self_reference parameter. 2221 code->CopyFrom(desc); 2222 if (sinfo != NULL) sinfo->Serialize(code); // write scope info 2223 2224 #ifdef DEBUG 2225 code->Verify(); 2226 #endif 2227 return code; 2228 } 2229 2230 2231 Object* Heap::CopyCode(Code* code) { 2232 // Allocate an object the same size as the code object. 2233 int obj_size = code->Size(); 2234 Object* result; 2235 if (obj_size > MaxObjectSizeInPagedSpace()) { 2236 result = lo_space_->AllocateRawCode(obj_size); 2237 } else { 2238 result = code_space_->AllocateRaw(obj_size); 2239 } 2240 2241 if (result->IsFailure()) return result; 2242 2243 // Copy code object. 2244 Address old_addr = code->address(); 2245 Address new_addr = reinterpret_cast<HeapObject*>(result)->address(); 2246 CopyBlock(reinterpret_cast<Object**>(new_addr), 2247 reinterpret_cast<Object**>(old_addr), 2248 obj_size); 2249 // Relocate the copy. 2250 Code* new_code = Code::cast(result); 2251 ASSERT(!CodeRange::exists() || CodeRange::contains(code->address())); 2252 new_code->Relocate(new_addr - old_addr); 2253 return new_code; 2254 } 2255 2256 2257 Object* Heap::Allocate(Map* map, AllocationSpace space) { 2258 ASSERT(gc_state_ == NOT_IN_GC); 2259 ASSERT(map->instance_type() != MAP_TYPE); 2260 // If allocation failures are disallowed, we may allocate in a different 2261 // space when new space is full and the object is not a large object. 2262 AllocationSpace retry_space = 2263 (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type()); 2264 Object* result = 2265 AllocateRaw(map->instance_size(), space, retry_space); 2266 if (result->IsFailure()) return result; 2267 HeapObject::cast(result)->set_map(map); 2268 #ifdef ENABLE_LOGGING_AND_PROFILING 2269 ProducerHeapProfile::RecordJSObjectAllocation(result); 2270 #endif 2271 return result; 2272 } 2273 2274 2275 Object* Heap::InitializeFunction(JSFunction* function, 2276 SharedFunctionInfo* shared, 2277 Object* prototype) { 2278 ASSERT(!prototype->IsMap()); 2279 function->initialize_properties(); 2280 function->initialize_elements(); 2281 function->set_shared(shared); 2282 function->set_prototype_or_initial_map(prototype); 2283 function->set_context(undefined_value()); 2284 function->set_literals(empty_fixed_array()); 2285 return function; 2286 } 2287 2288 2289 Object* Heap::AllocateFunctionPrototype(JSFunction* function) { 2290 // Allocate the prototype. Make sure to use the object function 2291 // from the function's context, since the function can be from a 2292 // different context. 2293 JSFunction* object_function = 2294 function->context()->global_context()->object_function(); 2295 Object* prototype = AllocateJSObject(object_function); 2296 if (prototype->IsFailure()) return prototype; 2297 // When creating the prototype for the function we must set its 2298 // constructor to the function. 2299 Object* result = 2300 JSObject::cast(prototype)->SetProperty(constructor_symbol(), 2301 function, 2302 DONT_ENUM); 2303 if (result->IsFailure()) return result; 2304 return prototype; 2305 } 2306 2307 2308 Object* Heap::AllocateFunction(Map* function_map, 2309 SharedFunctionInfo* shared, 2310 Object* prototype, 2311 PretenureFlag pretenure) { 2312 AllocationSpace space = 2313 (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; 2314 Object* result = Allocate(function_map, space); 2315 if (result->IsFailure()) return result; 2316 return InitializeFunction(JSFunction::cast(result), shared, prototype); 2317 } 2318 2319 2320 Object* Heap::AllocateArgumentsObject(Object* callee, int length) { 2321 // To get fast allocation and map sharing for arguments objects we 2322 // allocate them based on an arguments boilerplate. 2323 2324 // This calls Copy directly rather than using Heap::AllocateRaw so we 2325 // duplicate the check here. 2326 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); 2327 2328 JSObject* boilerplate = 2329 Top::context()->global_context()->arguments_boilerplate(); 2330 2331 // Check that the size of the boilerplate matches our 2332 // expectations. The ArgumentsAccessStub::GenerateNewObject relies 2333 // on the size being a known constant. 2334 ASSERT(kArgumentsObjectSize == boilerplate->map()->instance_size()); 2335 2336 // Do the allocation. 2337 Object* result = 2338 AllocateRaw(kArgumentsObjectSize, NEW_SPACE, OLD_POINTER_SPACE); 2339 if (result->IsFailure()) return result; 2340 2341 // Copy the content. The arguments boilerplate doesn't have any 2342 // fields that point to new space so it's safe to skip the write 2343 // barrier here. 2344 CopyBlock(reinterpret_cast<Object**>(HeapObject::cast(result)->address()), 2345 reinterpret_cast<Object**>(boilerplate->address()), 2346 kArgumentsObjectSize); 2347 2348 // Set the two properties. 2349 JSObject::cast(result)->InObjectPropertyAtPut(arguments_callee_index, 2350 callee); 2351 JSObject::cast(result)->InObjectPropertyAtPut(arguments_length_index, 2352 Smi::FromInt(length), 2353 SKIP_WRITE_BARRIER); 2354 2355 // Check the state of the object 2356 ASSERT(JSObject::cast(result)->HasFastProperties()); 2357 ASSERT(JSObject::cast(result)->HasFastElements()); 2358 2359 return result; 2360 } 2361 2362 2363 Object* Heap::AllocateInitialMap(JSFunction* fun) { 2364 ASSERT(!fun->has_initial_map()); 2365 2366 // First create a new map with the size and number of in-object properties 2367 // suggested by the function. 2368 int instance_size = fun->shared()->CalculateInstanceSize(); 2369 int in_object_properties = fun->shared()->CalculateInObjectProperties(); 2370 Object* map_obj = Heap::AllocateMap(JS_OBJECT_TYPE, instance_size); 2371 if (map_obj->IsFailure()) return map_obj; 2372 2373 // Fetch or allocate prototype. 2374 Object* prototype; 2375 if (fun->has_instance_prototype()) { 2376 prototype = fun->instance_prototype(); 2377 } else { 2378 prototype = AllocateFunctionPrototype(fun); 2379 if (prototype->IsFailure()) return prototype; 2380 } 2381 Map* map = Map::cast(map_obj); 2382 map->set_inobject_properties(in_object_properties); 2383 map->set_unused_property_fields(in_object_properties); 2384 map->set_prototype(prototype); 2385 2386 // If the function has only simple this property assignments add 2387 // field descriptors for these to the initial map as the object 2388 // cannot be constructed without having these properties. Guard by 2389 // the inline_new flag so we only change the map if we generate a 2390 // specialized construct stub. 2391 ASSERT(in_object_properties <= Map::kMaxPreAllocatedPropertyFields); 2392 if (fun->shared()->CanGenerateInlineConstructor(prototype)) { 2393 int count = fun->shared()->this_property_assignments_count(); 2394 if (count > in_object_properties) { 2395 count = in_object_properties; 2396 } 2397 Object* descriptors_obj = DescriptorArray::Allocate(count); 2398 if (descriptors_obj->IsFailure()) return descriptors_obj; 2399 DescriptorArray* descriptors = DescriptorArray::cast(descriptors_obj); 2400 for (int i = 0; i < count; i++) { 2401 String* name = fun->shared()->GetThisPropertyAssignmentName(i); 2402 ASSERT(name->IsSymbol()); 2403 FieldDescriptor field(name, i, NONE); 2404 field.SetEnumerationIndex(i); 2405 descriptors->Set(i, &field); 2406 } 2407 descriptors->SetNextEnumerationIndex(count); 2408 descriptors->Sort(); 2409 map->set_instance_descriptors(descriptors); 2410 map->set_pre_allocated_property_fields(count); 2411 map->set_unused_property_fields(in_object_properties - count); 2412 } 2413 return map; 2414 } 2415 2416 2417 void Heap::InitializeJSObjectFromMap(JSObject* obj, 2418 FixedArray* properties, 2419 Map* map) { 2420 obj->set_properties(properties); 2421 obj->initialize_elements(); 2422 // TODO(1240798): Initialize the object's body using valid initial values 2423 // according to the object's initial map. For example, if the map's 2424 // instance type is JS_ARRAY_TYPE, the length field should be initialized 2425 // to a number (eg, Smi::FromInt(0)) and the elements initialized to a 2426 // fixed array (eg, Heap::empty_fixed_array()). Currently, the object 2427 // verification code has to cope with (temporarily) invalid objects. See 2428 // for example, JSArray::JSArrayVerify). 2429 obj->InitializeBody(map->instance_size()); 2430 } 2431 2432 2433 Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) { 2434 // JSFunctions should be allocated using AllocateFunction to be 2435 // properly initialized. 2436 ASSERT(map->instance_type() != JS_FUNCTION_TYPE); 2437 2438 // Both types of globla objects should be allocated using 2439 // AllocateGloblaObject to be properly initialized. 2440 ASSERT(map->instance_type() != JS_GLOBAL_OBJECT_TYPE); 2441 ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE); 2442 2443 // Allocate the backing storage for the properties. 2444 int prop_size = 2445 map->pre_allocated_property_fields() + 2446 map->unused_property_fields() - 2447 map->inobject_properties(); 2448 ASSERT(prop_size >= 0); 2449 Object* properties = AllocateFixedArray(prop_size, pretenure); 2450 if (properties->IsFailure()) return properties; 2451 2452 // Allocate the JSObject. 2453 AllocationSpace space = 2454 (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; 2455 if (map->instance_size() > MaxObjectSizeInPagedSpace()) space = LO_SPACE; 2456 Object* obj = Allocate(map, space); 2457 if (obj->IsFailure()) return obj; 2458 2459 // Initialize the JSObject. 2460 InitializeJSObjectFromMap(JSObject::cast(obj), 2461 FixedArray::cast(properties), 2462 map); 2463 return obj; 2464 } 2465 2466 2467 Object* Heap::AllocateJSObject(JSFunction* constructor, 2468 PretenureFlag pretenure) { 2469 // Allocate the initial map if absent. 2470 if (!constructor->has_initial_map()) { 2471 Object* initial_map = AllocateInitialMap(constructor); 2472 if (initial_map->IsFailure()) return initial_map; 2473 constructor->set_initial_map(Map::cast(initial_map)); 2474 Map::cast(initial_map)->set_constructor(constructor); 2475 } 2476 // Allocate the object based on the constructors initial map. 2477 Object* result = 2478 AllocateJSObjectFromMap(constructor->initial_map(), pretenure); 2479 // Make sure result is NOT a global object if valid. 2480 ASSERT(result->IsFailure() || !result->IsGlobalObject()); 2481 return result; 2482 } 2483 2484 2485 Object* Heap::AllocateGlobalObject(JSFunction* constructor) { 2486 ASSERT(constructor->has_initial_map()); 2487 Map* map = constructor->initial_map(); 2488 2489 // Make sure no field properties are described in the initial map. 2490 // This guarantees us that normalizing the properties does not 2491 // require us to change property values to JSGlobalPropertyCells. 2492 ASSERT(map->NextFreePropertyIndex() == 0); 2493 2494 // Make sure we don't have a ton of pre-allocated slots in the 2495 // global objects. They will be unused once we normalize the object. 2496 ASSERT(map->unused_property_fields() == 0); 2497 ASSERT(map->inobject_properties() == 0); 2498 2499 // Initial size of the backing store to avoid resize of the storage during 2500 // bootstrapping. The size differs between the JS global object ad the 2501 // builtins object. 2502 int initial_size = map->instance_type() == JS_GLOBAL_OBJECT_TYPE ? 64 : 512; 2503 2504 // Allocate a dictionary object for backing storage. 2505 Object* obj = 2506 StringDictionary::Allocate( 2507 map->NumberOfDescribedProperties() * 2 + initial_size); 2508 if (obj->IsFailure()) return obj; 2509 StringDictionary* dictionary = StringDictionary::cast(obj); 2510 2511 // The global object might be created from an object template with accessors. 2512 // Fill these accessors into the dictionary. 2513 DescriptorArray* descs = map->instance_descriptors(); 2514 for (int i = 0; i < descs->number_of_descriptors(); i++) { 2515 PropertyDetails details = descs->GetDetails(i); 2516 ASSERT(details.type() == CALLBACKS); // Only accessors are expected. 2517 PropertyDetails d = 2518 PropertyDetails(details.attributes(), CALLBACKS, details.index()); 2519 Object* value = descs->GetCallbacksObject(i); 2520 value = Heap::AllocateJSGlobalPropertyCell(value); 2521 if (value->IsFailure()) return value; 2522 2523 Object* result = dictionary->Add(descs->GetKey(i), value, d); 2524 if (result->IsFailure()) return result; 2525 dictionary = StringDictionary::cast(result); 2526 } 2527 2528 // Allocate the global object and initialize it with the backing store. 2529 obj = Allocate(map, OLD_POINTER_SPACE); 2530 if (obj->IsFailure()) return obj; 2531 JSObject* global = JSObject::cast(obj); 2532 InitializeJSObjectFromMap(global, dictionary, map); 2533 2534 // Create a new map for the global object. 2535 obj = map->CopyDropDescriptors(); 2536 if (obj->IsFailure()) return obj; 2537 Map* new_map = Map::cast(obj); 2538 2539 // Setup the global object as a normalized object. 2540 global->set_map(new_map); 2541 global->map()->set_instance_descriptors(Heap::empty_descriptor_array()); 2542 global->set_properties(dictionary); 2543 2544 // Make sure result is a global object with properties in dictionary. 2545 ASSERT(global->IsGlobalObject()); 2546 ASSERT(!global->HasFastProperties()); 2547 return global; 2548 } 2549 2550 2551 Object* Heap::CopyJSObject(JSObject* source) { 2552 // Never used to copy functions. If functions need to be copied we 2553 // have to be careful to clear the literals array. 2554 ASSERT(!source->IsJSFunction()); 2555 2556 // Make the clone. 2557 Map* map = source->map(); 2558 int object_size = map->instance_size(); 2559 Object* clone; 2560 2561 // If we're forced to always allocate, we use the general allocation 2562 // functions which may leave us with an object in old space. 2563 if (always_allocate()) { 2564 clone = AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE); 2565 if (clone->IsFailure()) return clone; 2566 Address clone_address = HeapObject::cast(clone)->address(); 2567 CopyBlock(reinterpret_cast<Object**>(clone_address), 2568 reinterpret_cast<Object**>(source->address()), 2569 object_size); 2570 // Update write barrier for all fields that lie beyond the header. 2571 for (int offset = JSObject::kHeaderSize; 2572 offset < object_size; 2573 offset += kPointerSize) { 2574 RecordWrite(clone_address, offset); 2575 } 2576 } else { 2577 clone = new_space_.AllocateRaw(object_size); 2578 if (clone->IsFailure()) return clone; 2579 ASSERT(Heap::InNewSpace(clone)); 2580 // Since we know the clone is allocated in new space, we can copy 2581 // the contents without worrying about updating the write barrier. 2582 CopyBlock(reinterpret_cast<Object**>(HeapObject::cast(clone)->address()), 2583 reinterpret_cast<Object**>(source->address()), 2584 object_size); 2585 } 2586 2587 FixedArray* elements = FixedArray::cast(source->elements()); 2588 FixedArray* properties = FixedArray::cast(source->properties()); 2589 // Update elements if necessary. 2590 if (elements->length()> 0) { 2591 Object* elem = CopyFixedArray(elements); 2592 if (elem->IsFailure()) return elem; 2593 JSObject::cast(clone)->set_elements(FixedArray::cast(elem)); 2594 } 2595 // Update properties if necessary. 2596 if (properties->length() > 0) { 2597 Object* prop = CopyFixedArray(properties); 2598 if (prop->IsFailure()) return prop; 2599 JSObject::cast(clone)->set_properties(FixedArray::cast(prop)); 2600 } 2601 // Return the new clone. 2602 #ifdef ENABLE_LOGGING_AND_PROFILING 2603 ProducerHeapProfile::RecordJSObjectAllocation(clone); 2604 #endif 2605 return clone; 2606 } 2607 2608 2609 Object* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor, 2610 JSGlobalProxy* object) { 2611 // Allocate initial map if absent. 2612 if (!constructor->has_initial_map()) { 2613 Object* initial_map = AllocateInitialMap(constructor); 2614 if (initial_map->IsFailure()) return initial_map; 2615 constructor->set_initial_map(Map::cast(initial_map)); 2616 Map::cast(initial_map)->set_constructor(constructor); 2617 } 2618 2619 Map* map = constructor->initial_map(); 2620 2621 // Check that the already allocated object has the same size as 2622 // objects allocated using the constructor. 2623 ASSERT(map->instance_size() == object->map()->instance_size()); 2624 2625 // Allocate the backing storage for the properties. 2626 int prop_size = map->unused_property_fields() - map->inobject_properties(); 2627 Object* properties = AllocateFixedArray(prop_size, TENURED); 2628 if (properties->IsFailure()) return properties; 2629 2630 // Reset the map for the object. 2631 object->set_map(constructor->initial_map()); 2632 2633 // Reinitialize the object from the constructor map. 2634 InitializeJSObjectFromMap(object, FixedArray::cast(properties), map); 2635 return object; 2636 } 2637 2638 2639 Object* Heap::AllocateStringFromAscii(Vector<const char> string, 2640 PretenureFlag pretenure) { 2641 Object* result = AllocateRawAsciiString(string.length(), pretenure); 2642 if (result->IsFailure()) return result; 2643 2644 // Copy the characters into the new object. 2645 SeqAsciiString* string_result = SeqAsciiString::cast(result); 2646 for (int i = 0; i < string.length(); i++) { 2647 string_result->SeqAsciiStringSet(i, string[i]); 2648 } 2649 return result; 2650 } 2651 2652 2653 Object* Heap::AllocateStringFromUtf8(Vector<const char> string, 2654 PretenureFlag pretenure) { 2655 // Count the number of characters in the UTF-8 string and check if 2656 // it is an ASCII string. 2657 Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder()); 2658 decoder->Reset(string.start(), string.length()); 2659 int chars = 0; 2660 bool is_ascii = true; 2661 while (decoder->has_more()) { 2662 uc32 r = decoder->GetNext(); 2663 if (r > String::kMaxAsciiCharCode) is_ascii = false; 2664 chars++; 2665 } 2666 2667 // If the string is ascii, we do not need to convert the characters 2668 // since UTF8 is backwards compatible with ascii. 2669 if (is_ascii) return AllocateStringFromAscii(string, pretenure); 2670 2671 Object* result = AllocateRawTwoByteString(chars, pretenure); 2672 if (result->IsFailure()) return result; 2673 2674 // Convert and copy the characters into the new object. 2675 String* string_result = String::cast(result); 2676 decoder->Reset(string.start(), string.length()); 2677 for (int i = 0; i < chars; i++) { 2678 uc32 r = decoder->GetNext(); 2679 string_result->Set(i, r); 2680 } 2681 return result; 2682 } 2683 2684 2685 Object* Heap::AllocateStringFromTwoByte(Vector<const uc16> string, 2686 PretenureFlag pretenure) { 2687 // Check if the string is an ASCII string. 2688 int i = 0; 2689 while (i < string.length() && string[i] <= String::kMaxAsciiCharCode) i++; 2690 2691 Object* result; 2692 if (i == string.length()) { // It's an ASCII string. 2693 result = AllocateRawAsciiString(string.length(), pretenure); 2694 } else { // It's not an ASCII string. 2695 result = AllocateRawTwoByteString(string.length(), pretenure); 2696 } 2697 if (result->IsFailure()) return result; 2698 2699 // Copy the characters into the new object, which may be either ASCII or 2700 // UTF-16. 2701 String* string_result = String::cast(result); 2702 for (int i = 0; i < string.length(); i++) { 2703 string_result->Set(i, string[i]); 2704 } 2705 return result; 2706 } 2707 2708 2709 Map* Heap::SymbolMapForString(String* string) { 2710 // If the string is in new space it cannot be used as a symbol. 2711 if (InNewSpace(string)) return NULL; 2712 2713 // Find the corresponding symbol map for strings. 2714 Map* map = string->map(); 2715 if (map == ascii_string_map()) return ascii_symbol_map(); 2716 if (map == string_map()) return symbol_map(); 2717 if (map == cons_string_map()) return cons_symbol_map(); 2718 if (map == cons_ascii_string_map()) return cons_ascii_symbol_map(); 2719 if (map == external_string_map()) return external_symbol_map(); 2720 if (map == external_ascii_string_map()) return external_ascii_symbol_map(); 2721 2722 // No match found. 2723 return NULL; 2724 } 2725 2726 2727 Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, 2728 int chars, 2729 uint32_t hash_field) { 2730 ASSERT(chars >= 0); 2731 // Ensure the chars matches the number of characters in the buffer. 2732 ASSERT(static_cast<unsigned>(chars) == buffer->Length()); 2733 // Determine whether the string is ascii. 2734 bool is_ascii = true; 2735 while (buffer->has_more()) { 2736 if (buffer->GetNext() > unibrow::Utf8::kMaxOneByteChar) { 2737 is_ascii = false; 2738 break; 2739 } 2740 } 2741 buffer->Rewind(); 2742 2743 // Compute map and object size. 2744 int size; 2745 Map* map; 2746 2747 if (is_ascii) { 2748 if (chars > SeqAsciiString::kMaxLength) { 2749 return Failure::OutOfMemoryException(); 2750 } 2751 map = ascii_symbol_map(); 2752 size = SeqAsciiString::SizeFor(chars); 2753 } else { 2754 if (chars > SeqTwoByteString::kMaxLength) { 2755 return Failure::OutOfMemoryException(); 2756 } 2757 map = symbol_map(); 2758 size = SeqTwoByteString::SizeFor(chars); 2759 } 2760 2761 // Allocate string. 2762 Object* result = (size > MaxObjectSizeInPagedSpace()) 2763 ? lo_space_->AllocateRaw(size) 2764 : old_data_space_->AllocateRaw(size); 2765 if (result->IsFailure()) return result; 2766 2767 reinterpret_cast<HeapObject*>(result)->set_map(map); 2768 // Set length and hash fields of the allocated string. 2769 String* answer = String::cast(result); 2770 answer->set_length(chars); 2771 answer->set_hash_field(hash_field); 2772 2773 ASSERT_EQ(size, answer->Size()); 2774 2775 // Fill in the characters. 2776 for (int i = 0; i < chars; i++) { 2777 answer->Set(i, buffer->GetNext()); 2778 } 2779 return answer; 2780 } 2781 2782 2783 Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { 2784 if (length < 0 || length > SeqAsciiString::kMaxLength) { 2785 return Failure::OutOfMemoryException(); 2786 } 2787 2788 int size = SeqAsciiString::SizeFor(length); 2789 ASSERT(size <= SeqAsciiString::kMaxSize); 2790 2791 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; 2792 AllocationSpace retry_space = OLD_DATA_SPACE; 2793 2794 if (space == NEW_SPACE) { 2795 if (size > kMaxObjectSizeInNewSpace) { 2796 // Allocate in large object space, retry space will be ignored. 2797 space = LO_SPACE; 2798 } else if (size > MaxObjectSizeInPagedSpace()) { 2799 // Allocate in new space, retry in large object space. 2800 retry_space = LO_SPACE; 2801 } 2802 } else if (space == OLD_DATA_SPACE && size > MaxObjectSizeInPagedSpace()) { 2803 space = LO_SPACE; 2804 } 2805 Object* result = AllocateRaw(size, space, retry_space); 2806 if (result->IsFailure()) return result; 2807 2808 // Partially initialize the object. 2809 HeapObject::cast(result)->set_map(ascii_string_map()); 2810 String::cast(result)->set_length(length); 2811 String::cast(result)->set_hash_field(String::kEmptyHashField); 2812 ASSERT_EQ(size, HeapObject::cast(result)->Size()); 2813 return result; 2814 } 2815 2816 2817 Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) { 2818 if (length < 0 || length > SeqTwoByteString::kMaxLength) { 2819 return Failure::OutOfMemoryException(); 2820 } 2821 int size = SeqTwoByteString::SizeFor(length); 2822 ASSERT(size <= SeqTwoByteString::kMaxSize); 2823 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; 2824 AllocationSpace retry_space = OLD_DATA_SPACE; 2825 2826 if (space == NEW_SPACE) { 2827 if (size > kMaxObjectSizeInNewSpace) { 2828 // Allocate in large object space, retry space will be ignored. 2829 space = LO_SPACE; 2830 } else if (size > MaxObjectSizeInPagedSpace()) { 2831 // Allocate in new space, retry in large object space. 2832 retry_space = LO_SPACE; 2833 } 2834 } else if (space == OLD_DATA_SPACE && size > MaxObjectSizeInPagedSpace()) { 2835 space = LO_SPACE; 2836 } 2837 Object* result = AllocateRaw(size, space, retry_space); 2838 if (result->IsFailure()) return result; 2839 2840 // Partially initialize the object. 2841 HeapObject::cast(result)->set_map(string_map()); 2842 String::cast(result)->set_length(length); 2843 String::cast(result)->set_hash_field(String::kEmptyHashField); 2844 ASSERT_EQ(size, HeapObject::cast(result)->Size()); 2845 return result; 2846 } 2847 2848 2849 Object* Heap::AllocateEmptyFixedArray() { 2850 int size = FixedArray::SizeFor(0); 2851 Object* result = AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE); 2852 if (result->IsFailure()) return result; 2853 // Initialize the object. 2854 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); 2855 reinterpret_cast<Array*>(result)->set_length(0); 2856 return result; 2857 } 2858 2859 2860 Object* Heap::AllocateRawFixedArray(int length) { 2861 if (length < 0 || length > FixedArray::kMaxLength) { 2862 return Failure::OutOfMemoryException(); 2863 } 2864 // Use the general function if we're forced to always allocate. 2865 if (always_allocate()) return AllocateFixedArray(length, TENURED); 2866 // Allocate the raw data for a fixed array. 2867 int size = FixedArray::SizeFor(length); 2868 return size <= kMaxObjectSizeInNewSpace 2869 ? new_space_.AllocateRaw(size) 2870 : lo_space_->AllocateRawFixedArray(size); 2871 } 2872 2873 2874 Object* Heap::CopyFixedArray(FixedArray* src) { 2875 int len = src->length(); 2876 Object* obj = AllocateRawFixedArray(len); 2877 if (obj->IsFailure()) return obj; 2878 if (Heap::InNewSpace(obj)) { 2879 HeapObject* dst = HeapObject::cast(obj); 2880 CopyBlock(reinterpret_cast<Object**>(dst->address()), 2881 reinterpret_cast<Object**>(src->address()), 2882 FixedArray::SizeFor(len)); 2883 return obj; 2884 } 2885 HeapObject::cast(obj)->set_map(src->map()); 2886 FixedArray* result = FixedArray::cast(obj); 2887 result->set_length(len); 2888 2889 // Copy the content 2890 AssertNoAllocation no_gc; 2891 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); 2892 for (int i = 0; i < len; i++) result->set(i, src->get(i), mode); 2893 return result; 2894 } 2895 2896 2897 Object* Heap::AllocateFixedArray(int length) { 2898 ASSERT(length >= 0); 2899 if (length == 0) return empty_fixed_array(); 2900 Object* result = AllocateRawFixedArray(length); 2901 if (!result->IsFailure()) { 2902 // Initialize header. 2903 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); 2904 FixedArray* array = FixedArray::cast(result); 2905 array->set_length(length); 2906 Object* value = undefined_value(); 2907 // Initialize body. 2908 for (int index = 0; index < length; index++) { 2909 ASSERT(!Heap::InNewSpace(value)); // value = undefined 2910 array->set(index, value, SKIP_WRITE_BARRIER); 2911 } 2912 } 2913 return result; 2914 } 2915 2916 2917 Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { 2918 ASSERT(length >= 0); 2919 ASSERT(empty_fixed_array()->IsFixedArray()); 2920 if (length < 0 || length > FixedArray::kMaxLength) { 2921 return Failure::OutOfMemoryException(); 2922 } 2923 if (length == 0) return empty_fixed_array(); 2924 2925 AllocationSpace space = 2926 (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; 2927 int size = FixedArray::SizeFor(length); 2928 if (space == NEW_SPACE && size > kMaxObjectSizeInNewSpace) { 2929 // Too big for new space. 2930 space = LO_SPACE; 2931 } else if (space == OLD_POINTER_SPACE && 2932 size > MaxObjectSizeInPagedSpace()) { 2933 // Too big for old pointer space. 2934 space = LO_SPACE; 2935 } 2936 2937 // Specialize allocation for the space. 2938 Object* result = Failure::OutOfMemoryException(); 2939 if (space == NEW_SPACE) { 2940 // We cannot use Heap::AllocateRaw() because it will not properly 2941 // allocate extra remembered set bits if always_allocate() is true and 2942 // new space allocation fails. 2943 result = new_space_.AllocateRaw(size); 2944 if (result->IsFailure() && always_allocate()) { 2945 if (size <= MaxObjectSizeInPagedSpace()) { 2946 result = old_pointer_space_->AllocateRaw(size); 2947 } else { 2948 result = lo_space_->AllocateRawFixedArray(size); 2949 } 2950 } 2951 } else if (space == OLD_POINTER_SPACE) { 2952 result = old_pointer_space_->AllocateRaw(size); 2953 } else { 2954 ASSERT(space == LO_SPACE); 2955 result = lo_space_->AllocateRawFixedArray(size); 2956 } 2957 if (result->IsFailure()) return result; 2958 2959 // Initialize the object. 2960 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); 2961 FixedArray* array = FixedArray::cast(result); 2962 array->set_length(length); 2963 Object* value = undefined_value(); 2964 for (int index = 0; index < length; index++) { 2965 ASSERT(!Heap::InNewSpace(value)); // value = undefined 2966 array->set(index, value, SKIP_WRITE_BARRIER); 2967 } 2968 return array; 2969 } 2970 2971 2972 Object* Heap::AllocateFixedArrayWithHoles(int length) { 2973 if (length == 0) return empty_fixed_array(); 2974 Object* result = AllocateRawFixedArray(length); 2975 if (!result->IsFailure()) { 2976 // Initialize header. 2977 reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); 2978 FixedArray* array = FixedArray::cast(result); 2979 array->set_length(length); 2980 // Initialize body. 2981 Object* value = the_hole_value(); 2982 for (int index = 0; index < length; index++) { 2983 ASSERT(!Heap::InNewSpace(value)); // value = the hole 2984 array->set(index, value, SKIP_WRITE_BARRIER); 2985 } 2986 } 2987 return result; 2988 } 2989 2990 2991 Object* Heap::AllocateHashTable(int length) { 2992 Object* result = Heap::AllocateFixedArray(length); 2993 if (result->IsFailure()) return result; 2994 reinterpret_cast<Array*>(result)->set_map(hash_table_map()); 2995 ASSERT(result->IsHashTable()); 2996 return result; 2997 } 2998 2999 3000 Object* Heap::AllocateGlobalContext() { 3001 Object* result = Heap::AllocateFixedArray(Context::GLOBAL_CONTEXT_SLOTS); 3002 if (result->IsFailure()) return result; 3003 Context* context = reinterpret_cast<Context*>(result); 3004 context->set_map(global_context_map()); 3005 ASSERT(context->IsGlobalContext()); 3006 ASSERT(result->IsContext()); 3007 return result; 3008 } 3009 3010 3011 Object* Heap::AllocateFunctionContext(int length, JSFunction* function) { 3012 ASSERT(length >= Context::MIN_CONTEXT_SLOTS); 3013 Object* result = Heap::AllocateFixedArray(length); 3014 if (result->IsFailure()) return result; 3015 Context* context = reinterpret_cast<Context*>(result); 3016 context->set_map(context_map()); 3017 context->set_closure(function); 3018 context->set_fcontext(context); 3019 context->set_previous(NULL); 3020 context->set_extension(NULL); 3021 context->set_global(function->context()->global()); 3022 ASSERT(!context->IsGlobalContext()); 3023 ASSERT(context->is_function_context()); 3024 ASSERT(result->IsContext()); 3025 return result; 3026 } 3027 3028 3029 Object* Heap::AllocateWithContext(Context* previous, 3030 JSObject* extension, 3031 bool is_catch_context) { 3032 Object* result = Heap::AllocateFixedArray(Context::MIN_CONTEXT_SLOTS); 3033 if (result->IsFailure()) return result; 3034 Context* context = reinterpret_cast<Context*>(result); 3035 context->set_map(is_catch_context ? catch_context_map() : context_map()); 3036 context->set_closure(previous->closure()); 3037 context->set_fcontext(previous->fcontext()); 3038 context->set_previous(previous); 3039 context->set_extension(extension); 3040 context->set_global(previous->global()); 3041 ASSERT(!context->IsGlobalContext()); 3042 ASSERT(!context->is_function_context()); 3043 ASSERT(result->IsContext()); 3044 return result; 3045 } 3046 3047 3048 Object* Heap::AllocateStruct(InstanceType type) { 3049 Map* map; 3050 switch (type) { 3051 #define MAKE_CASE(NAME, Name, name) case NAME##_TYPE: map = name##_map(); break; 3052 STRUCT_LIST(MAKE_CASE) 3053 #undef MAKE_CASE 3054 default: 3055 UNREACHABLE(); 3056 return Failure::InternalError(); 3057 } 3058 int size = map->instance_size(); 3059 AllocationSpace space = 3060 (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : OLD_POINTER_SPACE; 3061 Object* result = Heap::Allocate(map, space); 3062 if (result->IsFailure()) return result; 3063 Struct::cast(result)->InitializeBody(size); 3064 return result; 3065 } 3066 3067 3068 bool Heap::IdleNotification() { 3069 static const int kIdlesBeforeScavenge = 4; 3070 static const int kIdlesBeforeMarkSweep = 7; 3071 static const int kIdlesBeforeMarkCompact = 8; 3072 static int number_idle_notifications = 0; 3073 static int last_gc_count = gc_count_; 3074 3075 bool finished = false; 3076 3077 if (last_gc_count == gc_count_) { 3078 number_idle_notifications++; 3079 } else { 3080 number_idle_notifications = 0; 3081 last_gc_count = gc_count_; 3082 } 3083 3084 if (number_idle_notifications == kIdlesBeforeScavenge) { 3085 CollectGarbage(0, NEW_SPACE); 3086 new_space_.Shrink(); 3087 last_gc_count = gc_count_; 3088 3089 } else if (number_idle_notifications == kIdlesBeforeMarkSweep) { 3090 // Before doing the mark-sweep collections we clear the 3091 // compilation cache to avoid hanging on to source code and 3092 // generated code for cached functions. 3093 CompilationCache::Clear(); 3094 3095 CollectAllGarbage(false); 3096 new_space_.Shrink(); 3097 last_gc_count = gc_count_; 3098 3099 } else if (number_idle_notifications == kIdlesBeforeMarkCompact) { 3100 CollectAllGarbage(true); 3101 new_space_.Shrink(); 3102 last_gc_count = gc_count_; 3103 number_idle_notifications = 0; 3104 finished = true; 3105 } 3106 3107 // Uncommit unused memory in new space. 3108 Heap::UncommitFromSpace(); 3109 return finished; 3110 } 3111 3112 3113 #ifdef DEBUG 3114 3115 void Heap::Print() { 3116 if (!HasBeenSetup()) return; 3117 Top::PrintStack(); 3118 AllSpaces spaces; 3119 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) 3120 space->Print(); 3121 } 3122 3123 3124 void Heap::ReportCodeStatistics(const char* title) { 3125 PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title); 3126 PagedSpace::ResetCodeStatistics(); 3127 // We do not look for code in new space, map space, or old space. If code 3128 // somehow ends up in those spaces, we would miss it here. 3129 code_space_->CollectCodeStatistics(); 3130 lo_space_->CollectCodeStatistics(); 3131 PagedSpace::ReportCodeStatistics(); 3132 } 3133 3134 3135 // This function expects that NewSpace's allocated objects histogram is 3136 // populated (via a call to CollectStatistics or else as a side effect of a 3137 // just-completed scavenge collection). 3138 void Heap::ReportHeapStatistics(const char* title) { 3139 USE(title); 3140 PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n", 3141 title, gc_count_); 3142 PrintF("mark-compact GC : %d\n", mc_count_); 3143 PrintF("old_gen_promotion_limit_ %d\n", old_gen_promotion_limit_); 3144 PrintF("old_gen_allocation_limit_ %d\n", old_gen_allocation_limit_); 3145 3146 PrintF("\n"); 3147 PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles()); 3148 GlobalHandles::PrintStats(); 3149 PrintF("\n"); 3150 3151 PrintF("Heap statistics : "); 3152 MemoryAllocator::ReportStatistics(); 3153 PrintF("To space : "); 3154 new_space_.ReportStatistics(); 3155 PrintF("Old pointer space : "); 3156 old_pointer_space_->ReportStatistics(); 3157 PrintF("Old data space : "); 3158 old_data_space_->ReportStatistics(); 3159 PrintF("Code space : "); 3160 code_space_->ReportStatistics(); 3161 PrintF("Map space : "); 3162 map_space_->ReportStatistics(); 3163 PrintF("Cell space : "); 3164 cell_space_->ReportStatistics(); 3165 PrintF("Large object space : "); 3166 lo_space_->ReportStatistics(); 3167 PrintF(">>>>>> ========================================= >>>>>>\n"); 3168 } 3169 3170 #endif // DEBUG 3171 3172 bool Heap::Contains(HeapObject* value) { 3173 return Contains(value->address()); 3174 } 3175 3176 3177 bool Heap::Contains(Address addr) { 3178 if (OS::IsOutsideAllocatedSpace(addr)) return false; 3179 return HasBeenSetup() && 3180 (new_space_.ToSpaceContains(addr) || 3181 old_pointer_space_->Contains(addr) || 3182 old_data_space_->Contains(addr) || 3183 code_space_->Contains(addr) || 3184 map_space_->Contains(addr) || 3185 cell_space_->Contains(addr) || 3186 lo_space_->SlowContains(addr)); 3187 } 3188 3189 3190 bool Heap::InSpace(HeapObject* value, AllocationSpace space) { 3191 return InSpace(value->address(), space); 3192 } 3193 3194 3195 bool Heap::InSpace(Address addr, AllocationSpace space) { 3196 if (OS::IsOutsideAllocatedSpace(addr)) return false; 3197 if (!HasBeenSetup()) return false; 3198 3199 switch (space) { 3200 case NEW_SPACE: 3201 return new_space_.ToSpaceContains(addr); 3202 case OLD_POINTER_SPACE: 3203 return old_pointer_space_->Contains(addr); 3204 case OLD_DATA_SPACE: 3205 return old_data_space_->Contains(addr); 3206 case CODE_SPACE: 3207 return code_space_->Contains(addr); 3208 case MAP_SPACE: 3209 return map_space_->Contains(addr); 3210 case CELL_SPACE: 3211 return cell_space_->Contains(addr); 3212 case LO_SPACE: 3213 return lo_space_->SlowContains(addr); 3214 } 3215 3216 return false; 3217 } 3218 3219 3220 #ifdef DEBUG 3221 void Heap::Verify() { 3222 ASSERT(HasBeenSetup()); 3223 3224 VerifyPointersVisitor visitor; 3225 IterateRoots(&visitor, VISIT_ONLY_STRONG); 3226 3227 new_space_.Verify(); 3228 3229 VerifyPointersAndRSetVisitor rset_visitor; 3230 old_pointer_space_->Verify(&rset_visitor); 3231 map_space_->Verify(&rset_visitor); 3232 3233 VerifyPointersVisitor no_rset_visitor; 3234 old_data_space_->Verify(&no_rset_visitor); 3235 code_space_->Verify(&no_rset_visitor); 3236 cell_space_->Verify(&no_rset_visitor); 3237 3238 lo_space_->Verify(); 3239 } 3240 #endif // DEBUG 3241 3242 3243 Object* Heap::LookupSymbol(Vector<const char> string) { 3244 Object* symbol = NULL; 3245 Object* new_table = symbol_table()->LookupSymbol(string, &symbol); 3246 if (new_table->IsFailure()) return new_table; 3247 // Can't use set_symbol_table because SymbolTable::cast knows that 3248 // SymbolTable is a singleton and checks for identity. 3249 roots_[kSymbolTableRootIndex] = new_table; 3250 ASSERT(symbol != NULL); 3251 return symbol; 3252 } 3253 3254 3255 Object* Heap::LookupSymbol(String* string) { 3256 if (string->IsSymbol()) return string; 3257 Object* symbol = NULL; 3258 Object* new_table = symbol_table()->LookupString(string, &symbol); 3259 if (new_table->IsFailure()) return new_table; 3260 // Can't use set_symbol_table because SymbolTable::cast knows that 3261 // SymbolTable is a singleton and checks for identity. 3262 roots_[kSymbolTableRootIndex] = new_table; 3263 ASSERT(symbol != NULL); 3264 return symbol; 3265 } 3266 3267 3268 bool Heap::LookupSymbolIfExists(String* string, String** symbol) { 3269 if (string->IsSymbol()) { 3270 *symbol = string; 3271 return true; 3272 } 3273 return symbol_table()->LookupSymbolIfExists(string, symbol); 3274 } 3275 3276 3277 #ifdef DEBUG 3278 void Heap::ZapFromSpace() { 3279 ASSERT(reinterpret_cast<Object*>(kFromSpaceZapValue)->IsHeapObject()); 3280 for (Address a = new_space_.FromSpaceLow(); 3281 a < new_space_.FromSpaceHigh(); 3282 a += kPointerSize) { 3283 Memory::Address_at(a) = kFromSpaceZapValue; 3284 } 3285 } 3286 #endif // DEBUG 3287 3288 3289 int Heap::IterateRSetRange(Address object_start, 3290 Address object_end, 3291 Address rset_start, 3292 ObjectSlotCallback copy_object_func) { 3293 Address object_address = object_start; 3294 Address rset_address = rset_start; 3295 int set_bits_count = 0; 3296 3297 // Loop over all the pointers in [object_start, object_end). 3298 while (object_address < object_end) { 3299 uint32_t rset_word = Memory::uint32_at(rset_address); 3300 if (rset_word != 0) { 3301 uint32_t result_rset = rset_word; 3302 for (uint32_t bitmask = 1; bitmask != 0; bitmask = bitmask << 1) { 3303 // Do not dereference pointers at or past object_end. 3304 if ((rset_word & bitmask) != 0 && object_address < object_end) { 3305 Object** object_p = reinterpret_cast<Object**>(object_address); 3306 if (Heap::InNewSpace(*object_p)) { 3307 copy_object_func(reinterpret_cast<HeapObject**>(object_p)); 3308 } 3309 // If this pointer does not need to be remembered anymore, clear 3310 // the remembered set bit. 3311 if (!Heap::InNewSpace(*object_p)) result_rset &= ~bitmask; 3312 set_bits_count++; 3313 } 3314 object_address += kPointerSize; 3315 } 3316 // Update the remembered set if it has changed. 3317 if (result_rset != rset_word) { 3318 Memory::uint32_at(rset_address) = result_rset; 3319 } 3320 } else { 3321 // No bits in the word were set. This is the common case. 3322 object_address += kPointerSize * kBitsPerInt; 3323 } 3324 rset_address += kIntSize; 3325 } 3326 return set_bits_count; 3327 } 3328 3329 3330 void Heap::IterateRSet(PagedSpace* space, ObjectSlotCallback copy_object_func) { 3331 ASSERT(Page::is_rset_in_use()); 3332 ASSERT(space == old_pointer_space_ || space == map_space_); 3333 3334 static void* paged_rset_histogram = StatsTable::CreateHistogram( 3335 "V8.RSetPaged", 3336 0, 3337 Page::kObjectAreaSize / kPointerSize, 3338 30); 3339 3340 PageIterator it(space, PageIterator::PAGES_IN_USE); 3341 while (it.has_next()) { 3342 Page* page = it.next(); 3343 int count = IterateRSetRange(page->ObjectAreaStart(), page->AllocationTop(), 3344 page->RSetStart(), copy_object_func); 3345 if (paged_rset_histogram != NULL) { 3346 StatsTable::AddHistogramSample(paged_rset_histogram, count); 3347 } 3348 } 3349 } 3350 3351 3352 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) { 3353 IterateStrongRoots(v, mode); 3354 IterateWeakRoots(v, mode); 3355 } 3356 3357 3358 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { 3359 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); 3360 v->Synchronize("symbol_table"); 3361 if (mode != VISIT_ALL_IN_SCAVENGE) { 3362 // Scavenge collections have special processing for this. 3363 ExternalStringTable::Iterate(v); 3364 } 3365 v->Synchronize("external_string_table"); 3366 } 3367 3368 3369 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { 3370 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); 3371 v->Synchronize("strong_root_list"); 3372 3373 v->VisitPointer(bit_cast<Object**, String**>(&hidden_symbol_)); 3374 v->Synchronize("symbol"); 3375 3376 Bootstrapper::Iterate(v); 3377 v->Synchronize("bootstrapper"); 3378 Top::Iterate(v); 3379 v->Synchronize("top"); 3380 Relocatable::Iterate(v); 3381 v->Synchronize("relocatable"); 3382 3383 #ifdef ENABLE_DEBUGGER_SUPPORT 3384 Debug::Iterate(v); 3385 #endif 3386 v->Synchronize("debug"); 3387 CompilationCache::Iterate(v); 3388 v->Synchronize("compilationcache"); 3389 3390 // Iterate over local handles in handle scopes. 3391 HandleScopeImplementer::Iterate(v); 3392 v->Synchronize("handlescope"); 3393 3394 // Iterate over the builtin code objects and code stubs in the 3395 // heap. Note that it is not necessary to iterate over code objects 3396 // on scavenge collections. 3397 if (mode != VISIT_ALL_IN_SCAVENGE) { 3398 Builtins::IterateBuiltins(v); 3399 } 3400 v->Synchronize("builtins"); 3401 3402 // Iterate over global handles. 3403 if (mode == VISIT_ONLY_STRONG) { 3404 GlobalHandles::IterateStrongRoots(v); 3405 } else { 3406 GlobalHandles::IterateAllRoots(v); 3407 } 3408 v->Synchronize("globalhandles"); 3409 3410 // Iterate over pointers being held by inactive threads. 3411 ThreadManager::Iterate(v); 3412 v->Synchronize("threadmanager"); 3413 3414 // Iterate over the pointers the Serialization/Deserialization code is 3415 // holding. 3416 // During garbage collection this keeps the partial snapshot cache alive. 3417 // During deserialization of the startup snapshot this creates the partial 3418 // snapshot cache and deserializes the objects it refers to. During 3419 // serialization this does nothing, since the partial snapshot cache is 3420 // empty. However the next thing we do is create the partial snapshot, 3421 // filling up the partial snapshot cache with objects it needs as we go. 3422 SerializerDeserializer::Iterate(v); 3423 // We don't do a v->Synchronize call here, because in debug mode that will 3424 // output a flag to the snapshot. However at this point the serializer and 3425 // deserializer are deliberately a little unsynchronized (see above) so the 3426 // checking of the sync flag in the snapshot would fail. 3427 } 3428 3429 3430 // Flag is set when the heap has been configured. The heap can be repeatedly 3431 // configured through the API until it is setup. 3432 static bool heap_configured = false; 3433 3434 // TODO(1236194): Since the heap size is configurable on the command line 3435 // and through the API, we should gracefully handle the case that the heap 3436 // size is not big enough to fit all the initial objects. 3437 bool Heap::ConfigureHeap(int max_semispace_size, int max_old_gen_size) { 3438 if (HasBeenSetup()) return false; 3439 3440 if (max_semispace_size > 0) max_semispace_size_ = max_semispace_size; 3441 3442 if (Snapshot::IsEnabled()) { 3443 // If we are using a snapshot we always reserve the default amount 3444 // of memory for each semispace because code in the snapshot has 3445 // write-barrier code that relies on the size and alignment of new 3446 // space. We therefore cannot use a larger max semispace size 3447 // than the default reserved semispace size. 3448 if (max_semispace_size_ > reserved_semispace_size_) { 3449 max_semispace_size_ = reserved_semispace_size_; 3450 } 3451 } else { 3452 // If we are not using snapshots we reserve space for the actual 3453 // max semispace size. 3454 reserved_semispace_size_ = max_semispace_size_; 3455 } 3456 3457 if (max_old_gen_size > 0) max_old_generation_size_ = max_old_gen_size; 3458 3459 // The new space size must be a power of two to support single-bit testing 3460 // for containment. 3461 max_semispace_size_ = RoundUpToPowerOf2(max_semispace_size_); 3462 reserved_semispace_size_ = RoundUpToPowerOf2(reserved_semispace_size_); 3463 initial_semispace_size_ = Min(initial_semispace_size_, max_semispace_size_); 3464 external_allocation_limit_ = 10 * max_semispace_size_; 3465 3466 // The old generation is paged. 3467 max_old_generation_size_ = RoundUp(max_old_generation_size_, Page::kPageSize); 3468 3469 heap_configured = true; 3470 return true; 3471 } 3472 3473 3474 bool Heap::ConfigureHeapDefault() { 3475 return ConfigureHeap(FLAG_max_new_space_size / 2, FLAG_max_old_space_size); 3476 } 3477 3478 3479 void Heap::RecordStats(HeapStats* stats) { 3480 *stats->start_marker = 0xDECADE00; 3481 *stats->end_marker = 0xDECADE01; 3482 *stats->new_space_size = new_space_.Size(); 3483 *stats->new_space_capacity = new_space_.Capacity(); 3484 *stats->old_pointer_space_size = old_pointer_space_->Size(); 3485 *stats->old_pointer_space_capacity = old_pointer_space_->Capacity(); 3486 *stats->old_data_space_size = old_data_space_->Size(); 3487 *stats->old_data_space_capacity = old_data_space_->Capacity(); 3488 *stats->code_space_size = code_space_->Size(); 3489 *stats->code_space_capacity = code_space_->Capacity(); 3490 *stats->map_space_size = map_space_->Size(); 3491 *stats->map_space_capacity = map_space_->Capacity(); 3492 *stats->cell_space_size = cell_space_->Size(); 3493 *stats->cell_space_capacity = cell_space_->Capacity(); 3494 *stats->lo_space_size = lo_space_->Size(); 3495 GlobalHandles::RecordStats(stats); 3496 } 3497 3498 3499 int Heap::PromotedSpaceSize() { 3500 return old_pointer_space_->Size() 3501 + old_data_space_->Size() 3502 + code_space_->Size() 3503 + map_space_->Size() 3504 + cell_space_->Size() 3505 + lo_space_->Size(); 3506 } 3507 3508 3509 int Heap::PromotedExternalMemorySize() { 3510 if (amount_of_external_allocated_memory_ 3511 <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; 3512 return amount_of_external_allocated_memory_ 3513 - amount_of_external_allocated_memory_at_last_global_gc_; 3514 } 3515 3516 3517 bool Heap::Setup(bool create_heap_objects) { 3518 // Initialize heap spaces and initial maps and objects. Whenever something 3519 // goes wrong, just return false. The caller should check the results and 3520 // call Heap::TearDown() to release allocated memory. 3521 // 3522 // If the heap is not yet configured (eg, through the API), configure it. 3523 // Configuration is based on the flags new-space-size (really the semispace 3524 // size) and old-space-size if set or the initial values of semispace_size_ 3525 // and old_generation_size_ otherwise. 3526 if (!heap_configured) { 3527 if (!ConfigureHeapDefault()) return false; 3528 } 3529 3530 // Setup memory allocator and reserve a chunk of memory for new 3531 // space. The chunk is double the size of the requested reserved 3532 // new space size to ensure that we can find a pair of semispaces that 3533 // are contiguous and aligned to their size. 3534 if (!MemoryAllocator::Setup(MaxReserved())) return false; 3535 void* chunk = 3536 MemoryAllocator::ReserveInitialChunk(4 * reserved_semispace_size_); 3537 if (chunk == NULL) return false; 3538 3539 // Align the pair of semispaces to their size, which must be a power 3540 // of 2. 3541 Address new_space_start = 3542 RoundUp(reinterpret_cast<byte*>(chunk), 2 * reserved_semispace_size_); 3543 if (!new_space_.Setup(new_space_start, 2 * reserved_semispace_size_)) { 3544 return false; 3545 } 3546 3547 // Initialize old pointer space. 3548 old_pointer_space_ = 3549 new OldSpace(max_old_generation_size_, OLD_POINTER_SPACE, NOT_EXECUTABLE); 3550 if (old_pointer_space_ == NULL) return false; 3551 if (!old_pointer_space_->Setup(NULL, 0)) return false; 3552 3553 // Initialize old data space. 3554 old_data_space_ = 3555 new OldSpace(max_old_generation_size_, OLD_DATA_SPACE, NOT_EXECUTABLE); 3556 if (old_data_space_ == NULL) return false; 3557 if (!old_data_space_->Setup(NULL, 0)) return false; 3558 3559 // Initialize the code space, set its maximum capacity to the old 3560 // generation size. It needs executable memory. 3561 // On 64-bit platform(s), we put all code objects in a 2 GB range of 3562 // virtual address space, so that they can call each other with near calls. 3563 if (code_range_size_ > 0) { 3564 if (!CodeRange::Setup(code_range_size_)) { 3565 return false; 3566 } 3567 } 3568 3569 code_space_ = 3570 new OldSpace(max_old_generation_size_, CODE_SPACE, EXECUTABLE); 3571 if (code_space_ == NULL) return false; 3572 if (!code_space_->Setup(NULL, 0)) return false; 3573 3574 // Initialize map space. 3575 map_space_ = new MapSpace(FLAG_use_big_map_space 3576 ? max_old_generation_size_ 3577 : MapSpace::kMaxMapPageIndex * Page::kPageSize, 3578 FLAG_max_map_space_pages, 3579 MAP_SPACE); 3580 if (map_space_ == NULL) return false; 3581 if (!map_space_->Setup(NULL, 0)) return false; 3582 3583 // Initialize global property cell space. 3584 cell_space_ = new CellSpace(max_old_generation_size_, CELL_SPACE); 3585 if (cell_space_ == NULL) return false; 3586 if (!cell_space_->Setup(NULL, 0)) return false; 3587 3588 // The large object code space may contain code or data. We set the memory 3589 // to be non-executable here for safety, but this means we need to enable it 3590 // explicitly when allocating large code objects. 3591 lo_space_ = new LargeObjectSpace(LO_SPACE); 3592 if (lo_space_ == NULL) return false; 3593 if (!lo_space_->Setup()) return false; 3594 3595 if (create_heap_objects) { 3596 // Create initial maps. 3597 if (!CreateInitialMaps()) return false; 3598 if (!CreateApiObjects()) return false; 3599 3600 // Create initial objects 3601 if (!CreateInitialObjects()) return false; 3602 } 3603 3604 LOG(IntEvent("heap-capacity", Capacity())); 3605 LOG(IntEvent("heap-available", Available())); 3606 3607 #ifdef ENABLE_LOGGING_AND_PROFILING 3608 // This should be called only after initial objects have been created. 3609 ProducerHeapProfile::Setup(); 3610 #endif 3611 3612 return true; 3613 } 3614 3615 3616 void Heap::SetStackLimits() { 3617 // On 64 bit machines, pointers are generally out of range of Smis. We write 3618 // something that looks like an out of range Smi to the GC. 3619 3620 // Set up the special root array entries containing the stack limits. 3621 // These are actually addresses, but the tag makes the GC ignore it. 3622 roots_[kStackLimitRootIndex] = 3623 reinterpret_cast<Object*>( 3624 (StackGuard::jslimit() & ~kSmiTagMask) | kSmiTag); 3625 roots_[kRealStackLimitRootIndex] = 3626 reinterpret_cast<Object*>( 3627 (StackGuard::real_jslimit() & ~kSmiTagMask) | kSmiTag); 3628 } 3629 3630 3631 void Heap::TearDown() { 3632 GlobalHandles::TearDown(); 3633 3634 ExternalStringTable::TearDown(); 3635 3636 new_space_.TearDown(); 3637 3638 if (old_pointer_space_ != NULL) { 3639 old_pointer_space_->TearDown(); 3640 delete old_pointer_space_; 3641 old_pointer_space_ = NULL; 3642 } 3643 3644 if (old_data_space_ != NULL) { 3645 old_data_space_->TearDown(); 3646 delete old_data_space_; 3647 old_data_space_ = NULL; 3648 } 3649 3650 if (code_space_ != NULL) { 3651 code_space_->TearDown(); 3652 delete code_space_; 3653 code_space_ = NULL; 3654 } 3655 3656 if (map_space_ != NULL) { 3657 map_space_->TearDown(); 3658 delete map_space_; 3659 map_space_ = NULL; 3660 } 3661 3662 if (cell_space_ != NULL) { 3663 cell_space_->TearDown(); 3664 delete cell_space_; 3665 cell_space_ = NULL; 3666 } 3667 3668 if (lo_space_ != NULL) { 3669 lo_space_->TearDown(); 3670 delete lo_space_; 3671 lo_space_ = NULL; 3672 } 3673 3674 MemoryAllocator::TearDown(); 3675 } 3676 3677 3678 void Heap::Shrink() { 3679 // Try to shrink all paged spaces. 3680 PagedSpaces spaces; 3681 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) 3682 space->Shrink(); 3683 } 3684 3685 3686 #ifdef ENABLE_HEAP_PROTECTION 3687 3688 void Heap::Protect() { 3689 if (HasBeenSetup()) { 3690 AllSpaces spaces; 3691 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) 3692 space->Protect(); 3693 } 3694 } 3695 3696 3697 void Heap::Unprotect() { 3698 if (HasBeenSetup()) { 3699 AllSpaces spaces; 3700 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) 3701 space->Unprotect(); 3702 } 3703 } 3704 3705 #endif 3706 3707 3708 #ifdef DEBUG 3709 3710 class PrintHandleVisitor: public ObjectVisitor { 3711 public: 3712 void VisitPointers(Object** start, Object** end) { 3713 for (Object** p = start; p < end; p++) 3714 PrintF(" handle %p to %p\n", p, *p); 3715 } 3716 }; 3717 3718 void Heap::PrintHandles() { 3719 PrintF("Handles:\n"); 3720 PrintHandleVisitor v; 3721 HandleScopeImplementer::Iterate(&v); 3722 } 3723 3724 #endif 3725 3726 3727 Space* AllSpaces::next() { 3728 switch (counter_++) { 3729 case NEW_SPACE: 3730 return Heap::new_space(); 3731 case OLD_POINTER_SPACE: 3732 return Heap::old_pointer_space(); 3733 case OLD_DATA_SPACE: 3734 return Heap::old_data_space(); 3735 case CODE_SPACE: 3736 return Heap::code_space(); 3737 case MAP_SPACE: 3738 return Heap::map_space(); 3739 case CELL_SPACE: 3740 return Heap::cell_space(); 3741 case LO_SPACE: 3742 return Heap::lo_space(); 3743 default: 3744 return NULL; 3745 } 3746 } 3747 3748 3749 PagedSpace* PagedSpaces::next() { 3750 switch (counter_++) { 3751 case OLD_POINTER_SPACE: 3752 return Heap::old_pointer_space(); 3753 case OLD_DATA_SPACE: 3754 return Heap::old_data_space(); 3755 case CODE_SPACE: 3756 return Heap::code_space(); 3757 case MAP_SPACE: 3758 return Heap::map_space(); 3759 case CELL_SPACE: 3760 return Heap::cell_space(); 3761 default: 3762 return NULL; 3763 } 3764 } 3765 3766 3767 3768 OldSpace* OldSpaces::next() { 3769 switch (counter_++) { 3770 case OLD_POINTER_SPACE: 3771 return Heap::old_pointer_space(); 3772 case OLD_DATA_SPACE: 3773 return Heap::old_data_space(); 3774 case CODE_SPACE: 3775 return Heap::code_space(); 3776 default: 3777 return NULL; 3778 } 3779 } 3780 3781 3782 SpaceIterator::SpaceIterator() : current_space_(FIRST_SPACE), iterator_(NULL) { 3783 } 3784 3785 3786 SpaceIterator::~SpaceIterator() { 3787 // Delete active iterator if any. 3788 delete iterator_; 3789 } 3790 3791 3792 bool SpaceIterator::has_next() { 3793 // Iterate until no more spaces. 3794 return current_space_ != LAST_SPACE; 3795 } 3796 3797 3798 ObjectIterator* SpaceIterator::next() { 3799 if (iterator_ != NULL) { 3800 delete iterator_; 3801 iterator_ = NULL; 3802 // Move to the next space 3803 current_space_++; 3804 if (current_space_ > LAST_SPACE) { 3805 return NULL; 3806 } 3807 } 3808 3809 // Return iterator for the new current space. 3810 return CreateIterator(); 3811 } 3812 3813 3814 // Create an iterator for the space to iterate. 3815 ObjectIterator* SpaceIterator::CreateIterator() { 3816 ASSERT(iterator_ == NULL); 3817 3818 switch (current_space_) { 3819 case NEW_SPACE: 3820 iterator_ = new SemiSpaceIterator(Heap::new_space()); 3821 break; 3822 case OLD_POINTER_SPACE: 3823 iterator_ = new HeapObjectIterator(Heap::old_pointer_space()); 3824 break; 3825 case OLD_DATA_SPACE: 3826 iterator_ = new HeapObjectIterator(Heap::old_data_space()); 3827 break; 3828 case CODE_SPACE: 3829 iterator_ = new HeapObjectIterator(Heap::code_space()); 3830 break; 3831 case MAP_SPACE: 3832 iterator_ = new HeapObjectIterator(Heap::map_space()); 3833 break; 3834 case CELL_SPACE: 3835 iterator_ = new HeapObjectIterator(Heap::cell_space()); 3836 break; 3837 case LO_SPACE: 3838 iterator_ = new LargeObjectIterator(Heap::lo_space()); 3839 break; 3840 } 3841 3842 // Return the newly allocated iterator; 3843 ASSERT(iterator_ != NULL); 3844 return iterator_; 3845 } 3846 3847 3848 HeapIterator::HeapIterator() { 3849 Init(); 3850 } 3851 3852 3853 HeapIterator::~HeapIterator() { 3854 Shutdown(); 3855 } 3856 3857 3858 void HeapIterator::Init() { 3859 // Start the iteration. 3860 space_iterator_ = new SpaceIterator(); 3861 object_iterator_ = space_iterator_->next(); 3862 } 3863 3864 3865 void HeapIterator::Shutdown() { 3866 // Make sure the last iterator is deallocated. 3867 delete space_iterator_; 3868 space_iterator_ = NULL; 3869 object_iterator_ = NULL; 3870 } 3871 3872 3873 HeapObject* HeapIterator::next() { 3874 // No iterator means we are done. 3875 if (object_iterator_ == NULL) return NULL; 3876 3877 if (HeapObject* obj = object_iterator_->next_object()) { 3878 // If the current iterator has more objects we are fine. 3879 return obj; 3880 } else { 3881 // Go though the spaces looking for one that has objects. 3882 while (space_iterator_->has_next()) { 3883 object_iterator_ = space_iterator_->next(); 3884 if (HeapObject* obj = object_iterator_->next_object()) { 3885 return obj; 3886 } 3887 } 3888 } 3889 // Done with the last space. 3890 object_iterator_ = NULL; 3891 return NULL; 3892 } 3893 3894 3895 void HeapIterator::reset() { 3896 // Restart the iterator. 3897 Shutdown(); 3898 Init(); 3899 } 3900 3901 3902 #ifdef DEBUG 3903 3904 static bool search_for_any_global; 3905 static Object* search_target; 3906 static bool found_target; 3907 static List<Object*> object_stack(20); 3908 3909 3910 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. 3911 static const int kMarkTag = 2; 3912 3913 static void MarkObjectRecursively(Object** p); 3914 class MarkObjectVisitor : public ObjectVisitor { 3915 public: 3916 void VisitPointers(Object** start, Object** end) { 3917 // Copy all HeapObject pointers in [start, end) 3918 for (Object** p = start; p < end; p++) { 3919 if ((*p)->IsHeapObject()) 3920 MarkObjectRecursively(p); 3921 } 3922 } 3923 }; 3924 3925 static MarkObjectVisitor mark_visitor; 3926 3927 static void MarkObjectRecursively(Object** p) { 3928 if (!(*p)->IsHeapObject()) return; 3929 3930 HeapObject* obj = HeapObject::cast(*p); 3931 3932 Object* map = obj->map(); 3933 3934 if (!map->IsHeapObject()) return; // visited before 3935 3936 if (found_target) return; // stop if target found 3937 object_stack.Add(obj); 3938 if ((search_for_any_global && obj->IsJSGlobalObject()) || 3939 (!search_for_any_global && (obj == search_target))) { 3940 found_target = true; 3941 return; 3942 } 3943 3944 // not visited yet 3945 Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map)); 3946 3947 Address map_addr = map_p->address(); 3948 3949 obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag)); 3950 3951 MarkObjectRecursively(&map); 3952 3953 obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p), 3954 &mark_visitor); 3955 3956 if (!found_target) // don't pop if found the target 3957 object_stack.RemoveLast(); 3958 } 3959 3960 3961 static void UnmarkObjectRecursively(Object** p); 3962 class UnmarkObjectVisitor : public ObjectVisitor { 3963 public: 3964 void VisitPointers(Object** start, Object** end) { 3965 // Copy all HeapObject pointers in [start, end) 3966 for (Object** p = start; p < end; p++) { 3967 if ((*p)->IsHeapObject()) 3968 UnmarkObjectRecursively(p); 3969 } 3970 } 3971 }; 3972 3973 static UnmarkObjectVisitor unmark_visitor; 3974 3975 static void UnmarkObjectRecursively(Object** p) { 3976 if (!(*p)->IsHeapObject()) return; 3977 3978 HeapObject* obj = HeapObject::cast(*p); 3979 3980 Object* map = obj->map(); 3981 3982 if (map->IsHeapObject()) return; // unmarked already 3983 3984 Address map_addr = reinterpret_cast<Address>(map); 3985 3986 map_addr -= kMarkTag; 3987 3988 ASSERT_TAG_ALIGNED(map_addr); 3989 3990 HeapObject* map_p = HeapObject::FromAddress(map_addr); 3991 3992 obj->set_map(reinterpret_cast<Map*>(map_p)); 3993 3994 UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p)); 3995 3996 obj->IterateBody(Map::cast(map_p)->instance_type(), 3997 obj->SizeFromMap(Map::cast(map_p)), 3998 &unmark_visitor); 3999 } 4000 4001 4002 static void MarkRootObjectRecursively(Object** root) { 4003 if (search_for_any_global) { 4004 ASSERT(search_target == NULL); 4005 } else { 4006 ASSERT(search_target->IsHeapObject()); 4007 } 4008 found_target = false; 4009 object_stack.Clear(); 4010 4011 MarkObjectRecursively(root); 4012 UnmarkObjectRecursively(root); 4013 4014 if (found_target) { 4015 PrintF("=====================================\n"); 4016 PrintF("==== Path to object ====\n"); 4017 PrintF("=====================================\n\n"); 4018 4019 ASSERT(!object_stack.is_empty()); 4020 for (int i = 0; i < object_stack.length(); i++) { 4021 if (i > 0) PrintF("\n |\n |\n V\n\n"); 4022 Object* obj = object_stack[i]; 4023 obj->Print(); 4024 } 4025 PrintF("=====================================\n"); 4026 } 4027 } 4028 4029 4030 // Helper class for visiting HeapObjects recursively. 4031 class MarkRootVisitor: public ObjectVisitor { 4032 public: 4033 void VisitPointers(Object** start, Object** end) { 4034 // Visit all HeapObject pointers in [start, end) 4035 for (Object** p = start; p < end; p++) { 4036 if ((*p)->IsHeapObject()) 4037 MarkRootObjectRecursively(p); 4038 } 4039 } 4040 }; 4041 4042 4043 // Triggers a depth-first traversal of reachable objects from roots 4044 // and finds a path to a specific heap object and prints it. 4045 void Heap::TracePathToObject(Object* target) { 4046 search_target = target; 4047 search_for_any_global = false; 4048 4049 MarkRootVisitor root_visitor; 4050 IterateRoots(&root_visitor, VISIT_ONLY_STRONG); 4051 } 4052 4053 4054 // Triggers a depth-first traversal of reachable objects from roots 4055 // and finds a path to any global object and prints it. Useful for 4056 // determining the source for leaks of global objects. 4057 void Heap::TracePathToGlobal() { 4058 search_target = NULL; 4059 search_for_any_global = true; 4060 4061 MarkRootVisitor root_visitor; 4062 IterateRoots(&root_visitor, VISIT_ONLY_STRONG); 4063 } 4064 #endif 4065 4066 4067 GCTracer::GCTracer() 4068 : start_time_(0.0), 4069 start_size_(0.0), 4070 gc_count_(0), 4071 full_gc_count_(0), 4072 is_compacting_(false), 4073 marked_count_(0) { 4074 // These two fields reflect the state of the previous full collection. 4075 // Set them before they are changed by the collector. 4076 previous_has_compacted_ = MarkCompactCollector::HasCompacted(); 4077 previous_marked_count_ = MarkCompactCollector::previous_marked_count(); 4078 if (!FLAG_trace_gc) return; 4079 start_time_ = OS::TimeCurrentMillis(); 4080 start_size_ = SizeOfHeapObjects(); 4081 } 4082 4083 4084 GCTracer::~GCTracer() { 4085 if (!FLAG_trace_gc) return; 4086 // Printf ONE line iff flag is set. 4087 PrintF("%s %.1f -> %.1f MB, %d ms.\n", 4088 CollectorString(), 4089 start_size_, SizeOfHeapObjects(), 4090 static_cast<int>(OS::TimeCurrentMillis() - start_time_)); 4091 4092 #if defined(ENABLE_LOGGING_AND_PROFILING) 4093 Heap::PrintShortHeapStatistics(); 4094 #endif 4095 } 4096 4097 4098 const char* GCTracer::CollectorString() { 4099 switch (collector_) { 4100 case SCAVENGER: 4101 return "Scavenge"; 4102 case MARK_COMPACTOR: 4103 return MarkCompactCollector::HasCompacted() ? "Mark-compact" 4104 : "Mark-sweep"; 4105 } 4106 return "Unknown GC"; 4107 } 4108 4109 4110 int KeyedLookupCache::Hash(Map* map, String* name) { 4111 // Uses only lower 32 bits if pointers are larger. 4112 uintptr_t addr_hash = 4113 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map)) >> kMapHashShift; 4114 return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask); 4115 } 4116 4117 4118 int KeyedLookupCache::Lookup(Map* map, String* name) { 4119 int index = Hash(map, name); 4120 Key& key = keys_[index]; 4121 if ((key.map == map) && key.name->Equals(name)) { 4122 return field_offsets_[index]; 4123 } 4124 return -1; 4125 } 4126 4127 4128 void KeyedLookupCache::Update(Map* map, String* name, int field_offset) { 4129 String* symbol; 4130 if (Heap::LookupSymbolIfExists(name, &symbol)) { 4131 int index = Hash(map, symbol); 4132 Key& key = keys_[index]; 4133 key.map = map; 4134 key.name = symbol; 4135 field_offsets_[index] = field_offset; 4136 } 4137 } 4138 4139 4140 void KeyedLookupCache::Clear() { 4141 for (int index = 0; index < kLength; index++) keys_[index].map = NULL; 4142 } 4143 4144 4145 KeyedLookupCache::Key KeyedLookupCache::keys_[KeyedLookupCache::kLength]; 4146 4147 4148 int KeyedLookupCache::field_offsets_[KeyedLookupCache::kLength]; 4149 4150 4151 void DescriptorLookupCache::Clear() { 4152 for (int index = 0; index < kLength; index++) keys_[index].array = NULL; 4153 } 4154 4155 4156 DescriptorLookupCache::Key 4157 DescriptorLookupCache::keys_[DescriptorLookupCache::kLength]; 4158 4159 int DescriptorLookupCache::results_[DescriptorLookupCache::kLength]; 4160 4161 4162 #ifdef DEBUG 4163 bool Heap::GarbageCollectionGreedyCheck() { 4164 ASSERT(FLAG_gc_greedy); 4165 if (Bootstrapper::IsActive()) return true; 4166 if (disallow_allocation_failure()) return true; 4167 return CollectGarbage(0, NEW_SPACE); 4168 } 4169 #endif 4170 4171 4172 TranscendentalCache::TranscendentalCache(TranscendentalCache::Type t) 4173 : type_(t) { 4174 uint32_t in0 = 0xffffffffu; // Bit-pattern for a NaN that isn't 4175 uint32_t in1 = 0xffffffffu; // generated by the FPU. 4176 for (int i = 0; i < kCacheSize; i++) { 4177 elements_[i].in[0] = in0; 4178 elements_[i].in[1] = in1; 4179 elements_[i].output = NULL; 4180 } 4181 } 4182 4183 4184 TranscendentalCache* TranscendentalCache::caches_[kNumberOfCaches]; 4185 4186 4187 void TranscendentalCache::Clear() { 4188 for (int i = 0; i < kNumberOfCaches; i++) { 4189 if (caches_[i] != NULL) { 4190 delete caches_[i]; 4191 caches_[i] = NULL; 4192 } 4193 } 4194 } 4195 4196 4197 void ExternalStringTable::CleanUp() { 4198 int last = 0; 4199 for (int i = 0; i < new_space_strings_.length(); ++i) { 4200 if (new_space_strings_[i] == Heap::raw_unchecked_null_value()) continue; 4201 if (Heap::InNewSpace(new_space_strings_[i])) { 4202 new_space_strings_[last++] = new_space_strings_[i]; 4203 } else { 4204 old_space_strings_.Add(new_space_strings_[i]); 4205 } 4206 } 4207 new_space_strings_.Rewind(last); 4208 last = 0; 4209 for (int i = 0; i < old_space_strings_.length(); ++i) { 4210 if (old_space_strings_[i] == Heap::raw_unchecked_null_value()) continue; 4211 ASSERT(!Heap::InNewSpace(old_space_strings_[i])); 4212 old_space_strings_[last++] = old_space_strings_[i]; 4213 } 4214 old_space_strings_.Rewind(last); 4215 Verify(); 4216 } 4217 4218 4219 void ExternalStringTable::TearDown() { 4220 new_space_strings_.Free(); 4221 old_space_strings_.Free(); 4222 } 4223 4224 4225 List<Object*> ExternalStringTable::new_space_strings_; 4226 List<Object*> ExternalStringTable::old_space_strings_; 4227 4228 } } // namespace v8::internal 4229