Home | History | Annotate | Download | only in src
      1 // Copyright 2011 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.h"
     34 #include "compilation-cache.h"
     35 #include "debug.h"
     36 #include "heap-profiler.h"
     37 #include "global-handles.h"
     38 #include "liveobjectlist-inl.h"
     39 #include "mark-compact.h"
     40 #include "natives.h"
     41 #include "objects-visiting.h"
     42 #include "runtime-profiler.h"
     43 #include "scanner-base.h"
     44 #include "scopeinfo.h"
     45 #include "snapshot.h"
     46 #include "v8threads.h"
     47 #include "vm-state-inl.h"
     48 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
     49 #include "regexp-macro-assembler.h"
     50 #include "arm/regexp-macro-assembler-arm.h"
     51 #endif
     52 #if V8_TARGET_ARCH_MIPS && !V8_INTERPRETED_REGEXP
     53 #include "regexp-macro-assembler.h"
     54 #include "mips/regexp-macro-assembler-mips.h"
     55 #endif
     56 
     57 namespace v8 {
     58 namespace internal {
     59 
     60 
     61 static const intptr_t kMinimumPromotionLimit = 2 * MB;
     62 static const intptr_t kMinimumAllocationLimit = 8 * MB;
     63 
     64 
     65 static Mutex* gc_initializer_mutex = OS::CreateMutex();
     66 
     67 
     68 Heap::Heap()
     69     : isolate_(NULL),
     70 // semispace_size_ should be a power of 2 and old_generation_size_ should be
     71 // a multiple of Page::kPageSize.
     72 #if defined(ANDROID)
     73       reserved_semispace_size_(2*MB),
     74       max_semispace_size_(2*MB),
     75       initial_semispace_size_(128*KB),
     76       max_old_generation_size_(192*MB),
     77       max_executable_size_(max_old_generation_size_),
     78       code_range_size_(0),
     79 #elif defined(V8_TARGET_ARCH_X64)
     80       reserved_semispace_size_(16*MB),
     81       max_semispace_size_(16*MB),
     82       initial_semispace_size_(1*MB),
     83       max_old_generation_size_(1*GB),
     84       max_executable_size_(256*MB),
     85       code_range_size_(512*MB),
     86 #else
     87       reserved_semispace_size_(8*MB),
     88       max_semispace_size_(8*MB),
     89       initial_semispace_size_(512*KB),
     90       max_old_generation_size_(512*MB),
     91       max_executable_size_(128*MB),
     92       code_range_size_(0),
     93 #endif
     94 // Variables set based on semispace_size_ and old_generation_size_ in
     95 // ConfigureHeap (survived_since_last_expansion_, external_allocation_limit_)
     96 // Will be 4 * reserved_semispace_size_ to ensure that young
     97 // generation can be aligned to its size.
     98       survived_since_last_expansion_(0),
     99       always_allocate_scope_depth_(0),
    100       linear_allocation_scope_depth_(0),
    101       contexts_disposed_(0),
    102       new_space_(this),
    103       old_pointer_space_(NULL),
    104       old_data_space_(NULL),
    105       code_space_(NULL),
    106       map_space_(NULL),
    107       cell_space_(NULL),
    108       lo_space_(NULL),
    109       gc_state_(NOT_IN_GC),
    110       mc_count_(0),
    111       ms_count_(0),
    112       gc_count_(0),
    113       unflattened_strings_length_(0),
    114 #ifdef DEBUG
    115       allocation_allowed_(true),
    116       allocation_timeout_(0),
    117       disallow_allocation_failure_(false),
    118       debug_utils_(NULL),
    119 #endif  // DEBUG
    120       old_gen_promotion_limit_(kMinimumPromotionLimit),
    121       old_gen_allocation_limit_(kMinimumAllocationLimit),
    122       external_allocation_limit_(0),
    123       amount_of_external_allocated_memory_(0),
    124       amount_of_external_allocated_memory_at_last_global_gc_(0),
    125       old_gen_exhausted_(false),
    126       hidden_symbol_(NULL),
    127       global_gc_prologue_callback_(NULL),
    128       global_gc_epilogue_callback_(NULL),
    129       gc_safe_size_of_old_object_(NULL),
    130       total_regexp_code_generated_(0),
    131       tracer_(NULL),
    132       young_survivors_after_last_gc_(0),
    133       high_survival_rate_period_length_(0),
    134       survival_rate_(0),
    135       previous_survival_rate_trend_(Heap::STABLE),
    136       survival_rate_trend_(Heap::STABLE),
    137       max_gc_pause_(0),
    138       max_alive_after_gc_(0),
    139       min_in_mutator_(kMaxInt),
    140       alive_after_last_gc_(0),
    141       last_gc_end_timestamp_(0.0),
    142       page_watermark_invalidated_mark_(1 << Page::WATERMARK_INVALIDATED),
    143       number_idle_notifications_(0),
    144       last_idle_notification_gc_count_(0),
    145       last_idle_notification_gc_count_init_(false),
    146       configured_(false),
    147       is_safe_to_read_maps_(true) {
    148   // Allow build-time customization of the max semispace size. Building
    149   // V8 with snapshots and a non-default max semispace size is much
    150   // easier if you can define it as part of the build environment.
    151 #if defined(V8_MAX_SEMISPACE_SIZE)
    152   max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE;
    153 #endif
    154 
    155   memset(roots_, 0, sizeof(roots_[0]) * kRootListLength);
    156   global_contexts_list_ = NULL;
    157   mark_compact_collector_.heap_ = this;
    158   external_string_table_.heap_ = this;
    159 }
    160 
    161 
    162 intptr_t Heap::Capacity() {
    163   if (!HasBeenSetup()) return 0;
    164 
    165   return new_space_.Capacity() +
    166       old_pointer_space_->Capacity() +
    167       old_data_space_->Capacity() +
    168       code_space_->Capacity() +
    169       map_space_->Capacity() +
    170       cell_space_->Capacity();
    171 }
    172 
    173 
    174 intptr_t Heap::CommittedMemory() {
    175   if (!HasBeenSetup()) return 0;
    176 
    177   return new_space_.CommittedMemory() +
    178       old_pointer_space_->CommittedMemory() +
    179       old_data_space_->CommittedMemory() +
    180       code_space_->CommittedMemory() +
    181       map_space_->CommittedMemory() +
    182       cell_space_->CommittedMemory() +
    183       lo_space_->Size();
    184 }
    185 
    186 intptr_t Heap::CommittedMemoryExecutable() {
    187   if (!HasBeenSetup()) return 0;
    188 
    189   return isolate()->memory_allocator()->SizeExecutable();
    190 }
    191 
    192 
    193 intptr_t Heap::Available() {
    194   if (!HasBeenSetup()) return 0;
    195 
    196   return new_space_.Available() +
    197       old_pointer_space_->Available() +
    198       old_data_space_->Available() +
    199       code_space_->Available() +
    200       map_space_->Available() +
    201       cell_space_->Available();
    202 }
    203 
    204 
    205 bool Heap::HasBeenSetup() {
    206   return old_pointer_space_ != NULL &&
    207          old_data_space_ != NULL &&
    208          code_space_ != NULL &&
    209          map_space_ != NULL &&
    210          cell_space_ != NULL &&
    211          lo_space_ != NULL;
    212 }
    213 
    214 
    215 int Heap::GcSafeSizeOfOldObject(HeapObject* object) {
    216   ASSERT(!HEAP->InNewSpace(object));  // Code only works for old objects.
    217   ASSERT(!HEAP->mark_compact_collector()->are_map_pointers_encoded());
    218   MapWord map_word = object->map_word();
    219   map_word.ClearMark();
    220   map_word.ClearOverflow();
    221   return object->SizeFromMap(map_word.ToMap());
    222 }
    223 
    224 
    225 int Heap::GcSafeSizeOfOldObjectWithEncodedMap(HeapObject* object) {
    226   ASSERT(!HEAP->InNewSpace(object));  // Code only works for old objects.
    227   ASSERT(HEAP->mark_compact_collector()->are_map_pointers_encoded());
    228   uint32_t marker = Memory::uint32_at(object->address());
    229   if (marker == MarkCompactCollector::kSingleFreeEncoding) {
    230     return kIntSize;
    231   } else if (marker == MarkCompactCollector::kMultiFreeEncoding) {
    232     return Memory::int_at(object->address() + kIntSize);
    233   } else {
    234     MapWord map_word = object->map_word();
    235     Address map_address = map_word.DecodeMapAddress(HEAP->map_space());
    236     Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_address));
    237     return object->SizeFromMap(map);
    238   }
    239 }
    240 
    241 
    242 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) {
    243   // Is global GC requested?
    244   if (space != NEW_SPACE || FLAG_gc_global) {
    245     isolate_->counters()->gc_compactor_caused_by_request()->Increment();
    246     return MARK_COMPACTOR;
    247   }
    248 
    249   // Is enough data promoted to justify a global GC?
    250   if (OldGenerationPromotionLimitReached()) {
    251     isolate_->counters()->gc_compactor_caused_by_promoted_data()->Increment();
    252     return MARK_COMPACTOR;
    253   }
    254 
    255   // Have allocation in OLD and LO failed?
    256   if (old_gen_exhausted_) {
    257     isolate_->counters()->
    258         gc_compactor_caused_by_oldspace_exhaustion()->Increment();
    259     return MARK_COMPACTOR;
    260   }
    261 
    262   // Is there enough space left in OLD to guarantee that a scavenge can
    263   // succeed?
    264   //
    265   // Note that MemoryAllocator->MaxAvailable() undercounts the memory available
    266   // for object promotion. It counts only the bytes that the memory
    267   // allocator has not yet allocated from the OS and assigned to any space,
    268   // and does not count available bytes already in the old space or code
    269   // space.  Undercounting is safe---we may get an unrequested full GC when
    270   // a scavenge would have succeeded.
    271   if (isolate_->memory_allocator()->MaxAvailable() <= new_space_.Size()) {
    272     isolate_->counters()->
    273         gc_compactor_caused_by_oldspace_exhaustion()->Increment();
    274     return MARK_COMPACTOR;
    275   }
    276 
    277   // Default
    278   return SCAVENGER;
    279 }
    280 
    281 
    282 // TODO(1238405): Combine the infrastructure for --heap-stats and
    283 // --log-gc to avoid the complicated preprocessor and flag testing.
    284 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
    285 void Heap::ReportStatisticsBeforeGC() {
    286   // Heap::ReportHeapStatistics will also log NewSpace statistics when
    287   // compiled with ENABLE_LOGGING_AND_PROFILING and --log-gc is set.  The
    288   // following logic is used to avoid double logging.
    289 #if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING)
    290   if (FLAG_heap_stats || FLAG_log_gc) new_space_.CollectStatistics();
    291   if (FLAG_heap_stats) {
    292     ReportHeapStatistics("Before GC");
    293   } else if (FLAG_log_gc) {
    294     new_space_.ReportStatistics();
    295   }
    296   if (FLAG_heap_stats || FLAG_log_gc) new_space_.ClearHistograms();
    297 #elif defined(DEBUG)
    298   if (FLAG_heap_stats) {
    299     new_space_.CollectStatistics();
    300     ReportHeapStatistics("Before GC");
    301     new_space_.ClearHistograms();
    302   }
    303 #elif defined(ENABLE_LOGGING_AND_PROFILING)
    304   if (FLAG_log_gc) {
    305     new_space_.CollectStatistics();
    306     new_space_.ReportStatistics();
    307     new_space_.ClearHistograms();
    308   }
    309 #endif
    310 }
    311 
    312 
    313 #if defined(ENABLE_LOGGING_AND_PROFILING)
    314 void Heap::PrintShortHeapStatistics() {
    315   if (!FLAG_trace_gc_verbose) return;
    316   PrintF("Memory allocator,   used: %8" V8_PTR_PREFIX "d"
    317              ", available: %8" V8_PTR_PREFIX "d\n",
    318          isolate_->memory_allocator()->Size(),
    319          isolate_->memory_allocator()->Available());
    320   PrintF("New space,          used: %8" V8_PTR_PREFIX "d"
    321              ", available: %8" V8_PTR_PREFIX "d\n",
    322          Heap::new_space_.Size(),
    323          new_space_.Available());
    324   PrintF("Old pointers,       used: %8" V8_PTR_PREFIX "d"
    325              ", available: %8" V8_PTR_PREFIX "d"
    326              ", waste: %8" V8_PTR_PREFIX "d\n",
    327          old_pointer_space_->Size(),
    328          old_pointer_space_->Available(),
    329          old_pointer_space_->Waste());
    330   PrintF("Old data space,     used: %8" V8_PTR_PREFIX "d"
    331              ", available: %8" V8_PTR_PREFIX "d"
    332              ", waste: %8" V8_PTR_PREFIX "d\n",
    333          old_data_space_->Size(),
    334          old_data_space_->Available(),
    335          old_data_space_->Waste());
    336   PrintF("Code space,         used: %8" V8_PTR_PREFIX "d"
    337              ", available: %8" V8_PTR_PREFIX "d"
    338              ", waste: %8" V8_PTR_PREFIX "d\n",
    339          code_space_->Size(),
    340          code_space_->Available(),
    341          code_space_->Waste());
    342   PrintF("Map space,          used: %8" V8_PTR_PREFIX "d"
    343              ", available: %8" V8_PTR_PREFIX "d"
    344              ", waste: %8" V8_PTR_PREFIX "d\n",
    345          map_space_->Size(),
    346          map_space_->Available(),
    347          map_space_->Waste());
    348   PrintF("Cell space,         used: %8" V8_PTR_PREFIX "d"
    349              ", available: %8" V8_PTR_PREFIX "d"
    350              ", waste: %8" V8_PTR_PREFIX "d\n",
    351          cell_space_->Size(),
    352          cell_space_->Available(),
    353          cell_space_->Waste());
    354   PrintF("Large object space, used: %8" V8_PTR_PREFIX "d"
    355              ", available: %8" V8_PTR_PREFIX "d\n",
    356          lo_space_->Size(),
    357          lo_space_->Available());
    358 }
    359 #endif
    360 
    361 
    362 // TODO(1238405): Combine the infrastructure for --heap-stats and
    363 // --log-gc to avoid the complicated preprocessor and flag testing.
    364 void Heap::ReportStatisticsAfterGC() {
    365   // Similar to the before GC, we use some complicated logic to ensure that
    366   // NewSpace statistics are logged exactly once when --log-gc is turned on.
    367 #if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING)
    368   if (FLAG_heap_stats) {
    369     new_space_.CollectStatistics();
    370     ReportHeapStatistics("After GC");
    371   } else if (FLAG_log_gc) {
    372     new_space_.ReportStatistics();
    373   }
    374 #elif defined(DEBUG)
    375   if (FLAG_heap_stats) ReportHeapStatistics("After GC");
    376 #elif defined(ENABLE_LOGGING_AND_PROFILING)
    377   if (FLAG_log_gc) new_space_.ReportStatistics();
    378 #endif
    379 }
    380 #endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
    381 
    382 
    383 void Heap::GarbageCollectionPrologue() {
    384   isolate_->transcendental_cache()->Clear();
    385   ClearJSFunctionResultCaches();
    386   gc_count_++;
    387   unflattened_strings_length_ = 0;
    388 #ifdef DEBUG
    389   ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
    390   allow_allocation(false);
    391 
    392   if (FLAG_verify_heap) {
    393     Verify();
    394   }
    395 
    396   if (FLAG_gc_verbose) Print();
    397 #endif
    398 
    399 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
    400   ReportStatisticsBeforeGC();
    401 #endif
    402 
    403   LiveObjectList::GCPrologue();
    404 }
    405 
    406 intptr_t Heap::SizeOfObjects() {
    407   intptr_t total = 0;
    408   AllSpaces spaces;
    409   for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
    410     total += space->SizeOfObjects();
    411   }
    412   return total;
    413 }
    414 
    415 void Heap::GarbageCollectionEpilogue() {
    416   LiveObjectList::GCEpilogue();
    417 #ifdef DEBUG
    418   allow_allocation(true);
    419   ZapFromSpace();
    420 
    421   if (FLAG_verify_heap) {
    422     Verify();
    423   }
    424 
    425   if (FLAG_print_global_handles) isolate_->global_handles()->Print();
    426   if (FLAG_print_handles) PrintHandles();
    427   if (FLAG_gc_verbose) Print();
    428   if (FLAG_code_stats) ReportCodeStatistics("After GC");
    429 #endif
    430 
    431   isolate_->counters()->alive_after_last_gc()->Set(
    432       static_cast<int>(SizeOfObjects()));
    433 
    434   isolate_->counters()->symbol_table_capacity()->Set(
    435       symbol_table()->Capacity());
    436   isolate_->counters()->number_of_symbols()->Set(
    437       symbol_table()->NumberOfElements());
    438 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
    439   ReportStatisticsAfterGC();
    440 #endif
    441 #ifdef ENABLE_DEBUGGER_SUPPORT
    442   isolate_->debug()->AfterGarbageCollection();
    443 #endif
    444 }
    445 
    446 
    447 void Heap::CollectAllGarbage(bool force_compaction) {
    448   // Since we are ignoring the return value, the exact choice of space does
    449   // not matter, so long as we do not specify NEW_SPACE, which would not
    450   // cause a full GC.
    451   mark_compact_collector_.SetForceCompaction(force_compaction);
    452   CollectGarbage(OLD_POINTER_SPACE);
    453   mark_compact_collector_.SetForceCompaction(false);
    454 }
    455 
    456 
    457 void Heap::CollectAllAvailableGarbage() {
    458   // Since we are ignoring the return value, the exact choice of space does
    459   // not matter, so long as we do not specify NEW_SPACE, which would not
    460   // cause a full GC.
    461   mark_compact_collector()->SetForceCompaction(true);
    462 
    463   // Major GC would invoke weak handle callbacks on weakly reachable
    464   // handles, but won't collect weakly reachable objects until next
    465   // major GC.  Therefore if we collect aggressively and weak handle callback
    466   // has been invoked, we rerun major GC to release objects which become
    467   // garbage.
    468   // Note: as weak callbacks can execute arbitrary code, we cannot
    469   // hope that eventually there will be no weak callbacks invocations.
    470   // Therefore stop recollecting after several attempts.
    471   const int kMaxNumberOfAttempts = 7;
    472   for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) {
    473     if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR)) {
    474       break;
    475     }
    476   }
    477   mark_compact_collector()->SetForceCompaction(false);
    478 }
    479 
    480 
    481 bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) {
    482   // The VM is in the GC state until exiting this function.
    483   VMState state(isolate_, GC);
    484 
    485 #ifdef DEBUG
    486   // Reset the allocation timeout to the GC interval, but make sure to
    487   // allow at least a few allocations after a collection. The reason
    488   // for this is that we have a lot of allocation sequences and we
    489   // assume that a garbage collection will allow the subsequent
    490   // allocation attempts to go through.
    491   allocation_timeout_ = Max(6, FLAG_gc_interval);
    492 #endif
    493 
    494   bool next_gc_likely_to_collect_more = false;
    495 
    496   { GCTracer tracer(this);
    497     GarbageCollectionPrologue();
    498     // The GC count was incremented in the prologue.  Tell the tracer about
    499     // it.
    500     tracer.set_gc_count(gc_count_);
    501 
    502     // Tell the tracer which collector we've selected.
    503     tracer.set_collector(collector);
    504 
    505     HistogramTimer* rate = (collector == SCAVENGER)
    506         ? isolate_->counters()->gc_scavenger()
    507         : isolate_->counters()->gc_compactor();
    508     rate->Start();
    509     next_gc_likely_to_collect_more =
    510         PerformGarbageCollection(collector, &tracer);
    511     rate->Stop();
    512 
    513     GarbageCollectionEpilogue();
    514   }
    515 
    516 
    517 #ifdef ENABLE_LOGGING_AND_PROFILING
    518   if (FLAG_log_gc) HeapProfiler::WriteSample();
    519 #endif
    520 
    521   return next_gc_likely_to_collect_more;
    522 }
    523 
    524 
    525 void Heap::PerformScavenge() {
    526   GCTracer tracer(this);
    527   PerformGarbageCollection(SCAVENGER, &tracer);
    528 }
    529 
    530 
    531 #ifdef DEBUG
    532 // Helper class for verifying the symbol table.
    533 class SymbolTableVerifier : public ObjectVisitor {
    534  public:
    535   void VisitPointers(Object** start, Object** end) {
    536     // Visit all HeapObject pointers in [start, end).
    537     for (Object** p = start; p < end; p++) {
    538       if ((*p)->IsHeapObject()) {
    539         // Check that the symbol is actually a symbol.
    540         ASSERT((*p)->IsNull() || (*p)->IsUndefined() || (*p)->IsSymbol());
    541       }
    542     }
    543   }
    544 };
    545 #endif  // DEBUG
    546 
    547 
    548 static void VerifySymbolTable() {
    549 #ifdef DEBUG
    550   SymbolTableVerifier verifier;
    551   HEAP->symbol_table()->IterateElements(&verifier);
    552 #endif  // DEBUG
    553 }
    554 
    555 
    556 void Heap::ReserveSpace(
    557     int new_space_size,
    558     int pointer_space_size,
    559     int data_space_size,
    560     int code_space_size,
    561     int map_space_size,
    562     int cell_space_size,
    563     int large_object_size) {
    564   NewSpace* new_space = Heap::new_space();
    565   PagedSpace* old_pointer_space = Heap::old_pointer_space();
    566   PagedSpace* old_data_space = Heap::old_data_space();
    567   PagedSpace* code_space = Heap::code_space();
    568   PagedSpace* map_space = Heap::map_space();
    569   PagedSpace* cell_space = Heap::cell_space();
    570   LargeObjectSpace* lo_space = Heap::lo_space();
    571   bool gc_performed = true;
    572   while (gc_performed) {
    573     gc_performed = false;
    574     if (!new_space->ReserveSpace(new_space_size)) {
    575       Heap::CollectGarbage(NEW_SPACE);
    576       gc_performed = true;
    577     }
    578     if (!old_pointer_space->ReserveSpace(pointer_space_size)) {
    579       Heap::CollectGarbage(OLD_POINTER_SPACE);
    580       gc_performed = true;
    581     }
    582     if (!(old_data_space->ReserveSpace(data_space_size))) {
    583       Heap::CollectGarbage(OLD_DATA_SPACE);
    584       gc_performed = true;
    585     }
    586     if (!(code_space->ReserveSpace(code_space_size))) {
    587       Heap::CollectGarbage(CODE_SPACE);
    588       gc_performed = true;
    589     }
    590     if (!(map_space->ReserveSpace(map_space_size))) {
    591       Heap::CollectGarbage(MAP_SPACE);
    592       gc_performed = true;
    593     }
    594     if (!(cell_space->ReserveSpace(cell_space_size))) {
    595       Heap::CollectGarbage(CELL_SPACE);
    596       gc_performed = true;
    597     }
    598     // We add a slack-factor of 2 in order to have space for a series of
    599     // large-object allocations that are only just larger than the page size.
    600     large_object_size *= 2;
    601     // The ReserveSpace method on the large object space checks how much
    602     // we can expand the old generation.  This includes expansion caused by
    603     // allocation in the other spaces.
    604     large_object_size += cell_space_size + map_space_size + code_space_size +
    605         data_space_size + pointer_space_size;
    606     if (!(lo_space->ReserveSpace(large_object_size))) {
    607       Heap::CollectGarbage(LO_SPACE);
    608       gc_performed = true;
    609     }
    610   }
    611 }
    612 
    613 
    614 void Heap::EnsureFromSpaceIsCommitted() {
    615   if (new_space_.CommitFromSpaceIfNeeded()) return;
    616 
    617   // Committing memory to from space failed.
    618   // Try shrinking and try again.
    619   PagedSpaces spaces;
    620   for (PagedSpace* space = spaces.next();
    621        space != NULL;
    622        space = spaces.next()) {
    623     space->RelinkPageListInChunkOrder(true);
    624   }
    625 
    626   Shrink();
    627   if (new_space_.CommitFromSpaceIfNeeded()) return;
    628 
    629   // Committing memory to from space failed again.
    630   // Memory is exhausted and we will die.
    631   V8::FatalProcessOutOfMemory("Committing semi space failed.");
    632 }
    633 
    634 
    635 void Heap::ClearJSFunctionResultCaches() {
    636   if (isolate_->bootstrapper()->IsActive()) return;
    637 
    638   Object* context = global_contexts_list_;
    639   while (!context->IsUndefined()) {
    640     // Get the caches for this context:
    641     FixedArray* caches =
    642       Context::cast(context)->jsfunction_result_caches();
    643     // Clear the caches:
    644     int length = caches->length();
    645     for (int i = 0; i < length; i++) {
    646       JSFunctionResultCache::cast(caches->get(i))->Clear();
    647     }
    648     // Get the next context:
    649     context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
    650   }
    651 }
    652 
    653 
    654 
    655 void Heap::ClearNormalizedMapCaches() {
    656   if (isolate_->bootstrapper()->IsActive()) return;
    657 
    658   Object* context = global_contexts_list_;
    659   while (!context->IsUndefined()) {
    660     Context::cast(context)->normalized_map_cache()->Clear();
    661     context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
    662   }
    663 }
    664 
    665 
    666 #ifdef DEBUG
    667 
    668 enum PageWatermarkValidity {
    669   ALL_VALID,
    670   ALL_INVALID
    671 };
    672 
    673 static void VerifyPageWatermarkValidity(PagedSpace* space,
    674                                         PageWatermarkValidity validity) {
    675   PageIterator it(space, PageIterator::PAGES_IN_USE);
    676   bool expected_value = (validity == ALL_VALID);
    677   while (it.has_next()) {
    678     Page* page = it.next();
    679     ASSERT(page->IsWatermarkValid() == expected_value);
    680   }
    681 }
    682 #endif
    683 
    684 void Heap::UpdateSurvivalRateTrend(int start_new_space_size) {
    685   double survival_rate =
    686       (static_cast<double>(young_survivors_after_last_gc_) * 100) /
    687       start_new_space_size;
    688 
    689   if (survival_rate > kYoungSurvivalRateThreshold) {
    690     high_survival_rate_period_length_++;
    691   } else {
    692     high_survival_rate_period_length_ = 0;
    693   }
    694 
    695   double survival_rate_diff = survival_rate_ - survival_rate;
    696 
    697   if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) {
    698     set_survival_rate_trend(DECREASING);
    699   } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) {
    700     set_survival_rate_trend(INCREASING);
    701   } else {
    702     set_survival_rate_trend(STABLE);
    703   }
    704 
    705   survival_rate_ = survival_rate;
    706 }
    707 
    708 bool Heap::PerformGarbageCollection(GarbageCollector collector,
    709                                     GCTracer* tracer) {
    710   bool next_gc_likely_to_collect_more = false;
    711 
    712   if (collector != SCAVENGER) {
    713     PROFILE(isolate_, CodeMovingGCEvent());
    714   }
    715 
    716   VerifySymbolTable();
    717   if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) {
    718     ASSERT(!allocation_allowed_);
    719     GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL);
    720     global_gc_prologue_callback_();
    721   }
    722 
    723   GCType gc_type =
    724       collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge;
    725 
    726   for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) {
    727     if (gc_type & gc_prologue_callbacks_[i].gc_type) {
    728       gc_prologue_callbacks_[i].callback(gc_type, kNoGCCallbackFlags);
    729     }
    730   }
    731 
    732   EnsureFromSpaceIsCommitted();
    733 
    734   int start_new_space_size = Heap::new_space()->SizeAsInt();
    735 
    736   if (collector == MARK_COMPACTOR) {
    737     // Perform mark-sweep with optional compaction.
    738     MarkCompact(tracer);
    739 
    740     bool high_survival_rate_during_scavenges = IsHighSurvivalRate() &&
    741         IsStableOrIncreasingSurvivalTrend();
    742 
    743     UpdateSurvivalRateTrend(start_new_space_size);
    744 
    745     intptr_t old_gen_size = PromotedSpaceSize();
    746     old_gen_promotion_limit_ =
    747         old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3);
    748     old_gen_allocation_limit_ =
    749         old_gen_size + Max(kMinimumAllocationLimit, old_gen_size / 2);
    750 
    751     if (high_survival_rate_during_scavenges &&
    752         IsStableOrIncreasingSurvivalTrend()) {
    753       // Stable high survival rates of young objects both during partial and
    754       // full collection indicate that mutator is either building or modifying
    755       // a structure with a long lifetime.
    756       // In this case we aggressively raise old generation memory limits to
    757       // postpone subsequent mark-sweep collection and thus trade memory
    758       // space for the mutation speed.
    759       old_gen_promotion_limit_ *= 2;
    760       old_gen_allocation_limit_ *= 2;
    761     }
    762 
    763     old_gen_exhausted_ = false;
    764   } else {
    765     tracer_ = tracer;
    766     Scavenge();
    767     tracer_ = NULL;
    768 
    769     UpdateSurvivalRateTrend(start_new_space_size);
    770   }
    771 
    772   isolate_->counters()->objs_since_last_young()->Set(0);
    773 
    774   if (collector == MARK_COMPACTOR) {
    775     DisableAssertNoAllocation allow_allocation;
    776     GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL);
    777     next_gc_likely_to_collect_more =
    778         isolate_->global_handles()->PostGarbageCollectionProcessing();
    779   }
    780 
    781   // Update relocatables.
    782   Relocatable::PostGarbageCollectionProcessing();
    783 
    784   if (collector == MARK_COMPACTOR) {
    785     // Register the amount of external allocated memory.
    786     amount_of_external_allocated_memory_at_last_global_gc_ =
    787         amount_of_external_allocated_memory_;
    788   }
    789 
    790   GCCallbackFlags callback_flags = tracer->is_compacting()
    791       ? kGCCallbackFlagCompacted
    792       : kNoGCCallbackFlags;
    793   for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
    794     if (gc_type & gc_epilogue_callbacks_[i].gc_type) {
    795       gc_epilogue_callbacks_[i].callback(gc_type, callback_flags);
    796     }
    797   }
    798 
    799   if (collector == MARK_COMPACTOR && global_gc_epilogue_callback_) {
    800     ASSERT(!allocation_allowed_);
    801     GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL);
    802     global_gc_epilogue_callback_();
    803   }
    804   VerifySymbolTable();
    805 
    806   return next_gc_likely_to_collect_more;
    807 }
    808 
    809 
    810 void Heap::MarkCompact(GCTracer* tracer) {
    811   gc_state_ = MARK_COMPACT;
    812   LOG(isolate_, ResourceEvent("markcompact", "begin"));
    813 
    814   mark_compact_collector_.Prepare(tracer);
    815 
    816   bool is_compacting = mark_compact_collector_.IsCompacting();
    817 
    818   if (is_compacting) {
    819     mc_count_++;
    820   } else {
    821     ms_count_++;
    822   }
    823   tracer->set_full_gc_count(mc_count_ + ms_count_);
    824 
    825   MarkCompactPrologue(is_compacting);
    826 
    827   is_safe_to_read_maps_ = false;
    828   mark_compact_collector_.CollectGarbage();
    829   is_safe_to_read_maps_ = true;
    830 
    831   LOG(isolate_, ResourceEvent("markcompact", "end"));
    832 
    833   gc_state_ = NOT_IN_GC;
    834 
    835   Shrink();
    836 
    837   isolate_->counters()->objs_since_last_full()->Set(0);
    838 
    839   contexts_disposed_ = 0;
    840 }
    841 
    842 
    843 void Heap::MarkCompactPrologue(bool is_compacting) {
    844   // At any old GC clear the keyed lookup cache to enable collection of unused
    845   // maps.
    846   isolate_->keyed_lookup_cache()->Clear();
    847   isolate_->context_slot_cache()->Clear();
    848   isolate_->descriptor_lookup_cache()->Clear();
    849 
    850   isolate_->compilation_cache()->MarkCompactPrologue();
    851 
    852   CompletelyClearInstanceofCache();
    853 
    854   if (is_compacting) FlushNumberStringCache();
    855 
    856   ClearNormalizedMapCaches();
    857 }
    858 
    859 
    860 Object* Heap::FindCodeObject(Address a) {
    861   Object* obj = NULL;  // Initialization to please compiler.
    862   { MaybeObject* maybe_obj = code_space_->FindObject(a);
    863     if (!maybe_obj->ToObject(&obj)) {
    864       obj = lo_space_->FindObject(a)->ToObjectUnchecked();
    865     }
    866   }
    867   return obj;
    868 }
    869 
    870 
    871 // Helper class for copying HeapObjects
    872 class ScavengeVisitor: public ObjectVisitor {
    873  public:
    874   explicit ScavengeVisitor(Heap* heap) : heap_(heap) {}
    875 
    876   void VisitPointer(Object** p) { ScavengePointer(p); }
    877 
    878   void VisitPointers(Object** start, Object** end) {
    879     // Copy all HeapObject pointers in [start, end)
    880     for (Object** p = start; p < end; p++) ScavengePointer(p);
    881   }
    882 
    883  private:
    884   void ScavengePointer(Object** p) {
    885     Object* object = *p;
    886     if (!heap_->InNewSpace(object)) return;
    887     Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
    888                          reinterpret_cast<HeapObject*>(object));
    889   }
    890 
    891   Heap* heap_;
    892 };
    893 
    894 
    895 #ifdef DEBUG
    896 // Visitor class to verify pointers in code or data space do not point into
    897 // new space.
    898 class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor {
    899  public:
    900   void VisitPointers(Object** start, Object**end) {
    901     for (Object** current = start; current < end; current++) {
    902       if ((*current)->IsHeapObject()) {
    903         ASSERT(!HEAP->InNewSpace(HeapObject::cast(*current)));
    904       }
    905     }
    906   }
    907 };
    908 
    909 
    910 static void VerifyNonPointerSpacePointers() {
    911   // Verify that there are no pointers to new space in spaces where we
    912   // do not expect them.
    913   VerifyNonPointerSpacePointersVisitor v;
    914   HeapObjectIterator code_it(HEAP->code_space());
    915   for (HeapObject* object = code_it.next();
    916        object != NULL; object = code_it.next())
    917     object->Iterate(&v);
    918 
    919   HeapObjectIterator data_it(HEAP->old_data_space());
    920   for (HeapObject* object = data_it.next();
    921        object != NULL; object = data_it.next())
    922     object->Iterate(&v);
    923 }
    924 #endif
    925 
    926 
    927 void Heap::CheckNewSpaceExpansionCriteria() {
    928   if (new_space_.Capacity() < new_space_.MaximumCapacity() &&
    929       survived_since_last_expansion_ > new_space_.Capacity()) {
    930     // Grow the size of new space if there is room to grow and enough
    931     // data has survived scavenge since the last expansion.
    932     new_space_.Grow();
    933     survived_since_last_expansion_ = 0;
    934   }
    935 }
    936 
    937 
    938 void Heap::Scavenge() {
    939 #ifdef DEBUG
    940   if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers();
    941 #endif
    942 
    943   gc_state_ = SCAVENGE;
    944 
    945   SwitchScavengingVisitorsTableIfProfilingWasEnabled();
    946 
    947   Page::FlipMeaningOfInvalidatedWatermarkFlag(this);
    948 #ifdef DEBUG
    949   VerifyPageWatermarkValidity(old_pointer_space_, ALL_VALID);
    950   VerifyPageWatermarkValidity(map_space_, ALL_VALID);
    951 #endif
    952 
    953   // We do not update an allocation watermark of the top page during linear
    954   // allocation to avoid overhead. So to maintain the watermark invariant
    955   // we have to manually cache the watermark and mark the top page as having an
    956   // invalid watermark. This guarantees that dirty regions iteration will use a
    957   // correct watermark even if a linear allocation happens.
    958   old_pointer_space_->FlushTopPageWatermark();
    959   map_space_->FlushTopPageWatermark();
    960 
    961   // Implements Cheney's copying algorithm
    962   LOG(isolate_, ResourceEvent("scavenge", "begin"));
    963 
    964   // Clear descriptor cache.
    965   isolate_->descriptor_lookup_cache()->Clear();
    966 
    967   // Used for updating survived_since_last_expansion_ at function end.
    968   intptr_t survived_watermark = PromotedSpaceSize();
    969 
    970   CheckNewSpaceExpansionCriteria();
    971 
    972   // Flip the semispaces.  After flipping, to space is empty, from space has
    973   // live objects.
    974   new_space_.Flip();
    975   new_space_.ResetAllocationInfo();
    976 
    977   // We need to sweep newly copied objects which can be either in the
    978   // to space or promoted to the old generation.  For to-space
    979   // objects, we treat the bottom of the to space as a queue.  Newly
    980   // copied and unswept objects lie between a 'front' mark and the
    981   // allocation pointer.
    982   //
    983   // Promoted objects can go into various old-generation spaces, and
    984   // can be allocated internally in the spaces (from the free list).
    985   // We treat the top of the to space as a queue of addresses of
    986   // promoted objects.  The addresses of newly promoted and unswept
    987   // objects lie between a 'front' mark and a 'rear' mark that is
    988   // updated as a side effect of promoting an object.
    989   //
    990   // There is guaranteed to be enough room at the top of the to space
    991   // for the addresses of promoted objects: every object promoted
    992   // frees up its size in bytes from the top of the new space, and
    993   // objects are at least one pointer in size.
    994   Address new_space_front = new_space_.ToSpaceLow();
    995   promotion_queue_.Initialize(new_space_.ToSpaceHigh());
    996 
    997   is_safe_to_read_maps_ = false;
    998   ScavengeVisitor scavenge_visitor(this);
    999   // Copy roots.
   1000   IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE);
   1001 
   1002   // Copy objects reachable from the old generation.  By definition,
   1003   // there are no intergenerational pointers in code or data spaces.
   1004   IterateDirtyRegions(old_pointer_space_,
   1005                       &Heap::IteratePointersInDirtyRegion,
   1006                       &ScavengePointer,
   1007                       WATERMARK_CAN_BE_INVALID);
   1008 
   1009   IterateDirtyRegions(map_space_,
   1010                       &IteratePointersInDirtyMapsRegion,
   1011                       &ScavengePointer,
   1012                       WATERMARK_CAN_BE_INVALID);
   1013 
   1014   lo_space_->IterateDirtyRegions(&ScavengePointer);
   1015 
   1016   // Copy objects reachable from cells by scavenging cell values directly.
   1017   HeapObjectIterator cell_iterator(cell_space_);
   1018   for (HeapObject* cell = cell_iterator.next();
   1019        cell != NULL; cell = cell_iterator.next()) {
   1020     if (cell->IsJSGlobalPropertyCell()) {
   1021       Address value_address =
   1022           reinterpret_cast<Address>(cell) +
   1023           (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag);
   1024       scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
   1025     }
   1026   }
   1027 
   1028   // Scavenge object reachable from the global contexts list directly.
   1029   scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_));
   1030 
   1031   new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
   1032 
   1033   UpdateNewSpaceReferencesInExternalStringTable(
   1034       &UpdateNewSpaceReferenceInExternalStringTableEntry);
   1035 
   1036   LiveObjectList::UpdateReferencesForScavengeGC();
   1037   isolate()->runtime_profiler()->UpdateSamplesAfterScavenge();
   1038 
   1039   ASSERT(new_space_front == new_space_.top());
   1040 
   1041   is_safe_to_read_maps_ = true;
   1042 
   1043   // Set age mark.
   1044   new_space_.set_age_mark(new_space_.top());
   1045 
   1046   // Update how much has survived scavenge.
   1047   IncrementYoungSurvivorsCounter(static_cast<int>(
   1048       (PromotedSpaceSize() - survived_watermark) + new_space_.Size()));
   1049 
   1050   LOG(isolate_, ResourceEvent("scavenge", "end"));
   1051 
   1052   gc_state_ = NOT_IN_GC;
   1053 }
   1054 
   1055 
   1056 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
   1057                                                                 Object** p) {
   1058   MapWord first_word = HeapObject::cast(*p)->map_word();
   1059 
   1060   if (!first_word.IsForwardingAddress()) {
   1061     // Unreachable external string can be finalized.
   1062     heap->FinalizeExternalString(String::cast(*p));
   1063     return NULL;
   1064   }
   1065 
   1066   // String is still reachable.
   1067   return String::cast(first_word.ToForwardingAddress());
   1068 }
   1069 
   1070 
   1071 void Heap::UpdateNewSpaceReferencesInExternalStringTable(
   1072     ExternalStringTableUpdaterCallback updater_func) {
   1073   external_string_table_.Verify();
   1074 
   1075   if (external_string_table_.new_space_strings_.is_empty()) return;
   1076 
   1077   Object** start = &external_string_table_.new_space_strings_[0];
   1078   Object** end = start + external_string_table_.new_space_strings_.length();
   1079   Object** last = start;
   1080 
   1081   for (Object** p = start; p < end; ++p) {
   1082     ASSERT(InFromSpace(*p));
   1083     String* target = updater_func(this, p);
   1084 
   1085     if (target == NULL) continue;
   1086 
   1087     ASSERT(target->IsExternalString());
   1088 
   1089     if (InNewSpace(target)) {
   1090       // String is still in new space.  Update the table entry.
   1091       *last = target;
   1092       ++last;
   1093     } else {
   1094       // String got promoted.  Move it to the old string list.
   1095       external_string_table_.AddOldString(target);
   1096     }
   1097   }
   1098 
   1099   ASSERT(last <= end);
   1100   external_string_table_.ShrinkNewStrings(static_cast<int>(last - start));
   1101 }
   1102 
   1103 
   1104 static Object* ProcessFunctionWeakReferences(Heap* heap,
   1105                                              Object* function,
   1106                                              WeakObjectRetainer* retainer) {
   1107   Object* head = heap->undefined_value();
   1108   JSFunction* tail = NULL;
   1109   Object* candidate = function;
   1110   while (candidate != heap->undefined_value()) {
   1111     // Check whether to keep the candidate in the list.
   1112     JSFunction* candidate_function = reinterpret_cast<JSFunction*>(candidate);
   1113     Object* retain = retainer->RetainAs(candidate);
   1114     if (retain != NULL) {
   1115       if (head == heap->undefined_value()) {
   1116         // First element in the list.
   1117         head = candidate_function;
   1118       } else {
   1119         // Subsequent elements in the list.
   1120         ASSERT(tail != NULL);
   1121         tail->set_next_function_link(candidate_function);
   1122       }
   1123       // Retained function is new tail.
   1124       tail = candidate_function;
   1125     }
   1126     // Move to next element in the list.
   1127     candidate = candidate_function->next_function_link();
   1128   }
   1129 
   1130   // Terminate the list if there is one or more elements.
   1131   if (tail != NULL) {
   1132     tail->set_next_function_link(heap->undefined_value());
   1133   }
   1134 
   1135   return head;
   1136 }
   1137 
   1138 
   1139 void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
   1140   Object* head = undefined_value();
   1141   Context* tail = NULL;
   1142   Object* candidate = global_contexts_list_;
   1143   while (candidate != undefined_value()) {
   1144     // Check whether to keep the candidate in the list.
   1145     Context* candidate_context = reinterpret_cast<Context*>(candidate);
   1146     Object* retain = retainer->RetainAs(candidate);
   1147     if (retain != NULL) {
   1148       if (head == undefined_value()) {
   1149         // First element in the list.
   1150         head = candidate_context;
   1151       } else {
   1152         // Subsequent elements in the list.
   1153         ASSERT(tail != NULL);
   1154         tail->set_unchecked(this,
   1155                             Context::NEXT_CONTEXT_LINK,
   1156                             candidate_context,
   1157                             UPDATE_WRITE_BARRIER);
   1158       }
   1159       // Retained context is new tail.
   1160       tail = candidate_context;
   1161 
   1162       // Process the weak list of optimized functions for the context.
   1163       Object* function_list_head =
   1164           ProcessFunctionWeakReferences(
   1165               this,
   1166               candidate_context->get(Context::OPTIMIZED_FUNCTIONS_LIST),
   1167               retainer);
   1168       candidate_context->set_unchecked(this,
   1169                                        Context::OPTIMIZED_FUNCTIONS_LIST,
   1170                                        function_list_head,
   1171                                        UPDATE_WRITE_BARRIER);
   1172     }
   1173     // Move to next element in the list.
   1174     candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK);
   1175   }
   1176 
   1177   // Terminate the list if there is one or more elements.
   1178   if (tail != NULL) {
   1179     tail->set_unchecked(this,
   1180                         Context::NEXT_CONTEXT_LINK,
   1181                         Heap::undefined_value(),
   1182                         UPDATE_WRITE_BARRIER);
   1183   }
   1184 
   1185   // Update the head of the list of contexts.
   1186   global_contexts_list_ = head;
   1187 }
   1188 
   1189 
   1190 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> {
   1191  public:
   1192   static inline void VisitPointer(Heap* heap, Object** p) {
   1193     Object* object = *p;
   1194     if (!heap->InNewSpace(object)) return;
   1195     Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
   1196                          reinterpret_cast<HeapObject*>(object));
   1197   }
   1198 };
   1199 
   1200 
   1201 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
   1202                          Address new_space_front) {
   1203   do {
   1204     ASSERT(new_space_front <= new_space_.top());
   1205 
   1206     // The addresses new_space_front and new_space_.top() define a
   1207     // queue of unprocessed copied objects.  Process them until the
   1208     // queue is empty.
   1209     while (new_space_front < new_space_.top()) {
   1210       HeapObject* object = HeapObject::FromAddress(new_space_front);
   1211       new_space_front += NewSpaceScavenger::IterateBody(object->map(), object);
   1212     }
   1213 
   1214     // Promote and process all the to-be-promoted objects.
   1215     while (!promotion_queue_.is_empty()) {
   1216       HeapObject* target;
   1217       int size;
   1218       promotion_queue_.remove(&target, &size);
   1219 
   1220       // Promoted object might be already partially visited
   1221       // during dirty regions iteration. Thus we search specificly
   1222       // for pointers to from semispace instead of looking for pointers
   1223       // to new space.
   1224       ASSERT(!target->IsMap());
   1225       IterateAndMarkPointersToFromSpace(target->address(),
   1226                                         target->address() + size,
   1227                                         &ScavengePointer);
   1228     }
   1229 
   1230     // Take another spin if there are now unswept objects in new space
   1231     // (there are currently no more unswept promoted objects).
   1232   } while (new_space_front < new_space_.top());
   1233 
   1234   return new_space_front;
   1235 }
   1236 
   1237 
   1238 enum LoggingAndProfiling {
   1239   LOGGING_AND_PROFILING_ENABLED,
   1240   LOGGING_AND_PROFILING_DISABLED
   1241 };
   1242 
   1243 
   1244 typedef void (*ScavengingCallback)(Map* map,
   1245                                    HeapObject** slot,
   1246                                    HeapObject* object);
   1247 
   1248 
   1249 static Atomic32 scavenging_visitors_table_mode_;
   1250 static VisitorDispatchTable<ScavengingCallback> scavenging_visitors_table_;
   1251 
   1252 
   1253 INLINE(static void DoScavengeObject(Map* map,
   1254                                     HeapObject** slot,
   1255                                     HeapObject* obj));
   1256 
   1257 
   1258 void DoScavengeObject(Map* map, HeapObject** slot, HeapObject* obj) {
   1259   scavenging_visitors_table_.GetVisitor(map)(map, slot, obj);
   1260 }
   1261 
   1262 
   1263 template<LoggingAndProfiling logging_and_profiling_mode>
   1264 class ScavengingVisitor : public StaticVisitorBase {
   1265  public:
   1266   static void Initialize() {
   1267     table_.Register(kVisitSeqAsciiString, &EvacuateSeqAsciiString);
   1268     table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString);
   1269     table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate);
   1270     table_.Register(kVisitByteArray, &EvacuateByteArray);
   1271     table_.Register(kVisitFixedArray, &EvacuateFixedArray);
   1272 
   1273     table_.Register(kVisitGlobalContext,
   1274                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1275                         template VisitSpecialized<Context::kSize>);
   1276 
   1277     table_.Register(kVisitConsString,
   1278                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1279                         template VisitSpecialized<ConsString::kSize>);
   1280 
   1281     table_.Register(kVisitSharedFunctionInfo,
   1282                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1283                         template VisitSpecialized<SharedFunctionInfo::kSize>);
   1284 
   1285     table_.Register(kVisitJSFunction,
   1286                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1287                         template VisitSpecialized<JSFunction::kSize>);
   1288 
   1289     table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>,
   1290                                    kVisitDataObject,
   1291                                    kVisitDataObjectGeneric>();
   1292 
   1293     table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
   1294                                    kVisitJSObject,
   1295                                    kVisitJSObjectGeneric>();
   1296 
   1297     table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
   1298                                    kVisitStruct,
   1299                                    kVisitStructGeneric>();
   1300   }
   1301 
   1302   static VisitorDispatchTable<ScavengingCallback>* GetTable() {
   1303     return &table_;
   1304   }
   1305 
   1306  private:
   1307   enum ObjectContents  { DATA_OBJECT, POINTER_OBJECT };
   1308   enum SizeRestriction { SMALL, UNKNOWN_SIZE };
   1309 
   1310 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
   1311   static void RecordCopiedObject(Heap* heap, HeapObject* obj) {
   1312     bool should_record = false;
   1313 #ifdef DEBUG
   1314     should_record = FLAG_heap_stats;
   1315 #endif
   1316 #ifdef ENABLE_LOGGING_AND_PROFILING
   1317     should_record = should_record || FLAG_log_gc;
   1318 #endif
   1319     if (should_record) {
   1320       if (heap->new_space()->Contains(obj)) {
   1321         heap->new_space()->RecordAllocation(obj);
   1322       } else {
   1323         heap->new_space()->RecordPromotion(obj);
   1324       }
   1325     }
   1326   }
   1327 #endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
   1328 
   1329   // Helper function used by CopyObject to copy a source object to an
   1330   // allocated target object and update the forwarding pointer in the source
   1331   // object.  Returns the target object.
   1332   INLINE(static HeapObject* MigrateObject(Heap* heap,
   1333                                           HeapObject* source,
   1334                                           HeapObject* target,
   1335                                           int size)) {
   1336     // Copy the content of source to target.
   1337     heap->CopyBlock(target->address(), source->address(), size);
   1338 
   1339     // Set the forwarding address.
   1340     source->set_map_word(MapWord::FromForwardingAddress(target));
   1341 
   1342     if (logging_and_profiling_mode == LOGGING_AND_PROFILING_ENABLED) {
   1343 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
   1344       // Update NewSpace stats if necessary.
   1345       RecordCopiedObject(heap, target);
   1346 #endif
   1347       HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address()));
   1348 #if defined(ENABLE_LOGGING_AND_PROFILING)
   1349       Isolate* isolate = heap->isolate();
   1350       if (isolate->logger()->is_logging() ||
   1351           isolate->cpu_profiler()->is_profiling()) {
   1352         if (target->IsSharedFunctionInfo()) {
   1353           PROFILE(isolate, SharedFunctionInfoMoveEvent(
   1354               source->address(), target->address()));
   1355         }
   1356       }
   1357 #endif
   1358     }
   1359 
   1360     return target;
   1361   }
   1362 
   1363 
   1364   template<ObjectContents object_contents, SizeRestriction size_restriction>
   1365   static inline void EvacuateObject(Map* map,
   1366                                     HeapObject** slot,
   1367                                     HeapObject* object,
   1368                                     int object_size) {
   1369     ASSERT((size_restriction != SMALL) ||
   1370            (object_size <= Page::kMaxHeapObjectSize));
   1371     ASSERT(object->Size() == object_size);
   1372 
   1373     Heap* heap = map->heap();
   1374     if (heap->ShouldBePromoted(object->address(), object_size)) {
   1375       MaybeObject* maybe_result;
   1376 
   1377       if ((size_restriction != SMALL) &&
   1378           (object_size > Page::kMaxHeapObjectSize)) {
   1379         maybe_result = heap->lo_space()->AllocateRawFixedArray(object_size);
   1380       } else {
   1381         if (object_contents == DATA_OBJECT) {
   1382           maybe_result = heap->old_data_space()->AllocateRaw(object_size);
   1383         } else {
   1384           maybe_result = heap->old_pointer_space()->AllocateRaw(object_size);
   1385         }
   1386       }
   1387 
   1388       Object* result = NULL;  // Initialization to please compiler.
   1389       if (maybe_result->ToObject(&result)) {
   1390         HeapObject* target = HeapObject::cast(result);
   1391         *slot = MigrateObject(heap, object , target, object_size);
   1392 
   1393         if (object_contents == POINTER_OBJECT) {
   1394           heap->promotion_queue()->insert(target, object_size);
   1395         }
   1396 
   1397         heap->tracer()->increment_promoted_objects_size(object_size);
   1398         return;
   1399       }
   1400     }
   1401     Object* result =
   1402         heap->new_space()->AllocateRaw(object_size)->ToObjectUnchecked();
   1403     *slot = MigrateObject(heap, object, HeapObject::cast(result), object_size);
   1404     return;
   1405   }
   1406 
   1407 
   1408   static inline void EvacuateFixedArray(Map* map,
   1409                                         HeapObject** slot,
   1410                                         HeapObject* object) {
   1411     int object_size = FixedArray::BodyDescriptor::SizeOf(map, object);
   1412     EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map,
   1413                                                  slot,
   1414                                                  object,
   1415                                                  object_size);
   1416   }
   1417 
   1418 
   1419   static inline void EvacuateByteArray(Map* map,
   1420                                        HeapObject** slot,
   1421                                        HeapObject* object) {
   1422     int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize();
   1423     EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
   1424   }
   1425 
   1426 
   1427   static inline void EvacuateSeqAsciiString(Map* map,
   1428                                             HeapObject** slot,
   1429                                             HeapObject* object) {
   1430     int object_size = SeqAsciiString::cast(object)->
   1431         SeqAsciiStringSize(map->instance_type());
   1432     EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
   1433   }
   1434 
   1435 
   1436   static inline void EvacuateSeqTwoByteString(Map* map,
   1437                                               HeapObject** slot,
   1438                                               HeapObject* object) {
   1439     int object_size = SeqTwoByteString::cast(object)->
   1440         SeqTwoByteStringSize(map->instance_type());
   1441     EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
   1442   }
   1443 
   1444 
   1445   static inline bool IsShortcutCandidate(int type) {
   1446     return ((type & kShortcutTypeMask) == kShortcutTypeTag);
   1447   }
   1448 
   1449   static inline void EvacuateShortcutCandidate(Map* map,
   1450                                                HeapObject** slot,
   1451                                                HeapObject* object) {
   1452     ASSERT(IsShortcutCandidate(map->instance_type()));
   1453 
   1454     if (ConsString::cast(object)->unchecked_second() ==
   1455         map->heap()->empty_string()) {
   1456       HeapObject* first =
   1457           HeapObject::cast(ConsString::cast(object)->unchecked_first());
   1458 
   1459       *slot = first;
   1460 
   1461       if (!map->heap()->InNewSpace(first)) {
   1462         object->set_map_word(MapWord::FromForwardingAddress(first));
   1463         return;
   1464       }
   1465 
   1466       MapWord first_word = first->map_word();
   1467       if (first_word.IsForwardingAddress()) {
   1468         HeapObject* target = first_word.ToForwardingAddress();
   1469 
   1470         *slot = target;
   1471         object->set_map_word(MapWord::FromForwardingAddress(target));
   1472         return;
   1473       }
   1474 
   1475       DoScavengeObject(first->map(), slot, first);
   1476       object->set_map_word(MapWord::FromForwardingAddress(*slot));
   1477       return;
   1478     }
   1479 
   1480     int object_size = ConsString::kSize;
   1481     EvacuateObject<POINTER_OBJECT, SMALL>(map, slot, object, object_size);
   1482   }
   1483 
   1484   template<ObjectContents object_contents>
   1485   class ObjectEvacuationStrategy {
   1486    public:
   1487     template<int object_size>
   1488     static inline void VisitSpecialized(Map* map,
   1489                                         HeapObject** slot,
   1490                                         HeapObject* object) {
   1491       EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
   1492     }
   1493 
   1494     static inline void Visit(Map* map,
   1495                              HeapObject** slot,
   1496                              HeapObject* object) {
   1497       int object_size = map->instance_size();
   1498       EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
   1499     }
   1500   };
   1501 
   1502   static VisitorDispatchTable<ScavengingCallback> table_;
   1503 };
   1504 
   1505 
   1506 template<LoggingAndProfiling logging_and_profiling_mode>
   1507 VisitorDispatchTable<ScavengingCallback>
   1508     ScavengingVisitor<logging_and_profiling_mode>::table_;
   1509 
   1510 
   1511 static void InitializeScavengingVisitorsTables() {
   1512   ScavengingVisitor<LOGGING_AND_PROFILING_DISABLED>::Initialize();
   1513   ScavengingVisitor<LOGGING_AND_PROFILING_ENABLED>::Initialize();
   1514   scavenging_visitors_table_.CopyFrom(
   1515       ScavengingVisitor<LOGGING_AND_PROFILING_DISABLED>::GetTable());
   1516   scavenging_visitors_table_mode_ = LOGGING_AND_PROFILING_DISABLED;
   1517 }
   1518 
   1519 
   1520 void Heap::SwitchScavengingVisitorsTableIfProfilingWasEnabled() {
   1521   if (scavenging_visitors_table_mode_ == LOGGING_AND_PROFILING_ENABLED) {
   1522     // Table was already updated by some isolate.
   1523     return;
   1524   }
   1525 
   1526   if (isolate()->logger()->is_logging() ||
   1527       isolate()->cpu_profiler()->is_profiling() ||
   1528       (isolate()->heap_profiler() != NULL &&
   1529        isolate()->heap_profiler()->is_profiling())) {
   1530     // If one of the isolates is doing scavenge at this moment of time
   1531     // it might see this table in an inconsitent state when
   1532     // some of the callbacks point to
   1533     // ScavengingVisitor<LOGGING_AND_PROFILING_ENABLED> and others
   1534     // to ScavengingVisitor<LOGGING_AND_PROFILING_DISABLED>.
   1535     // However this does not lead to any bugs as such isolate does not have
   1536     // profiling enabled and any isolate with enabled profiling is guaranteed
   1537     // to see the table in the consistent state.
   1538     scavenging_visitors_table_.CopyFrom(
   1539         ScavengingVisitor<LOGGING_AND_PROFILING_ENABLED>::GetTable());
   1540 
   1541     // We use Release_Store to prevent reordering of this write before writes
   1542     // to the table.
   1543     Release_Store(&scavenging_visitors_table_mode_,
   1544                   LOGGING_AND_PROFILING_ENABLED);
   1545   }
   1546 }
   1547 
   1548 
   1549 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
   1550   ASSERT(HEAP->InFromSpace(object));
   1551   MapWord first_word = object->map_word();
   1552   ASSERT(!first_word.IsForwardingAddress());
   1553   Map* map = first_word.ToMap();
   1554   DoScavengeObject(map, p, object);
   1555 }
   1556 
   1557 
   1558 MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type,
   1559                                       int instance_size) {
   1560   Object* result;
   1561   { MaybeObject* maybe_result = AllocateRawMap();
   1562     if (!maybe_result->ToObject(&result)) return maybe_result;
   1563   }
   1564 
   1565   // Map::cast cannot be used due to uninitialized map field.
   1566   reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map());
   1567   reinterpret_cast<Map*>(result)->set_instance_type(instance_type);
   1568   reinterpret_cast<Map*>(result)->set_instance_size(instance_size);
   1569   reinterpret_cast<Map*>(result)->set_visitor_id(
   1570         StaticVisitorBase::GetVisitorId(instance_type, instance_size));
   1571   reinterpret_cast<Map*>(result)->set_inobject_properties(0);
   1572   reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0);
   1573   reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
   1574   reinterpret_cast<Map*>(result)->set_bit_field(0);
   1575   reinterpret_cast<Map*>(result)->set_bit_field2(0);
   1576   return result;
   1577 }
   1578 
   1579 
   1580 MaybeObject* Heap::AllocateMap(InstanceType instance_type, int instance_size) {
   1581   Object* result;
   1582   { MaybeObject* maybe_result = AllocateRawMap();
   1583     if (!maybe_result->ToObject(&result)) return maybe_result;
   1584   }
   1585 
   1586   Map* map = reinterpret_cast<Map*>(result);
   1587   map->set_map(meta_map());
   1588   map->set_instance_type(instance_type);
   1589   map->set_visitor_id(
   1590       StaticVisitorBase::GetVisitorId(instance_type, instance_size));
   1591   map->set_prototype(null_value());
   1592   map->set_constructor(null_value());
   1593   map->set_instance_size(instance_size);
   1594   map->set_inobject_properties(0);
   1595   map->set_pre_allocated_property_fields(0);
   1596   map->set_instance_descriptors(empty_descriptor_array());
   1597   map->set_code_cache(empty_fixed_array());
   1598   map->set_prototype_transitions(empty_fixed_array());
   1599   map->set_unused_property_fields(0);
   1600   map->set_bit_field(0);
   1601   map->set_bit_field2((1 << Map::kIsExtensible) | (1 << Map::kHasFastElements));
   1602 
   1603   // If the map object is aligned fill the padding area with Smi 0 objects.
   1604   if (Map::kPadStart < Map::kSize) {
   1605     memset(reinterpret_cast<byte*>(map) + Map::kPadStart - kHeapObjectTag,
   1606            0,
   1607            Map::kSize - Map::kPadStart);
   1608   }
   1609   return map;
   1610 }
   1611 
   1612 
   1613 MaybeObject* Heap::AllocateCodeCache() {
   1614   Object* result;
   1615   { MaybeObject* maybe_result = AllocateStruct(CODE_CACHE_TYPE);
   1616     if (!maybe_result->ToObject(&result)) return maybe_result;
   1617   }
   1618   CodeCache* code_cache = CodeCache::cast(result);
   1619   code_cache->set_default_cache(empty_fixed_array());
   1620   code_cache->set_normal_type_cache(undefined_value());
   1621   return code_cache;
   1622 }
   1623 
   1624 
   1625 const Heap::StringTypeTable Heap::string_type_table[] = {
   1626 #define STRING_TYPE_ELEMENT(type, size, name, camel_name)                      \
   1627   {type, size, k##camel_name##MapRootIndex},
   1628   STRING_TYPE_LIST(STRING_TYPE_ELEMENT)
   1629 #undef STRING_TYPE_ELEMENT
   1630 };
   1631 
   1632 
   1633 const Heap::ConstantSymbolTable Heap::constant_symbol_table[] = {
   1634 #define CONSTANT_SYMBOL_ELEMENT(name, contents)                                \
   1635   {contents, k##name##RootIndex},
   1636   SYMBOL_LIST(CONSTANT_SYMBOL_ELEMENT)
   1637 #undef CONSTANT_SYMBOL_ELEMENT
   1638 };
   1639 
   1640 
   1641 const Heap::StructTable Heap::struct_table[] = {
   1642 #define STRUCT_TABLE_ELEMENT(NAME, Name, name)                                 \
   1643   { NAME##_TYPE, Name::kSize, k##Name##MapRootIndex },
   1644   STRUCT_LIST(STRUCT_TABLE_ELEMENT)
   1645 #undef STRUCT_TABLE_ELEMENT
   1646 };
   1647 
   1648 
   1649 bool Heap::CreateInitialMaps() {
   1650   Object* obj;
   1651   { MaybeObject* maybe_obj = AllocatePartialMap(MAP_TYPE, Map::kSize);
   1652     if (!maybe_obj->ToObject(&obj)) return false;
   1653   }
   1654   // Map::cast cannot be used due to uninitialized map field.
   1655   Map* new_meta_map = reinterpret_cast<Map*>(obj);
   1656   set_meta_map(new_meta_map);
   1657   new_meta_map->set_map(new_meta_map);
   1658 
   1659   { MaybeObject* maybe_obj =
   1660         AllocatePartialMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   1661     if (!maybe_obj->ToObject(&obj)) return false;
   1662   }
   1663   set_fixed_array_map(Map::cast(obj));
   1664 
   1665   { MaybeObject* maybe_obj = AllocatePartialMap(ODDBALL_TYPE, Oddball::kSize);
   1666     if (!maybe_obj->ToObject(&obj)) return false;
   1667   }
   1668   set_oddball_map(Map::cast(obj));
   1669 
   1670   // Allocate the empty array.
   1671   { MaybeObject* maybe_obj = AllocateEmptyFixedArray();
   1672     if (!maybe_obj->ToObject(&obj)) return false;
   1673   }
   1674   set_empty_fixed_array(FixedArray::cast(obj));
   1675 
   1676   { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_DATA_SPACE);
   1677     if (!maybe_obj->ToObject(&obj)) return false;
   1678   }
   1679   set_null_value(obj);
   1680   Oddball::cast(obj)->set_kind(Oddball::kNull);
   1681 
   1682   // Allocate the empty descriptor array.
   1683   { MaybeObject* maybe_obj = AllocateEmptyFixedArray();
   1684     if (!maybe_obj->ToObject(&obj)) return false;
   1685   }
   1686   set_empty_descriptor_array(DescriptorArray::cast(obj));
   1687 
   1688   // Fix the instance_descriptors for the existing maps.
   1689   meta_map()->set_instance_descriptors(empty_descriptor_array());
   1690   meta_map()->set_code_cache(empty_fixed_array());
   1691   meta_map()->set_prototype_transitions(empty_fixed_array());
   1692 
   1693   fixed_array_map()->set_instance_descriptors(empty_descriptor_array());
   1694   fixed_array_map()->set_code_cache(empty_fixed_array());
   1695   fixed_array_map()->set_prototype_transitions(empty_fixed_array());
   1696 
   1697   oddball_map()->set_instance_descriptors(empty_descriptor_array());
   1698   oddball_map()->set_code_cache(empty_fixed_array());
   1699   oddball_map()->set_prototype_transitions(empty_fixed_array());
   1700 
   1701   // Fix prototype object for existing maps.
   1702   meta_map()->set_prototype(null_value());
   1703   meta_map()->set_constructor(null_value());
   1704 
   1705   fixed_array_map()->set_prototype(null_value());
   1706   fixed_array_map()->set_constructor(null_value());
   1707 
   1708   oddball_map()->set_prototype(null_value());
   1709   oddball_map()->set_constructor(null_value());
   1710 
   1711   { MaybeObject* maybe_obj =
   1712         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   1713     if (!maybe_obj->ToObject(&obj)) return false;
   1714   }
   1715   set_fixed_cow_array_map(Map::cast(obj));
   1716   ASSERT(fixed_array_map() != fixed_cow_array_map());
   1717 
   1718   { MaybeObject* maybe_obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize);
   1719     if (!maybe_obj->ToObject(&obj)) return false;
   1720   }
   1721   set_heap_number_map(Map::cast(obj));
   1722 
   1723   { MaybeObject* maybe_obj = AllocateMap(PROXY_TYPE, Proxy::kSize);
   1724     if (!maybe_obj->ToObject(&obj)) return false;
   1725   }
   1726   set_proxy_map(Map::cast(obj));
   1727 
   1728   for (unsigned i = 0; i < ARRAY_SIZE(string_type_table); i++) {
   1729     const StringTypeTable& entry = string_type_table[i];
   1730     { MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size);
   1731       if (!maybe_obj->ToObject(&obj)) return false;
   1732     }
   1733     roots_[entry.index] = Map::cast(obj);
   1734   }
   1735 
   1736   { MaybeObject* maybe_obj = AllocateMap(STRING_TYPE, kVariableSizeSentinel);
   1737     if (!maybe_obj->ToObject(&obj)) return false;
   1738   }
   1739   set_undetectable_string_map(Map::cast(obj));
   1740   Map::cast(obj)->set_is_undetectable();
   1741 
   1742   { MaybeObject* maybe_obj =
   1743         AllocateMap(ASCII_STRING_TYPE, kVariableSizeSentinel);
   1744     if (!maybe_obj->ToObject(&obj)) return false;
   1745   }
   1746   set_undetectable_ascii_string_map(Map::cast(obj));
   1747   Map::cast(obj)->set_is_undetectable();
   1748 
   1749   { MaybeObject* maybe_obj =
   1750         AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel);
   1751     if (!maybe_obj->ToObject(&obj)) return false;
   1752   }
   1753   set_byte_array_map(Map::cast(obj));
   1754 
   1755   { MaybeObject* maybe_obj = AllocateByteArray(0, TENURED);
   1756     if (!maybe_obj->ToObject(&obj)) return false;
   1757   }
   1758   set_empty_byte_array(ByteArray::cast(obj));
   1759 
   1760   { MaybeObject* maybe_obj =
   1761         AllocateMap(EXTERNAL_PIXEL_ARRAY_TYPE, ExternalArray::kAlignedSize);
   1762     if (!maybe_obj->ToObject(&obj)) return false;
   1763   }
   1764   set_external_pixel_array_map(Map::cast(obj));
   1765 
   1766   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE,
   1767                                          ExternalArray::kAlignedSize);
   1768     if (!maybe_obj->ToObject(&obj)) return false;
   1769   }
   1770   set_external_byte_array_map(Map::cast(obj));
   1771 
   1772   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
   1773                                          ExternalArray::kAlignedSize);
   1774     if (!maybe_obj->ToObject(&obj)) return false;
   1775   }
   1776   set_external_unsigned_byte_array_map(Map::cast(obj));
   1777 
   1778   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_SHORT_ARRAY_TYPE,
   1779                                          ExternalArray::kAlignedSize);
   1780     if (!maybe_obj->ToObject(&obj)) return false;
   1781   }
   1782   set_external_short_array_map(Map::cast(obj));
   1783 
   1784   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
   1785                                          ExternalArray::kAlignedSize);
   1786     if (!maybe_obj->ToObject(&obj)) return false;
   1787   }
   1788   set_external_unsigned_short_array_map(Map::cast(obj));
   1789 
   1790   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_INT_ARRAY_TYPE,
   1791                                          ExternalArray::kAlignedSize);
   1792     if (!maybe_obj->ToObject(&obj)) return false;
   1793   }
   1794   set_external_int_array_map(Map::cast(obj));
   1795 
   1796   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
   1797                                          ExternalArray::kAlignedSize);
   1798     if (!maybe_obj->ToObject(&obj)) return false;
   1799   }
   1800   set_external_unsigned_int_array_map(Map::cast(obj));
   1801 
   1802   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_FLOAT_ARRAY_TYPE,
   1803                                          ExternalArray::kAlignedSize);
   1804     if (!maybe_obj->ToObject(&obj)) return false;
   1805   }
   1806   set_external_float_array_map(Map::cast(obj));
   1807 
   1808   { MaybeObject* maybe_obj = AllocateMap(CODE_TYPE, kVariableSizeSentinel);
   1809     if (!maybe_obj->ToObject(&obj)) return false;
   1810   }
   1811   set_code_map(Map::cast(obj));
   1812 
   1813   { MaybeObject* maybe_obj = AllocateMap(JS_GLOBAL_PROPERTY_CELL_TYPE,
   1814                                          JSGlobalPropertyCell::kSize);
   1815     if (!maybe_obj->ToObject(&obj)) return false;
   1816   }
   1817   set_global_property_cell_map(Map::cast(obj));
   1818 
   1819   { MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, kPointerSize);
   1820     if (!maybe_obj->ToObject(&obj)) return false;
   1821   }
   1822   set_one_pointer_filler_map(Map::cast(obj));
   1823 
   1824   { MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, 2 * kPointerSize);
   1825     if (!maybe_obj->ToObject(&obj)) return false;
   1826   }
   1827   set_two_pointer_filler_map(Map::cast(obj));
   1828 
   1829   for (unsigned i = 0; i < ARRAY_SIZE(struct_table); i++) {
   1830     const StructTable& entry = struct_table[i];
   1831     { MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size);
   1832       if (!maybe_obj->ToObject(&obj)) return false;
   1833     }
   1834     roots_[entry.index] = Map::cast(obj);
   1835   }
   1836 
   1837   { MaybeObject* maybe_obj =
   1838         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   1839     if (!maybe_obj->ToObject(&obj)) return false;
   1840   }
   1841   set_hash_table_map(Map::cast(obj));
   1842 
   1843   { MaybeObject* maybe_obj =
   1844         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   1845     if (!maybe_obj->ToObject(&obj)) return false;
   1846   }
   1847   set_context_map(Map::cast(obj));
   1848 
   1849   { MaybeObject* maybe_obj =
   1850         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   1851     if (!maybe_obj->ToObject(&obj)) return false;
   1852   }
   1853   set_catch_context_map(Map::cast(obj));
   1854 
   1855   { MaybeObject* maybe_obj =
   1856         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   1857     if (!maybe_obj->ToObject(&obj)) return false;
   1858   }
   1859   Map* global_context_map = Map::cast(obj);
   1860   global_context_map->set_visitor_id(StaticVisitorBase::kVisitGlobalContext);
   1861   set_global_context_map(global_context_map);
   1862 
   1863   { MaybeObject* maybe_obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE,
   1864                                          SharedFunctionInfo::kAlignedSize);
   1865     if (!maybe_obj->ToObject(&obj)) return false;
   1866   }
   1867   set_shared_function_info_map(Map::cast(obj));
   1868 
   1869   { MaybeObject* maybe_obj = AllocateMap(JS_MESSAGE_OBJECT_TYPE,
   1870                                          JSMessageObject::kSize);
   1871     if (!maybe_obj->ToObject(&obj)) return false;
   1872   }
   1873   set_message_object_map(Map::cast(obj));
   1874 
   1875   ASSERT(!InNewSpace(empty_fixed_array()));
   1876   return true;
   1877 }
   1878 
   1879 
   1880 MaybeObject* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) {
   1881   // Statically ensure that it is safe to allocate heap numbers in paged
   1882   // spaces.
   1883   STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize);
   1884   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   1885 
   1886   Object* result;
   1887   { MaybeObject* maybe_result =
   1888         AllocateRaw(HeapNumber::kSize, space, OLD_DATA_SPACE);
   1889     if (!maybe_result->ToObject(&result)) return maybe_result;
   1890   }
   1891 
   1892   HeapObject::cast(result)->set_map(heap_number_map());
   1893   HeapNumber::cast(result)->set_value(value);
   1894   return result;
   1895 }
   1896 
   1897 
   1898 MaybeObject* Heap::AllocateHeapNumber(double value) {
   1899   // Use general version, if we're forced to always allocate.
   1900   if (always_allocate()) return AllocateHeapNumber(value, TENURED);
   1901 
   1902   // This version of AllocateHeapNumber is optimized for
   1903   // allocation in new space.
   1904   STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize);
   1905   ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
   1906   Object* result;
   1907   { MaybeObject* maybe_result = new_space_.AllocateRaw(HeapNumber::kSize);
   1908     if (!maybe_result->ToObject(&result)) return maybe_result;
   1909   }
   1910   HeapObject::cast(result)->set_map(heap_number_map());
   1911   HeapNumber::cast(result)->set_value(value);
   1912   return result;
   1913 }
   1914 
   1915 
   1916 MaybeObject* Heap::AllocateJSGlobalPropertyCell(Object* value) {
   1917   Object* result;
   1918   { MaybeObject* maybe_result = AllocateRawCell();
   1919     if (!maybe_result->ToObject(&result)) return maybe_result;
   1920   }
   1921   HeapObject::cast(result)->set_map(global_property_cell_map());
   1922   JSGlobalPropertyCell::cast(result)->set_value(value);
   1923   return result;
   1924 }
   1925 
   1926 
   1927 MaybeObject* Heap::CreateOddball(const char* to_string,
   1928                                  Object* to_number,
   1929                                  byte kind) {
   1930   Object* result;
   1931   { MaybeObject* maybe_result = Allocate(oddball_map(), OLD_DATA_SPACE);
   1932     if (!maybe_result->ToObject(&result)) return maybe_result;
   1933   }
   1934   return Oddball::cast(result)->Initialize(to_string, to_number, kind);
   1935 }
   1936 
   1937 
   1938 bool Heap::CreateApiObjects() {
   1939   Object* obj;
   1940 
   1941   { MaybeObject* maybe_obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
   1942     if (!maybe_obj->ToObject(&obj)) return false;
   1943   }
   1944   set_neander_map(Map::cast(obj));
   1945 
   1946   { MaybeObject* maybe_obj = AllocateJSObjectFromMap(neander_map());
   1947     if (!maybe_obj->ToObject(&obj)) return false;
   1948   }
   1949   Object* elements;
   1950   { MaybeObject* maybe_elements = AllocateFixedArray(2);
   1951     if (!maybe_elements->ToObject(&elements)) return false;
   1952   }
   1953   FixedArray::cast(elements)->set(0, Smi::FromInt(0));
   1954   JSObject::cast(obj)->set_elements(FixedArray::cast(elements));
   1955   set_message_listeners(JSObject::cast(obj));
   1956 
   1957   return true;
   1958 }
   1959 
   1960 
   1961 void Heap::CreateJSEntryStub() {
   1962   JSEntryStub stub;
   1963   set_js_entry_code(*stub.GetCode());
   1964 }
   1965 
   1966 
   1967 void Heap::CreateJSConstructEntryStub() {
   1968   JSConstructEntryStub stub;
   1969   set_js_construct_entry_code(*stub.GetCode());
   1970 }
   1971 
   1972 
   1973 void Heap::CreateFixedStubs() {
   1974   // Here we create roots for fixed stubs. They are needed at GC
   1975   // for cooking and uncooking (check out frames.cc).
   1976   // The eliminates the need for doing dictionary lookup in the
   1977   // stub cache for these stubs.
   1978   HandleScope scope;
   1979   // gcc-4.4 has problem generating correct code of following snippet:
   1980   // {  JSEntryStub stub;
   1981   //    js_entry_code_ = *stub.GetCode();
   1982   // }
   1983   // {  JSConstructEntryStub stub;
   1984   //    js_construct_entry_code_ = *stub.GetCode();
   1985   // }
   1986   // To workaround the problem, make separate functions without inlining.
   1987   Heap::CreateJSEntryStub();
   1988   Heap::CreateJSConstructEntryStub();
   1989 }
   1990 
   1991 
   1992 bool Heap::CreateInitialObjects() {
   1993   Object* obj;
   1994 
   1995   // The -0 value must be set before NumberFromDouble works.
   1996   { MaybeObject* maybe_obj = AllocateHeapNumber(-0.0, TENURED);
   1997     if (!maybe_obj->ToObject(&obj)) return false;
   1998   }
   1999   set_minus_zero_value(obj);
   2000   ASSERT(signbit(minus_zero_value()->Number()) != 0);
   2001 
   2002   { MaybeObject* maybe_obj = AllocateHeapNumber(OS::nan_value(), TENURED);
   2003     if (!maybe_obj->ToObject(&obj)) return false;
   2004   }
   2005   set_nan_value(obj);
   2006 
   2007   { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_DATA_SPACE);
   2008     if (!maybe_obj->ToObject(&obj)) return false;
   2009   }
   2010   set_undefined_value(obj);
   2011   Oddball::cast(obj)->set_kind(Oddball::kUndefined);
   2012   ASSERT(!InNewSpace(undefined_value()));
   2013 
   2014   // Allocate initial symbol table.
   2015   { MaybeObject* maybe_obj = SymbolTable::Allocate(kInitialSymbolTableSize);
   2016     if (!maybe_obj->ToObject(&obj)) return false;
   2017   }
   2018   // Don't use set_symbol_table() due to asserts.
   2019   roots_[kSymbolTableRootIndex] = obj;
   2020 
   2021   // Assign the print strings for oddballs after creating symboltable.
   2022   Object* symbol;
   2023   { MaybeObject* maybe_symbol = LookupAsciiSymbol("undefined");
   2024     if (!maybe_symbol->ToObject(&symbol)) return false;
   2025   }
   2026   Oddball::cast(undefined_value())->set_to_string(String::cast(symbol));
   2027   Oddball::cast(undefined_value())->set_to_number(nan_value());
   2028 
   2029   // Allocate the null_value
   2030   { MaybeObject* maybe_obj =
   2031         Oddball::cast(null_value())->Initialize("null",
   2032                                                 Smi::FromInt(0),
   2033                                                 Oddball::kNull);
   2034     if (!maybe_obj->ToObject(&obj)) return false;
   2035   }
   2036 
   2037   { MaybeObject* maybe_obj = CreateOddball("true",
   2038                                            Smi::FromInt(1),
   2039                                            Oddball::kTrue);
   2040     if (!maybe_obj->ToObject(&obj)) return false;
   2041   }
   2042   set_true_value(obj);
   2043 
   2044   { MaybeObject* maybe_obj = CreateOddball("false",
   2045                                            Smi::FromInt(0),
   2046                                            Oddball::kFalse);
   2047     if (!maybe_obj->ToObject(&obj)) return false;
   2048   }
   2049   set_false_value(obj);
   2050 
   2051   { MaybeObject* maybe_obj = CreateOddball("hole",
   2052                                            Smi::FromInt(-1),
   2053                                            Oddball::kTheHole);
   2054     if (!maybe_obj->ToObject(&obj)) return false;
   2055   }
   2056   set_the_hole_value(obj);
   2057 
   2058   { MaybeObject* maybe_obj = CreateOddball("arguments_marker",
   2059                                            Smi::FromInt(-4),
   2060                                            Oddball::kArgumentMarker);
   2061     if (!maybe_obj->ToObject(&obj)) return false;
   2062   }
   2063   set_arguments_marker(obj);
   2064 
   2065   { MaybeObject* maybe_obj = CreateOddball("no_interceptor_result_sentinel",
   2066                                            Smi::FromInt(-2),
   2067                                            Oddball::kOther);
   2068     if (!maybe_obj->ToObject(&obj)) return false;
   2069   }
   2070   set_no_interceptor_result_sentinel(obj);
   2071 
   2072   { MaybeObject* maybe_obj = CreateOddball("termination_exception",
   2073                                            Smi::FromInt(-3),
   2074                                            Oddball::kOther);
   2075     if (!maybe_obj->ToObject(&obj)) return false;
   2076   }
   2077   set_termination_exception(obj);
   2078 
   2079   // Allocate the empty string.
   2080   { MaybeObject* maybe_obj = AllocateRawAsciiString(0, TENURED);
   2081     if (!maybe_obj->ToObject(&obj)) return false;
   2082   }
   2083   set_empty_string(String::cast(obj));
   2084 
   2085   for (unsigned i = 0; i < ARRAY_SIZE(constant_symbol_table); i++) {
   2086     { MaybeObject* maybe_obj =
   2087           LookupAsciiSymbol(constant_symbol_table[i].contents);
   2088       if (!maybe_obj->ToObject(&obj)) return false;
   2089     }
   2090     roots_[constant_symbol_table[i].index] = String::cast(obj);
   2091   }
   2092 
   2093   // Allocate the hidden symbol which is used to identify the hidden properties
   2094   // in JSObjects. The hash code has a special value so that it will not match
   2095   // the empty string when searching for the property. It cannot be part of the
   2096   // loop above because it needs to be allocated manually with the special
   2097   // hash code in place. The hash code for the hidden_symbol is zero to ensure
   2098   // that it will always be at the first entry in property descriptors.
   2099   { MaybeObject* maybe_obj =
   2100         AllocateSymbol(CStrVector(""), 0, String::kZeroHash);
   2101     if (!maybe_obj->ToObject(&obj)) return false;
   2102   }
   2103   hidden_symbol_ = String::cast(obj);
   2104 
   2105   // Allocate the proxy for __proto__.
   2106   { MaybeObject* maybe_obj =
   2107         AllocateProxy((Address) &Accessors::ObjectPrototype);
   2108     if (!maybe_obj->ToObject(&obj)) return false;
   2109   }
   2110   set_prototype_accessors(Proxy::cast(obj));
   2111 
   2112   // Allocate the code_stubs dictionary. The initial size is set to avoid
   2113   // expanding the dictionary during bootstrapping.
   2114   { MaybeObject* maybe_obj = NumberDictionary::Allocate(128);
   2115     if (!maybe_obj->ToObject(&obj)) return false;
   2116   }
   2117   set_code_stubs(NumberDictionary::cast(obj));
   2118 
   2119   // Allocate the non_monomorphic_cache used in stub-cache.cc. The initial size
   2120   // is set to avoid expanding the dictionary during bootstrapping.
   2121   { MaybeObject* maybe_obj = NumberDictionary::Allocate(64);
   2122     if (!maybe_obj->ToObject(&obj)) return false;
   2123   }
   2124   set_non_monomorphic_cache(NumberDictionary::cast(obj));
   2125 
   2126   set_instanceof_cache_function(Smi::FromInt(0));
   2127   set_instanceof_cache_map(Smi::FromInt(0));
   2128   set_instanceof_cache_answer(Smi::FromInt(0));
   2129 
   2130   CreateFixedStubs();
   2131 
   2132   // Allocate the dictionary of intrinsic function names.
   2133   { MaybeObject* maybe_obj = StringDictionary::Allocate(Runtime::kNumFunctions);
   2134     if (!maybe_obj->ToObject(&obj)) return false;
   2135   }
   2136   { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(this,
   2137                                                                        obj);
   2138     if (!maybe_obj->ToObject(&obj)) return false;
   2139   }
   2140   set_intrinsic_function_names(StringDictionary::cast(obj));
   2141 
   2142   if (InitializeNumberStringCache()->IsFailure()) return false;
   2143 
   2144   // Allocate cache for single character ASCII strings.
   2145   { MaybeObject* maybe_obj =
   2146         AllocateFixedArray(String::kMaxAsciiCharCode + 1, TENURED);
   2147     if (!maybe_obj->ToObject(&obj)) return false;
   2148   }
   2149   set_single_character_string_cache(FixedArray::cast(obj));
   2150 
   2151   // Allocate cache for external strings pointing to native source code.
   2152   { MaybeObject* maybe_obj = AllocateFixedArray(Natives::GetBuiltinsCount());
   2153     if (!maybe_obj->ToObject(&obj)) return false;
   2154   }
   2155   set_natives_source_cache(FixedArray::cast(obj));
   2156 
   2157   // Handling of script id generation is in FACTORY->NewScript.
   2158   set_last_script_id(undefined_value());
   2159 
   2160   // Initialize keyed lookup cache.
   2161   isolate_->keyed_lookup_cache()->Clear();
   2162 
   2163   // Initialize context slot cache.
   2164   isolate_->context_slot_cache()->Clear();
   2165 
   2166   // Initialize descriptor cache.
   2167   isolate_->descriptor_lookup_cache()->Clear();
   2168 
   2169   // Initialize compilation cache.
   2170   isolate_->compilation_cache()->Clear();
   2171 
   2172   return true;
   2173 }
   2174 
   2175 
   2176 MaybeObject* Heap::InitializeNumberStringCache() {
   2177   // Compute the size of the number string cache based on the max heap size.
   2178   // max_semispace_size_ == 512 KB => number_string_cache_size = 32.
   2179   // max_semispace_size_ ==   8 MB => number_string_cache_size = 16KB.
   2180   int number_string_cache_size = max_semispace_size_ / 512;
   2181   number_string_cache_size = Max(32, Min(16*KB, number_string_cache_size));
   2182   Object* obj;
   2183   MaybeObject* maybe_obj =
   2184       AllocateFixedArray(number_string_cache_size * 2, TENURED);
   2185   if (maybe_obj->ToObject(&obj)) set_number_string_cache(FixedArray::cast(obj));
   2186   return maybe_obj;
   2187 }
   2188 
   2189 
   2190 void Heap::FlushNumberStringCache() {
   2191   // Flush the number to string cache.
   2192   int len = number_string_cache()->length();
   2193   for (int i = 0; i < len; i++) {
   2194     number_string_cache()->set_undefined(this, i);
   2195   }
   2196 }
   2197 
   2198 
   2199 static inline int double_get_hash(double d) {
   2200   DoubleRepresentation rep(d);
   2201   return static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32);
   2202 }
   2203 
   2204 
   2205 static inline int smi_get_hash(Smi* smi) {
   2206   return smi->value();
   2207 }
   2208 
   2209 
   2210 Object* Heap::GetNumberStringCache(Object* number) {
   2211   int hash;
   2212   int mask = (number_string_cache()->length() >> 1) - 1;
   2213   if (number->IsSmi()) {
   2214     hash = smi_get_hash(Smi::cast(number)) & mask;
   2215   } else {
   2216     hash = double_get_hash(number->Number()) & mask;
   2217   }
   2218   Object* key = number_string_cache()->get(hash * 2);
   2219   if (key == number) {
   2220     return String::cast(number_string_cache()->get(hash * 2 + 1));
   2221   } else if (key->IsHeapNumber() &&
   2222              number->IsHeapNumber() &&
   2223              key->Number() == number->Number()) {
   2224     return String::cast(number_string_cache()->get(hash * 2 + 1));
   2225   }
   2226   return undefined_value();
   2227 }
   2228 
   2229 
   2230 void Heap::SetNumberStringCache(Object* number, String* string) {
   2231   int hash;
   2232   int mask = (number_string_cache()->length() >> 1) - 1;
   2233   if (number->IsSmi()) {
   2234     hash = smi_get_hash(Smi::cast(number)) & mask;
   2235     number_string_cache()->set(hash * 2, Smi::cast(number));
   2236   } else {
   2237     hash = double_get_hash(number->Number()) & mask;
   2238     number_string_cache()->set(hash * 2, number);
   2239   }
   2240   number_string_cache()->set(hash * 2 + 1, string);
   2241 }
   2242 
   2243 
   2244 MaybeObject* Heap::NumberToString(Object* number,
   2245                                   bool check_number_string_cache) {
   2246   isolate_->counters()->number_to_string_runtime()->Increment();
   2247   if (check_number_string_cache) {
   2248     Object* cached = GetNumberStringCache(number);
   2249     if (cached != undefined_value()) {
   2250       return cached;
   2251     }
   2252   }
   2253 
   2254   char arr[100];
   2255   Vector<char> buffer(arr, ARRAY_SIZE(arr));
   2256   const char* str;
   2257   if (number->IsSmi()) {
   2258     int num = Smi::cast(number)->value();
   2259     str = IntToCString(num, buffer);
   2260   } else {
   2261     double num = HeapNumber::cast(number)->value();
   2262     str = DoubleToCString(num, buffer);
   2263   }
   2264 
   2265   Object* js_string;
   2266   MaybeObject* maybe_js_string = AllocateStringFromAscii(CStrVector(str));
   2267   if (maybe_js_string->ToObject(&js_string)) {
   2268     SetNumberStringCache(number, String::cast(js_string));
   2269   }
   2270   return maybe_js_string;
   2271 }
   2272 
   2273 
   2274 Map* Heap::MapForExternalArrayType(ExternalArrayType array_type) {
   2275   return Map::cast(roots_[RootIndexForExternalArrayType(array_type)]);
   2276 }
   2277 
   2278 
   2279 Heap::RootListIndex Heap::RootIndexForExternalArrayType(
   2280     ExternalArrayType array_type) {
   2281   switch (array_type) {
   2282     case kExternalByteArray:
   2283       return kExternalByteArrayMapRootIndex;
   2284     case kExternalUnsignedByteArray:
   2285       return kExternalUnsignedByteArrayMapRootIndex;
   2286     case kExternalShortArray:
   2287       return kExternalShortArrayMapRootIndex;
   2288     case kExternalUnsignedShortArray:
   2289       return kExternalUnsignedShortArrayMapRootIndex;
   2290     case kExternalIntArray:
   2291       return kExternalIntArrayMapRootIndex;
   2292     case kExternalUnsignedIntArray:
   2293       return kExternalUnsignedIntArrayMapRootIndex;
   2294     case kExternalFloatArray:
   2295       return kExternalFloatArrayMapRootIndex;
   2296     case kExternalPixelArray:
   2297       return kExternalPixelArrayMapRootIndex;
   2298     default:
   2299       UNREACHABLE();
   2300       return kUndefinedValueRootIndex;
   2301   }
   2302 }
   2303 
   2304 
   2305 MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) {
   2306   // We need to distinguish the minus zero value and this cannot be
   2307   // done after conversion to int. Doing this by comparing bit
   2308   // patterns is faster than using fpclassify() et al.
   2309   static const DoubleRepresentation minus_zero(-0.0);
   2310 
   2311   DoubleRepresentation rep(value);
   2312   if (rep.bits == minus_zero.bits) {
   2313     return AllocateHeapNumber(-0.0, pretenure);
   2314   }
   2315 
   2316   int int_value = FastD2I(value);
   2317   if (value == int_value && Smi::IsValid(int_value)) {
   2318     return Smi::FromInt(int_value);
   2319   }
   2320 
   2321   // Materialize the value in the heap.
   2322   return AllocateHeapNumber(value, pretenure);
   2323 }
   2324 
   2325 
   2326 MaybeObject* Heap::AllocateProxy(Address proxy, PretenureFlag pretenure) {
   2327   // Statically ensure that it is safe to allocate proxies in paged spaces.
   2328   STATIC_ASSERT(Proxy::kSize <= Page::kMaxHeapObjectSize);
   2329   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   2330   Object* result;
   2331   { MaybeObject* maybe_result = Allocate(proxy_map(), space);
   2332     if (!maybe_result->ToObject(&result)) return maybe_result;
   2333   }
   2334 
   2335   Proxy::cast(result)->set_proxy(proxy);
   2336   return result;
   2337 }
   2338 
   2339 
   2340 MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
   2341   Object* result;
   2342   { MaybeObject* maybe_result =
   2343         Allocate(shared_function_info_map(), OLD_POINTER_SPACE);
   2344     if (!maybe_result->ToObject(&result)) return maybe_result;
   2345   }
   2346 
   2347   SharedFunctionInfo* share = SharedFunctionInfo::cast(result);
   2348   share->set_name(name);
   2349   Code* illegal = isolate_->builtins()->builtin(Builtins::kIllegal);
   2350   share->set_code(illegal);
   2351   share->set_scope_info(SerializedScopeInfo::Empty());
   2352   Code* construct_stub = isolate_->builtins()->builtin(
   2353       Builtins::kJSConstructStubGeneric);
   2354   share->set_construct_stub(construct_stub);
   2355   share->set_expected_nof_properties(0);
   2356   share->set_length(0);
   2357   share->set_formal_parameter_count(0);
   2358   share->set_instance_class_name(Object_symbol());
   2359   share->set_function_data(undefined_value());
   2360   share->set_script(undefined_value());
   2361   share->set_start_position_and_type(0);
   2362   share->set_debug_info(undefined_value());
   2363   share->set_inferred_name(empty_string());
   2364   share->set_compiler_hints(0);
   2365   share->set_deopt_counter(Smi::FromInt(FLAG_deopt_every_n_times));
   2366   share->set_initial_map(undefined_value());
   2367   share->set_this_property_assignments_count(0);
   2368   share->set_this_property_assignments(undefined_value());
   2369   share->set_opt_count(0);
   2370   share->set_num_literals(0);
   2371   share->set_end_position(0);
   2372   share->set_function_token_position(0);
   2373   return result;
   2374 }
   2375 
   2376 
   2377 MaybeObject* Heap::AllocateJSMessageObject(String* type,
   2378                                            JSArray* arguments,
   2379                                            int start_position,
   2380                                            int end_position,
   2381                                            Object* script,
   2382                                            Object* stack_trace,
   2383                                            Object* stack_frames) {
   2384   Object* result;
   2385   { MaybeObject* maybe_result = Allocate(message_object_map(), NEW_SPACE);
   2386     if (!maybe_result->ToObject(&result)) return maybe_result;
   2387   }
   2388   JSMessageObject* message = JSMessageObject::cast(result);
   2389   message->set_properties(Heap::empty_fixed_array());
   2390   message->set_elements(Heap::empty_fixed_array());
   2391   message->set_type(type);
   2392   message->set_arguments(arguments);
   2393   message->set_start_position(start_position);
   2394   message->set_end_position(end_position);
   2395   message->set_script(script);
   2396   message->set_stack_trace(stack_trace);
   2397   message->set_stack_frames(stack_frames);
   2398   return result;
   2399 }
   2400 
   2401 
   2402 
   2403 // Returns true for a character in a range.  Both limits are inclusive.
   2404 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
   2405   // This makes uses of the the unsigned wraparound.
   2406   return character - from <= to - from;
   2407 }
   2408 
   2409 
   2410 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString(
   2411     Heap* heap,
   2412     uint32_t c1,
   2413     uint32_t c2) {
   2414   String* symbol;
   2415   // Numeric strings have a different hash algorithm not known by
   2416   // LookupTwoCharsSymbolIfExists, so we skip this step for such strings.
   2417   if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) &&
   2418       heap->symbol_table()->LookupTwoCharsSymbolIfExists(c1, c2, &symbol)) {
   2419     return symbol;
   2420   // Now we know the length is 2, we might as well make use of that fact
   2421   // when building the new string.
   2422   } else if ((c1 | c2) <= String::kMaxAsciiCharCodeU) {  // We can do this
   2423     ASSERT(IsPowerOf2(String::kMaxAsciiCharCodeU + 1));  // because of this.
   2424     Object* result;
   2425     { MaybeObject* maybe_result = heap->AllocateRawAsciiString(2);
   2426       if (!maybe_result->ToObject(&result)) return maybe_result;
   2427     }
   2428     char* dest = SeqAsciiString::cast(result)->GetChars();
   2429     dest[0] = c1;
   2430     dest[1] = c2;
   2431     return result;
   2432   } else {
   2433     Object* result;
   2434     { MaybeObject* maybe_result = heap->AllocateRawTwoByteString(2);
   2435       if (!maybe_result->ToObject(&result)) return maybe_result;
   2436     }
   2437     uc16* dest = SeqTwoByteString::cast(result)->GetChars();
   2438     dest[0] = c1;
   2439     dest[1] = c2;
   2440     return result;
   2441   }
   2442 }
   2443 
   2444 
   2445 MaybeObject* Heap::AllocateConsString(String* first, String* second) {
   2446   int first_length = first->length();
   2447   if (first_length == 0) {
   2448     return second;
   2449   }
   2450 
   2451   int second_length = second->length();
   2452   if (second_length == 0) {
   2453     return first;
   2454   }
   2455 
   2456   int length = first_length + second_length;
   2457 
   2458   // Optimization for 2-byte strings often used as keys in a decompression
   2459   // dictionary.  Check whether we already have the string in the symbol
   2460   // table to prevent creation of many unneccesary strings.
   2461   if (length == 2) {
   2462     unsigned c1 = first->Get(0);
   2463     unsigned c2 = second->Get(0);
   2464     return MakeOrFindTwoCharacterString(this, c1, c2);
   2465   }
   2466 
   2467   bool first_is_ascii = first->IsAsciiRepresentation();
   2468   bool second_is_ascii = second->IsAsciiRepresentation();
   2469   bool is_ascii = first_is_ascii && second_is_ascii;
   2470 
   2471   // Make sure that an out of memory exception is thrown if the length
   2472   // of the new cons string is too large.
   2473   if (length > String::kMaxLength || length < 0) {
   2474     isolate()->context()->mark_out_of_memory();
   2475     return Failure::OutOfMemoryException();
   2476   }
   2477 
   2478   bool is_ascii_data_in_two_byte_string = false;
   2479   if (!is_ascii) {
   2480     // At least one of the strings uses two-byte representation so we
   2481     // can't use the fast case code for short ascii strings below, but
   2482     // we can try to save memory if all chars actually fit in ascii.
   2483     is_ascii_data_in_two_byte_string =
   2484         first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars();
   2485     if (is_ascii_data_in_two_byte_string) {
   2486       isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
   2487     }
   2488   }
   2489 
   2490   // If the resulting string is small make a flat string.
   2491   if (length < String::kMinNonFlatLength) {
   2492     ASSERT(first->IsFlat());
   2493     ASSERT(second->IsFlat());
   2494     if (is_ascii) {
   2495       Object* result;
   2496       { MaybeObject* maybe_result = AllocateRawAsciiString(length);
   2497         if (!maybe_result->ToObject(&result)) return maybe_result;
   2498       }
   2499       // Copy the characters into the new object.
   2500       char* dest = SeqAsciiString::cast(result)->GetChars();
   2501       // Copy first part.
   2502       const char* src;
   2503       if (first->IsExternalString()) {
   2504         src = ExternalAsciiString::cast(first)->resource()->data();
   2505       } else {
   2506         src = SeqAsciiString::cast(first)->GetChars();
   2507       }
   2508       for (int i = 0; i < first_length; i++) *dest++ = src[i];
   2509       // Copy second part.
   2510       if (second->IsExternalString()) {
   2511         src = ExternalAsciiString::cast(second)->resource()->data();
   2512       } else {
   2513         src = SeqAsciiString::cast(second)->GetChars();
   2514       }
   2515       for (int i = 0; i < second_length; i++) *dest++ = src[i];
   2516       return result;
   2517     } else {
   2518       if (is_ascii_data_in_two_byte_string) {
   2519         Object* result;
   2520         { MaybeObject* maybe_result = AllocateRawAsciiString(length);
   2521           if (!maybe_result->ToObject(&result)) return maybe_result;
   2522         }
   2523         // Copy the characters into the new object.
   2524         char* dest = SeqAsciiString::cast(result)->GetChars();
   2525         String::WriteToFlat(first, dest, 0, first_length);
   2526         String::WriteToFlat(second, dest + first_length, 0, second_length);
   2527         isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
   2528         return result;
   2529       }
   2530 
   2531       Object* result;
   2532       { MaybeObject* maybe_result = AllocateRawTwoByteString(length);
   2533         if (!maybe_result->ToObject(&result)) return maybe_result;
   2534       }
   2535       // Copy the characters into the new object.
   2536       uc16* dest = SeqTwoByteString::cast(result)->GetChars();
   2537       String::WriteToFlat(first, dest, 0, first_length);
   2538       String::WriteToFlat(second, dest + first_length, 0, second_length);
   2539       return result;
   2540     }
   2541   }
   2542 
   2543   Map* map = (is_ascii || is_ascii_data_in_two_byte_string) ?
   2544       cons_ascii_string_map() : cons_string_map();
   2545 
   2546   Object* result;
   2547   { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
   2548     if (!maybe_result->ToObject(&result)) return maybe_result;
   2549   }
   2550 
   2551   AssertNoAllocation no_gc;
   2552   ConsString* cons_string = ConsString::cast(result);
   2553   WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc);
   2554   cons_string->set_length(length);
   2555   cons_string->set_hash_field(String::kEmptyHashField);
   2556   cons_string->set_first(first, mode);
   2557   cons_string->set_second(second, mode);
   2558   return result;
   2559 }
   2560 
   2561 
   2562 MaybeObject* Heap::AllocateSubString(String* buffer,
   2563                                 int start,
   2564                                 int end,
   2565                                 PretenureFlag pretenure) {
   2566   int length = end - start;
   2567 
   2568   if (length == 1) {
   2569     return LookupSingleCharacterStringFromCode(buffer->Get(start));
   2570   } else if (length == 2) {
   2571     // Optimization for 2-byte strings often used as keys in a decompression
   2572     // dictionary.  Check whether we already have the string in the symbol
   2573     // table to prevent creation of many unneccesary strings.
   2574     unsigned c1 = buffer->Get(start);
   2575     unsigned c2 = buffer->Get(start + 1);
   2576     return MakeOrFindTwoCharacterString(this, c1, c2);
   2577   }
   2578 
   2579   // Make an attempt to flatten the buffer to reduce access time.
   2580   buffer = buffer->TryFlattenGetString();
   2581 
   2582   Object* result;
   2583   { MaybeObject* maybe_result = buffer->IsAsciiRepresentation()
   2584                    ? AllocateRawAsciiString(length, pretenure )
   2585                    : AllocateRawTwoByteString(length, pretenure);
   2586     if (!maybe_result->ToObject(&result)) return maybe_result;
   2587   }
   2588   String* string_result = String::cast(result);
   2589   // Copy the characters into the new object.
   2590   if (buffer->IsAsciiRepresentation()) {
   2591     ASSERT(string_result->IsAsciiRepresentation());
   2592     char* dest = SeqAsciiString::cast(string_result)->GetChars();
   2593     String::WriteToFlat(buffer, dest, start, end);
   2594   } else {
   2595     ASSERT(string_result->IsTwoByteRepresentation());
   2596     uc16* dest = SeqTwoByteString::cast(string_result)->GetChars();
   2597     String::WriteToFlat(buffer, dest, start, end);
   2598   }
   2599 
   2600   return result;
   2601 }
   2602 
   2603 
   2604 MaybeObject* Heap::AllocateExternalStringFromAscii(
   2605     ExternalAsciiString::Resource* resource) {
   2606   size_t length = resource->length();
   2607   if (length > static_cast<size_t>(String::kMaxLength)) {
   2608     isolate()->context()->mark_out_of_memory();
   2609     return Failure::OutOfMemoryException();
   2610   }
   2611 
   2612   Map* map = external_ascii_string_map();
   2613   Object* result;
   2614   { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
   2615     if (!maybe_result->ToObject(&result)) return maybe_result;
   2616   }
   2617 
   2618   ExternalAsciiString* external_string = ExternalAsciiString::cast(result);
   2619   external_string->set_length(static_cast<int>(length));
   2620   external_string->set_hash_field(String::kEmptyHashField);
   2621   external_string->set_resource(resource);
   2622 
   2623   return result;
   2624 }
   2625 
   2626 
   2627 MaybeObject* Heap::AllocateExternalStringFromTwoByte(
   2628     ExternalTwoByteString::Resource* resource) {
   2629   size_t length = resource->length();
   2630   if (length > static_cast<size_t>(String::kMaxLength)) {
   2631     isolate()->context()->mark_out_of_memory();
   2632     return Failure::OutOfMemoryException();
   2633   }
   2634 
   2635   // For small strings we check whether the resource contains only
   2636   // ASCII characters.  If yes, we use a different string map.
   2637   static const size_t kAsciiCheckLengthLimit = 32;
   2638   bool is_ascii = length <= kAsciiCheckLengthLimit &&
   2639       String::IsAscii(resource->data(), static_cast<int>(length));
   2640   Map* map = is_ascii ?
   2641       external_string_with_ascii_data_map() : external_string_map();
   2642   Object* result;
   2643   { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
   2644     if (!maybe_result->ToObject(&result)) return maybe_result;
   2645   }
   2646 
   2647   ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result);
   2648   external_string->set_length(static_cast<int>(length));
   2649   external_string->set_hash_field(String::kEmptyHashField);
   2650   external_string->set_resource(resource);
   2651 
   2652   return result;
   2653 }
   2654 
   2655 
   2656 MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
   2657   if (code <= String::kMaxAsciiCharCode) {
   2658     Object* value = single_character_string_cache()->get(code);
   2659     if (value != undefined_value()) return value;
   2660 
   2661     char buffer[1];
   2662     buffer[0] = static_cast<char>(code);
   2663     Object* result;
   2664     MaybeObject* maybe_result = LookupSymbol(Vector<const char>(buffer, 1));
   2665 
   2666     if (!maybe_result->ToObject(&result)) return maybe_result;
   2667     single_character_string_cache()->set(code, result);
   2668     return result;
   2669   }
   2670 
   2671   Object* result;
   2672   { MaybeObject* maybe_result = AllocateRawTwoByteString(1);
   2673     if (!maybe_result->ToObject(&result)) return maybe_result;
   2674   }
   2675   String* answer = String::cast(result);
   2676   answer->Set(0, code);
   2677   return answer;
   2678 }
   2679 
   2680 
   2681 MaybeObject* Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
   2682   if (length < 0 || length > ByteArray::kMaxLength) {
   2683     return Failure::OutOfMemoryException();
   2684   }
   2685   if (pretenure == NOT_TENURED) {
   2686     return AllocateByteArray(length);
   2687   }
   2688   int size = ByteArray::SizeFor(length);
   2689   Object* result;
   2690   { MaybeObject* maybe_result = (size <= MaxObjectSizeInPagedSpace())
   2691                    ? old_data_space_->AllocateRaw(size)
   2692                    : lo_space_->AllocateRaw(size);
   2693     if (!maybe_result->ToObject(&result)) return maybe_result;
   2694   }
   2695 
   2696   reinterpret_cast<ByteArray*>(result)->set_map(byte_array_map());
   2697   reinterpret_cast<ByteArray*>(result)->set_length(length);
   2698   return result;
   2699 }
   2700 
   2701 
   2702 MaybeObject* Heap::AllocateByteArray(int length) {
   2703   if (length < 0 || length > ByteArray::kMaxLength) {
   2704     return Failure::OutOfMemoryException();
   2705   }
   2706   int size = ByteArray::SizeFor(length);
   2707   AllocationSpace space =
   2708       (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : NEW_SPACE;
   2709   Object* result;
   2710   { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
   2711     if (!maybe_result->ToObject(&result)) return maybe_result;
   2712   }
   2713 
   2714   reinterpret_cast<ByteArray*>(result)->set_map(byte_array_map());
   2715   reinterpret_cast<ByteArray*>(result)->set_length(length);
   2716   return result;
   2717 }
   2718 
   2719 
   2720 void Heap::CreateFillerObjectAt(Address addr, int size) {
   2721   if (size == 0) return;
   2722   HeapObject* filler = HeapObject::FromAddress(addr);
   2723   if (size == kPointerSize) {
   2724     filler->set_map(one_pointer_filler_map());
   2725   } else if (size == 2 * kPointerSize) {
   2726     filler->set_map(two_pointer_filler_map());
   2727   } else {
   2728     filler->set_map(byte_array_map());
   2729     ByteArray::cast(filler)->set_length(ByteArray::LengthFor(size));
   2730   }
   2731 }
   2732 
   2733 
   2734 MaybeObject* Heap::AllocateExternalArray(int length,
   2735                                          ExternalArrayType array_type,
   2736                                          void* external_pointer,
   2737                                          PretenureFlag pretenure) {
   2738   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   2739   Object* result;
   2740   { MaybeObject* maybe_result = AllocateRaw(ExternalArray::kAlignedSize,
   2741                                             space,
   2742                                             OLD_DATA_SPACE);
   2743     if (!maybe_result->ToObject(&result)) return maybe_result;
   2744   }
   2745 
   2746   reinterpret_cast<ExternalArray*>(result)->set_map(
   2747       MapForExternalArrayType(array_type));
   2748   reinterpret_cast<ExternalArray*>(result)->set_length(length);
   2749   reinterpret_cast<ExternalArray*>(result)->set_external_pointer(
   2750       external_pointer);
   2751 
   2752   return result;
   2753 }
   2754 
   2755 
   2756 MaybeObject* Heap::CreateCode(const CodeDesc& desc,
   2757                               Code::Flags flags,
   2758                               Handle<Object> self_reference,
   2759                               bool immovable) {
   2760   // Allocate ByteArray before the Code object, so that we do not risk
   2761   // leaving uninitialized Code object (and breaking the heap).
   2762   Object* reloc_info;
   2763   { MaybeObject* maybe_reloc_info = AllocateByteArray(desc.reloc_size, TENURED);
   2764     if (!maybe_reloc_info->ToObject(&reloc_info)) return maybe_reloc_info;
   2765   }
   2766 
   2767   // Compute size.
   2768   int body_size = RoundUp(desc.instr_size, kObjectAlignment);
   2769   int obj_size = Code::SizeFor(body_size);
   2770   ASSERT(IsAligned(static_cast<intptr_t>(obj_size), kCodeAlignment));
   2771   MaybeObject* maybe_result;
   2772   // Large code objects and code objects which should stay at a fixed address
   2773   // are allocated in large object space.
   2774   if (obj_size > MaxObjectSizeInPagedSpace() || immovable) {
   2775     maybe_result = lo_space_->AllocateRawCode(obj_size);
   2776   } else {
   2777     maybe_result = code_space_->AllocateRaw(obj_size);
   2778   }
   2779 
   2780   Object* result;
   2781   if (!maybe_result->ToObject(&result)) return maybe_result;
   2782 
   2783   // Initialize the object
   2784   HeapObject::cast(result)->set_map(code_map());
   2785   Code* code = Code::cast(result);
   2786   ASSERT(!isolate_->code_range()->exists() ||
   2787       isolate_->code_range()->contains(code->address()));
   2788   code->set_instruction_size(desc.instr_size);
   2789   code->set_relocation_info(ByteArray::cast(reloc_info));
   2790   code->set_flags(flags);
   2791   if (code->is_call_stub() || code->is_keyed_call_stub()) {
   2792     code->set_check_type(RECEIVER_MAP_CHECK);
   2793   }
   2794   code->set_deoptimization_data(empty_fixed_array());
   2795   // Allow self references to created code object by patching the handle to
   2796   // point to the newly allocated Code object.
   2797   if (!self_reference.is_null()) {
   2798     *(self_reference.location()) = code;
   2799   }
   2800   // Migrate generated code.
   2801   // The generated code can contain Object** values (typically from handles)
   2802   // that are dereferenced during the copy to point directly to the actual heap
   2803   // objects. These pointers can include references to the code object itself,
   2804   // through the self_reference parameter.
   2805   code->CopyFrom(desc);
   2806 
   2807 #ifdef DEBUG
   2808   code->Verify();
   2809 #endif
   2810   return code;
   2811 }
   2812 
   2813 
   2814 MaybeObject* Heap::CopyCode(Code* code) {
   2815   // Allocate an object the same size as the code object.
   2816   int obj_size = code->Size();
   2817   MaybeObject* maybe_result;
   2818   if (obj_size > MaxObjectSizeInPagedSpace()) {
   2819     maybe_result = lo_space_->AllocateRawCode(obj_size);
   2820   } else {
   2821     maybe_result = code_space_->AllocateRaw(obj_size);
   2822   }
   2823 
   2824   Object* result;
   2825   if (!maybe_result->ToObject(&result)) return maybe_result;
   2826 
   2827   // Copy code object.
   2828   Address old_addr = code->address();
   2829   Address new_addr = reinterpret_cast<HeapObject*>(result)->address();
   2830   CopyBlock(new_addr, old_addr, obj_size);
   2831   // Relocate the copy.
   2832   Code* new_code = Code::cast(result);
   2833   ASSERT(!isolate_->code_range()->exists() ||
   2834       isolate_->code_range()->contains(code->address()));
   2835   new_code->Relocate(new_addr - old_addr);
   2836   return new_code;
   2837 }
   2838 
   2839 
   2840 MaybeObject* Heap::CopyCode(Code* code, Vector<byte> reloc_info) {
   2841   // Allocate ByteArray before the Code object, so that we do not risk
   2842   // leaving uninitialized Code object (and breaking the heap).
   2843   Object* reloc_info_array;
   2844   { MaybeObject* maybe_reloc_info_array =
   2845         AllocateByteArray(reloc_info.length(), TENURED);
   2846     if (!maybe_reloc_info_array->ToObject(&reloc_info_array)) {
   2847       return maybe_reloc_info_array;
   2848     }
   2849   }
   2850 
   2851   int new_body_size = RoundUp(code->instruction_size(), kObjectAlignment);
   2852 
   2853   int new_obj_size = Code::SizeFor(new_body_size);
   2854 
   2855   Address old_addr = code->address();
   2856 
   2857   size_t relocation_offset =
   2858       static_cast<size_t>(code->instruction_end() - old_addr);
   2859 
   2860   MaybeObject* maybe_result;
   2861   if (new_obj_size > MaxObjectSizeInPagedSpace()) {
   2862     maybe_result = lo_space_->AllocateRawCode(new_obj_size);
   2863   } else {
   2864     maybe_result = code_space_->AllocateRaw(new_obj_size);
   2865   }
   2866 
   2867   Object* result;
   2868   if (!maybe_result->ToObject(&result)) return maybe_result;
   2869 
   2870   // Copy code object.
   2871   Address new_addr = reinterpret_cast<HeapObject*>(result)->address();
   2872 
   2873   // Copy header and instructions.
   2874   memcpy(new_addr, old_addr, relocation_offset);
   2875 
   2876   Code* new_code = Code::cast(result);
   2877   new_code->set_relocation_info(ByteArray::cast(reloc_info_array));
   2878 
   2879   // Copy patched rinfo.
   2880   memcpy(new_code->relocation_start(), reloc_info.start(), reloc_info.length());
   2881 
   2882   // Relocate the copy.
   2883   ASSERT(!isolate_->code_range()->exists() ||
   2884       isolate_->code_range()->contains(code->address()));
   2885   new_code->Relocate(new_addr - old_addr);
   2886 
   2887 #ifdef DEBUG
   2888   code->Verify();
   2889 #endif
   2890   return new_code;
   2891 }
   2892 
   2893 
   2894 MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) {
   2895   ASSERT(gc_state_ == NOT_IN_GC);
   2896   ASSERT(map->instance_type() != MAP_TYPE);
   2897   // If allocation failures are disallowed, we may allocate in a different
   2898   // space when new space is full and the object is not a large object.
   2899   AllocationSpace retry_space =
   2900       (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type());
   2901   Object* result;
   2902   { MaybeObject* maybe_result =
   2903         AllocateRaw(map->instance_size(), space, retry_space);
   2904     if (!maybe_result->ToObject(&result)) return maybe_result;
   2905   }
   2906   HeapObject::cast(result)->set_map(map);
   2907 #ifdef ENABLE_LOGGING_AND_PROFILING
   2908   isolate_->producer_heap_profile()->RecordJSObjectAllocation(result);
   2909 #endif
   2910   return result;
   2911 }
   2912 
   2913 
   2914 MaybeObject* Heap::InitializeFunction(JSFunction* function,
   2915                                       SharedFunctionInfo* shared,
   2916                                       Object* prototype) {
   2917   ASSERT(!prototype->IsMap());
   2918   function->initialize_properties();
   2919   function->initialize_elements();
   2920   function->set_shared(shared);
   2921   function->set_code(shared->code());
   2922   function->set_prototype_or_initial_map(prototype);
   2923   function->set_context(undefined_value());
   2924   function->set_literals(empty_fixed_array());
   2925   function->set_next_function_link(undefined_value());
   2926   return function;
   2927 }
   2928 
   2929 
   2930 MaybeObject* Heap::AllocateFunctionPrototype(JSFunction* function) {
   2931   // Allocate the prototype.  Make sure to use the object function
   2932   // from the function's context, since the function can be from a
   2933   // different context.
   2934   JSFunction* object_function =
   2935       function->context()->global_context()->object_function();
   2936   Object* prototype;
   2937   { MaybeObject* maybe_prototype = AllocateJSObject(object_function);
   2938     if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
   2939   }
   2940   // When creating the prototype for the function we must set its
   2941   // constructor to the function.
   2942   Object* result;
   2943   { MaybeObject* maybe_result =
   2944         JSObject::cast(prototype)->SetLocalPropertyIgnoreAttributes(
   2945             constructor_symbol(), function, DONT_ENUM);
   2946     if (!maybe_result->ToObject(&result)) return maybe_result;
   2947   }
   2948   return prototype;
   2949 }
   2950 
   2951 
   2952 MaybeObject* Heap::AllocateFunction(Map* function_map,
   2953                                     SharedFunctionInfo* shared,
   2954                                     Object* prototype,
   2955                                     PretenureFlag pretenure) {
   2956   AllocationSpace space =
   2957       (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
   2958   Object* result;
   2959   { MaybeObject* maybe_result = Allocate(function_map, space);
   2960     if (!maybe_result->ToObject(&result)) return maybe_result;
   2961   }
   2962   return InitializeFunction(JSFunction::cast(result), shared, prototype);
   2963 }
   2964 
   2965 
   2966 MaybeObject* Heap::AllocateArgumentsObject(Object* callee, int length) {
   2967   // To get fast allocation and map sharing for arguments objects we
   2968   // allocate them based on an arguments boilerplate.
   2969 
   2970   JSObject* boilerplate;
   2971   int arguments_object_size;
   2972   bool strict_mode_callee = callee->IsJSFunction() &&
   2973                             JSFunction::cast(callee)->shared()->strict_mode();
   2974   if (strict_mode_callee) {
   2975     boilerplate =
   2976         isolate()->context()->global_context()->
   2977             strict_mode_arguments_boilerplate();
   2978     arguments_object_size = kArgumentsObjectSizeStrict;
   2979   } else {
   2980     boilerplate =
   2981         isolate()->context()->global_context()->arguments_boilerplate();
   2982     arguments_object_size = kArgumentsObjectSize;
   2983   }
   2984 
   2985   // This calls Copy directly rather than using Heap::AllocateRaw so we
   2986   // duplicate the check here.
   2987   ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
   2988 
   2989   // Check that the size of the boilerplate matches our
   2990   // expectations. The ArgumentsAccessStub::GenerateNewObject relies
   2991   // on the size being a known constant.
   2992   ASSERT(arguments_object_size == boilerplate->map()->instance_size());
   2993 
   2994   // Do the allocation.
   2995   Object* result;
   2996   { MaybeObject* maybe_result =
   2997         AllocateRaw(arguments_object_size, NEW_SPACE, OLD_POINTER_SPACE);
   2998     if (!maybe_result->ToObject(&result)) return maybe_result;
   2999   }
   3000 
   3001   // Copy the content. The arguments boilerplate doesn't have any
   3002   // fields that point to new space so it's safe to skip the write
   3003   // barrier here.
   3004   CopyBlock(HeapObject::cast(result)->address(),
   3005             boilerplate->address(),
   3006             JSObject::kHeaderSize);
   3007 
   3008   // Set the length property.
   3009   JSObject::cast(result)->InObjectPropertyAtPut(kArgumentsLengthIndex,
   3010                                                 Smi::FromInt(length),
   3011                                                 SKIP_WRITE_BARRIER);
   3012   // Set the callee property for non-strict mode arguments object only.
   3013   if (!strict_mode_callee) {
   3014     JSObject::cast(result)->InObjectPropertyAtPut(kArgumentsCalleeIndex,
   3015                                                   callee);
   3016   }
   3017 
   3018   // Check the state of the object
   3019   ASSERT(JSObject::cast(result)->HasFastProperties());
   3020   ASSERT(JSObject::cast(result)->HasFastElements());
   3021 
   3022   return result;
   3023 }
   3024 
   3025 
   3026 static bool HasDuplicates(DescriptorArray* descriptors) {
   3027   int count = descriptors->number_of_descriptors();
   3028   if (count > 1) {
   3029     String* prev_key = descriptors->GetKey(0);
   3030     for (int i = 1; i != count; i++) {
   3031       String* current_key = descriptors->GetKey(i);
   3032       if (prev_key == current_key) return true;
   3033       prev_key = current_key;
   3034     }
   3035   }
   3036   return false;
   3037 }
   3038 
   3039 
   3040 MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) {
   3041   ASSERT(!fun->has_initial_map());
   3042 
   3043   // First create a new map with the size and number of in-object properties
   3044   // suggested by the function.
   3045   int instance_size = fun->shared()->CalculateInstanceSize();
   3046   int in_object_properties = fun->shared()->CalculateInObjectProperties();
   3047   Object* map_obj;
   3048   { MaybeObject* maybe_map_obj = AllocateMap(JS_OBJECT_TYPE, instance_size);
   3049     if (!maybe_map_obj->ToObject(&map_obj)) return maybe_map_obj;
   3050   }
   3051 
   3052   // Fetch or allocate prototype.
   3053   Object* prototype;
   3054   if (fun->has_instance_prototype()) {
   3055     prototype = fun->instance_prototype();
   3056   } else {
   3057     { MaybeObject* maybe_prototype = AllocateFunctionPrototype(fun);
   3058       if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
   3059     }
   3060   }
   3061   Map* map = Map::cast(map_obj);
   3062   map->set_inobject_properties(in_object_properties);
   3063   map->set_unused_property_fields(in_object_properties);
   3064   map->set_prototype(prototype);
   3065   ASSERT(map->has_fast_elements());
   3066 
   3067   // If the function has only simple this property assignments add
   3068   // field descriptors for these to the initial map as the object
   3069   // cannot be constructed without having these properties.  Guard by
   3070   // the inline_new flag so we only change the map if we generate a
   3071   // specialized construct stub.
   3072   ASSERT(in_object_properties <= Map::kMaxPreAllocatedPropertyFields);
   3073   if (fun->shared()->CanGenerateInlineConstructor(prototype)) {
   3074     int count = fun->shared()->this_property_assignments_count();
   3075     if (count > in_object_properties) {
   3076       // Inline constructor can only handle inobject properties.
   3077       fun->shared()->ForbidInlineConstructor();
   3078     } else {
   3079       Object* descriptors_obj;
   3080       { MaybeObject* maybe_descriptors_obj = DescriptorArray::Allocate(count);
   3081         if (!maybe_descriptors_obj->ToObject(&descriptors_obj)) {
   3082           return maybe_descriptors_obj;
   3083         }
   3084       }
   3085       DescriptorArray* descriptors = DescriptorArray::cast(descriptors_obj);
   3086       for (int i = 0; i < count; i++) {
   3087         String* name = fun->shared()->GetThisPropertyAssignmentName(i);
   3088         ASSERT(name->IsSymbol());
   3089         FieldDescriptor field(name, i, NONE);
   3090         field.SetEnumerationIndex(i);
   3091         descriptors->Set(i, &field);
   3092       }
   3093       descriptors->SetNextEnumerationIndex(count);
   3094       descriptors->SortUnchecked();
   3095 
   3096       // The descriptors may contain duplicates because the compiler does not
   3097       // guarantee the uniqueness of property names (it would have required
   3098       // quadratic time). Once the descriptors are sorted we can check for
   3099       // duplicates in linear time.
   3100       if (HasDuplicates(descriptors)) {
   3101         fun->shared()->ForbidInlineConstructor();
   3102       } else {
   3103         map->set_instance_descriptors(descriptors);
   3104         map->set_pre_allocated_property_fields(count);
   3105         map->set_unused_property_fields(in_object_properties - count);
   3106       }
   3107     }
   3108   }
   3109 
   3110   fun->shared()->StartInobjectSlackTracking(map);
   3111 
   3112   return map;
   3113 }
   3114 
   3115 
   3116 void Heap::InitializeJSObjectFromMap(JSObject* obj,
   3117                                      FixedArray* properties,
   3118                                      Map* map) {
   3119   obj->set_properties(properties);
   3120   obj->initialize_elements();
   3121   // TODO(1240798): Initialize the object's body using valid initial values
   3122   // according to the object's initial map.  For example, if the map's
   3123   // instance type is JS_ARRAY_TYPE, the length field should be initialized
   3124   // to a number (eg, Smi::FromInt(0)) and the elements initialized to a
   3125   // fixed array (eg, Heap::empty_fixed_array()).  Currently, the object
   3126   // verification code has to cope with (temporarily) invalid objects.  See
   3127   // for example, JSArray::JSArrayVerify).
   3128   Object* filler;
   3129   // We cannot always fill with one_pointer_filler_map because objects
   3130   // created from API functions expect their internal fields to be initialized
   3131   // with undefined_value.
   3132   if (map->constructor()->IsJSFunction() &&
   3133       JSFunction::cast(map->constructor())->shared()->
   3134           IsInobjectSlackTrackingInProgress()) {
   3135     // We might want to shrink the object later.
   3136     ASSERT(obj->GetInternalFieldCount() == 0);
   3137     filler = Heap::one_pointer_filler_map();
   3138   } else {
   3139     filler = Heap::undefined_value();
   3140   }
   3141   obj->InitializeBody(map->instance_size(), filler);
   3142 }
   3143 
   3144 
   3145 MaybeObject* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) {
   3146   // JSFunctions should be allocated using AllocateFunction to be
   3147   // properly initialized.
   3148   ASSERT(map->instance_type() != JS_FUNCTION_TYPE);
   3149 
   3150   // Both types of global objects should be allocated using
   3151   // AllocateGlobalObject to be properly initialized.
   3152   ASSERT(map->instance_type() != JS_GLOBAL_OBJECT_TYPE);
   3153   ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE);
   3154 
   3155   // Allocate the backing storage for the properties.
   3156   int prop_size =
   3157       map->pre_allocated_property_fields() +
   3158       map->unused_property_fields() -
   3159       map->inobject_properties();
   3160   ASSERT(prop_size >= 0);
   3161   Object* properties;
   3162   { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, pretenure);
   3163     if (!maybe_properties->ToObject(&properties)) return maybe_properties;
   3164   }
   3165 
   3166   // Allocate the JSObject.
   3167   AllocationSpace space =
   3168       (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
   3169   if (map->instance_size() > MaxObjectSizeInPagedSpace()) space = LO_SPACE;
   3170   Object* obj;
   3171   { MaybeObject* maybe_obj = Allocate(map, space);
   3172     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   3173   }
   3174 
   3175   // Initialize the JSObject.
   3176   InitializeJSObjectFromMap(JSObject::cast(obj),
   3177                             FixedArray::cast(properties),
   3178                             map);
   3179   ASSERT(JSObject::cast(obj)->HasFastElements());
   3180   return obj;
   3181 }
   3182 
   3183 
   3184 MaybeObject* Heap::AllocateJSObject(JSFunction* constructor,
   3185                                     PretenureFlag pretenure) {
   3186   // Allocate the initial map if absent.
   3187   if (!constructor->has_initial_map()) {
   3188     Object* initial_map;
   3189     { MaybeObject* maybe_initial_map = AllocateInitialMap(constructor);
   3190       if (!maybe_initial_map->ToObject(&initial_map)) return maybe_initial_map;
   3191     }
   3192     constructor->set_initial_map(Map::cast(initial_map));
   3193     Map::cast(initial_map)->set_constructor(constructor);
   3194   }
   3195   // Allocate the object based on the constructors initial map.
   3196   MaybeObject* result =
   3197       AllocateJSObjectFromMap(constructor->initial_map(), pretenure);
   3198 #ifdef DEBUG
   3199   // Make sure result is NOT a global object if valid.
   3200   Object* non_failure;
   3201   ASSERT(!result->ToObject(&non_failure) || !non_failure->IsGlobalObject());
   3202 #endif
   3203   return result;
   3204 }
   3205 
   3206 
   3207 MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) {
   3208   ASSERT(constructor->has_initial_map());
   3209   Map* map = constructor->initial_map();
   3210 
   3211   // Make sure no field properties are described in the initial map.
   3212   // This guarantees us that normalizing the properties does not
   3213   // require us to change property values to JSGlobalPropertyCells.
   3214   ASSERT(map->NextFreePropertyIndex() == 0);
   3215 
   3216   // Make sure we don't have a ton of pre-allocated slots in the
   3217   // global objects. They will be unused once we normalize the object.
   3218   ASSERT(map->unused_property_fields() == 0);
   3219   ASSERT(map->inobject_properties() == 0);
   3220 
   3221   // Initial size of the backing store to avoid resize of the storage during
   3222   // bootstrapping. The size differs between the JS global object ad the
   3223   // builtins object.
   3224   int initial_size = map->instance_type() == JS_GLOBAL_OBJECT_TYPE ? 64 : 512;
   3225 
   3226   // Allocate a dictionary object for backing storage.
   3227   Object* obj;
   3228   { MaybeObject* maybe_obj =
   3229         StringDictionary::Allocate(
   3230             map->NumberOfDescribedProperties() * 2 + initial_size);
   3231     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   3232   }
   3233   StringDictionary* dictionary = StringDictionary::cast(obj);
   3234 
   3235   // The global object might be created from an object template with accessors.
   3236   // Fill these accessors into the dictionary.
   3237   DescriptorArray* descs = map->instance_descriptors();
   3238   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   3239     PropertyDetails details(descs->GetDetails(i));
   3240     ASSERT(details.type() == CALLBACKS);  // Only accessors are expected.
   3241     PropertyDetails d =
   3242         PropertyDetails(details.attributes(), CALLBACKS, details.index());
   3243     Object* value = descs->GetCallbacksObject(i);
   3244     { MaybeObject* maybe_value = AllocateJSGlobalPropertyCell(value);
   3245       if (!maybe_value->ToObject(&value)) return maybe_value;
   3246     }
   3247 
   3248     Object* result;
   3249     { MaybeObject* maybe_result = dictionary->Add(descs->GetKey(i), value, d);
   3250       if (!maybe_result->ToObject(&result)) return maybe_result;
   3251     }
   3252     dictionary = StringDictionary::cast(result);
   3253   }
   3254 
   3255   // Allocate the global object and initialize it with the backing store.
   3256   { MaybeObject* maybe_obj = Allocate(map, OLD_POINTER_SPACE);
   3257     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   3258   }
   3259   JSObject* global = JSObject::cast(obj);
   3260   InitializeJSObjectFromMap(global, dictionary, map);
   3261 
   3262   // Create a new map for the global object.
   3263   { MaybeObject* maybe_obj = map->CopyDropDescriptors();
   3264     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   3265   }
   3266   Map* new_map = Map::cast(obj);
   3267 
   3268   // Setup the global object as a normalized object.
   3269   global->set_map(new_map);
   3270   global->map()->set_instance_descriptors(empty_descriptor_array());
   3271   global->set_properties(dictionary);
   3272 
   3273   // Make sure result is a global object with properties in dictionary.
   3274   ASSERT(global->IsGlobalObject());
   3275   ASSERT(!global->HasFastProperties());
   3276   return global;
   3277 }
   3278 
   3279 
   3280 MaybeObject* Heap::CopyJSObject(JSObject* source) {
   3281   // Never used to copy functions.  If functions need to be copied we
   3282   // have to be careful to clear the literals array.
   3283   ASSERT(!source->IsJSFunction());
   3284 
   3285   // Make the clone.
   3286   Map* map = source->map();
   3287   int object_size = map->instance_size();
   3288   Object* clone;
   3289 
   3290   // If we're forced to always allocate, we use the general allocation
   3291   // functions which may leave us with an object in old space.
   3292   if (always_allocate()) {
   3293     { MaybeObject* maybe_clone =
   3294           AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE);
   3295       if (!maybe_clone->ToObject(&clone)) return maybe_clone;
   3296     }
   3297     Address clone_address = HeapObject::cast(clone)->address();
   3298     CopyBlock(clone_address,
   3299               source->address(),
   3300               object_size);
   3301     // Update write barrier for all fields that lie beyond the header.
   3302     RecordWrites(clone_address,
   3303                  JSObject::kHeaderSize,
   3304                  (object_size - JSObject::kHeaderSize) / kPointerSize);
   3305   } else {
   3306     { MaybeObject* maybe_clone = new_space_.AllocateRaw(object_size);
   3307       if (!maybe_clone->ToObject(&clone)) return maybe_clone;
   3308     }
   3309     ASSERT(InNewSpace(clone));
   3310     // Since we know the clone is allocated in new space, we can copy
   3311     // the contents without worrying about updating the write barrier.
   3312     CopyBlock(HeapObject::cast(clone)->address(),
   3313               source->address(),
   3314               object_size);
   3315   }
   3316 
   3317   FixedArray* elements = FixedArray::cast(source->elements());
   3318   FixedArray* properties = FixedArray::cast(source->properties());
   3319   // Update elements if necessary.
   3320   if (elements->length() > 0) {
   3321     Object* elem;
   3322     { MaybeObject* maybe_elem =
   3323           (elements->map() == fixed_cow_array_map()) ?
   3324           elements : CopyFixedArray(elements);
   3325       if (!maybe_elem->ToObject(&elem)) return maybe_elem;
   3326     }
   3327     JSObject::cast(clone)->set_elements(FixedArray::cast(elem));
   3328   }
   3329   // Update properties if necessary.
   3330   if (properties->length() > 0) {
   3331     Object* prop;
   3332     { MaybeObject* maybe_prop = CopyFixedArray(properties);
   3333       if (!maybe_prop->ToObject(&prop)) return maybe_prop;
   3334     }
   3335     JSObject::cast(clone)->set_properties(FixedArray::cast(prop));
   3336   }
   3337   // Return the new clone.
   3338 #ifdef ENABLE_LOGGING_AND_PROFILING
   3339   isolate_->producer_heap_profile()->RecordJSObjectAllocation(clone);
   3340 #endif
   3341   return clone;
   3342 }
   3343 
   3344 
   3345 MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
   3346                                              JSGlobalProxy* object) {
   3347   ASSERT(constructor->has_initial_map());
   3348   Map* map = constructor->initial_map();
   3349 
   3350   // Check that the already allocated object has the same size and type as
   3351   // objects allocated using the constructor.
   3352   ASSERT(map->instance_size() == object->map()->instance_size());
   3353   ASSERT(map->instance_type() == object->map()->instance_type());
   3354 
   3355   // Allocate the backing storage for the properties.
   3356   int prop_size = map->unused_property_fields() - map->inobject_properties();
   3357   Object* properties;
   3358   { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, TENURED);
   3359     if (!maybe_properties->ToObject(&properties)) return maybe_properties;
   3360   }
   3361 
   3362   // Reset the map for the object.
   3363   object->set_map(constructor->initial_map());
   3364 
   3365   // Reinitialize the object from the constructor map.
   3366   InitializeJSObjectFromMap(object, FixedArray::cast(properties), map);
   3367   return object;
   3368 }
   3369 
   3370 
   3371 MaybeObject* Heap::AllocateStringFromAscii(Vector<const char> string,
   3372                                            PretenureFlag pretenure) {
   3373   Object* result;
   3374   { MaybeObject* maybe_result =
   3375         AllocateRawAsciiString(string.length(), pretenure);
   3376     if (!maybe_result->ToObject(&result)) return maybe_result;
   3377   }
   3378 
   3379   // Copy the characters into the new object.
   3380   SeqAsciiString* string_result = SeqAsciiString::cast(result);
   3381   for (int i = 0; i < string.length(); i++) {
   3382     string_result->SeqAsciiStringSet(i, string[i]);
   3383   }
   3384   return result;
   3385 }
   3386 
   3387 
   3388 MaybeObject* Heap::AllocateStringFromUtf8Slow(Vector<const char> string,
   3389                                               PretenureFlag pretenure) {
   3390   // V8 only supports characters in the Basic Multilingual Plane.
   3391   const uc32 kMaxSupportedChar = 0xFFFF;
   3392   // Count the number of characters in the UTF-8 string and check if
   3393   // it is an ASCII string.
   3394   Access<UnicodeCache::Utf8Decoder>
   3395       decoder(isolate_->unicode_cache()->utf8_decoder());
   3396   decoder->Reset(string.start(), string.length());
   3397   int chars = 0;
   3398   while (decoder->has_more()) {
   3399     decoder->GetNext();
   3400     chars++;
   3401   }
   3402 
   3403   Object* result;
   3404   { MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure);
   3405     if (!maybe_result->ToObject(&result)) return maybe_result;
   3406   }
   3407 
   3408   // Convert and copy the characters into the new object.
   3409   String* string_result = String::cast(result);
   3410   decoder->Reset(string.start(), string.length());
   3411   for (int i = 0; i < chars; i++) {
   3412     uc32 r = decoder->GetNext();
   3413     if (r > kMaxSupportedChar) { r = unibrow::Utf8::kBadChar; }
   3414     string_result->Set(i, r);
   3415   }
   3416   return result;
   3417 }
   3418 
   3419 
   3420 MaybeObject* Heap::AllocateStringFromTwoByte(Vector<const uc16> string,
   3421                                              PretenureFlag pretenure) {
   3422   // Check if the string is an ASCII string.
   3423   MaybeObject* maybe_result;
   3424   if (String::IsAscii(string.start(), string.length())) {
   3425     maybe_result = AllocateRawAsciiString(string.length(), pretenure);
   3426   } else {  // It's not an ASCII string.
   3427     maybe_result = AllocateRawTwoByteString(string.length(), pretenure);
   3428   }
   3429   Object* result;
   3430   if (!maybe_result->ToObject(&result)) return maybe_result;
   3431 
   3432   // Copy the characters into the new object, which may be either ASCII or
   3433   // UTF-16.
   3434   String* string_result = String::cast(result);
   3435   for (int i = 0; i < string.length(); i++) {
   3436     string_result->Set(i, string[i]);
   3437   }
   3438   return result;
   3439 }
   3440 
   3441 
   3442 Map* Heap::SymbolMapForString(String* string) {
   3443   // If the string is in new space it cannot be used as a symbol.
   3444   if (InNewSpace(string)) return NULL;
   3445 
   3446   // Find the corresponding symbol map for strings.
   3447   Map* map = string->map();
   3448   if (map == ascii_string_map()) {
   3449     return ascii_symbol_map();
   3450   }
   3451   if (map == string_map()) {
   3452     return symbol_map();
   3453   }
   3454   if (map == cons_string_map()) {
   3455     return cons_symbol_map();
   3456   }
   3457   if (map == cons_ascii_string_map()) {
   3458     return cons_ascii_symbol_map();
   3459   }
   3460   if (map == external_string_map()) {
   3461     return external_symbol_map();
   3462   }
   3463   if (map == external_ascii_string_map()) {
   3464     return external_ascii_symbol_map();
   3465   }
   3466   if (map == external_string_with_ascii_data_map()) {
   3467     return external_symbol_with_ascii_data_map();
   3468   }
   3469 
   3470   // No match found.
   3471   return NULL;
   3472 }
   3473 
   3474 
   3475 MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
   3476                                           int chars,
   3477                                           uint32_t hash_field) {
   3478   ASSERT(chars >= 0);
   3479   // Ensure the chars matches the number of characters in the buffer.
   3480   ASSERT(static_cast<unsigned>(chars) == buffer->Length());
   3481   // Determine whether the string is ascii.
   3482   bool is_ascii = true;
   3483   while (buffer->has_more()) {
   3484     if (buffer->GetNext() > unibrow::Utf8::kMaxOneByteChar) {
   3485       is_ascii = false;
   3486       break;
   3487     }
   3488   }
   3489   buffer->Rewind();
   3490 
   3491   // Compute map and object size.
   3492   int size;
   3493   Map* map;
   3494 
   3495   if (is_ascii) {
   3496     if (chars > SeqAsciiString::kMaxLength) {
   3497       return Failure::OutOfMemoryException();
   3498     }
   3499     map = ascii_symbol_map();
   3500     size = SeqAsciiString::SizeFor(chars);
   3501   } else {
   3502     if (chars > SeqTwoByteString::kMaxLength) {
   3503       return Failure::OutOfMemoryException();
   3504     }
   3505     map = symbol_map();
   3506     size = SeqTwoByteString::SizeFor(chars);
   3507   }
   3508 
   3509   // Allocate string.
   3510   Object* result;
   3511   { MaybeObject* maybe_result = (size > MaxObjectSizeInPagedSpace())
   3512                    ? lo_space_->AllocateRaw(size)
   3513                    : old_data_space_->AllocateRaw(size);
   3514     if (!maybe_result->ToObject(&result)) return maybe_result;
   3515   }
   3516 
   3517   reinterpret_cast<HeapObject*>(result)->set_map(map);
   3518   // Set length and hash fields of the allocated string.
   3519   String* answer = String::cast(result);
   3520   answer->set_length(chars);
   3521   answer->set_hash_field(hash_field);
   3522 
   3523   ASSERT_EQ(size, answer->Size());
   3524 
   3525   // Fill in the characters.
   3526   for (int i = 0; i < chars; i++) {
   3527     answer->Set(i, buffer->GetNext());
   3528   }
   3529   return answer;
   3530 }
   3531 
   3532 
   3533 MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
   3534   if (length < 0 || length > SeqAsciiString::kMaxLength) {
   3535     return Failure::OutOfMemoryException();
   3536   }
   3537 
   3538   int size = SeqAsciiString::SizeFor(length);
   3539   ASSERT(size <= SeqAsciiString::kMaxSize);
   3540 
   3541   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   3542   AllocationSpace retry_space = OLD_DATA_SPACE;
   3543 
   3544   if (space == NEW_SPACE) {
   3545     if (size > kMaxObjectSizeInNewSpace) {
   3546       // Allocate in large object space, retry space will be ignored.
   3547       space = LO_SPACE;
   3548     } else if (size > MaxObjectSizeInPagedSpace()) {
   3549       // Allocate in new space, retry in large object space.
   3550       retry_space = LO_SPACE;
   3551     }
   3552   } else if (space == OLD_DATA_SPACE && size > MaxObjectSizeInPagedSpace()) {
   3553     space = LO_SPACE;
   3554   }
   3555   Object* result;
   3556   { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space);
   3557     if (!maybe_result->ToObject(&result)) return maybe_result;
   3558   }
   3559 
   3560   // Partially initialize the object.
   3561   HeapObject::cast(result)->set_map(ascii_string_map());
   3562   String::cast(result)->set_length(length);
   3563   String::cast(result)->set_hash_field(String::kEmptyHashField);
   3564   ASSERT_EQ(size, HeapObject::cast(result)->Size());
   3565   return result;
   3566 }
   3567 
   3568 
   3569 MaybeObject* Heap::AllocateRawTwoByteString(int length,
   3570                                             PretenureFlag pretenure) {
   3571   if (length < 0 || length > SeqTwoByteString::kMaxLength) {
   3572     return Failure::OutOfMemoryException();
   3573   }
   3574   int size = SeqTwoByteString::SizeFor(length);
   3575   ASSERT(size <= SeqTwoByteString::kMaxSize);
   3576   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   3577   AllocationSpace retry_space = OLD_DATA_SPACE;
   3578 
   3579   if (space == NEW_SPACE) {
   3580     if (size > kMaxObjectSizeInNewSpace) {
   3581       // Allocate in large object space, retry space will be ignored.
   3582       space = LO_SPACE;
   3583     } else if (size > MaxObjectSizeInPagedSpace()) {
   3584       // Allocate in new space, retry in large object space.
   3585       retry_space = LO_SPACE;
   3586     }
   3587   } else if (space == OLD_DATA_SPACE && size > MaxObjectSizeInPagedSpace()) {
   3588     space = LO_SPACE;
   3589   }
   3590   Object* result;
   3591   { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space);
   3592     if (!maybe_result->ToObject(&result)) return maybe_result;
   3593   }
   3594 
   3595   // Partially initialize the object.
   3596   HeapObject::cast(result)->set_map(string_map());
   3597   String::cast(result)->set_length(length);
   3598   String::cast(result)->set_hash_field(String::kEmptyHashField);
   3599   ASSERT_EQ(size, HeapObject::cast(result)->Size());
   3600   return result;
   3601 }
   3602 
   3603 
   3604 MaybeObject* Heap::AllocateEmptyFixedArray() {
   3605   int size = FixedArray::SizeFor(0);
   3606   Object* result;
   3607   { MaybeObject* maybe_result =
   3608         AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE);
   3609     if (!maybe_result->ToObject(&result)) return maybe_result;
   3610   }
   3611   // Initialize the object.
   3612   reinterpret_cast<FixedArray*>(result)->set_map(fixed_array_map());
   3613   reinterpret_cast<FixedArray*>(result)->set_length(0);
   3614   return result;
   3615 }
   3616 
   3617 
   3618 MaybeObject* Heap::AllocateRawFixedArray(int length) {
   3619   if (length < 0 || length > FixedArray::kMaxLength) {
   3620     return Failure::OutOfMemoryException();
   3621   }
   3622   ASSERT(length > 0);
   3623   // Use the general function if we're forced to always allocate.
   3624   if (always_allocate()) return AllocateFixedArray(length, TENURED);
   3625   // Allocate the raw data for a fixed array.
   3626   int size = FixedArray::SizeFor(length);
   3627   return size <= kMaxObjectSizeInNewSpace
   3628       ? new_space_.AllocateRaw(size)
   3629       : lo_space_->AllocateRawFixedArray(size);
   3630 }
   3631 
   3632 
   3633 MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) {
   3634   int len = src->length();
   3635   Object* obj;
   3636   { MaybeObject* maybe_obj = AllocateRawFixedArray(len);
   3637     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   3638   }
   3639   if (InNewSpace(obj)) {
   3640     HeapObject* dst = HeapObject::cast(obj);
   3641     dst->set_map(map);
   3642     CopyBlock(dst->address() + kPointerSize,
   3643               src->address() + kPointerSize,
   3644               FixedArray::SizeFor(len) - kPointerSize);
   3645     return obj;
   3646   }
   3647   HeapObject::cast(obj)->set_map(map);
   3648   FixedArray* result = FixedArray::cast(obj);
   3649   result->set_length(len);
   3650 
   3651   // Copy the content
   3652   AssertNoAllocation no_gc;
   3653   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   3654   for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
   3655   return result;
   3656 }
   3657 
   3658 
   3659 MaybeObject* Heap::AllocateFixedArray(int length) {
   3660   ASSERT(length >= 0);
   3661   if (length == 0) return empty_fixed_array();
   3662   Object* result;
   3663   { MaybeObject* maybe_result = AllocateRawFixedArray(length);
   3664     if (!maybe_result->ToObject(&result)) return maybe_result;
   3665   }
   3666   // Initialize header.
   3667   FixedArray* array = reinterpret_cast<FixedArray*>(result);
   3668   array->set_map(fixed_array_map());
   3669   array->set_length(length);
   3670   // Initialize body.
   3671   ASSERT(!InNewSpace(undefined_value()));
   3672   MemsetPointer(array->data_start(), undefined_value(), length);
   3673   return result;
   3674 }
   3675 
   3676 
   3677 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) {
   3678   if (length < 0 || length > FixedArray::kMaxLength) {
   3679     return Failure::OutOfMemoryException();
   3680   }
   3681 
   3682   AllocationSpace space =
   3683       (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
   3684   int size = FixedArray::SizeFor(length);
   3685   if (space == NEW_SPACE && size > kMaxObjectSizeInNewSpace) {
   3686     // Too big for new space.
   3687     space = LO_SPACE;
   3688   } else if (space == OLD_POINTER_SPACE &&
   3689              size > MaxObjectSizeInPagedSpace()) {
   3690     // Too big for old pointer space.
   3691     space = LO_SPACE;
   3692   }
   3693 
   3694   AllocationSpace retry_space =
   3695       (size <= MaxObjectSizeInPagedSpace()) ? OLD_POINTER_SPACE : LO_SPACE;
   3696 
   3697   return AllocateRaw(size, space, retry_space);
   3698 }
   3699 
   3700 
   3701 MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller(
   3702     Heap* heap,
   3703     int length,
   3704     PretenureFlag pretenure,
   3705     Object* filler) {
   3706   ASSERT(length >= 0);
   3707   ASSERT(heap->empty_fixed_array()->IsFixedArray());
   3708   if (length == 0) return heap->empty_fixed_array();
   3709 
   3710   ASSERT(!heap->InNewSpace(filler));
   3711   Object* result;
   3712   { MaybeObject* maybe_result = heap->AllocateRawFixedArray(length, pretenure);
   3713     if (!maybe_result->ToObject(&result)) return maybe_result;
   3714   }
   3715 
   3716   HeapObject::cast(result)->set_map(heap->fixed_array_map());
   3717   FixedArray* array = FixedArray::cast(result);
   3718   array->set_length(length);
   3719   MemsetPointer(array->data_start(), filler, length);
   3720   return array;
   3721 }
   3722 
   3723 
   3724 MaybeObject* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
   3725   return AllocateFixedArrayWithFiller(this,
   3726                                       length,
   3727                                       pretenure,
   3728                                       undefined_value());
   3729 }
   3730 
   3731 
   3732 MaybeObject* Heap::AllocateFixedArrayWithHoles(int length,
   3733                                                PretenureFlag pretenure) {
   3734   return AllocateFixedArrayWithFiller(this,
   3735                                       length,
   3736                                       pretenure,
   3737                                       the_hole_value());
   3738 }
   3739 
   3740 
   3741 MaybeObject* Heap::AllocateUninitializedFixedArray(int length) {
   3742   if (length == 0) return empty_fixed_array();
   3743 
   3744   Object* obj;
   3745   { MaybeObject* maybe_obj = AllocateRawFixedArray(length);
   3746     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   3747   }
   3748 
   3749   reinterpret_cast<FixedArray*>(obj)->set_map(fixed_array_map());
   3750   FixedArray::cast(obj)->set_length(length);
   3751   return obj;
   3752 }
   3753 
   3754 
   3755 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) {
   3756   Object* result;
   3757   { MaybeObject* maybe_result = AllocateFixedArray(length, pretenure);
   3758     if (!maybe_result->ToObject(&result)) return maybe_result;
   3759   }
   3760   reinterpret_cast<HeapObject*>(result)->set_map(hash_table_map());
   3761   ASSERT(result->IsHashTable());
   3762   return result;
   3763 }
   3764 
   3765 
   3766 MaybeObject* Heap::AllocateGlobalContext() {
   3767   Object* result;
   3768   { MaybeObject* maybe_result =
   3769         AllocateFixedArray(Context::GLOBAL_CONTEXT_SLOTS);
   3770     if (!maybe_result->ToObject(&result)) return maybe_result;
   3771   }
   3772   Context* context = reinterpret_cast<Context*>(result);
   3773   context->set_map(global_context_map());
   3774   ASSERT(context->IsGlobalContext());
   3775   ASSERT(result->IsContext());
   3776   return result;
   3777 }
   3778 
   3779 
   3780 MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
   3781   ASSERT(length >= Context::MIN_CONTEXT_SLOTS);
   3782   Object* result;
   3783   { MaybeObject* maybe_result = AllocateFixedArray(length);
   3784     if (!maybe_result->ToObject(&result)) return maybe_result;
   3785   }
   3786   Context* context = reinterpret_cast<Context*>(result);
   3787   context->set_map(context_map());
   3788   context->set_closure(function);
   3789   context->set_fcontext(context);
   3790   context->set_previous(NULL);
   3791   context->set_extension(NULL);
   3792   context->set_global(function->context()->global());
   3793   ASSERT(!context->IsGlobalContext());
   3794   ASSERT(context->is_function_context());
   3795   ASSERT(result->IsContext());
   3796   return result;
   3797 }
   3798 
   3799 
   3800 MaybeObject* Heap::AllocateWithContext(Context* previous,
   3801                                        JSObject* extension,
   3802                                        bool is_catch_context) {
   3803   Object* result;
   3804   { MaybeObject* maybe_result = AllocateFixedArray(Context::MIN_CONTEXT_SLOTS);
   3805     if (!maybe_result->ToObject(&result)) return maybe_result;
   3806   }
   3807   Context* context = reinterpret_cast<Context*>(result);
   3808   context->set_map(is_catch_context ? catch_context_map() :
   3809       context_map());
   3810   context->set_closure(previous->closure());
   3811   context->set_fcontext(previous->fcontext());
   3812   context->set_previous(previous);
   3813   context->set_extension(extension);
   3814   context->set_global(previous->global());
   3815   ASSERT(!context->IsGlobalContext());
   3816   ASSERT(!context->is_function_context());
   3817   ASSERT(result->IsContext());
   3818   return result;
   3819 }
   3820 
   3821 
   3822 MaybeObject* Heap::AllocateStruct(InstanceType type) {
   3823   Map* map;
   3824   switch (type) {
   3825 #define MAKE_CASE(NAME, Name, name) \
   3826     case NAME##_TYPE: map = name##_map(); break;
   3827 STRUCT_LIST(MAKE_CASE)
   3828 #undef MAKE_CASE
   3829     default:
   3830       UNREACHABLE();
   3831       return Failure::InternalError();
   3832   }
   3833   int size = map->instance_size();
   3834   AllocationSpace space =
   3835       (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : OLD_POINTER_SPACE;
   3836   Object* result;
   3837   { MaybeObject* maybe_result = Allocate(map, space);
   3838     if (!maybe_result->ToObject(&result)) return maybe_result;
   3839   }
   3840   Struct::cast(result)->InitializeBody(size);
   3841   return result;
   3842 }
   3843 
   3844 
   3845 bool Heap::IdleNotification() {
   3846   static const int kIdlesBeforeScavenge = 4;
   3847   static const int kIdlesBeforeMarkSweep = 7;
   3848   static const int kIdlesBeforeMarkCompact = 8;
   3849   static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1;
   3850   static const unsigned int kGCsBetweenCleanup = 4;
   3851 
   3852   if (!last_idle_notification_gc_count_init_) {
   3853     last_idle_notification_gc_count_ = gc_count_;
   3854     last_idle_notification_gc_count_init_ = true;
   3855   }
   3856 
   3857   bool uncommit = true;
   3858   bool finished = false;
   3859 
   3860   // Reset the number of idle notifications received when a number of
   3861   // GCs have taken place. This allows another round of cleanup based
   3862   // on idle notifications if enough work has been carried out to
   3863   // provoke a number of garbage collections.
   3864   if (gc_count_ - last_idle_notification_gc_count_ < kGCsBetweenCleanup) {
   3865     number_idle_notifications_ =
   3866         Min(number_idle_notifications_ + 1, kMaxIdleCount);
   3867   } else {
   3868     number_idle_notifications_ = 0;
   3869     last_idle_notification_gc_count_ = gc_count_;
   3870   }
   3871 
   3872   if (number_idle_notifications_ == kIdlesBeforeScavenge) {
   3873     if (contexts_disposed_ > 0) {
   3874       HistogramTimerScope scope(isolate_->counters()->gc_context());
   3875       CollectAllGarbage(false);
   3876     } else {
   3877       CollectGarbage(NEW_SPACE);
   3878     }
   3879     new_space_.Shrink();
   3880     last_idle_notification_gc_count_ = gc_count_;
   3881   } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) {
   3882     // Before doing the mark-sweep collections we clear the
   3883     // compilation cache to avoid hanging on to source code and
   3884     // generated code for cached functions.
   3885     isolate_->compilation_cache()->Clear();
   3886 
   3887     CollectAllGarbage(false);
   3888     new_space_.Shrink();
   3889     last_idle_notification_gc_count_ = gc_count_;
   3890 
   3891   } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) {
   3892     CollectAllGarbage(true);
   3893     new_space_.Shrink();
   3894     last_idle_notification_gc_count_ = gc_count_;
   3895     number_idle_notifications_ = 0;
   3896     finished = true;
   3897   } else if (contexts_disposed_ > 0) {
   3898     if (FLAG_expose_gc) {
   3899       contexts_disposed_ = 0;
   3900     } else {
   3901       HistogramTimerScope scope(isolate_->counters()->gc_context());
   3902       CollectAllGarbage(false);
   3903       last_idle_notification_gc_count_ = gc_count_;
   3904     }
   3905     // If this is the first idle notification, we reset the
   3906     // notification count to avoid letting idle notifications for
   3907     // context disposal garbage collections start a potentially too
   3908     // aggressive idle GC cycle.
   3909     if (number_idle_notifications_ <= 1) {
   3910       number_idle_notifications_ = 0;
   3911       uncommit = false;
   3912     }
   3913   } else if (number_idle_notifications_ > kIdlesBeforeMarkCompact) {
   3914     // If we have received more than kIdlesBeforeMarkCompact idle
   3915     // notifications we do not perform any cleanup because we don't
   3916     // expect to gain much by doing so.
   3917     finished = true;
   3918   }
   3919 
   3920   // Make sure that we have no pending context disposals and
   3921   // conditionally uncommit from space.
   3922   ASSERT(contexts_disposed_ == 0);
   3923   if (uncommit) UncommitFromSpace();
   3924   return finished;
   3925 }
   3926 
   3927 
   3928 #ifdef DEBUG
   3929 
   3930 void Heap::Print() {
   3931   if (!HasBeenSetup()) return;
   3932   isolate()->PrintStack();
   3933   AllSpaces spaces;
   3934   for (Space* space = spaces.next(); space != NULL; space = spaces.next())
   3935     space->Print();
   3936 }
   3937 
   3938 
   3939 void Heap::ReportCodeStatistics(const char* title) {
   3940   PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title);
   3941   PagedSpace::ResetCodeStatistics();
   3942   // We do not look for code in new space, map space, or old space.  If code
   3943   // somehow ends up in those spaces, we would miss it here.
   3944   code_space_->CollectCodeStatistics();
   3945   lo_space_->CollectCodeStatistics();
   3946   PagedSpace::ReportCodeStatistics();
   3947 }
   3948 
   3949 
   3950 // This function expects that NewSpace's allocated objects histogram is
   3951 // populated (via a call to CollectStatistics or else as a side effect of a
   3952 // just-completed scavenge collection).
   3953 void Heap::ReportHeapStatistics(const char* title) {
   3954   USE(title);
   3955   PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n",
   3956          title, gc_count_);
   3957   PrintF("mark-compact GC : %d\n", mc_count_);
   3958   PrintF("old_gen_promotion_limit_ %" V8_PTR_PREFIX "d\n",
   3959          old_gen_promotion_limit_);
   3960   PrintF("old_gen_allocation_limit_ %" V8_PTR_PREFIX "d\n",
   3961          old_gen_allocation_limit_);
   3962 
   3963   PrintF("\n");
   3964   PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles());
   3965   isolate_->global_handles()->PrintStats();
   3966   PrintF("\n");
   3967 
   3968   PrintF("Heap statistics : ");
   3969   isolate_->memory_allocator()->ReportStatistics();
   3970   PrintF("To space : ");
   3971   new_space_.ReportStatistics();
   3972   PrintF("Old pointer space : ");
   3973   old_pointer_space_->ReportStatistics();
   3974   PrintF("Old data space : ");
   3975   old_data_space_->ReportStatistics();
   3976   PrintF("Code space : ");
   3977   code_space_->ReportStatistics();
   3978   PrintF("Map space : ");
   3979   map_space_->ReportStatistics();
   3980   PrintF("Cell space : ");
   3981   cell_space_->ReportStatistics();
   3982   PrintF("Large object space : ");
   3983   lo_space_->ReportStatistics();
   3984   PrintF(">>>>>> ========================================= >>>>>>\n");
   3985 }
   3986 
   3987 #endif  // DEBUG
   3988 
   3989 bool Heap::Contains(HeapObject* value) {
   3990   return Contains(value->address());
   3991 }
   3992 
   3993 
   3994 bool Heap::Contains(Address addr) {
   3995   if (OS::IsOutsideAllocatedSpace(addr)) return false;
   3996   return HasBeenSetup() &&
   3997     (new_space_.ToSpaceContains(addr) ||
   3998      old_pointer_space_->Contains(addr) ||
   3999      old_data_space_->Contains(addr) ||
   4000      code_space_->Contains(addr) ||
   4001      map_space_->Contains(addr) ||
   4002      cell_space_->Contains(addr) ||
   4003      lo_space_->SlowContains(addr));
   4004 }
   4005 
   4006 
   4007 bool Heap::InSpace(HeapObject* value, AllocationSpace space) {
   4008   return InSpace(value->address(), space);
   4009 }
   4010 
   4011 
   4012 bool Heap::InSpace(Address addr, AllocationSpace space) {
   4013   if (OS::IsOutsideAllocatedSpace(addr)) return false;
   4014   if (!HasBeenSetup()) return false;
   4015 
   4016   switch (space) {
   4017     case NEW_SPACE:
   4018       return new_space_.ToSpaceContains(addr);
   4019     case OLD_POINTER_SPACE:
   4020       return old_pointer_space_->Contains(addr);
   4021     case OLD_DATA_SPACE:
   4022       return old_data_space_->Contains(addr);
   4023     case CODE_SPACE:
   4024       return code_space_->Contains(addr);
   4025     case MAP_SPACE:
   4026       return map_space_->Contains(addr);
   4027     case CELL_SPACE:
   4028       return cell_space_->Contains(addr);
   4029     case LO_SPACE:
   4030       return lo_space_->SlowContains(addr);
   4031   }
   4032 
   4033   return false;
   4034 }
   4035 
   4036 
   4037 #ifdef DEBUG
   4038 static void DummyScavengePointer(HeapObject** p) {
   4039 }
   4040 
   4041 
   4042 static void VerifyPointersUnderWatermark(
   4043     PagedSpace* space,
   4044     DirtyRegionCallback visit_dirty_region) {
   4045   PageIterator it(space, PageIterator::PAGES_IN_USE);
   4046 
   4047   while (it.has_next()) {
   4048     Page* page = it.next();
   4049     Address start = page->ObjectAreaStart();
   4050     Address end = page->AllocationWatermark();
   4051 
   4052     HEAP->IterateDirtyRegions(Page::kAllRegionsDirtyMarks,
   4053                               start,
   4054                               end,
   4055                               visit_dirty_region,
   4056                               &DummyScavengePointer);
   4057   }
   4058 }
   4059 
   4060 
   4061 static void VerifyPointersUnderWatermark(LargeObjectSpace* space) {
   4062   LargeObjectIterator it(space);
   4063   for (HeapObject* object = it.next(); object != NULL; object = it.next()) {
   4064     if (object->IsFixedArray()) {
   4065       Address slot_address = object->address();
   4066       Address end = object->address() + object->Size();
   4067 
   4068       while (slot_address < end) {
   4069         HeapObject** slot = reinterpret_cast<HeapObject**>(slot_address);
   4070         // When we are not in GC the Heap::InNewSpace() predicate
   4071         // checks that pointers which satisfy predicate point into
   4072         // the active semispace.
   4073         HEAP->InNewSpace(*slot);
   4074         slot_address += kPointerSize;
   4075       }
   4076     }
   4077   }
   4078 }
   4079 
   4080 
   4081 void Heap::Verify() {
   4082   ASSERT(HasBeenSetup());
   4083 
   4084   VerifyPointersVisitor visitor;
   4085   IterateRoots(&visitor, VISIT_ONLY_STRONG);
   4086 
   4087   new_space_.Verify();
   4088 
   4089   VerifyPointersAndDirtyRegionsVisitor dirty_regions_visitor;
   4090   old_pointer_space_->Verify(&dirty_regions_visitor);
   4091   map_space_->Verify(&dirty_regions_visitor);
   4092 
   4093   VerifyPointersUnderWatermark(old_pointer_space_,
   4094                                &IteratePointersInDirtyRegion);
   4095   VerifyPointersUnderWatermark(map_space_,
   4096                                &IteratePointersInDirtyMapsRegion);
   4097   VerifyPointersUnderWatermark(lo_space_);
   4098 
   4099   VerifyPageWatermarkValidity(old_pointer_space_, ALL_INVALID);
   4100   VerifyPageWatermarkValidity(map_space_, ALL_INVALID);
   4101 
   4102   VerifyPointersVisitor no_dirty_regions_visitor;
   4103   old_data_space_->Verify(&no_dirty_regions_visitor);
   4104   code_space_->Verify(&no_dirty_regions_visitor);
   4105   cell_space_->Verify(&no_dirty_regions_visitor);
   4106 
   4107   lo_space_->Verify();
   4108 }
   4109 #endif  // DEBUG
   4110 
   4111 
   4112 MaybeObject* Heap::LookupSymbol(Vector<const char> string) {
   4113   Object* symbol = NULL;
   4114   Object* new_table;
   4115   { MaybeObject* maybe_new_table =
   4116         symbol_table()->LookupSymbol(string, &symbol);
   4117     if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
   4118   }
   4119   // Can't use set_symbol_table because SymbolTable::cast knows that
   4120   // SymbolTable is a singleton and checks for identity.
   4121   roots_[kSymbolTableRootIndex] = new_table;
   4122   ASSERT(symbol != NULL);
   4123   return symbol;
   4124 }
   4125 
   4126 
   4127 MaybeObject* Heap::LookupAsciiSymbol(Vector<const char> string) {
   4128   Object* symbol = NULL;
   4129   Object* new_table;
   4130   { MaybeObject* maybe_new_table =
   4131         symbol_table()->LookupAsciiSymbol(string, &symbol);
   4132     if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
   4133   }
   4134   // Can't use set_symbol_table because SymbolTable::cast knows that
   4135   // SymbolTable is a singleton and checks for identity.
   4136   roots_[kSymbolTableRootIndex] = new_table;
   4137   ASSERT(symbol != NULL);
   4138   return symbol;
   4139 }
   4140 
   4141 
   4142 MaybeObject* Heap::LookupTwoByteSymbol(Vector<const uc16> string) {
   4143   Object* symbol = NULL;
   4144   Object* new_table;
   4145   { MaybeObject* maybe_new_table =
   4146         symbol_table()->LookupTwoByteSymbol(string, &symbol);
   4147     if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
   4148   }
   4149   // Can't use set_symbol_table because SymbolTable::cast knows that
   4150   // SymbolTable is a singleton and checks for identity.
   4151   roots_[kSymbolTableRootIndex] = new_table;
   4152   ASSERT(symbol != NULL);
   4153   return symbol;
   4154 }
   4155 
   4156 
   4157 MaybeObject* Heap::LookupSymbol(String* string) {
   4158   if (string->IsSymbol()) return string;
   4159   Object* symbol = NULL;
   4160   Object* new_table;
   4161   { MaybeObject* maybe_new_table =
   4162         symbol_table()->LookupString(string, &symbol);
   4163     if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
   4164   }
   4165   // Can't use set_symbol_table because SymbolTable::cast knows that
   4166   // SymbolTable is a singleton and checks for identity.
   4167   roots_[kSymbolTableRootIndex] = new_table;
   4168   ASSERT(symbol != NULL);
   4169   return symbol;
   4170 }
   4171 
   4172 
   4173 bool Heap::LookupSymbolIfExists(String* string, String** symbol) {
   4174   if (string->IsSymbol()) {
   4175     *symbol = string;
   4176     return true;
   4177   }
   4178   return symbol_table()->LookupSymbolIfExists(string, symbol);
   4179 }
   4180 
   4181 
   4182 #ifdef DEBUG
   4183 void Heap::ZapFromSpace() {
   4184   ASSERT(reinterpret_cast<Object*>(kFromSpaceZapValue)->IsFailure());
   4185   for (Address a = new_space_.FromSpaceLow();
   4186        a < new_space_.FromSpaceHigh();
   4187        a += kPointerSize) {
   4188     Memory::Address_at(a) = kFromSpaceZapValue;
   4189   }
   4190 }
   4191 #endif  // DEBUG
   4192 
   4193 
   4194 bool Heap::IteratePointersInDirtyRegion(Heap* heap,
   4195                                         Address start,
   4196                                         Address end,
   4197                                         ObjectSlotCallback copy_object_func) {
   4198   Address slot_address = start;
   4199   bool pointers_to_new_space_found = false;
   4200 
   4201   while (slot_address < end) {
   4202     Object** slot = reinterpret_cast<Object**>(slot_address);
   4203     if (heap->InNewSpace(*slot)) {
   4204       ASSERT((*slot)->IsHeapObject());
   4205       copy_object_func(reinterpret_cast<HeapObject**>(slot));
   4206       if (heap->InNewSpace(*slot)) {
   4207         ASSERT((*slot)->IsHeapObject());
   4208         pointers_to_new_space_found = true;
   4209       }
   4210     }
   4211     slot_address += kPointerSize;
   4212   }
   4213   return pointers_to_new_space_found;
   4214 }
   4215 
   4216 
   4217 // Compute start address of the first map following given addr.
   4218 static inline Address MapStartAlign(Address addr) {
   4219   Address page = Page::FromAddress(addr)->ObjectAreaStart();
   4220   return page + (((addr - page) + (Map::kSize - 1)) / Map::kSize * Map::kSize);
   4221 }
   4222 
   4223 
   4224 // Compute end address of the first map preceding given addr.
   4225 static inline Address MapEndAlign(Address addr) {
   4226   Address page = Page::FromAllocationTop(addr)->ObjectAreaStart();
   4227   return page + ((addr - page) / Map::kSize * Map::kSize);
   4228 }
   4229 
   4230 
   4231 static bool IteratePointersInDirtyMaps(Address start,
   4232                                        Address end,
   4233                                        ObjectSlotCallback copy_object_func) {
   4234   ASSERT(MapStartAlign(start) == start);
   4235   ASSERT(MapEndAlign(end) == end);
   4236 
   4237   Address map_address = start;
   4238   bool pointers_to_new_space_found = false;
   4239 
   4240   Heap* heap = HEAP;
   4241   while (map_address < end) {
   4242     ASSERT(!heap->InNewSpace(Memory::Object_at(map_address)));
   4243     ASSERT(Memory::Object_at(map_address)->IsMap());
   4244 
   4245     Address pointer_fields_start = map_address + Map::kPointerFieldsBeginOffset;
   4246     Address pointer_fields_end = map_address + Map::kPointerFieldsEndOffset;
   4247 
   4248     if (Heap::IteratePointersInDirtyRegion(heap,
   4249                                            pointer_fields_start,
   4250                                            pointer_fields_end,
   4251                                            copy_object_func)) {
   4252       pointers_to_new_space_found = true;
   4253     }
   4254 
   4255     map_address += Map::kSize;
   4256   }
   4257 
   4258   return pointers_to_new_space_found;
   4259 }
   4260 
   4261 
   4262 bool Heap::IteratePointersInDirtyMapsRegion(
   4263     Heap* heap,
   4264     Address start,
   4265     Address end,
   4266     ObjectSlotCallback copy_object_func) {
   4267   Address map_aligned_start = MapStartAlign(start);
   4268   Address map_aligned_end   = MapEndAlign(end);
   4269 
   4270   bool contains_pointers_to_new_space = false;
   4271 
   4272   if (map_aligned_start != start) {
   4273     Address prev_map = map_aligned_start - Map::kSize;
   4274     ASSERT(Memory::Object_at(prev_map)->IsMap());
   4275 
   4276     Address pointer_fields_start =
   4277         Max(start, prev_map + Map::kPointerFieldsBeginOffset);
   4278 
   4279     Address pointer_fields_end =
   4280         Min(prev_map + Map::kPointerFieldsEndOffset, end);
   4281 
   4282     contains_pointers_to_new_space =
   4283       IteratePointersInDirtyRegion(heap,
   4284                                    pointer_fields_start,
   4285                                    pointer_fields_end,
   4286                                    copy_object_func)
   4287         || contains_pointers_to_new_space;
   4288   }
   4289 
   4290   contains_pointers_to_new_space =
   4291     IteratePointersInDirtyMaps(map_aligned_start,
   4292                                map_aligned_end,
   4293                                copy_object_func)
   4294       || contains_pointers_to_new_space;
   4295 
   4296   if (map_aligned_end != end) {
   4297     ASSERT(Memory::Object_at(map_aligned_end)->IsMap());
   4298 
   4299     Address pointer_fields_start =
   4300         map_aligned_end + Map::kPointerFieldsBeginOffset;
   4301 
   4302     Address pointer_fields_end =
   4303         Min(end, map_aligned_end + Map::kPointerFieldsEndOffset);
   4304 
   4305     contains_pointers_to_new_space =
   4306       IteratePointersInDirtyRegion(heap,
   4307                                    pointer_fields_start,
   4308                                    pointer_fields_end,
   4309                                    copy_object_func)
   4310         || contains_pointers_to_new_space;
   4311   }
   4312 
   4313   return contains_pointers_to_new_space;
   4314 }
   4315 
   4316 
   4317 void Heap::IterateAndMarkPointersToFromSpace(Address start,
   4318                                              Address end,
   4319                                              ObjectSlotCallback callback) {
   4320   Address slot_address = start;
   4321   Page* page = Page::FromAddress(start);
   4322 
   4323   uint32_t marks = page->GetRegionMarks();
   4324 
   4325   while (slot_address < end) {
   4326     Object** slot = reinterpret_cast<Object**>(slot_address);
   4327     if (InFromSpace(*slot)) {
   4328       ASSERT((*slot)->IsHeapObject());
   4329       callback(reinterpret_cast<HeapObject**>(slot));
   4330       if (InNewSpace(*slot)) {
   4331         ASSERT((*slot)->IsHeapObject());
   4332         marks |= page->GetRegionMaskForAddress(slot_address);
   4333       }
   4334     }
   4335     slot_address += kPointerSize;
   4336   }
   4337 
   4338   page->SetRegionMarks(marks);
   4339 }
   4340 
   4341 
   4342 uint32_t Heap::IterateDirtyRegions(
   4343     uint32_t marks,
   4344     Address area_start,
   4345     Address area_end,
   4346     DirtyRegionCallback visit_dirty_region,
   4347     ObjectSlotCallback copy_object_func) {
   4348   uint32_t newmarks = 0;
   4349   uint32_t mask = 1;
   4350 
   4351   if (area_start >= area_end) {
   4352     return newmarks;
   4353   }
   4354 
   4355   Address region_start = area_start;
   4356 
   4357   // area_start does not necessarily coincide with start of the first region.
   4358   // Thus to calculate the beginning of the next region we have to align
   4359   // area_start by Page::kRegionSize.
   4360   Address second_region =
   4361       reinterpret_cast<Address>(
   4362           reinterpret_cast<intptr_t>(area_start + Page::kRegionSize) &
   4363           ~Page::kRegionAlignmentMask);
   4364 
   4365   // Next region might be beyond area_end.
   4366   Address region_end = Min(second_region, area_end);
   4367 
   4368   if (marks & mask) {
   4369     if (visit_dirty_region(this, region_start, region_end, copy_object_func)) {
   4370       newmarks |= mask;
   4371     }
   4372   }
   4373   mask <<= 1;
   4374 
   4375   // Iterate subsequent regions which fully lay inside [area_start, area_end[.
   4376   region_start = region_end;
   4377   region_end = region_start + Page::kRegionSize;
   4378 
   4379   while (region_end <= area_end) {
   4380     if (marks & mask) {
   4381       if (visit_dirty_region(this,
   4382                              region_start,
   4383                              region_end,
   4384                              copy_object_func)) {
   4385         newmarks |= mask;
   4386       }
   4387     }
   4388 
   4389     region_start = region_end;
   4390     region_end = region_start + Page::kRegionSize;
   4391 
   4392     mask <<= 1;
   4393   }
   4394 
   4395   if (region_start != area_end) {
   4396     // A small piece of area left uniterated because area_end does not coincide
   4397     // with region end. Check whether region covering last part of area is
   4398     // dirty.
   4399     if (marks & mask) {
   4400       if (visit_dirty_region(this, region_start, area_end, copy_object_func)) {
   4401         newmarks |= mask;
   4402       }
   4403     }
   4404   }
   4405 
   4406   return newmarks;
   4407 }
   4408 
   4409 
   4410 
   4411 void Heap::IterateDirtyRegions(
   4412     PagedSpace* space,
   4413     DirtyRegionCallback visit_dirty_region,
   4414     ObjectSlotCallback copy_object_func,
   4415     ExpectedPageWatermarkState expected_page_watermark_state) {
   4416 
   4417   PageIterator it(space, PageIterator::PAGES_IN_USE);
   4418 
   4419   while (it.has_next()) {
   4420     Page* page = it.next();
   4421     uint32_t marks = page->GetRegionMarks();
   4422 
   4423     if (marks != Page::kAllRegionsCleanMarks) {
   4424       Address start = page->ObjectAreaStart();
   4425 
   4426       // Do not try to visit pointers beyond page allocation watermark.
   4427       // Page can contain garbage pointers there.
   4428       Address end;
   4429 
   4430       if ((expected_page_watermark_state == WATERMARK_SHOULD_BE_VALID) ||
   4431           page->IsWatermarkValid()) {
   4432         end = page->AllocationWatermark();
   4433       } else {
   4434         end = page->CachedAllocationWatermark();
   4435       }
   4436 
   4437       ASSERT(space == old_pointer_space_ ||
   4438              (space == map_space_ &&
   4439               ((page->ObjectAreaStart() - end) % Map::kSize == 0)));
   4440 
   4441       page->SetRegionMarks(IterateDirtyRegions(marks,
   4442                                                start,
   4443                                                end,
   4444                                                visit_dirty_region,
   4445                                                copy_object_func));
   4446     }
   4447 
   4448     // Mark page watermark as invalid to maintain watermark validity invariant.
   4449     // See Page::FlipMeaningOfInvalidatedWatermarkFlag() for details.
   4450     page->InvalidateWatermark(true);
   4451   }
   4452 }
   4453 
   4454 
   4455 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) {
   4456   IterateStrongRoots(v, mode);
   4457   IterateWeakRoots(v, mode);
   4458 }
   4459 
   4460 
   4461 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) {
   4462   v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex]));
   4463   v->Synchronize("symbol_table");
   4464   if (mode != VISIT_ALL_IN_SCAVENGE) {
   4465     // Scavenge collections have special processing for this.
   4466     external_string_table_.Iterate(v);
   4467   }
   4468   v->Synchronize("external_string_table");
   4469 }
   4470 
   4471 
   4472 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
   4473   v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]);
   4474   v->Synchronize("strong_root_list");
   4475 
   4476   v->VisitPointer(BitCast<Object**>(&hidden_symbol_));
   4477   v->Synchronize("symbol");
   4478 
   4479   isolate_->bootstrapper()->Iterate(v);
   4480   v->Synchronize("bootstrapper");
   4481   isolate_->Iterate(v);
   4482   v->Synchronize("top");
   4483   Relocatable::Iterate(v);
   4484   v->Synchronize("relocatable");
   4485 
   4486 #ifdef ENABLE_DEBUGGER_SUPPORT
   4487   isolate_->debug()->Iterate(v);
   4488 #endif
   4489   v->Synchronize("debug");
   4490   isolate_->compilation_cache()->Iterate(v);
   4491   v->Synchronize("compilationcache");
   4492 
   4493   // Iterate over local handles in handle scopes.
   4494   isolate_->handle_scope_implementer()->Iterate(v);
   4495   v->Synchronize("handlescope");
   4496 
   4497   // Iterate over the builtin code objects and code stubs in the
   4498   // heap. Note that it is not necessary to iterate over code objects
   4499   // on scavenge collections.
   4500   if (mode != VISIT_ALL_IN_SCAVENGE) {
   4501     isolate_->builtins()->IterateBuiltins(v);
   4502   }
   4503   v->Synchronize("builtins");
   4504 
   4505   // Iterate over global handles.
   4506   if (mode == VISIT_ONLY_STRONG) {
   4507     isolate_->global_handles()->IterateStrongRoots(v);
   4508   } else {
   4509     isolate_->global_handles()->IterateAllRoots(v);
   4510   }
   4511   v->Synchronize("globalhandles");
   4512 
   4513   // Iterate over pointers being held by inactive threads.
   4514   isolate_->thread_manager()->Iterate(v);
   4515   v->Synchronize("threadmanager");
   4516 
   4517   // Iterate over the pointers the Serialization/Deserialization code is
   4518   // holding.
   4519   // During garbage collection this keeps the partial snapshot cache alive.
   4520   // During deserialization of the startup snapshot this creates the partial
   4521   // snapshot cache and deserializes the objects it refers to.  During
   4522   // serialization this does nothing, since the partial snapshot cache is
   4523   // empty.  However the next thing we do is create the partial snapshot,
   4524   // filling up the partial snapshot cache with objects it needs as we go.
   4525   SerializerDeserializer::Iterate(v);
   4526   // We don't do a v->Synchronize call here, because in debug mode that will
   4527   // output a flag to the snapshot.  However at this point the serializer and
   4528   // deserializer are deliberately a little unsynchronized (see above) so the
   4529   // checking of the sync flag in the snapshot would fail.
   4530 }
   4531 
   4532 
   4533 // TODO(1236194): Since the heap size is configurable on the command line
   4534 // and through the API, we should gracefully handle the case that the heap
   4535 // size is not big enough to fit all the initial objects.
   4536 bool Heap::ConfigureHeap(int max_semispace_size,
   4537                          int max_old_gen_size,
   4538                          int max_executable_size) {
   4539   if (HasBeenSetup()) return false;
   4540 
   4541   if (max_semispace_size > 0) max_semispace_size_ = max_semispace_size;
   4542 
   4543   if (Snapshot::IsEnabled()) {
   4544     // If we are using a snapshot we always reserve the default amount
   4545     // of memory for each semispace because code in the snapshot has
   4546     // write-barrier code that relies on the size and alignment of new
   4547     // space.  We therefore cannot use a larger max semispace size
   4548     // than the default reserved semispace size.
   4549     if (max_semispace_size_ > reserved_semispace_size_) {
   4550       max_semispace_size_ = reserved_semispace_size_;
   4551     }
   4552   } else {
   4553     // If we are not using snapshots we reserve space for the actual
   4554     // max semispace size.
   4555     reserved_semispace_size_ = max_semispace_size_;
   4556   }
   4557 
   4558   if (max_old_gen_size > 0) max_old_generation_size_ = max_old_gen_size;
   4559   if (max_executable_size > 0) {
   4560     max_executable_size_ = RoundUp(max_executable_size, Page::kPageSize);
   4561   }
   4562 
   4563   // The max executable size must be less than or equal to the max old
   4564   // generation size.
   4565   if (max_executable_size_ > max_old_generation_size_) {
   4566     max_executable_size_ = max_old_generation_size_;
   4567   }
   4568 
   4569   // The new space size must be a power of two to support single-bit testing
   4570   // for containment.
   4571   max_semispace_size_ = RoundUpToPowerOf2(max_semispace_size_);
   4572   reserved_semispace_size_ = RoundUpToPowerOf2(reserved_semispace_size_);
   4573   initial_semispace_size_ = Min(initial_semispace_size_, max_semispace_size_);
   4574   external_allocation_limit_ = 10 * max_semispace_size_;
   4575 
   4576   // The old generation is paged.
   4577   max_old_generation_size_ = RoundUp(max_old_generation_size_, Page::kPageSize);
   4578 
   4579   configured_ = true;
   4580   return true;
   4581 }
   4582 
   4583 
   4584 bool Heap::ConfigureHeapDefault() {
   4585   return ConfigureHeap(FLAG_max_new_space_size / 2 * KB,
   4586                        FLAG_max_old_space_size * MB,
   4587                        FLAG_max_executable_size * MB);
   4588 }
   4589 
   4590 
   4591 void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
   4592   *stats->start_marker = HeapStats::kStartMarker;
   4593   *stats->end_marker = HeapStats::kEndMarker;
   4594   *stats->new_space_size = new_space_.SizeAsInt();
   4595   *stats->new_space_capacity = static_cast<int>(new_space_.Capacity());
   4596   *stats->old_pointer_space_size = old_pointer_space_->Size();
   4597   *stats->old_pointer_space_capacity = old_pointer_space_->Capacity();
   4598   *stats->old_data_space_size = old_data_space_->Size();
   4599   *stats->old_data_space_capacity = old_data_space_->Capacity();
   4600   *stats->code_space_size = code_space_->Size();
   4601   *stats->code_space_capacity = code_space_->Capacity();
   4602   *stats->map_space_size = map_space_->Size();
   4603   *stats->map_space_capacity = map_space_->Capacity();
   4604   *stats->cell_space_size = cell_space_->Size();
   4605   *stats->cell_space_capacity = cell_space_->Capacity();
   4606   *stats->lo_space_size = lo_space_->Size();
   4607   isolate_->global_handles()->RecordStats(stats);
   4608   *stats->memory_allocator_size = isolate()->memory_allocator()->Size();
   4609   *stats->memory_allocator_capacity =
   4610       isolate()->memory_allocator()->Size() +
   4611       isolate()->memory_allocator()->Available();
   4612   *stats->os_error = OS::GetLastError();
   4613       isolate()->memory_allocator()->Available();
   4614   if (take_snapshot) {
   4615     HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
   4616     for (HeapObject* obj = iterator.next();
   4617          obj != NULL;
   4618          obj = iterator.next()) {
   4619       InstanceType type = obj->map()->instance_type();
   4620       ASSERT(0 <= type && type <= LAST_TYPE);
   4621       stats->objects_per_type[type]++;
   4622       stats->size_per_type[type] += obj->Size();
   4623     }
   4624   }
   4625 }
   4626 
   4627 
   4628 intptr_t Heap::PromotedSpaceSize() {
   4629   return old_pointer_space_->Size()
   4630       + old_data_space_->Size()
   4631       + code_space_->Size()
   4632       + map_space_->Size()
   4633       + cell_space_->Size()
   4634       + lo_space_->Size();
   4635 }
   4636 
   4637 
   4638 int Heap::PromotedExternalMemorySize() {
   4639   if (amount_of_external_allocated_memory_
   4640       <= amount_of_external_allocated_memory_at_last_global_gc_) return 0;
   4641   return amount_of_external_allocated_memory_
   4642       - amount_of_external_allocated_memory_at_last_global_gc_;
   4643 }
   4644 
   4645 #ifdef DEBUG
   4646 
   4647 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject.
   4648 static const int kMarkTag = 2;
   4649 
   4650 
   4651 class HeapDebugUtils {
   4652  public:
   4653   explicit HeapDebugUtils(Heap* heap)
   4654     : search_for_any_global_(false),
   4655       search_target_(NULL),
   4656       found_target_(false),
   4657       object_stack_(20),
   4658       heap_(heap) {
   4659   }
   4660 
   4661   class MarkObjectVisitor : public ObjectVisitor {
   4662    public:
   4663     explicit MarkObjectVisitor(HeapDebugUtils* utils) : utils_(utils) { }
   4664 
   4665     void VisitPointers(Object** start, Object** end) {
   4666       // Copy all HeapObject pointers in [start, end)
   4667       for (Object** p = start; p < end; p++) {
   4668         if ((*p)->IsHeapObject())
   4669           utils_->MarkObjectRecursively(p);
   4670       }
   4671     }
   4672 
   4673     HeapDebugUtils* utils_;
   4674   };
   4675 
   4676   void MarkObjectRecursively(Object** p) {
   4677     if (!(*p)->IsHeapObject()) return;
   4678 
   4679     HeapObject* obj = HeapObject::cast(*p);
   4680 
   4681     Object* map = obj->map();
   4682 
   4683     if (!map->IsHeapObject()) return;  // visited before
   4684 
   4685     if (found_target_) return;  // stop if target found
   4686     object_stack_.Add(obj);
   4687     if ((search_for_any_global_ && obj->IsJSGlobalObject()) ||
   4688         (!search_for_any_global_ && (obj == search_target_))) {
   4689       found_target_ = true;
   4690       return;
   4691     }
   4692 
   4693     // not visited yet
   4694     Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map));
   4695 
   4696     Address map_addr = map_p->address();
   4697 
   4698     obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag));
   4699 
   4700     MarkObjectRecursively(&map);
   4701 
   4702     MarkObjectVisitor mark_visitor(this);
   4703 
   4704     obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p),
   4705                      &mark_visitor);
   4706 
   4707     if (!found_target_)  // don't pop if found the target
   4708       object_stack_.RemoveLast();
   4709   }
   4710 
   4711 
   4712   class UnmarkObjectVisitor : public ObjectVisitor {
   4713    public:
   4714     explicit UnmarkObjectVisitor(HeapDebugUtils* utils) : utils_(utils) { }
   4715 
   4716     void VisitPointers(Object** start, Object** end) {
   4717       // Copy all HeapObject pointers in [start, end)
   4718       for (Object** p = start; p < end; p++) {
   4719         if ((*p)->IsHeapObject())
   4720           utils_->UnmarkObjectRecursively(p);
   4721       }
   4722     }
   4723 
   4724     HeapDebugUtils* utils_;
   4725   };
   4726 
   4727 
   4728   void UnmarkObjectRecursively(Object** p) {
   4729     if (!(*p)->IsHeapObject()) return;
   4730 
   4731     HeapObject* obj = HeapObject::cast(*p);
   4732 
   4733     Object* map = obj->map();
   4734 
   4735     if (map->IsHeapObject()) return;  // unmarked already
   4736 
   4737     Address map_addr = reinterpret_cast<Address>(map);
   4738 
   4739     map_addr -= kMarkTag;
   4740 
   4741     ASSERT_TAG_ALIGNED(map_addr);
   4742 
   4743     HeapObject* map_p = HeapObject::FromAddress(map_addr);
   4744 
   4745     obj->set_map(reinterpret_cast<Map*>(map_p));
   4746 
   4747     UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p));
   4748 
   4749     UnmarkObjectVisitor unmark_visitor(this);
   4750 
   4751     obj->IterateBody(Map::cast(map_p)->instance_type(),
   4752                      obj->SizeFromMap(Map::cast(map_p)),
   4753                      &unmark_visitor);
   4754   }
   4755 
   4756 
   4757   void MarkRootObjectRecursively(Object** root) {
   4758     if (search_for_any_global_) {
   4759       ASSERT(search_target_ == NULL);
   4760     } else {
   4761       ASSERT(search_target_->IsHeapObject());
   4762     }
   4763     found_target_ = false;
   4764     object_stack_.Clear();
   4765 
   4766     MarkObjectRecursively(root);
   4767     UnmarkObjectRecursively(root);
   4768 
   4769     if (found_target_) {
   4770       PrintF("=====================================\n");
   4771       PrintF("====        Path to object       ====\n");
   4772       PrintF("=====================================\n\n");
   4773 
   4774       ASSERT(!object_stack_.is_empty());
   4775       for (int i = 0; i < object_stack_.length(); i++) {
   4776         if (i > 0) PrintF("\n     |\n     |\n     V\n\n");
   4777         Object* obj = object_stack_[i];
   4778         obj->Print();
   4779       }
   4780       PrintF("=====================================\n");
   4781     }
   4782   }
   4783 
   4784   // Helper class for visiting HeapObjects recursively.
   4785   class MarkRootVisitor: public ObjectVisitor {
   4786    public:
   4787     explicit MarkRootVisitor(HeapDebugUtils* utils) : utils_(utils) { }
   4788 
   4789     void VisitPointers(Object** start, Object** end) {
   4790       // Visit all HeapObject pointers in [start, end)
   4791       for (Object** p = start; p < end; p++) {
   4792         if ((*p)->IsHeapObject())
   4793           utils_->MarkRootObjectRecursively(p);
   4794       }
   4795     }
   4796 
   4797     HeapDebugUtils* utils_;
   4798   };
   4799 
   4800   bool search_for_any_global_;
   4801   Object* search_target_;
   4802   bool found_target_;
   4803   List<Object*> object_stack_;
   4804   Heap* heap_;
   4805 
   4806   friend class Heap;
   4807 };
   4808 
   4809 #endif
   4810 
   4811 bool Heap::Setup(bool create_heap_objects) {
   4812 #ifdef DEBUG
   4813   debug_utils_ = new HeapDebugUtils(this);
   4814 #endif
   4815 
   4816   // Initialize heap spaces and initial maps and objects. Whenever something
   4817   // goes wrong, just return false. The caller should check the results and
   4818   // call Heap::TearDown() to release allocated memory.
   4819   //
   4820   // If the heap is not yet configured (eg, through the API), configure it.
   4821   // Configuration is based on the flags new-space-size (really the semispace
   4822   // size) and old-space-size if set or the initial values of semispace_size_
   4823   // and old_generation_size_ otherwise.
   4824   if (!configured_) {
   4825     if (!ConfigureHeapDefault()) return false;
   4826   }
   4827 
   4828   gc_initializer_mutex->Lock();
   4829   static bool initialized_gc = false;
   4830   if (!initialized_gc) {
   4831     initialized_gc = true;
   4832     InitializeScavengingVisitorsTables();
   4833     NewSpaceScavenger::Initialize();
   4834     MarkCompactCollector::Initialize();
   4835   }
   4836   gc_initializer_mutex->Unlock();
   4837 
   4838   MarkMapPointersAsEncoded(false);
   4839 
   4840   // Setup memory allocator and reserve a chunk of memory for new
   4841   // space.  The chunk is double the size of the requested reserved
   4842   // new space size to ensure that we can find a pair of semispaces that
   4843   // are contiguous and aligned to their size.
   4844   if (!isolate_->memory_allocator()->Setup(MaxReserved(), MaxExecutableSize()))
   4845       return false;
   4846   void* chunk =
   4847       isolate_->memory_allocator()->ReserveInitialChunk(
   4848           4 * reserved_semispace_size_);
   4849   if (chunk == NULL) return false;
   4850 
   4851   // Align the pair of semispaces to their size, which must be a power
   4852   // of 2.
   4853   Address new_space_start =
   4854       RoundUp(reinterpret_cast<byte*>(chunk), 2 * reserved_semispace_size_);
   4855   if (!new_space_.Setup(new_space_start, 2 * reserved_semispace_size_)) {
   4856     return false;
   4857   }
   4858 
   4859   // Initialize old pointer space.
   4860   old_pointer_space_ =
   4861       new OldSpace(this,
   4862                    max_old_generation_size_,
   4863                    OLD_POINTER_SPACE,
   4864                    NOT_EXECUTABLE);
   4865   if (old_pointer_space_ == NULL) return false;
   4866   if (!old_pointer_space_->Setup(NULL, 0)) return false;
   4867 
   4868   // Initialize old data space.
   4869   old_data_space_ =
   4870       new OldSpace(this,
   4871                    max_old_generation_size_,
   4872                    OLD_DATA_SPACE,
   4873                    NOT_EXECUTABLE);
   4874   if (old_data_space_ == NULL) return false;
   4875   if (!old_data_space_->Setup(NULL, 0)) return false;
   4876 
   4877   // Initialize the code space, set its maximum capacity to the old
   4878   // generation size. It needs executable memory.
   4879   // On 64-bit platform(s), we put all code objects in a 2 GB range of
   4880   // virtual address space, so that they can call each other with near calls.
   4881   if (code_range_size_ > 0) {
   4882     if (!isolate_->code_range()->Setup(code_range_size_)) {
   4883       return false;
   4884     }
   4885   }
   4886 
   4887   code_space_ =
   4888       new OldSpace(this, max_old_generation_size_, CODE_SPACE, EXECUTABLE);
   4889   if (code_space_ == NULL) return false;
   4890   if (!code_space_->Setup(NULL, 0)) return false;
   4891 
   4892   // Initialize map space.
   4893   map_space_ = new MapSpace(this, FLAG_use_big_map_space
   4894       ? max_old_generation_size_
   4895       : MapSpace::kMaxMapPageIndex * Page::kPageSize,
   4896       FLAG_max_map_space_pages,
   4897       MAP_SPACE);
   4898   if (map_space_ == NULL) return false;
   4899   if (!map_space_->Setup(NULL, 0)) return false;
   4900 
   4901   // Initialize global property cell space.
   4902   cell_space_ = new CellSpace(this, max_old_generation_size_, CELL_SPACE);
   4903   if (cell_space_ == NULL) return false;
   4904   if (!cell_space_->Setup(NULL, 0)) return false;
   4905 
   4906   // The large object code space may contain code or data.  We set the memory
   4907   // to be non-executable here for safety, but this means we need to enable it
   4908   // explicitly when allocating large code objects.
   4909   lo_space_ = new LargeObjectSpace(this, LO_SPACE);
   4910   if (lo_space_ == NULL) return false;
   4911   if (!lo_space_->Setup()) return false;
   4912 
   4913   if (create_heap_objects) {
   4914     // Create initial maps.
   4915     if (!CreateInitialMaps()) return false;
   4916     if (!CreateApiObjects()) return false;
   4917 
   4918     // Create initial objects
   4919     if (!CreateInitialObjects()) return false;
   4920 
   4921     global_contexts_list_ = undefined_value();
   4922   }
   4923 
   4924   LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
   4925   LOG(isolate_, IntPtrTEvent("heap-available", Available()));
   4926 
   4927 #ifdef ENABLE_LOGGING_AND_PROFILING
   4928   // This should be called only after initial objects have been created.
   4929   isolate_->producer_heap_profile()->Setup();
   4930 #endif
   4931 
   4932   return true;
   4933 }
   4934 
   4935 
   4936 void Heap::SetStackLimits() {
   4937   ASSERT(isolate_ != NULL);
   4938   ASSERT(isolate_ == isolate());
   4939   // On 64 bit machines, pointers are generally out of range of Smis.  We write
   4940   // something that looks like an out of range Smi to the GC.
   4941 
   4942   // Set up the special root array entries containing the stack limits.
   4943   // These are actually addresses, but the tag makes the GC ignore it.
   4944   roots_[kStackLimitRootIndex] =
   4945       reinterpret_cast<Object*>(
   4946           (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag);
   4947   roots_[kRealStackLimitRootIndex] =
   4948       reinterpret_cast<Object*>(
   4949           (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag);
   4950 }
   4951 
   4952 
   4953 void Heap::TearDown() {
   4954   if (FLAG_print_cumulative_gc_stat) {
   4955     PrintF("\n\n");
   4956     PrintF("gc_count=%d ", gc_count_);
   4957     PrintF("mark_sweep_count=%d ", ms_count_);
   4958     PrintF("mark_compact_count=%d ", mc_count_);
   4959     PrintF("max_gc_pause=%d ", get_max_gc_pause());
   4960     PrintF("min_in_mutator=%d ", get_min_in_mutator());
   4961     PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ",
   4962            get_max_alive_after_gc());
   4963     PrintF("\n\n");
   4964   }
   4965 
   4966   isolate_->global_handles()->TearDown();
   4967 
   4968   external_string_table_.TearDown();
   4969 
   4970   new_space_.TearDown();
   4971 
   4972   if (old_pointer_space_ != NULL) {
   4973     old_pointer_space_->TearDown();
   4974     delete old_pointer_space_;
   4975     old_pointer_space_ = NULL;
   4976   }
   4977 
   4978   if (old_data_space_ != NULL) {
   4979     old_data_space_->TearDown();
   4980     delete old_data_space_;
   4981     old_data_space_ = NULL;
   4982   }
   4983 
   4984   if (code_space_ != NULL) {
   4985     code_space_->TearDown();
   4986     delete code_space_;
   4987     code_space_ = NULL;
   4988   }
   4989 
   4990   if (map_space_ != NULL) {
   4991     map_space_->TearDown();
   4992     delete map_space_;
   4993     map_space_ = NULL;
   4994   }
   4995 
   4996   if (cell_space_ != NULL) {
   4997     cell_space_->TearDown();
   4998     delete cell_space_;
   4999     cell_space_ = NULL;
   5000   }
   5001 
   5002   if (lo_space_ != NULL) {
   5003     lo_space_->TearDown();
   5004     delete lo_space_;
   5005     lo_space_ = NULL;
   5006   }
   5007 
   5008   isolate_->memory_allocator()->TearDown();
   5009 
   5010 #ifdef DEBUG
   5011   delete debug_utils_;
   5012   debug_utils_ = NULL;
   5013 #endif
   5014 }
   5015 
   5016 
   5017 void Heap::Shrink() {
   5018   // Try to shrink all paged spaces.
   5019   PagedSpaces spaces;
   5020   for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next())
   5021     space->Shrink();
   5022 }
   5023 
   5024 
   5025 #ifdef ENABLE_HEAP_PROTECTION
   5026 
   5027 void Heap::Protect() {
   5028   if (HasBeenSetup()) {
   5029     AllSpaces spaces;
   5030     for (Space* space = spaces.next(); space != NULL; space = spaces.next())
   5031       space->Protect();
   5032   }
   5033 }
   5034 
   5035 
   5036 void Heap::Unprotect() {
   5037   if (HasBeenSetup()) {
   5038     AllSpaces spaces;
   5039     for (Space* space = spaces.next(); space != NULL; space = spaces.next())
   5040       space->Unprotect();
   5041   }
   5042 }
   5043 
   5044 #endif
   5045 
   5046 
   5047 void Heap::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
   5048   ASSERT(callback != NULL);
   5049   GCPrologueCallbackPair pair(callback, gc_type);
   5050   ASSERT(!gc_prologue_callbacks_.Contains(pair));
   5051   return gc_prologue_callbacks_.Add(pair);
   5052 }
   5053 
   5054 
   5055 void Heap::RemoveGCPrologueCallback(GCPrologueCallback callback) {
   5056   ASSERT(callback != NULL);
   5057   for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) {
   5058     if (gc_prologue_callbacks_[i].callback == callback) {
   5059       gc_prologue_callbacks_.Remove(i);
   5060       return;
   5061     }
   5062   }
   5063   UNREACHABLE();
   5064 }
   5065 
   5066 
   5067 void Heap::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
   5068   ASSERT(callback != NULL);
   5069   GCEpilogueCallbackPair pair(callback, gc_type);
   5070   ASSERT(!gc_epilogue_callbacks_.Contains(pair));
   5071   return gc_epilogue_callbacks_.Add(pair);
   5072 }
   5073 
   5074 
   5075 void Heap::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
   5076   ASSERT(callback != NULL);
   5077   for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
   5078     if (gc_epilogue_callbacks_[i].callback == callback) {
   5079       gc_epilogue_callbacks_.Remove(i);
   5080       return;
   5081     }
   5082   }
   5083   UNREACHABLE();
   5084 }
   5085 
   5086 
   5087 #ifdef DEBUG
   5088 
   5089 class PrintHandleVisitor: public ObjectVisitor {
   5090  public:
   5091   void VisitPointers(Object** start, Object** end) {
   5092     for (Object** p = start; p < end; p++)
   5093       PrintF("  handle %p to %p\n",
   5094              reinterpret_cast<void*>(p),
   5095              reinterpret_cast<void*>(*p));
   5096   }
   5097 };
   5098 
   5099 void Heap::PrintHandles() {
   5100   PrintF("Handles:\n");
   5101   PrintHandleVisitor v;
   5102   isolate_->handle_scope_implementer()->Iterate(&v);
   5103 }
   5104 
   5105 #endif
   5106 
   5107 
   5108 Space* AllSpaces::next() {
   5109   switch (counter_++) {
   5110     case NEW_SPACE:
   5111       return HEAP->new_space();
   5112     case OLD_POINTER_SPACE:
   5113       return HEAP->old_pointer_space();
   5114     case OLD_DATA_SPACE:
   5115       return HEAP->old_data_space();
   5116     case CODE_SPACE:
   5117       return HEAP->code_space();
   5118     case MAP_SPACE:
   5119       return HEAP->map_space();
   5120     case CELL_SPACE:
   5121       return HEAP->cell_space();
   5122     case LO_SPACE:
   5123       return HEAP->lo_space();
   5124     default:
   5125       return NULL;
   5126   }
   5127 }
   5128 
   5129 
   5130 PagedSpace* PagedSpaces::next() {
   5131   switch (counter_++) {
   5132     case OLD_POINTER_SPACE:
   5133       return HEAP->old_pointer_space();
   5134     case OLD_DATA_SPACE:
   5135       return HEAP->old_data_space();
   5136     case CODE_SPACE:
   5137       return HEAP->code_space();
   5138     case MAP_SPACE:
   5139       return HEAP->map_space();
   5140     case CELL_SPACE:
   5141       return HEAP->cell_space();
   5142     default:
   5143       return NULL;
   5144   }
   5145 }
   5146 
   5147 
   5148 
   5149 OldSpace* OldSpaces::next() {
   5150   switch (counter_++) {
   5151     case OLD_POINTER_SPACE:
   5152       return HEAP->old_pointer_space();
   5153     case OLD_DATA_SPACE:
   5154       return HEAP->old_data_space();
   5155     case CODE_SPACE:
   5156       return HEAP->code_space();
   5157     default:
   5158       return NULL;
   5159   }
   5160 }
   5161 
   5162 
   5163 SpaceIterator::SpaceIterator()
   5164     : current_space_(FIRST_SPACE),
   5165       iterator_(NULL),
   5166       size_func_(NULL) {
   5167 }
   5168 
   5169 
   5170 SpaceIterator::SpaceIterator(HeapObjectCallback size_func)
   5171     : current_space_(FIRST_SPACE),
   5172       iterator_(NULL),
   5173       size_func_(size_func) {
   5174 }
   5175 
   5176 
   5177 SpaceIterator::~SpaceIterator() {
   5178   // Delete active iterator if any.
   5179   delete iterator_;
   5180 }
   5181 
   5182 
   5183 bool SpaceIterator::has_next() {
   5184   // Iterate until no more spaces.
   5185   return current_space_ != LAST_SPACE;
   5186 }
   5187 
   5188 
   5189 ObjectIterator* SpaceIterator::next() {
   5190   if (iterator_ != NULL) {
   5191     delete iterator_;
   5192     iterator_ = NULL;
   5193     // Move to the next space
   5194     current_space_++;
   5195     if (current_space_ > LAST_SPACE) {
   5196       return NULL;
   5197     }
   5198   }
   5199 
   5200   // Return iterator for the new current space.
   5201   return CreateIterator();
   5202 }
   5203 
   5204 
   5205 // Create an iterator for the space to iterate.
   5206 ObjectIterator* SpaceIterator::CreateIterator() {
   5207   ASSERT(iterator_ == NULL);
   5208 
   5209   switch (current_space_) {
   5210     case NEW_SPACE:
   5211       iterator_ = new SemiSpaceIterator(HEAP->new_space(), size_func_);
   5212       break;
   5213     case OLD_POINTER_SPACE:
   5214       iterator_ = new HeapObjectIterator(HEAP->old_pointer_space(), size_func_);
   5215       break;
   5216     case OLD_DATA_SPACE:
   5217       iterator_ = new HeapObjectIterator(HEAP->old_data_space(), size_func_);
   5218       break;
   5219     case CODE_SPACE:
   5220       iterator_ = new HeapObjectIterator(HEAP->code_space(), size_func_);
   5221       break;
   5222     case MAP_SPACE:
   5223       iterator_ = new HeapObjectIterator(HEAP->map_space(), size_func_);
   5224       break;
   5225     case CELL_SPACE:
   5226       iterator_ = new HeapObjectIterator(HEAP->cell_space(), size_func_);
   5227       break;
   5228     case LO_SPACE:
   5229       iterator_ = new LargeObjectIterator(HEAP->lo_space(), size_func_);
   5230       break;
   5231   }
   5232 
   5233   // Return the newly allocated iterator;
   5234   ASSERT(iterator_ != NULL);
   5235   return iterator_;
   5236 }
   5237 
   5238 
   5239 class HeapObjectsFilter {
   5240  public:
   5241   virtual ~HeapObjectsFilter() {}
   5242   virtual bool SkipObject(HeapObject* object) = 0;
   5243 };
   5244 
   5245 
   5246 class FreeListNodesFilter : public HeapObjectsFilter {
   5247  public:
   5248   FreeListNodesFilter() {
   5249     MarkFreeListNodes();
   5250   }
   5251 
   5252   bool SkipObject(HeapObject* object) {
   5253     if (object->IsMarked()) {
   5254       object->ClearMark();
   5255       return true;
   5256     } else {
   5257       return false;
   5258     }
   5259   }
   5260 
   5261  private:
   5262   void MarkFreeListNodes() {
   5263     Heap* heap = HEAP;
   5264     heap->old_pointer_space()->MarkFreeListNodes();
   5265     heap->old_data_space()->MarkFreeListNodes();
   5266     MarkCodeSpaceFreeListNodes(heap);
   5267     heap->map_space()->MarkFreeListNodes();
   5268     heap->cell_space()->MarkFreeListNodes();
   5269   }
   5270 
   5271   void MarkCodeSpaceFreeListNodes(Heap* heap) {
   5272     // For code space, using FreeListNode::IsFreeListNode is OK.
   5273     HeapObjectIterator iter(heap->code_space());
   5274     for (HeapObject* obj = iter.next_object();
   5275          obj != NULL;
   5276          obj = iter.next_object()) {
   5277       if (FreeListNode::IsFreeListNode(obj)) obj->SetMark();
   5278     }
   5279   }
   5280 
   5281   AssertNoAllocation no_alloc;
   5282 };
   5283 
   5284 
   5285 class UnreachableObjectsFilter : public HeapObjectsFilter {
   5286  public:
   5287   UnreachableObjectsFilter() {
   5288     MarkUnreachableObjects();
   5289   }
   5290 
   5291   bool SkipObject(HeapObject* object) {
   5292     if (object->IsMarked()) {
   5293       object->ClearMark();
   5294       return true;
   5295     } else {
   5296       return false;
   5297     }
   5298   }
   5299 
   5300  private:
   5301   class UnmarkingVisitor : public ObjectVisitor {
   5302    public:
   5303     UnmarkingVisitor() : list_(10) {}
   5304 
   5305     void VisitPointers(Object** start, Object** end) {
   5306       for (Object** p = start; p < end; p++) {
   5307         if (!(*p)->IsHeapObject()) continue;
   5308         HeapObject* obj = HeapObject::cast(*p);
   5309         if (obj->IsMarked()) {
   5310           obj->ClearMark();
   5311           list_.Add(obj);
   5312         }
   5313       }
   5314     }
   5315 
   5316     bool can_process() { return !list_.is_empty(); }
   5317 
   5318     void ProcessNext() {
   5319       HeapObject* obj = list_.RemoveLast();
   5320       obj->Iterate(this);
   5321     }
   5322 
   5323    private:
   5324     List<HeapObject*> list_;
   5325   };
   5326 
   5327   void MarkUnreachableObjects() {
   5328     HeapIterator iterator;
   5329     for (HeapObject* obj = iterator.next();
   5330          obj != NULL;
   5331          obj = iterator.next()) {
   5332       obj->SetMark();
   5333     }
   5334     UnmarkingVisitor visitor;
   5335     HEAP->IterateRoots(&visitor, VISIT_ALL);
   5336     while (visitor.can_process())
   5337       visitor.ProcessNext();
   5338   }
   5339 
   5340   AssertNoAllocation no_alloc;
   5341 };
   5342 
   5343 
   5344 HeapIterator::HeapIterator()
   5345     : filtering_(HeapIterator::kNoFiltering),
   5346       filter_(NULL) {
   5347   Init();
   5348 }
   5349 
   5350 
   5351 HeapIterator::HeapIterator(HeapIterator::HeapObjectsFiltering filtering)
   5352     : filtering_(filtering),
   5353       filter_(NULL) {
   5354   Init();
   5355 }
   5356 
   5357 
   5358 HeapIterator::~HeapIterator() {
   5359   Shutdown();
   5360 }
   5361 
   5362 
   5363 void HeapIterator::Init() {
   5364   // Start the iteration.
   5365   space_iterator_ = filtering_ == kNoFiltering ? new SpaceIterator :
   5366       new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject);
   5367   switch (filtering_) {
   5368     case kFilterFreeListNodes:
   5369       filter_ = new FreeListNodesFilter;
   5370       break;
   5371     case kFilterUnreachable:
   5372       filter_ = new UnreachableObjectsFilter;
   5373       break;
   5374     default:
   5375       break;
   5376   }
   5377   object_iterator_ = space_iterator_->next();
   5378 }
   5379 
   5380 
   5381 void HeapIterator::Shutdown() {
   5382 #ifdef DEBUG
   5383   // Assert that in filtering mode we have iterated through all
   5384   // objects. Otherwise, heap will be left in an inconsistent state.
   5385   if (filtering_ != kNoFiltering) {
   5386     ASSERT(object_iterator_ == NULL);
   5387   }
   5388 #endif
   5389   // Make sure the last iterator is deallocated.
   5390   delete space_iterator_;
   5391   space_iterator_ = NULL;
   5392   object_iterator_ = NULL;
   5393   delete filter_;
   5394   filter_ = NULL;
   5395 }
   5396 
   5397 
   5398 HeapObject* HeapIterator::next() {
   5399   if (filter_ == NULL) return NextObject();
   5400 
   5401   HeapObject* obj = NextObject();
   5402   while (obj != NULL && filter_->SkipObject(obj)) obj = NextObject();
   5403   return obj;
   5404 }
   5405 
   5406 
   5407 HeapObject* HeapIterator::NextObject() {
   5408   // No iterator means we are done.
   5409   if (object_iterator_ == NULL) return NULL;
   5410 
   5411   if (HeapObject* obj = object_iterator_->next_object()) {
   5412     // If the current iterator has more objects we are fine.
   5413     return obj;
   5414   } else {
   5415     // Go though the spaces looking for one that has objects.
   5416     while (space_iterator_->has_next()) {
   5417       object_iterator_ = space_iterator_->next();
   5418       if (HeapObject* obj = object_iterator_->next_object()) {
   5419         return obj;
   5420       }
   5421     }
   5422   }
   5423   // Done with the last space.
   5424   object_iterator_ = NULL;
   5425   return NULL;
   5426 }
   5427 
   5428 
   5429 void HeapIterator::reset() {
   5430   // Restart the iterator.
   5431   Shutdown();
   5432   Init();
   5433 }
   5434 
   5435 
   5436 #if defined(DEBUG) || defined(LIVE_OBJECT_LIST)
   5437 
   5438 Object* const PathTracer::kAnyGlobalObject = reinterpret_cast<Object*>(NULL);
   5439 
   5440 class PathTracer::MarkVisitor: public ObjectVisitor {
   5441  public:
   5442   explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
   5443   void VisitPointers(Object** start, Object** end) {
   5444     // Scan all HeapObject pointers in [start, end)
   5445     for (Object** p = start; !tracer_->found() && (p < end); p++) {
   5446       if ((*p)->IsHeapObject())
   5447         tracer_->MarkRecursively(p, this);
   5448     }
   5449   }
   5450 
   5451  private:
   5452   PathTracer* tracer_;
   5453 };
   5454 
   5455 
   5456 class PathTracer::UnmarkVisitor: public ObjectVisitor {
   5457  public:
   5458   explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
   5459   void VisitPointers(Object** start, Object** end) {
   5460     // Scan all HeapObject pointers in [start, end)
   5461     for (Object** p = start; p < end; p++) {
   5462       if ((*p)->IsHeapObject())
   5463         tracer_->UnmarkRecursively(p, this);
   5464     }
   5465   }
   5466 
   5467  private:
   5468   PathTracer* tracer_;
   5469 };
   5470 
   5471 
   5472 void PathTracer::VisitPointers(Object** start, Object** end) {
   5473   bool done = ((what_to_find_ == FIND_FIRST) && found_target_);
   5474   // Visit all HeapObject pointers in [start, end)
   5475   for (Object** p = start; !done && (p < end); p++) {
   5476     if ((*p)->IsHeapObject()) {
   5477       TracePathFrom(p);
   5478       done = ((what_to_find_ == FIND_FIRST) && found_target_);
   5479     }
   5480   }
   5481 }
   5482 
   5483 
   5484 void PathTracer::Reset() {
   5485   found_target_ = false;
   5486   object_stack_.Clear();
   5487 }
   5488 
   5489 
   5490 void PathTracer::TracePathFrom(Object** root) {
   5491   ASSERT((search_target_ == kAnyGlobalObject) ||
   5492          search_target_->IsHeapObject());
   5493   found_target_in_trace_ = false;
   5494   object_stack_.Clear();
   5495 
   5496   MarkVisitor mark_visitor(this);
   5497   MarkRecursively(root, &mark_visitor);
   5498 
   5499   UnmarkVisitor unmark_visitor(this);
   5500   UnmarkRecursively(root, &unmark_visitor);
   5501 
   5502   ProcessResults();
   5503 }
   5504 
   5505 
   5506 void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) {
   5507   if (!(*p)->IsHeapObject()) return;
   5508 
   5509   HeapObject* obj = HeapObject::cast(*p);
   5510 
   5511   Object* map = obj->map();
   5512 
   5513   if (!map->IsHeapObject()) return;  // visited before
   5514 
   5515   if (found_target_in_trace_) return;  // stop if target found
   5516   object_stack_.Add(obj);
   5517   if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) ||
   5518       (obj == search_target_)) {
   5519     found_target_in_trace_ = true;
   5520     found_target_ = true;
   5521     return;
   5522   }
   5523 
   5524   bool is_global_context = obj->IsGlobalContext();
   5525 
   5526   // not visited yet
   5527   Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map));
   5528 
   5529   Address map_addr = map_p->address();
   5530 
   5531   obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag));
   5532 
   5533   // Scan the object body.
   5534   if (is_global_context && (visit_mode_ == VISIT_ONLY_STRONG)) {
   5535     // This is specialized to scan Context's properly.
   5536     Object** start = reinterpret_cast<Object**>(obj->address() +
   5537                                                 Context::kHeaderSize);
   5538     Object** end = reinterpret_cast<Object**>(obj->address() +
   5539         Context::kHeaderSize + Context::FIRST_WEAK_SLOT * kPointerSize);
   5540     mark_visitor->VisitPointers(start, end);
   5541   } else {
   5542     obj->IterateBody(map_p->instance_type(),
   5543                      obj->SizeFromMap(map_p),
   5544                      mark_visitor);
   5545   }
   5546 
   5547   // Scan the map after the body because the body is a lot more interesting
   5548   // when doing leak detection.
   5549   MarkRecursively(&map, mark_visitor);
   5550 
   5551   if (!found_target_in_trace_)  // don't pop if found the target
   5552     object_stack_.RemoveLast();
   5553 }
   5554 
   5555 
   5556 void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) {
   5557   if (!(*p)->IsHeapObject()) return;
   5558 
   5559   HeapObject* obj = HeapObject::cast(*p);
   5560 
   5561   Object* map = obj->map();
   5562 
   5563   if (map->IsHeapObject()) return;  // unmarked already
   5564 
   5565   Address map_addr = reinterpret_cast<Address>(map);
   5566 
   5567   map_addr -= kMarkTag;
   5568 
   5569   ASSERT_TAG_ALIGNED(map_addr);
   5570 
   5571   HeapObject* map_p = HeapObject::FromAddress(map_addr);
   5572 
   5573   obj->set_map(reinterpret_cast<Map*>(map_p));
   5574 
   5575   UnmarkRecursively(reinterpret_cast<Object**>(&map_p), unmark_visitor);
   5576 
   5577   obj->IterateBody(Map::cast(map_p)->instance_type(),
   5578                    obj->SizeFromMap(Map::cast(map_p)),
   5579                    unmark_visitor);
   5580 }
   5581 
   5582 
   5583 void PathTracer::ProcessResults() {
   5584   if (found_target_) {
   5585     PrintF("=====================================\n");
   5586     PrintF("====        Path to object       ====\n");
   5587     PrintF("=====================================\n\n");
   5588 
   5589     ASSERT(!object_stack_.is_empty());
   5590     for (int i = 0; i < object_stack_.length(); i++) {
   5591       if (i > 0) PrintF("\n     |\n     |\n     V\n\n");
   5592       Object* obj = object_stack_[i];
   5593 #ifdef OBJECT_PRINT
   5594       obj->Print();
   5595 #else
   5596       obj->ShortPrint();
   5597 #endif
   5598     }
   5599     PrintF("=====================================\n");
   5600   }
   5601 }
   5602 #endif  // DEBUG || LIVE_OBJECT_LIST
   5603 
   5604 
   5605 #ifdef DEBUG
   5606 // Triggers a depth-first traversal of reachable objects from roots
   5607 // and finds a path to a specific heap object and prints it.
   5608 void Heap::TracePathToObject(Object* target) {
   5609   PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
   5610   IterateRoots(&tracer, VISIT_ONLY_STRONG);
   5611 }
   5612 
   5613 
   5614 // Triggers a depth-first traversal of reachable objects from roots
   5615 // and finds a path to any global object and prints it. Useful for
   5616 // determining the source for leaks of global objects.
   5617 void Heap::TracePathToGlobal() {
   5618   PathTracer tracer(PathTracer::kAnyGlobalObject,
   5619                     PathTracer::FIND_ALL,
   5620                     VISIT_ALL);
   5621   IterateRoots(&tracer, VISIT_ONLY_STRONG);
   5622 }
   5623 #endif
   5624 
   5625 
   5626 static intptr_t CountTotalHolesSize() {
   5627   intptr_t holes_size = 0;
   5628   OldSpaces spaces;
   5629   for (OldSpace* space = spaces.next();
   5630        space != NULL;
   5631        space = spaces.next()) {
   5632     holes_size += space->Waste() + space->AvailableFree();
   5633   }
   5634   return holes_size;
   5635 }
   5636 
   5637 
   5638 GCTracer::GCTracer(Heap* heap)
   5639     : start_time_(0.0),
   5640       start_size_(0),
   5641       gc_count_(0),
   5642       full_gc_count_(0),
   5643       is_compacting_(false),
   5644       marked_count_(0),
   5645       allocated_since_last_gc_(0),
   5646       spent_in_mutator_(0),
   5647       promoted_objects_size_(0),
   5648       heap_(heap) {
   5649   // These two fields reflect the state of the previous full collection.
   5650   // Set them before they are changed by the collector.
   5651   previous_has_compacted_ = heap_->mark_compact_collector_.HasCompacted();
   5652   previous_marked_count_ =
   5653       heap_->mark_compact_collector_.previous_marked_count();
   5654   if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return;
   5655   start_time_ = OS::TimeCurrentMillis();
   5656   start_size_ = heap_->SizeOfObjects();
   5657 
   5658   for (int i = 0; i < Scope::kNumberOfScopes; i++) {
   5659     scopes_[i] = 0;
   5660   }
   5661 
   5662   in_free_list_or_wasted_before_gc_ = CountTotalHolesSize();
   5663 
   5664   allocated_since_last_gc_ =
   5665       heap_->SizeOfObjects() - heap_->alive_after_last_gc_;
   5666 
   5667   if (heap_->last_gc_end_timestamp_ > 0) {
   5668     spent_in_mutator_ = Max(start_time_ - heap_->last_gc_end_timestamp_, 0.0);
   5669   }
   5670 }
   5671 
   5672 
   5673 GCTracer::~GCTracer() {
   5674   // Printf ONE line iff flag is set.
   5675   if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return;
   5676 
   5677   bool first_gc = (heap_->last_gc_end_timestamp_ == 0);
   5678 
   5679   heap_->alive_after_last_gc_ = heap_->SizeOfObjects();
   5680   heap_->last_gc_end_timestamp_ = OS::TimeCurrentMillis();
   5681 
   5682   int time = static_cast<int>(heap_->last_gc_end_timestamp_ - start_time_);
   5683 
   5684   // Update cumulative GC statistics if required.
   5685   if (FLAG_print_cumulative_gc_stat) {
   5686     heap_->max_gc_pause_ = Max(heap_->max_gc_pause_, time);
   5687     heap_->max_alive_after_gc_ = Max(heap_->max_alive_after_gc_,
   5688                                      heap_->alive_after_last_gc_);
   5689     if (!first_gc) {
   5690       heap_->min_in_mutator_ = Min(heap_->min_in_mutator_,
   5691                                    static_cast<int>(spent_in_mutator_));
   5692     }
   5693   }
   5694 
   5695   if (!FLAG_trace_gc_nvp) {
   5696     int external_time = static_cast<int>(scopes_[Scope::EXTERNAL]);
   5697 
   5698     PrintF("%s %.1f -> %.1f MB, ",
   5699            CollectorString(),
   5700            static_cast<double>(start_size_) / MB,
   5701            SizeOfHeapObjects());
   5702 
   5703     if (external_time > 0) PrintF("%d / ", external_time);
   5704     PrintF("%d ms.\n", time);
   5705   } else {
   5706     PrintF("pause=%d ", time);
   5707     PrintF("mutator=%d ",
   5708            static_cast<int>(spent_in_mutator_));
   5709 
   5710     PrintF("gc=");
   5711     switch (collector_) {
   5712       case SCAVENGER:
   5713         PrintF("s");
   5714         break;
   5715       case MARK_COMPACTOR:
   5716         PrintF("%s",
   5717                heap_->mark_compact_collector_.HasCompacted() ? "mc" : "ms");
   5718         break;
   5719       default:
   5720         UNREACHABLE();
   5721     }
   5722     PrintF(" ");
   5723 
   5724     PrintF("external=%d ", static_cast<int>(scopes_[Scope::EXTERNAL]));
   5725     PrintF("mark=%d ", static_cast<int>(scopes_[Scope::MC_MARK]));
   5726     PrintF("sweep=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP]));
   5727     PrintF("sweepns=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP_NEWSPACE]));
   5728     PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT]));
   5729 
   5730     PrintF("total_size_before=%" V8_PTR_PREFIX "d ", start_size_);
   5731     PrintF("total_size_after=%" V8_PTR_PREFIX "d ", heap_->SizeOfObjects());
   5732     PrintF("holes_size_before=%" V8_PTR_PREFIX "d ",
   5733            in_free_list_or_wasted_before_gc_);
   5734     PrintF("holes_size_after=%" V8_PTR_PREFIX "d ", CountTotalHolesSize());
   5735 
   5736     PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc_);
   5737     PrintF("promoted=%" V8_PTR_PREFIX "d ", promoted_objects_size_);
   5738 
   5739     PrintF("\n");
   5740   }
   5741 
   5742 #if defined(ENABLE_LOGGING_AND_PROFILING)
   5743   heap_->PrintShortHeapStatistics();
   5744 #endif
   5745 }
   5746 
   5747 
   5748 const char* GCTracer::CollectorString() {
   5749   switch (collector_) {
   5750     case SCAVENGER:
   5751       return "Scavenge";
   5752     case MARK_COMPACTOR:
   5753       return heap_->mark_compact_collector_.HasCompacted() ? "Mark-compact"
   5754                                                            : "Mark-sweep";
   5755   }
   5756   return "Unknown GC";
   5757 }
   5758 
   5759 
   5760 int KeyedLookupCache::Hash(Map* map, String* name) {
   5761   // Uses only lower 32 bits if pointers are larger.
   5762   uintptr_t addr_hash =
   5763       static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map)) >> kMapHashShift;
   5764   return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask);
   5765 }
   5766 
   5767 
   5768 int KeyedLookupCache::Lookup(Map* map, String* name) {
   5769   int index = Hash(map, name);
   5770   Key& key = keys_[index];
   5771   if ((key.map == map) && key.name->Equals(name)) {
   5772     return field_offsets_[index];
   5773   }
   5774   return kNotFound;
   5775 }
   5776 
   5777 
   5778 void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
   5779   String* symbol;
   5780   if (HEAP->LookupSymbolIfExists(name, &symbol)) {
   5781     int index = Hash(map, symbol);
   5782     Key& key = keys_[index];
   5783     key.map = map;
   5784     key.name = symbol;
   5785     field_offsets_[index] = field_offset;
   5786   }
   5787 }
   5788 
   5789 
   5790 void KeyedLookupCache::Clear() {
   5791   for (int index = 0; index < kLength; index++) keys_[index].map = NULL;
   5792 }
   5793 
   5794 
   5795 void DescriptorLookupCache::Clear() {
   5796   for (int index = 0; index < kLength; index++) keys_[index].array = NULL;
   5797 }
   5798 
   5799 
   5800 #ifdef DEBUG
   5801 void Heap::GarbageCollectionGreedyCheck() {
   5802   ASSERT(FLAG_gc_greedy);
   5803   if (isolate_->bootstrapper()->IsActive()) return;
   5804   if (disallow_allocation_failure()) return;
   5805   CollectGarbage(NEW_SPACE);
   5806 }
   5807 #endif
   5808 
   5809 
   5810 TranscendentalCache::SubCache::SubCache(Type t)
   5811   : type_(t),
   5812     isolate_(Isolate::Current()) {
   5813   uint32_t in0 = 0xffffffffu;  // Bit-pattern for a NaN that isn't
   5814   uint32_t in1 = 0xffffffffu;  // generated by the FPU.
   5815   for (int i = 0; i < kCacheSize; i++) {
   5816     elements_[i].in[0] = in0;
   5817     elements_[i].in[1] = in1;
   5818     elements_[i].output = NULL;
   5819   }
   5820 }
   5821 
   5822 
   5823 void TranscendentalCache::Clear() {
   5824   for (int i = 0; i < kNumberOfCaches; i++) {
   5825     if (caches_[i] != NULL) {
   5826       delete caches_[i];
   5827       caches_[i] = NULL;
   5828     }
   5829   }
   5830 }
   5831 
   5832 
   5833 void ExternalStringTable::CleanUp() {
   5834   int last = 0;
   5835   for (int i = 0; i < new_space_strings_.length(); ++i) {
   5836     if (new_space_strings_[i] == heap_->raw_unchecked_null_value()) continue;
   5837     if (heap_->InNewSpace(new_space_strings_[i])) {
   5838       new_space_strings_[last++] = new_space_strings_[i];
   5839     } else {
   5840       old_space_strings_.Add(new_space_strings_[i]);
   5841     }
   5842   }
   5843   new_space_strings_.Rewind(last);
   5844   last = 0;
   5845   for (int i = 0; i < old_space_strings_.length(); ++i) {
   5846     if (old_space_strings_[i] == heap_->raw_unchecked_null_value()) continue;
   5847     ASSERT(!heap_->InNewSpace(old_space_strings_[i]));
   5848     old_space_strings_[last++] = old_space_strings_[i];
   5849   }
   5850   old_space_strings_.Rewind(last);
   5851   Verify();
   5852 }
   5853 
   5854 
   5855 void ExternalStringTable::TearDown() {
   5856   new_space_strings_.Free();
   5857   old_space_strings_.Free();
   5858 }
   5859 
   5860 
   5861 } }  // namespace v8::internal
   5862