Home | History | Annotate | Download | only in src
      1 // Copyright 2012 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 "cpu-profiler.h"
     36 #include "debug.h"
     37 #include "deoptimizer.h"
     38 #include "global-handles.h"
     39 #include "heap-profiler.h"
     40 #include "incremental-marking.h"
     41 #include "mark-compact.h"
     42 #include "natives.h"
     43 #include "objects-visiting.h"
     44 #include "objects-visiting-inl.h"
     45 #include "once.h"
     46 #include "runtime-profiler.h"
     47 #include "scopeinfo.h"
     48 #include "snapshot.h"
     49 #include "store-buffer.h"
     50 #include "v8threads.h"
     51 #include "v8utils.h"
     52 #include "vm-state-inl.h"
     53 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
     54 #include "regexp-macro-assembler.h"
     55 #include "arm/regexp-macro-assembler-arm.h"
     56 #endif
     57 #if V8_TARGET_ARCH_MIPS && !V8_INTERPRETED_REGEXP
     58 #include "regexp-macro-assembler.h"
     59 #include "mips/regexp-macro-assembler-mips.h"
     60 #endif
     61 
     62 namespace v8 {
     63 namespace internal {
     64 
     65 
     66 Heap::Heap()
     67     : isolate_(NULL),
     68 // semispace_size_ should be a power of 2 and old_generation_size_ should be
     69 // a multiple of Page::kPageSize.
     70 #if V8_TARGET_ARCH_X64
     71 #define LUMP_OF_MEMORY (2 * MB)
     72       code_range_size_(512*MB),
     73 #else
     74 #define LUMP_OF_MEMORY MB
     75       code_range_size_(0),
     76 #endif
     77 #if defined(ANDROID) || V8_TARGET_ARCH_MIPS
     78       reserved_semispace_size_(4 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
     79       max_semispace_size_(4 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
     80       initial_semispace_size_(Page::kPageSize),
     81       max_old_generation_size_(192*MB),
     82       max_executable_size_(max_old_generation_size_),
     83 #else
     84       reserved_semispace_size_(8 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
     85       max_semispace_size_(8 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
     86       initial_semispace_size_(Page::kPageSize),
     87       max_old_generation_size_(700ul * LUMP_OF_MEMORY),
     88       max_executable_size_(256l * LUMP_OF_MEMORY),
     89 #endif
     90 
     91 // Variables set based on semispace_size_ and old_generation_size_ in
     92 // ConfigureHeap (survived_since_last_expansion_, external_allocation_limit_)
     93 // Will be 4 * reserved_semispace_size_ to ensure that young
     94 // generation can be aligned to its size.
     95       survived_since_last_expansion_(0),
     96       sweep_generation_(0),
     97       always_allocate_scope_depth_(0),
     98       linear_allocation_scope_depth_(0),
     99       contexts_disposed_(0),
    100       global_ic_age_(0),
    101       flush_monomorphic_ics_(false),
    102       scan_on_scavenge_pages_(0),
    103       new_space_(this),
    104       old_pointer_space_(NULL),
    105       old_data_space_(NULL),
    106       code_space_(NULL),
    107       map_space_(NULL),
    108       cell_space_(NULL),
    109       property_cell_space_(NULL),
    110       lo_space_(NULL),
    111       gc_state_(NOT_IN_GC),
    112       gc_post_processing_depth_(0),
    113       ms_count_(0),
    114       gc_count_(0),
    115       remembered_unmapped_pages_index_(0),
    116       unflattened_strings_length_(0),
    117 #ifdef DEBUG
    118       allocation_timeout_(0),
    119       disallow_allocation_failure_(false),
    120 #endif  // DEBUG
    121       new_space_high_promotion_mode_active_(false),
    122       old_generation_allocation_limit_(kMinimumOldGenerationAllocationLimit),
    123       size_of_old_gen_at_last_old_space_gc_(0),
    124       external_allocation_limit_(0),
    125       amount_of_external_allocated_memory_(0),
    126       amount_of_external_allocated_memory_at_last_global_gc_(0),
    127       old_gen_exhausted_(false),
    128       store_buffer_rebuilder_(store_buffer()),
    129       hidden_string_(NULL),
    130       global_gc_prologue_callback_(NULL),
    131       global_gc_epilogue_callback_(NULL),
    132       gc_safe_size_of_old_object_(NULL),
    133       total_regexp_code_generated_(0),
    134       tracer_(NULL),
    135       young_survivors_after_last_gc_(0),
    136       high_survival_rate_period_length_(0),
    137       low_survival_rate_period_length_(0),
    138       survival_rate_(0),
    139       previous_survival_rate_trend_(Heap::STABLE),
    140       survival_rate_trend_(Heap::STABLE),
    141       max_gc_pause_(0.0),
    142       total_gc_time_ms_(0.0),
    143       max_alive_after_gc_(0),
    144       min_in_mutator_(kMaxInt),
    145       alive_after_last_gc_(0),
    146       last_gc_end_timestamp_(0.0),
    147       marking_time_(0.0),
    148       sweeping_time_(0.0),
    149       store_buffer_(this),
    150       marking_(this),
    151       incremental_marking_(this),
    152       number_idle_notifications_(0),
    153       last_idle_notification_gc_count_(0),
    154       last_idle_notification_gc_count_init_(false),
    155       mark_sweeps_since_idle_round_started_(0),
    156       gc_count_at_last_idle_gc_(0),
    157       scavenges_since_last_idle_round_(kIdleScavengeThreshold),
    158       gcs_since_last_deopt_(0),
    159 #ifdef VERIFY_HEAP
    160       no_weak_embedded_maps_verification_scope_depth_(0),
    161 #endif
    162       promotion_queue_(this),
    163       configured_(false),
    164       chunks_queued_for_free_(NULL),
    165       relocation_mutex_(NULL) {
    166   // Allow build-time customization of the max semispace size. Building
    167   // V8 with snapshots and a non-default max semispace size is much
    168   // easier if you can define it as part of the build environment.
    169 #if defined(V8_MAX_SEMISPACE_SIZE)
    170   max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE;
    171 #endif
    172 
    173   intptr_t max_virtual = OS::MaxVirtualMemory();
    174 
    175   if (max_virtual > 0) {
    176     if (code_range_size_ > 0) {
    177       // Reserve no more than 1/8 of the memory for the code range.
    178       code_range_size_ = Min(code_range_size_, max_virtual >> 3);
    179     }
    180   }
    181 
    182   memset(roots_, 0, sizeof(roots_[0]) * kRootListLength);
    183   native_contexts_list_ = NULL;
    184   array_buffers_list_ = Smi::FromInt(0);
    185   allocation_sites_list_ = Smi::FromInt(0);
    186   mark_compact_collector_.heap_ = this;
    187   external_string_table_.heap_ = this;
    188   // Put a dummy entry in the remembered pages so we can find the list the
    189   // minidump even if there are no real unmapped pages.
    190   RememberUnmappedPage(NULL, false);
    191 
    192   ClearObjectStats(true);
    193 }
    194 
    195 
    196 intptr_t Heap::Capacity() {
    197   if (!HasBeenSetUp()) return 0;
    198 
    199   return new_space_.Capacity() +
    200       old_pointer_space_->Capacity() +
    201       old_data_space_->Capacity() +
    202       code_space_->Capacity() +
    203       map_space_->Capacity() +
    204       cell_space_->Capacity() +
    205       property_cell_space_->Capacity();
    206 }
    207 
    208 
    209 intptr_t Heap::CommittedMemory() {
    210   if (!HasBeenSetUp()) return 0;
    211 
    212   return new_space_.CommittedMemory() +
    213       old_pointer_space_->CommittedMemory() +
    214       old_data_space_->CommittedMemory() +
    215       code_space_->CommittedMemory() +
    216       map_space_->CommittedMemory() +
    217       cell_space_->CommittedMemory() +
    218       property_cell_space_->CommittedMemory() +
    219       lo_space_->Size();
    220 }
    221 
    222 
    223 size_t Heap::CommittedPhysicalMemory() {
    224   if (!HasBeenSetUp()) return 0;
    225 
    226   return new_space_.CommittedPhysicalMemory() +
    227       old_pointer_space_->CommittedPhysicalMemory() +
    228       old_data_space_->CommittedPhysicalMemory() +
    229       code_space_->CommittedPhysicalMemory() +
    230       map_space_->CommittedPhysicalMemory() +
    231       cell_space_->CommittedPhysicalMemory() +
    232       property_cell_space_->CommittedPhysicalMemory() +
    233       lo_space_->CommittedPhysicalMemory();
    234 }
    235 
    236 
    237 intptr_t Heap::CommittedMemoryExecutable() {
    238   if (!HasBeenSetUp()) return 0;
    239 
    240   return isolate()->memory_allocator()->SizeExecutable();
    241 }
    242 
    243 
    244 intptr_t Heap::Available() {
    245   if (!HasBeenSetUp()) return 0;
    246 
    247   return new_space_.Available() +
    248       old_pointer_space_->Available() +
    249       old_data_space_->Available() +
    250       code_space_->Available() +
    251       map_space_->Available() +
    252       cell_space_->Available() +
    253       property_cell_space_->Available();
    254 }
    255 
    256 
    257 bool Heap::HasBeenSetUp() {
    258   return old_pointer_space_ != NULL &&
    259          old_data_space_ != NULL &&
    260          code_space_ != NULL &&
    261          map_space_ != NULL &&
    262          cell_space_ != NULL &&
    263          property_cell_space_ != NULL &&
    264          lo_space_ != NULL;
    265 }
    266 
    267 
    268 int Heap::GcSafeSizeOfOldObject(HeapObject* object) {
    269   if (IntrusiveMarking::IsMarked(object)) {
    270     return IntrusiveMarking::SizeOfMarkedObject(object);
    271   }
    272   return object->SizeFromMap(object->map());
    273 }
    274 
    275 
    276 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space,
    277                                               const char** reason) {
    278   // Is global GC requested?
    279   if (space != NEW_SPACE) {
    280     isolate_->counters()->gc_compactor_caused_by_request()->Increment();
    281     *reason = "GC in old space requested";
    282     return MARK_COMPACTOR;
    283   }
    284 
    285   if (FLAG_gc_global || (FLAG_stress_compaction && (gc_count_ & 1) != 0)) {
    286     *reason = "GC in old space forced by flags";
    287     return MARK_COMPACTOR;
    288   }
    289 
    290   // Is enough data promoted to justify a global GC?
    291   if (OldGenerationAllocationLimitReached()) {
    292     isolate_->counters()->gc_compactor_caused_by_promoted_data()->Increment();
    293     *reason = "promotion limit reached";
    294     return MARK_COMPACTOR;
    295   }
    296 
    297   // Have allocation in OLD and LO failed?
    298   if (old_gen_exhausted_) {
    299     isolate_->counters()->
    300         gc_compactor_caused_by_oldspace_exhaustion()->Increment();
    301     *reason = "old generations exhausted";
    302     return MARK_COMPACTOR;
    303   }
    304 
    305   // Is there enough space left in OLD to guarantee that a scavenge can
    306   // succeed?
    307   //
    308   // Note that MemoryAllocator->MaxAvailable() undercounts the memory available
    309   // for object promotion. It counts only the bytes that the memory
    310   // allocator has not yet allocated from the OS and assigned to any space,
    311   // and does not count available bytes already in the old space or code
    312   // space.  Undercounting is safe---we may get an unrequested full GC when
    313   // a scavenge would have succeeded.
    314   if (isolate_->memory_allocator()->MaxAvailable() <= new_space_.Size()) {
    315     isolate_->counters()->
    316         gc_compactor_caused_by_oldspace_exhaustion()->Increment();
    317     *reason = "scavenge might not succeed";
    318     return MARK_COMPACTOR;
    319   }
    320 
    321   // Default
    322   *reason = NULL;
    323   return SCAVENGER;
    324 }
    325 
    326 
    327 // TODO(1238405): Combine the infrastructure for --heap-stats and
    328 // --log-gc to avoid the complicated preprocessor and flag testing.
    329 void Heap::ReportStatisticsBeforeGC() {
    330   // Heap::ReportHeapStatistics will also log NewSpace statistics when
    331   // compiled --log-gc is set.  The following logic is used to avoid
    332   // double logging.
    333 #ifdef DEBUG
    334   if (FLAG_heap_stats || FLAG_log_gc) new_space_.CollectStatistics();
    335   if (FLAG_heap_stats) {
    336     ReportHeapStatistics("Before GC");
    337   } else if (FLAG_log_gc) {
    338     new_space_.ReportStatistics();
    339   }
    340   if (FLAG_heap_stats || FLAG_log_gc) new_space_.ClearHistograms();
    341 #else
    342   if (FLAG_log_gc) {
    343     new_space_.CollectStatistics();
    344     new_space_.ReportStatistics();
    345     new_space_.ClearHistograms();
    346   }
    347 #endif  // DEBUG
    348 }
    349 
    350 
    351 void Heap::PrintShortHeapStatistics() {
    352   if (!FLAG_trace_gc_verbose) return;
    353   PrintPID("Memory allocator,   used: %6" V8_PTR_PREFIX "d KB"
    354                ", available: %6" V8_PTR_PREFIX "d KB\n",
    355            isolate_->memory_allocator()->Size() / KB,
    356            isolate_->memory_allocator()->Available() / KB);
    357   PrintPID("New space,          used: %6" V8_PTR_PREFIX "d KB"
    358                ", available: %6" V8_PTR_PREFIX "d KB"
    359                ", committed: %6" V8_PTR_PREFIX "d KB\n",
    360            new_space_.Size() / KB,
    361            new_space_.Available() / KB,
    362            new_space_.CommittedMemory() / KB);
    363   PrintPID("Old pointers,       used: %6" V8_PTR_PREFIX "d KB"
    364                ", available: %6" V8_PTR_PREFIX "d KB"
    365                ", committed: %6" V8_PTR_PREFIX "d KB\n",
    366            old_pointer_space_->SizeOfObjects() / KB,
    367            old_pointer_space_->Available() / KB,
    368            old_pointer_space_->CommittedMemory() / KB);
    369   PrintPID("Old data space,     used: %6" V8_PTR_PREFIX "d KB"
    370                ", available: %6" V8_PTR_PREFIX "d KB"
    371                ", committed: %6" V8_PTR_PREFIX "d KB\n",
    372            old_data_space_->SizeOfObjects() / KB,
    373            old_data_space_->Available() / KB,
    374            old_data_space_->CommittedMemory() / KB);
    375   PrintPID("Code space,         used: %6" V8_PTR_PREFIX "d KB"
    376                ", available: %6" V8_PTR_PREFIX "d KB"
    377                ", committed: %6" V8_PTR_PREFIX "d KB\n",
    378            code_space_->SizeOfObjects() / KB,
    379            code_space_->Available() / KB,
    380            code_space_->CommittedMemory() / KB);
    381   PrintPID("Map space,          used: %6" V8_PTR_PREFIX "d KB"
    382                ", available: %6" V8_PTR_PREFIX "d KB"
    383                ", committed: %6" V8_PTR_PREFIX "d KB\n",
    384            map_space_->SizeOfObjects() / KB,
    385            map_space_->Available() / KB,
    386            map_space_->CommittedMemory() / KB);
    387   PrintPID("Cell space,         used: %6" V8_PTR_PREFIX "d KB"
    388                ", available: %6" V8_PTR_PREFIX "d KB"
    389                ", committed: %6" V8_PTR_PREFIX "d KB\n",
    390            cell_space_->SizeOfObjects() / KB,
    391            cell_space_->Available() / KB,
    392            cell_space_->CommittedMemory() / KB);
    393   PrintPID("PropertyCell space, used: %6" V8_PTR_PREFIX "d KB"
    394                ", available: %6" V8_PTR_PREFIX "d KB"
    395                ", committed: %6" V8_PTR_PREFIX "d KB\n",
    396            property_cell_space_->SizeOfObjects() / KB,
    397            property_cell_space_->Available() / KB,
    398            property_cell_space_->CommittedMemory() / KB);
    399   PrintPID("Large object space, used: %6" V8_PTR_PREFIX "d KB"
    400                ", available: %6" V8_PTR_PREFIX "d KB"
    401                ", committed: %6" V8_PTR_PREFIX "d KB\n",
    402            lo_space_->SizeOfObjects() / KB,
    403            lo_space_->Available() / KB,
    404            lo_space_->CommittedMemory() / KB);
    405   PrintPID("All spaces,         used: %6" V8_PTR_PREFIX "d KB"
    406                ", available: %6" V8_PTR_PREFIX "d KB"
    407                ", committed: %6" V8_PTR_PREFIX "d KB\n",
    408            this->SizeOfObjects() / KB,
    409            this->Available() / KB,
    410            this->CommittedMemory() / KB);
    411   PrintPID("External memory reported: %6" V8_PTR_PREFIX "d KB\n",
    412            amount_of_external_allocated_memory_ / KB);
    413   PrintPID("Total time spent in GC  : %.1f ms\n", total_gc_time_ms_);
    414 }
    415 
    416 
    417 // TODO(1238405): Combine the infrastructure for --heap-stats and
    418 // --log-gc to avoid the complicated preprocessor and flag testing.
    419 void Heap::ReportStatisticsAfterGC() {
    420   // Similar to the before GC, we use some complicated logic to ensure that
    421   // NewSpace statistics are logged exactly once when --log-gc is turned on.
    422 #if defined(DEBUG)
    423   if (FLAG_heap_stats) {
    424     new_space_.CollectStatistics();
    425     ReportHeapStatistics("After GC");
    426   } else if (FLAG_log_gc) {
    427     new_space_.ReportStatistics();
    428   }
    429 #else
    430   if (FLAG_log_gc) new_space_.ReportStatistics();
    431 #endif  // DEBUG
    432 }
    433 
    434 
    435 void Heap::GarbageCollectionPrologue() {
    436   {  AllowHeapAllocation for_the_first_part_of_prologue;
    437     isolate_->transcendental_cache()->Clear();
    438     ClearJSFunctionResultCaches();
    439     gc_count_++;
    440     unflattened_strings_length_ = 0;
    441 
    442     if (FLAG_flush_code && FLAG_flush_code_incrementally) {
    443       mark_compact_collector()->EnableCodeFlushing(true);
    444     }
    445 
    446 #ifdef VERIFY_HEAP
    447     if (FLAG_verify_heap) {
    448       Verify();
    449     }
    450 #endif
    451   }
    452 
    453 #ifdef DEBUG
    454   ASSERT(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC);
    455 
    456   if (FLAG_gc_verbose) Print();
    457 
    458   ReportStatisticsBeforeGC();
    459 #endif  // DEBUG
    460 
    461   store_buffer()->GCPrologue();
    462 }
    463 
    464 
    465 intptr_t Heap::SizeOfObjects() {
    466   intptr_t total = 0;
    467   AllSpaces spaces(this);
    468   for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
    469     total += space->SizeOfObjects();
    470   }
    471   return total;
    472 }
    473 
    474 
    475 void Heap::RepairFreeListsAfterBoot() {
    476   PagedSpaces spaces(this);
    477   for (PagedSpace* space = spaces.next();
    478        space != NULL;
    479        space = spaces.next()) {
    480     space->RepairFreeListsAfterBoot();
    481   }
    482 }
    483 
    484 
    485 void Heap::GarbageCollectionEpilogue() {
    486   store_buffer()->GCEpilogue();
    487 
    488   // In release mode, we only zap the from space under heap verification.
    489   if (Heap::ShouldZapGarbage()) {
    490     ZapFromSpace();
    491   }
    492 
    493 #ifdef VERIFY_HEAP
    494   if (FLAG_verify_heap) {
    495     Verify();
    496   }
    497 #endif
    498 
    499   AllowHeapAllocation for_the_rest_of_the_epilogue;
    500 
    501 #ifdef DEBUG
    502   if (FLAG_print_global_handles) isolate_->global_handles()->Print();
    503   if (FLAG_print_handles) PrintHandles();
    504   if (FLAG_gc_verbose) Print();
    505   if (FLAG_code_stats) ReportCodeStatistics("After GC");
    506 #endif
    507   if (FLAG_deopt_every_n_garbage_collections > 0) {
    508     if (++gcs_since_last_deopt_ == FLAG_deopt_every_n_garbage_collections) {
    509       Deoptimizer::DeoptimizeAll(isolate());
    510       gcs_since_last_deopt_ = 0;
    511     }
    512   }
    513 
    514   isolate_->counters()->alive_after_last_gc()->Set(
    515       static_cast<int>(SizeOfObjects()));
    516 
    517   isolate_->counters()->string_table_capacity()->Set(
    518       string_table()->Capacity());
    519   isolate_->counters()->number_of_symbols()->Set(
    520       string_table()->NumberOfElements());
    521 
    522   if (CommittedMemory() > 0) {
    523     isolate_->counters()->external_fragmentation_total()->AddSample(
    524         static_cast<int>(100 - (SizeOfObjects() * 100.0) / CommittedMemory()));
    525 
    526     isolate_->counters()->heap_fraction_map_space()->AddSample(
    527         static_cast<int>(
    528             (map_space()->CommittedMemory() * 100.0) / CommittedMemory()));
    529     isolate_->counters()->heap_fraction_cell_space()->AddSample(
    530         static_cast<int>(
    531             (cell_space()->CommittedMemory() * 100.0) / CommittedMemory()));
    532     isolate_->counters()->heap_fraction_property_cell_space()->
    533         AddSample(static_cast<int>(
    534             (property_cell_space()->CommittedMemory() * 100.0) /
    535             CommittedMemory()));
    536 
    537     isolate_->counters()->heap_sample_total_committed()->AddSample(
    538         static_cast<int>(CommittedMemory() / KB));
    539     isolate_->counters()->heap_sample_total_used()->AddSample(
    540         static_cast<int>(SizeOfObjects() / KB));
    541     isolate_->counters()->heap_sample_map_space_committed()->AddSample(
    542         static_cast<int>(map_space()->CommittedMemory() / KB));
    543     isolate_->counters()->heap_sample_cell_space_committed()->AddSample(
    544         static_cast<int>(cell_space()->CommittedMemory() / KB));
    545     isolate_->counters()->
    546         heap_sample_property_cell_space_committed()->
    547             AddSample(static_cast<int>(
    548                 property_cell_space()->CommittedMemory() / KB));
    549   }
    550 
    551 #define UPDATE_COUNTERS_FOR_SPACE(space)                                       \
    552   isolate_->counters()->space##_bytes_available()->Set(                        \
    553       static_cast<int>(space()->Available()));                                 \
    554   isolate_->counters()->space##_bytes_committed()->Set(                        \
    555       static_cast<int>(space()->CommittedMemory()));                           \
    556   isolate_->counters()->space##_bytes_used()->Set(                             \
    557       static_cast<int>(space()->SizeOfObjects()));
    558 #define UPDATE_FRAGMENTATION_FOR_SPACE(space)                                  \
    559   if (space()->CommittedMemory() > 0) {                                        \
    560     isolate_->counters()->external_fragmentation_##space()->AddSample(         \
    561         static_cast<int>(100 -                                                 \
    562             (space()->SizeOfObjects() * 100.0) / space()->CommittedMemory())); \
    563   }
    564 #define UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(space)                     \
    565   UPDATE_COUNTERS_FOR_SPACE(space)                                             \
    566   UPDATE_FRAGMENTATION_FOR_SPACE(space)
    567 
    568   UPDATE_COUNTERS_FOR_SPACE(new_space)
    569   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(old_pointer_space)
    570   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(old_data_space)
    571   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(code_space)
    572   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(map_space)
    573   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(cell_space)
    574   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(property_cell_space)
    575   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(lo_space)
    576 #undef UPDATE_COUNTERS_FOR_SPACE
    577 #undef UPDATE_FRAGMENTATION_FOR_SPACE
    578 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE
    579 
    580 #if defined(DEBUG)
    581   ReportStatisticsAfterGC();
    582 #endif  // DEBUG
    583 #ifdef ENABLE_DEBUGGER_SUPPORT
    584   isolate_->debug()->AfterGarbageCollection();
    585 #endif  // ENABLE_DEBUGGER_SUPPORT
    586 }
    587 
    588 
    589 void Heap::CollectAllGarbage(int flags, const char* gc_reason) {
    590   // Since we are ignoring the return value, the exact choice of space does
    591   // not matter, so long as we do not specify NEW_SPACE, which would not
    592   // cause a full GC.
    593   mark_compact_collector_.SetFlags(flags);
    594   CollectGarbage(OLD_POINTER_SPACE, gc_reason);
    595   mark_compact_collector_.SetFlags(kNoGCFlags);
    596 }
    597 
    598 
    599 void Heap::CollectAllAvailableGarbage(const char* gc_reason) {
    600   // Since we are ignoring the return value, the exact choice of space does
    601   // not matter, so long as we do not specify NEW_SPACE, which would not
    602   // cause a full GC.
    603   // Major GC would invoke weak handle callbacks on weakly reachable
    604   // handles, but won't collect weakly reachable objects until next
    605   // major GC.  Therefore if we collect aggressively and weak handle callback
    606   // has been invoked, we rerun major GC to release objects which become
    607   // garbage.
    608   // Note: as weak callbacks can execute arbitrary code, we cannot
    609   // hope that eventually there will be no weak callbacks invocations.
    610   // Therefore stop recollecting after several attempts.
    611   mark_compact_collector()->SetFlags(kMakeHeapIterableMask |
    612                                      kReduceMemoryFootprintMask);
    613   isolate_->compilation_cache()->Clear();
    614   const int kMaxNumberOfAttempts = 7;
    615   const int kMinNumberOfAttempts = 2;
    616   for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) {
    617     if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR, gc_reason, NULL) &&
    618         attempt + 1 >= kMinNumberOfAttempts) {
    619       break;
    620     }
    621   }
    622   mark_compact_collector()->SetFlags(kNoGCFlags);
    623   new_space_.Shrink();
    624   UncommitFromSpace();
    625   incremental_marking()->UncommitMarkingDeque();
    626 }
    627 
    628 
    629 bool Heap::CollectGarbage(AllocationSpace space,
    630                           GarbageCollector collector,
    631                           const char* gc_reason,
    632                           const char* collector_reason) {
    633   // The VM is in the GC state until exiting this function.
    634   VMState<GC> state(isolate_);
    635 
    636 #ifdef DEBUG
    637   // Reset the allocation timeout to the GC interval, but make sure to
    638   // allow at least a few allocations after a collection. The reason
    639   // for this is that we have a lot of allocation sequences and we
    640   // assume that a garbage collection will allow the subsequent
    641   // allocation attempts to go through.
    642   allocation_timeout_ = Max(6, FLAG_gc_interval);
    643 #endif
    644 
    645   if (collector == SCAVENGER && !incremental_marking()->IsStopped()) {
    646     if (FLAG_trace_incremental_marking) {
    647       PrintF("[IncrementalMarking] Scavenge during marking.\n");
    648     }
    649   }
    650 
    651   if (collector == MARK_COMPACTOR &&
    652       !mark_compact_collector()->abort_incremental_marking() &&
    653       !incremental_marking()->IsStopped() &&
    654       !incremental_marking()->should_hurry() &&
    655       FLAG_incremental_marking_steps) {
    656     // Make progress in incremental marking.
    657     const intptr_t kStepSizeWhenDelayedByScavenge = 1 * MB;
    658     incremental_marking()->Step(kStepSizeWhenDelayedByScavenge,
    659                                 IncrementalMarking::NO_GC_VIA_STACK_GUARD);
    660     if (!incremental_marking()->IsComplete()) {
    661       if (FLAG_trace_incremental_marking) {
    662         PrintF("[IncrementalMarking] Delaying MarkSweep.\n");
    663       }
    664       collector = SCAVENGER;
    665       collector_reason = "incremental marking delaying mark-sweep";
    666     }
    667   }
    668 
    669   bool next_gc_likely_to_collect_more = false;
    670 
    671   { GCTracer tracer(this, gc_reason, collector_reason);
    672     ASSERT(AllowHeapAllocation::IsAllowed());
    673     DisallowHeapAllocation no_allocation_during_gc;
    674     GarbageCollectionPrologue();
    675     // The GC count was incremented in the prologue.  Tell the tracer about
    676     // it.
    677     tracer.set_gc_count(gc_count_);
    678 
    679     // Tell the tracer which collector we've selected.
    680     tracer.set_collector(collector);
    681 
    682     {
    683       HistogramTimerScope histogram_timer_scope(
    684           (collector == SCAVENGER) ? isolate_->counters()->gc_scavenger()
    685                                    : isolate_->counters()->gc_compactor());
    686       next_gc_likely_to_collect_more =
    687           PerformGarbageCollection(collector, &tracer);
    688     }
    689 
    690     GarbageCollectionEpilogue();
    691   }
    692 
    693   // Start incremental marking for the next cycle. The heap snapshot
    694   // generator needs incremental marking to stay off after it aborted.
    695   if (!mark_compact_collector()->abort_incremental_marking() &&
    696       incremental_marking()->IsStopped() &&
    697       incremental_marking()->WorthActivating() &&
    698       NextGCIsLikelyToBeFull()) {
    699     incremental_marking()->Start();
    700   }
    701 
    702   return next_gc_likely_to_collect_more;
    703 }
    704 
    705 
    706 int Heap::NotifyContextDisposed() {
    707   if (FLAG_parallel_recompilation) {
    708     // Flush the queued recompilation tasks.
    709     isolate()->optimizing_compiler_thread()->Flush();
    710   }
    711   flush_monomorphic_ics_ = true;
    712   return ++contexts_disposed_;
    713 }
    714 
    715 
    716 void Heap::PerformScavenge() {
    717   GCTracer tracer(this, NULL, NULL);
    718   if (incremental_marking()->IsStopped()) {
    719     PerformGarbageCollection(SCAVENGER, &tracer);
    720   } else {
    721     PerformGarbageCollection(MARK_COMPACTOR, &tracer);
    722   }
    723 }
    724 
    725 
    726 void Heap::MoveElements(FixedArray* array,
    727                         int dst_index,
    728                         int src_index,
    729                         int len) {
    730   if (len == 0) return;
    731 
    732   ASSERT(array->map() != HEAP->fixed_cow_array_map());
    733   Object** dst_objects = array->data_start() + dst_index;
    734   OS::MemMove(dst_objects,
    735               array->data_start() + src_index,
    736               len * kPointerSize);
    737   if (!InNewSpace(array)) {
    738     for (int i = 0; i < len; i++) {
    739       // TODO(hpayer): check store buffer for entries
    740       if (InNewSpace(dst_objects[i])) {
    741         RecordWrite(array->address(), array->OffsetOfElementAt(dst_index + i));
    742       }
    743     }
    744   }
    745   incremental_marking()->RecordWrites(array);
    746 }
    747 
    748 
    749 #ifdef VERIFY_HEAP
    750 // Helper class for verifying the string table.
    751 class StringTableVerifier : public ObjectVisitor {
    752  public:
    753   void VisitPointers(Object** start, Object** end) {
    754     // Visit all HeapObject pointers in [start, end).
    755     for (Object** p = start; p < end; p++) {
    756       if ((*p)->IsHeapObject()) {
    757         // Check that the string is actually internalized.
    758         CHECK((*p)->IsTheHole() || (*p)->IsUndefined() ||
    759               (*p)->IsInternalizedString());
    760       }
    761     }
    762   }
    763 };
    764 
    765 
    766 static void VerifyStringTable() {
    767   StringTableVerifier verifier;
    768   HEAP->string_table()->IterateElements(&verifier);
    769 }
    770 #endif  // VERIFY_HEAP
    771 
    772 
    773 static bool AbortIncrementalMarkingAndCollectGarbage(
    774     Heap* heap,
    775     AllocationSpace space,
    776     const char* gc_reason = NULL) {
    777   heap->mark_compact_collector()->SetFlags(Heap::kAbortIncrementalMarkingMask);
    778   bool result = heap->CollectGarbage(space, gc_reason);
    779   heap->mark_compact_collector()->SetFlags(Heap::kNoGCFlags);
    780   return result;
    781 }
    782 
    783 
    784 void Heap::ReserveSpace(
    785     int *sizes,
    786     Address *locations_out) {
    787   bool gc_performed = true;
    788   int counter = 0;
    789   static const int kThreshold = 20;
    790   while (gc_performed && counter++ < kThreshold) {
    791     gc_performed = false;
    792     ASSERT(NEW_SPACE == FIRST_PAGED_SPACE - 1);
    793     for (int space = NEW_SPACE; space <= LAST_PAGED_SPACE; space++) {
    794       if (sizes[space] != 0) {
    795         MaybeObject* allocation;
    796         if (space == NEW_SPACE) {
    797           allocation = new_space()->AllocateRaw(sizes[space]);
    798         } else {
    799           allocation = paged_space(space)->AllocateRaw(sizes[space]);
    800         }
    801         FreeListNode* node;
    802         if (!allocation->To<FreeListNode>(&node)) {
    803           if (space == NEW_SPACE) {
    804             Heap::CollectGarbage(NEW_SPACE,
    805                                  "failed to reserve space in the new space");
    806           } else {
    807             AbortIncrementalMarkingAndCollectGarbage(
    808                 this,
    809                 static_cast<AllocationSpace>(space),
    810                 "failed to reserve space in paged space");
    811           }
    812           gc_performed = true;
    813           break;
    814         } else {
    815           // Mark with a free list node, in case we have a GC before
    816           // deserializing.
    817           node->set_size(this, sizes[space]);
    818           locations_out[space] = node->address();
    819         }
    820       }
    821     }
    822   }
    823 
    824   if (gc_performed) {
    825     // Failed to reserve the space after several attempts.
    826     V8::FatalProcessOutOfMemory("Heap::ReserveSpace");
    827   }
    828 }
    829 
    830 
    831 void Heap::EnsureFromSpaceIsCommitted() {
    832   if (new_space_.CommitFromSpaceIfNeeded()) return;
    833 
    834   // Committing memory to from space failed.
    835   // Memory is exhausted and we will die.
    836   V8::FatalProcessOutOfMemory("Committing semi space failed.");
    837 }
    838 
    839 
    840 void Heap::ClearJSFunctionResultCaches() {
    841   if (isolate_->bootstrapper()->IsActive()) return;
    842 
    843   Object* context = native_contexts_list_;
    844   while (!context->IsUndefined()) {
    845     // Get the caches for this context. GC can happen when the context
    846     // is not fully initialized, so the caches can be undefined.
    847     Object* caches_or_undefined =
    848         Context::cast(context)->get(Context::JSFUNCTION_RESULT_CACHES_INDEX);
    849     if (!caches_or_undefined->IsUndefined()) {
    850       FixedArray* caches = FixedArray::cast(caches_or_undefined);
    851       // Clear the caches:
    852       int length = caches->length();
    853       for (int i = 0; i < length; i++) {
    854         JSFunctionResultCache::cast(caches->get(i))->Clear();
    855       }
    856     }
    857     // Get the next context:
    858     context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
    859   }
    860 }
    861 
    862 
    863 void Heap::ClearNormalizedMapCaches() {
    864   if (isolate_->bootstrapper()->IsActive() &&
    865       !incremental_marking()->IsMarking()) {
    866     return;
    867   }
    868 
    869   Object* context = native_contexts_list_;
    870   while (!context->IsUndefined()) {
    871     // GC can happen when the context is not fully initialized,
    872     // so the cache can be undefined.
    873     Object* cache =
    874         Context::cast(context)->get(Context::NORMALIZED_MAP_CACHE_INDEX);
    875     if (!cache->IsUndefined()) {
    876       NormalizedMapCache::cast(cache)->Clear();
    877     }
    878     context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
    879   }
    880 }
    881 
    882 
    883 void Heap::UpdateSurvivalRateTrend(int start_new_space_size) {
    884   double survival_rate =
    885       (static_cast<double>(young_survivors_after_last_gc_) * 100) /
    886       start_new_space_size;
    887 
    888   if (survival_rate > kYoungSurvivalRateHighThreshold) {
    889     high_survival_rate_period_length_++;
    890   } else {
    891     high_survival_rate_period_length_ = 0;
    892   }
    893 
    894   if (survival_rate < kYoungSurvivalRateLowThreshold) {
    895     low_survival_rate_period_length_++;
    896   } else {
    897     low_survival_rate_period_length_ = 0;
    898   }
    899 
    900   double survival_rate_diff = survival_rate_ - survival_rate;
    901 
    902   if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) {
    903     set_survival_rate_trend(DECREASING);
    904   } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) {
    905     set_survival_rate_trend(INCREASING);
    906   } else {
    907     set_survival_rate_trend(STABLE);
    908   }
    909 
    910   survival_rate_ = survival_rate;
    911 }
    912 
    913 bool Heap::PerformGarbageCollection(GarbageCollector collector,
    914                                     GCTracer* tracer) {
    915   bool next_gc_likely_to_collect_more = false;
    916 
    917   if (collector != SCAVENGER) {
    918     PROFILE(isolate_, CodeMovingGCEvent());
    919   }
    920 
    921 #ifdef VERIFY_HEAP
    922   if (FLAG_verify_heap) {
    923     VerifyStringTable();
    924   }
    925 #endif
    926 
    927   GCType gc_type =
    928       collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge;
    929 
    930   {
    931     GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL);
    932     VMState<EXTERNAL> state(isolate_);
    933     HandleScope handle_scope(isolate_);
    934     CallGCPrologueCallbacks(gc_type, kNoGCCallbackFlags);
    935   }
    936 
    937   EnsureFromSpaceIsCommitted();
    938 
    939   int start_new_space_size = Heap::new_space()->SizeAsInt();
    940 
    941   if (IsHighSurvivalRate()) {
    942     // We speed up the incremental marker if it is running so that it
    943     // does not fall behind the rate of promotion, which would cause a
    944     // constantly growing old space.
    945     incremental_marking()->NotifyOfHighPromotionRate();
    946   }
    947 
    948   if (collector == MARK_COMPACTOR) {
    949     // Perform mark-sweep with optional compaction.
    950     MarkCompact(tracer);
    951     sweep_generation_++;
    952 
    953     UpdateSurvivalRateTrend(start_new_space_size);
    954 
    955     size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSizeOfObjects();
    956 
    957     old_generation_allocation_limit_ =
    958         OldGenerationAllocationLimit(size_of_old_gen_at_last_old_space_gc_);
    959 
    960     old_gen_exhausted_ = false;
    961   } else {
    962     tracer_ = tracer;
    963     Scavenge();
    964     tracer_ = NULL;
    965 
    966     UpdateSurvivalRateTrend(start_new_space_size);
    967   }
    968 
    969   if (!new_space_high_promotion_mode_active_ &&
    970       new_space_.Capacity() == new_space_.MaximumCapacity() &&
    971       IsStableOrIncreasingSurvivalTrend() &&
    972       IsHighSurvivalRate()) {
    973     // Stable high survival rates even though young generation is at
    974     // maximum capacity indicates that most objects will be promoted.
    975     // To decrease scavenger pauses and final mark-sweep pauses, we
    976     // have to limit maximal capacity of the young generation.
    977     SetNewSpaceHighPromotionModeActive(true);
    978     if (FLAG_trace_gc) {
    979       PrintPID("Limited new space size due to high promotion rate: %d MB\n",
    980                new_space_.InitialCapacity() / MB);
    981     }
    982     // Support for global pre-tenuring uses the high promotion mode as a
    983     // heuristic indicator of whether to pretenure or not, we trigger
    984     // deoptimization here to take advantage of pre-tenuring as soon as
    985     // possible.
    986     if (FLAG_pretenuring) {
    987       isolate_->stack_guard()->FullDeopt();
    988     }
    989   } else if (new_space_high_promotion_mode_active_ &&
    990       IsStableOrDecreasingSurvivalTrend() &&
    991       IsLowSurvivalRate()) {
    992     // Decreasing low survival rates might indicate that the above high
    993     // promotion mode is over and we should allow the young generation
    994     // to grow again.
    995     SetNewSpaceHighPromotionModeActive(false);
    996     if (FLAG_trace_gc) {
    997       PrintPID("Unlimited new space size due to low promotion rate: %d MB\n",
    998                new_space_.MaximumCapacity() / MB);
    999     }
   1000     // Trigger deoptimization here to turn off pre-tenuring as soon as
   1001     // possible.
   1002     if (FLAG_pretenuring) {
   1003       isolate_->stack_guard()->FullDeopt();
   1004     }
   1005   }
   1006 
   1007   if (new_space_high_promotion_mode_active_ &&
   1008       new_space_.Capacity() > new_space_.InitialCapacity()) {
   1009     new_space_.Shrink();
   1010   }
   1011 
   1012   isolate_->counters()->objs_since_last_young()->Set(0);
   1013 
   1014   // Callbacks that fire after this point might trigger nested GCs and
   1015   // restart incremental marking, the assertion can't be moved down.
   1016   ASSERT(collector == SCAVENGER || incremental_marking()->IsStopped());
   1017 
   1018   gc_post_processing_depth_++;
   1019   { AllowHeapAllocation allow_allocation;
   1020     GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL);
   1021     next_gc_likely_to_collect_more =
   1022         isolate_->global_handles()->PostGarbageCollectionProcessing(
   1023             collector, tracer);
   1024   }
   1025   gc_post_processing_depth_--;
   1026 
   1027   isolate_->eternal_handles()->PostGarbageCollectionProcessing(this);
   1028 
   1029   // Update relocatables.
   1030   Relocatable::PostGarbageCollectionProcessing();
   1031 
   1032   if (collector == MARK_COMPACTOR) {
   1033     // Register the amount of external allocated memory.
   1034     amount_of_external_allocated_memory_at_last_global_gc_ =
   1035         amount_of_external_allocated_memory_;
   1036   }
   1037 
   1038   {
   1039     GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL);
   1040     VMState<EXTERNAL> state(isolate_);
   1041     HandleScope handle_scope(isolate_);
   1042     CallGCEpilogueCallbacks(gc_type);
   1043   }
   1044 
   1045 #ifdef VERIFY_HEAP
   1046   if (FLAG_verify_heap) {
   1047     VerifyStringTable();
   1048   }
   1049 #endif
   1050 
   1051   return next_gc_likely_to_collect_more;
   1052 }
   1053 
   1054 
   1055 void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) {
   1056   if (gc_type == kGCTypeMarkSweepCompact && global_gc_prologue_callback_) {
   1057     global_gc_prologue_callback_();
   1058   }
   1059   for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) {
   1060     if (gc_type & gc_prologue_callbacks_[i].gc_type) {
   1061       gc_prologue_callbacks_[i].callback(gc_type, flags);
   1062     }
   1063   }
   1064 }
   1065 
   1066 
   1067 void Heap::CallGCEpilogueCallbacks(GCType gc_type) {
   1068   for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
   1069     if (gc_type & gc_epilogue_callbacks_[i].gc_type) {
   1070       gc_epilogue_callbacks_[i].callback(gc_type, kNoGCCallbackFlags);
   1071     }
   1072   }
   1073   if (gc_type == kGCTypeMarkSweepCompact && global_gc_epilogue_callback_) {
   1074     global_gc_epilogue_callback_();
   1075   }
   1076 }
   1077 
   1078 
   1079 void Heap::MarkCompact(GCTracer* tracer) {
   1080   gc_state_ = MARK_COMPACT;
   1081   LOG(isolate_, ResourceEvent("markcompact", "begin"));
   1082 
   1083   mark_compact_collector_.Prepare(tracer);
   1084 
   1085   ms_count_++;
   1086   tracer->set_full_gc_count(ms_count_);
   1087 
   1088   MarkCompactPrologue();
   1089 
   1090   mark_compact_collector_.CollectGarbage();
   1091 
   1092   LOG(isolate_, ResourceEvent("markcompact", "end"));
   1093 
   1094   gc_state_ = NOT_IN_GC;
   1095 
   1096   isolate_->counters()->objs_since_last_full()->Set(0);
   1097 
   1098   contexts_disposed_ = 0;
   1099 
   1100   flush_monomorphic_ics_ = false;
   1101 }
   1102 
   1103 
   1104 void Heap::MarkCompactPrologue() {
   1105   // At any old GC clear the keyed lookup cache to enable collection of unused
   1106   // maps.
   1107   isolate_->keyed_lookup_cache()->Clear();
   1108   isolate_->context_slot_cache()->Clear();
   1109   isolate_->descriptor_lookup_cache()->Clear();
   1110   RegExpResultsCache::Clear(string_split_cache());
   1111   RegExpResultsCache::Clear(regexp_multiple_cache());
   1112 
   1113   isolate_->compilation_cache()->MarkCompactPrologue();
   1114 
   1115   CompletelyClearInstanceofCache();
   1116 
   1117   FlushNumberStringCache();
   1118   if (FLAG_cleanup_code_caches_at_gc) {
   1119     polymorphic_code_cache()->set_cache(undefined_value());
   1120   }
   1121 
   1122   ClearNormalizedMapCaches();
   1123 }
   1124 
   1125 
   1126 // Helper class for copying HeapObjects
   1127 class ScavengeVisitor: public ObjectVisitor {
   1128  public:
   1129   explicit ScavengeVisitor(Heap* heap) : heap_(heap) {}
   1130 
   1131   void VisitPointer(Object** p) { ScavengePointer(p); }
   1132 
   1133   void VisitPointers(Object** start, Object** end) {
   1134     // Copy all HeapObject pointers in [start, end)
   1135     for (Object** p = start; p < end; p++) ScavengePointer(p);
   1136   }
   1137 
   1138  private:
   1139   void ScavengePointer(Object** p) {
   1140     Object* object = *p;
   1141     if (!heap_->InNewSpace(object)) return;
   1142     Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
   1143                          reinterpret_cast<HeapObject*>(object));
   1144   }
   1145 
   1146   Heap* heap_;
   1147 };
   1148 
   1149 
   1150 #ifdef VERIFY_HEAP
   1151 // Visitor class to verify pointers in code or data space do not point into
   1152 // new space.
   1153 class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor {
   1154  public:
   1155   void VisitPointers(Object** start, Object**end) {
   1156     for (Object** current = start; current < end; current++) {
   1157       if ((*current)->IsHeapObject()) {
   1158         CHECK(!HEAP->InNewSpace(HeapObject::cast(*current)));
   1159       }
   1160     }
   1161   }
   1162 };
   1163 
   1164 
   1165 static void VerifyNonPointerSpacePointers() {
   1166   // Verify that there are no pointers to new space in spaces where we
   1167   // do not expect them.
   1168   VerifyNonPointerSpacePointersVisitor v;
   1169   HeapObjectIterator code_it(HEAP->code_space());
   1170   for (HeapObject* object = code_it.Next();
   1171        object != NULL; object = code_it.Next())
   1172     object->Iterate(&v);
   1173 
   1174   // The old data space was normally swept conservatively so that the iterator
   1175   // doesn't work, so we normally skip the next bit.
   1176   if (!HEAP->old_data_space()->was_swept_conservatively()) {
   1177     HeapObjectIterator data_it(HEAP->old_data_space());
   1178     for (HeapObject* object = data_it.Next();
   1179          object != NULL; object = data_it.Next())
   1180       object->Iterate(&v);
   1181   }
   1182 }
   1183 #endif  // VERIFY_HEAP
   1184 
   1185 
   1186 void Heap::CheckNewSpaceExpansionCriteria() {
   1187   if (new_space_.Capacity() < new_space_.MaximumCapacity() &&
   1188       survived_since_last_expansion_ > new_space_.Capacity() &&
   1189       !new_space_high_promotion_mode_active_) {
   1190     // Grow the size of new space if there is room to grow, enough data
   1191     // has survived scavenge since the last expansion and we are not in
   1192     // high promotion mode.
   1193     new_space_.Grow();
   1194     survived_since_last_expansion_ = 0;
   1195   }
   1196 }
   1197 
   1198 
   1199 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) {
   1200   return heap->InNewSpace(*p) &&
   1201       !HeapObject::cast(*p)->map_word().IsForwardingAddress();
   1202 }
   1203 
   1204 
   1205 void Heap::ScavengeStoreBufferCallback(
   1206     Heap* heap,
   1207     MemoryChunk* page,
   1208     StoreBufferEvent event) {
   1209   heap->store_buffer_rebuilder_.Callback(page, event);
   1210 }
   1211 
   1212 
   1213 void StoreBufferRebuilder::Callback(MemoryChunk* page, StoreBufferEvent event) {
   1214   if (event == kStoreBufferStartScanningPagesEvent) {
   1215     start_of_current_page_ = NULL;
   1216     current_page_ = NULL;
   1217   } else if (event == kStoreBufferScanningPageEvent) {
   1218     if (current_page_ != NULL) {
   1219       // If this page already overflowed the store buffer during this iteration.
   1220       if (current_page_->scan_on_scavenge()) {
   1221         // Then we should wipe out the entries that have been added for it.
   1222         store_buffer_->SetTop(start_of_current_page_);
   1223       } else if (store_buffer_->Top() - start_of_current_page_ >=
   1224                  (store_buffer_->Limit() - store_buffer_->Top()) >> 2) {
   1225         // Did we find too many pointers in the previous page?  The heuristic is
   1226         // that no page can take more then 1/5 the remaining slots in the store
   1227         // buffer.
   1228         current_page_->set_scan_on_scavenge(true);
   1229         store_buffer_->SetTop(start_of_current_page_);
   1230       } else {
   1231         // In this case the page we scanned took a reasonable number of slots in
   1232         // the store buffer.  It has now been rehabilitated and is no longer
   1233         // marked scan_on_scavenge.
   1234         ASSERT(!current_page_->scan_on_scavenge());
   1235       }
   1236     }
   1237     start_of_current_page_ = store_buffer_->Top();
   1238     current_page_ = page;
   1239   } else if (event == kStoreBufferFullEvent) {
   1240     // The current page overflowed the store buffer again.  Wipe out its entries
   1241     // in the store buffer and mark it scan-on-scavenge again.  This may happen
   1242     // several times while scanning.
   1243     if (current_page_ == NULL) {
   1244       // Store Buffer overflowed while scanning promoted objects.  These are not
   1245       // in any particular page, though they are likely to be clustered by the
   1246       // allocation routines.
   1247       store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize / 2);
   1248     } else {
   1249       // Store Buffer overflowed while scanning a particular old space page for
   1250       // pointers to new space.
   1251       ASSERT(current_page_ == page);
   1252       ASSERT(page != NULL);
   1253       current_page_->set_scan_on_scavenge(true);
   1254       ASSERT(start_of_current_page_ != store_buffer_->Top());
   1255       store_buffer_->SetTop(start_of_current_page_);
   1256     }
   1257   } else {
   1258     UNREACHABLE();
   1259   }
   1260 }
   1261 
   1262 
   1263 void PromotionQueue::Initialize() {
   1264   // Assumes that a NewSpacePage exactly fits a number of promotion queue
   1265   // entries (where each is a pair of intptr_t). This allows us to simplify
   1266   // the test fpr when to switch pages.
   1267   ASSERT((Page::kPageSize - MemoryChunk::kBodyOffset) % (2 * kPointerSize)
   1268          == 0);
   1269   limit_ = reinterpret_cast<intptr_t*>(heap_->new_space()->ToSpaceStart());
   1270   front_ = rear_ =
   1271       reinterpret_cast<intptr_t*>(heap_->new_space()->ToSpaceEnd());
   1272   emergency_stack_ = NULL;
   1273   guard_ = false;
   1274 }
   1275 
   1276 
   1277 void PromotionQueue::RelocateQueueHead() {
   1278   ASSERT(emergency_stack_ == NULL);
   1279 
   1280   Page* p = Page::FromAllocationTop(reinterpret_cast<Address>(rear_));
   1281   intptr_t* head_start = rear_;
   1282   intptr_t* head_end =
   1283       Min(front_, reinterpret_cast<intptr_t*>(p->area_end()));
   1284 
   1285   int entries_count =
   1286       static_cast<int>(head_end - head_start) / kEntrySizeInWords;
   1287 
   1288   emergency_stack_ = new List<Entry>(2 * entries_count);
   1289 
   1290   while (head_start != head_end) {
   1291     int size = static_cast<int>(*(head_start++));
   1292     HeapObject* obj = reinterpret_cast<HeapObject*>(*(head_start++));
   1293     emergency_stack_->Add(Entry(obj, size));
   1294   }
   1295   rear_ = head_end;
   1296 }
   1297 
   1298 
   1299 class ScavengeWeakObjectRetainer : public WeakObjectRetainer {
   1300  public:
   1301   explicit ScavengeWeakObjectRetainer(Heap* heap) : heap_(heap) { }
   1302 
   1303   virtual Object* RetainAs(Object* object) {
   1304     if (!heap_->InFromSpace(object)) {
   1305       return object;
   1306     }
   1307 
   1308     MapWord map_word = HeapObject::cast(object)->map_word();
   1309     if (map_word.IsForwardingAddress()) {
   1310       return map_word.ToForwardingAddress();
   1311     }
   1312     return NULL;
   1313   }
   1314 
   1315  private:
   1316   Heap* heap_;
   1317 };
   1318 
   1319 
   1320 void Heap::Scavenge() {
   1321   RelocationLock relocation_lock(this);
   1322 
   1323 #ifdef VERIFY_HEAP
   1324   if (FLAG_verify_heap) VerifyNonPointerSpacePointers();
   1325 #endif
   1326 
   1327   gc_state_ = SCAVENGE;
   1328 
   1329   // Implements Cheney's copying algorithm
   1330   LOG(isolate_, ResourceEvent("scavenge", "begin"));
   1331 
   1332   // Clear descriptor cache.
   1333   isolate_->descriptor_lookup_cache()->Clear();
   1334 
   1335   // Used for updating survived_since_last_expansion_ at function end.
   1336   intptr_t survived_watermark = PromotedSpaceSizeOfObjects();
   1337 
   1338   CheckNewSpaceExpansionCriteria();
   1339 
   1340   SelectScavengingVisitorsTable();
   1341 
   1342   incremental_marking()->PrepareForScavenge();
   1343 
   1344   paged_space(OLD_DATA_SPACE)->EnsureSweeperProgress(new_space_.Size());
   1345   paged_space(OLD_POINTER_SPACE)->EnsureSweeperProgress(new_space_.Size());
   1346 
   1347   // Flip the semispaces.  After flipping, to space is empty, from space has
   1348   // live objects.
   1349   new_space_.Flip();
   1350   new_space_.ResetAllocationInfo();
   1351 
   1352   // We need to sweep newly copied objects which can be either in the
   1353   // to space or promoted to the old generation.  For to-space
   1354   // objects, we treat the bottom of the to space as a queue.  Newly
   1355   // copied and unswept objects lie between a 'front' mark and the
   1356   // allocation pointer.
   1357   //
   1358   // Promoted objects can go into various old-generation spaces, and
   1359   // can be allocated internally in the spaces (from the free list).
   1360   // We treat the top of the to space as a queue of addresses of
   1361   // promoted objects.  The addresses of newly promoted and unswept
   1362   // objects lie between a 'front' mark and a 'rear' mark that is
   1363   // updated as a side effect of promoting an object.
   1364   //
   1365   // There is guaranteed to be enough room at the top of the to space
   1366   // for the addresses of promoted objects: every object promoted
   1367   // frees up its size in bytes from the top of the new space, and
   1368   // objects are at least one pointer in size.
   1369   Address new_space_front = new_space_.ToSpaceStart();
   1370   promotion_queue_.Initialize();
   1371 
   1372 #ifdef DEBUG
   1373   store_buffer()->Clean();
   1374 #endif
   1375 
   1376   ScavengeVisitor scavenge_visitor(this);
   1377   // Copy roots.
   1378   IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE);
   1379 
   1380   // Copy objects reachable from the old generation.
   1381   {
   1382     StoreBufferRebuildScope scope(this,
   1383                                   store_buffer(),
   1384                                   &ScavengeStoreBufferCallback);
   1385     store_buffer()->IteratePointersToNewSpace(&ScavengeObject);
   1386   }
   1387 
   1388   // Copy objects reachable from simple cells by scavenging cell values
   1389   // directly.
   1390   HeapObjectIterator cell_iterator(cell_space_);
   1391   for (HeapObject* heap_object = cell_iterator.Next();
   1392        heap_object != NULL;
   1393        heap_object = cell_iterator.Next()) {
   1394     if (heap_object->IsCell()) {
   1395       Cell* cell = Cell::cast(heap_object);
   1396       Address value_address = cell->ValueAddress();
   1397       scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
   1398     }
   1399   }
   1400 
   1401   // Copy objects reachable from global property cells by scavenging global
   1402   // property cell values directly.
   1403   HeapObjectIterator js_global_property_cell_iterator(property_cell_space_);
   1404   for (HeapObject* heap_object = js_global_property_cell_iterator.Next();
   1405        heap_object != NULL;
   1406        heap_object = js_global_property_cell_iterator.Next()) {
   1407     if (heap_object->IsPropertyCell()) {
   1408       PropertyCell* cell = PropertyCell::cast(heap_object);
   1409       Address value_address = cell->ValueAddress();
   1410       scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
   1411       Address type_address = cell->TypeAddress();
   1412       scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(type_address));
   1413     }
   1414   }
   1415 
   1416   // Copy objects reachable from the code flushing candidates list.
   1417   MarkCompactCollector* collector = mark_compact_collector();
   1418   if (collector->is_code_flushing_enabled()) {
   1419     collector->code_flusher()->IteratePointersToFromSpace(&scavenge_visitor);
   1420   }
   1421 
   1422   // Scavenge object reachable from the native contexts list directly.
   1423   scavenge_visitor.VisitPointer(BitCast<Object**>(&native_contexts_list_));
   1424 
   1425   new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
   1426 
   1427   while (isolate()->global_handles()->IterateObjectGroups(
   1428       &scavenge_visitor, &IsUnscavengedHeapObject)) {
   1429     new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
   1430   }
   1431   isolate()->global_handles()->RemoveObjectGroups();
   1432   isolate()->global_handles()->RemoveImplicitRefGroups();
   1433 
   1434   isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles(
   1435       &IsUnscavengedHeapObject);
   1436   isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots(
   1437       &scavenge_visitor);
   1438   new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
   1439 
   1440   UpdateNewSpaceReferencesInExternalStringTable(
   1441       &UpdateNewSpaceReferenceInExternalStringTableEntry);
   1442 
   1443   promotion_queue_.Destroy();
   1444 
   1445   if (!FLAG_watch_ic_patching) {
   1446     isolate()->runtime_profiler()->UpdateSamplesAfterScavenge();
   1447   }
   1448   incremental_marking()->UpdateMarkingDequeAfterScavenge();
   1449 
   1450   ScavengeWeakObjectRetainer weak_object_retainer(this);
   1451   ProcessWeakReferences(&weak_object_retainer);
   1452 
   1453   ASSERT(new_space_front == new_space_.top());
   1454 
   1455   // Set age mark.
   1456   new_space_.set_age_mark(new_space_.top());
   1457 
   1458   new_space_.LowerInlineAllocationLimit(
   1459       new_space_.inline_allocation_limit_step());
   1460 
   1461   // Update how much has survived scavenge.
   1462   IncrementYoungSurvivorsCounter(static_cast<int>(
   1463       (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size()));
   1464 
   1465   LOG(isolate_, ResourceEvent("scavenge", "end"));
   1466 
   1467   gc_state_ = NOT_IN_GC;
   1468 
   1469   scavenges_since_last_idle_round_++;
   1470 }
   1471 
   1472 
   1473 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
   1474                                                                 Object** p) {
   1475   MapWord first_word = HeapObject::cast(*p)->map_word();
   1476 
   1477   if (!first_word.IsForwardingAddress()) {
   1478     // Unreachable external string can be finalized.
   1479     heap->FinalizeExternalString(String::cast(*p));
   1480     return NULL;
   1481   }
   1482 
   1483   // String is still reachable.
   1484   return String::cast(first_word.ToForwardingAddress());
   1485 }
   1486 
   1487 
   1488 void Heap::UpdateNewSpaceReferencesInExternalStringTable(
   1489     ExternalStringTableUpdaterCallback updater_func) {
   1490 #ifdef VERIFY_HEAP
   1491   if (FLAG_verify_heap) {
   1492     external_string_table_.Verify();
   1493   }
   1494 #endif
   1495 
   1496   if (external_string_table_.new_space_strings_.is_empty()) return;
   1497 
   1498   Object** start = &external_string_table_.new_space_strings_[0];
   1499   Object** end = start + external_string_table_.new_space_strings_.length();
   1500   Object** last = start;
   1501 
   1502   for (Object** p = start; p < end; ++p) {
   1503     ASSERT(InFromSpace(*p));
   1504     String* target = updater_func(this, p);
   1505 
   1506     if (target == NULL) continue;
   1507 
   1508     ASSERT(target->IsExternalString());
   1509 
   1510     if (InNewSpace(target)) {
   1511       // String is still in new space.  Update the table entry.
   1512       *last = target;
   1513       ++last;
   1514     } else {
   1515       // String got promoted.  Move it to the old string list.
   1516       external_string_table_.AddOldString(target);
   1517     }
   1518   }
   1519 
   1520   ASSERT(last <= end);
   1521   external_string_table_.ShrinkNewStrings(static_cast<int>(last - start));
   1522 }
   1523 
   1524 
   1525 void Heap::UpdateReferencesInExternalStringTable(
   1526     ExternalStringTableUpdaterCallback updater_func) {
   1527 
   1528   // Update old space string references.
   1529   if (external_string_table_.old_space_strings_.length() > 0) {
   1530     Object** start = &external_string_table_.old_space_strings_[0];
   1531     Object** end = start + external_string_table_.old_space_strings_.length();
   1532     for (Object** p = start; p < end; ++p) *p = updater_func(this, p);
   1533   }
   1534 
   1535   UpdateNewSpaceReferencesInExternalStringTable(updater_func);
   1536 }
   1537 
   1538 
   1539 template <class T>
   1540 struct WeakListVisitor;
   1541 
   1542 
   1543 template <class T>
   1544 static Object* VisitWeakList(Heap* heap,
   1545                              Object* list,
   1546                              WeakObjectRetainer* retainer,
   1547                              bool record_slots) {
   1548   Object* undefined = heap->undefined_value();
   1549   Object* head = undefined;
   1550   T* tail = NULL;
   1551   MarkCompactCollector* collector = heap->mark_compact_collector();
   1552   while (list != undefined) {
   1553     // Check whether to keep the candidate in the list.
   1554     T* candidate = reinterpret_cast<T*>(list);
   1555     Object* retained = retainer->RetainAs(list);
   1556     if (retained != NULL) {
   1557       if (head == undefined) {
   1558         // First element in the list.
   1559         head = retained;
   1560       } else {
   1561         // Subsequent elements in the list.
   1562         ASSERT(tail != NULL);
   1563         WeakListVisitor<T>::SetWeakNext(tail, retained);
   1564         if (record_slots) {
   1565           Object** next_slot =
   1566             HeapObject::RawField(tail, WeakListVisitor<T>::WeakNextOffset());
   1567           collector->RecordSlot(next_slot, next_slot, retained);
   1568         }
   1569       }
   1570       // Retained object is new tail.
   1571       ASSERT(!retained->IsUndefined());
   1572       candidate = reinterpret_cast<T*>(retained);
   1573       tail = candidate;
   1574 
   1575 
   1576       // tail is a live object, visit it.
   1577       WeakListVisitor<T>::VisitLiveObject(
   1578           heap, tail, retainer, record_slots);
   1579     } else {
   1580       WeakListVisitor<T>::VisitPhantomObject(heap, candidate);
   1581     }
   1582 
   1583     // Move to next element in the list.
   1584     list = WeakListVisitor<T>::WeakNext(candidate);
   1585   }
   1586 
   1587   // Terminate the list if there is one or more elements.
   1588   if (tail != NULL) {
   1589     WeakListVisitor<T>::SetWeakNext(tail, undefined);
   1590   }
   1591   return head;
   1592 }
   1593 
   1594 
   1595 template<>
   1596 struct WeakListVisitor<JSFunction> {
   1597   static void SetWeakNext(JSFunction* function, Object* next) {
   1598     function->set_next_function_link(next);
   1599   }
   1600 
   1601   static Object* WeakNext(JSFunction* function) {
   1602     return function->next_function_link();
   1603   }
   1604 
   1605   static int WeakNextOffset() {
   1606     return JSFunction::kNextFunctionLinkOffset;
   1607   }
   1608 
   1609   static void VisitLiveObject(Heap*, JSFunction*,
   1610                               WeakObjectRetainer*, bool) {
   1611   }
   1612 
   1613   static void VisitPhantomObject(Heap*, JSFunction*) {
   1614   }
   1615 };
   1616 
   1617 
   1618 template<>
   1619 struct WeakListVisitor<Context> {
   1620   static void SetWeakNext(Context* context, Object* next) {
   1621     context->set(Context::NEXT_CONTEXT_LINK,
   1622                  next,
   1623                  UPDATE_WRITE_BARRIER);
   1624   }
   1625 
   1626   static Object* WeakNext(Context* context) {
   1627     return context->get(Context::NEXT_CONTEXT_LINK);
   1628   }
   1629 
   1630   static void VisitLiveObject(Heap* heap,
   1631                               Context* context,
   1632                               WeakObjectRetainer* retainer,
   1633                               bool record_slots) {
   1634     // Process the weak list of optimized functions for the context.
   1635     Object* function_list_head =
   1636         VisitWeakList<JSFunction>(
   1637             heap,
   1638             context->get(Context::OPTIMIZED_FUNCTIONS_LIST),
   1639             retainer,
   1640             record_slots);
   1641     context->set(Context::OPTIMIZED_FUNCTIONS_LIST,
   1642                  function_list_head,
   1643                  UPDATE_WRITE_BARRIER);
   1644     if (record_slots) {
   1645       Object** optimized_functions =
   1646           HeapObject::RawField(
   1647               context, FixedArray::SizeFor(Context::OPTIMIZED_FUNCTIONS_LIST));
   1648       heap->mark_compact_collector()->RecordSlot(
   1649           optimized_functions, optimized_functions, function_list_head);
   1650     }
   1651   }
   1652 
   1653   static void VisitPhantomObject(Heap*, Context*) {
   1654   }
   1655 
   1656   static int WeakNextOffset() {
   1657     return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK);
   1658   }
   1659 };
   1660 
   1661 
   1662 void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
   1663   // We don't record weak slots during marking or scavenges.
   1664   // Instead we do it once when we complete mark-compact cycle.
   1665   // Note that write barrier has no effect if we are already in the middle of
   1666   // compacting mark-sweep cycle and we have to record slots manually.
   1667   bool record_slots =
   1668       gc_state() == MARK_COMPACT &&
   1669       mark_compact_collector()->is_compacting();
   1670   ProcessArrayBuffers(retainer, record_slots);
   1671   ProcessNativeContexts(retainer, record_slots);
   1672   ProcessAllocationSites(retainer, record_slots);
   1673 }
   1674 
   1675 void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer,
   1676                                  bool record_slots) {
   1677   Object* head =
   1678       VisitWeakList<Context>(
   1679           this, native_contexts_list(), retainer, record_slots);
   1680   // Update the head of the list of contexts.
   1681   native_contexts_list_ = head;
   1682 }
   1683 
   1684 
   1685 template<>
   1686 struct WeakListVisitor<JSArrayBufferView> {
   1687   static void SetWeakNext(JSArrayBufferView* obj, Object* next) {
   1688     obj->set_weak_next(next);
   1689   }
   1690 
   1691   static Object* WeakNext(JSArrayBufferView* obj) {
   1692     return obj->weak_next();
   1693   }
   1694 
   1695   static void VisitLiveObject(Heap*,
   1696                               JSArrayBufferView* obj,
   1697                               WeakObjectRetainer* retainer,
   1698                               bool record_slots) {}
   1699 
   1700   static void VisitPhantomObject(Heap*, JSArrayBufferView*) {}
   1701 
   1702   static int WeakNextOffset() {
   1703     return JSArrayBufferView::kWeakNextOffset;
   1704   }
   1705 };
   1706 
   1707 
   1708 template<>
   1709 struct WeakListVisitor<JSArrayBuffer> {
   1710   static void SetWeakNext(JSArrayBuffer* obj, Object* next) {
   1711     obj->set_weak_next(next);
   1712   }
   1713 
   1714   static Object* WeakNext(JSArrayBuffer* obj) {
   1715     return obj->weak_next();
   1716   }
   1717 
   1718   static void VisitLiveObject(Heap* heap,
   1719                               JSArrayBuffer* array_buffer,
   1720                               WeakObjectRetainer* retainer,
   1721                               bool record_slots) {
   1722     Object* typed_array_obj =
   1723         VisitWeakList<JSArrayBufferView>(
   1724             heap,
   1725             array_buffer->weak_first_view(),
   1726             retainer, record_slots);
   1727     array_buffer->set_weak_first_view(typed_array_obj);
   1728     if (typed_array_obj != heap->undefined_value() && record_slots) {
   1729       Object** slot = HeapObject::RawField(
   1730           array_buffer, JSArrayBuffer::kWeakFirstViewOffset);
   1731       heap->mark_compact_collector()->RecordSlot(slot, slot, typed_array_obj);
   1732     }
   1733   }
   1734 
   1735   static void VisitPhantomObject(Heap* heap, JSArrayBuffer* phantom) {
   1736     Runtime::FreeArrayBuffer(heap->isolate(), phantom);
   1737   }
   1738 
   1739   static int WeakNextOffset() {
   1740     return JSArrayBuffer::kWeakNextOffset;
   1741   }
   1742 };
   1743 
   1744 
   1745 void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer,
   1746                                bool record_slots) {
   1747   Object* array_buffer_obj =
   1748       VisitWeakList<JSArrayBuffer>(this,
   1749                                    array_buffers_list(),
   1750                                    retainer, record_slots);
   1751   set_array_buffers_list(array_buffer_obj);
   1752 }
   1753 
   1754 
   1755 void Heap::TearDownArrayBuffers() {
   1756   Object* undefined = undefined_value();
   1757   for (Object* o = array_buffers_list(); o != undefined;) {
   1758     JSArrayBuffer* buffer = JSArrayBuffer::cast(o);
   1759     Runtime::FreeArrayBuffer(isolate(), buffer);
   1760     o = buffer->weak_next();
   1761   }
   1762   array_buffers_list_ = undefined;
   1763 }
   1764 
   1765 
   1766 template<>
   1767 struct WeakListVisitor<AllocationSite> {
   1768   static void SetWeakNext(AllocationSite* obj, Object* next) {
   1769     obj->set_weak_next(next);
   1770   }
   1771 
   1772   static Object* WeakNext(AllocationSite* obj) {
   1773     return obj->weak_next();
   1774   }
   1775 
   1776   static void VisitLiveObject(Heap* heap,
   1777                               AllocationSite* array_buffer,
   1778                               WeakObjectRetainer* retainer,
   1779                               bool record_slots) {}
   1780 
   1781   static void VisitPhantomObject(Heap* heap, AllocationSite* phantom) {}
   1782 
   1783   static int WeakNextOffset() {
   1784     return AllocationSite::kWeakNextOffset;
   1785   }
   1786 };
   1787 
   1788 
   1789 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer,
   1790                                   bool record_slots) {
   1791   Object* allocation_site_obj =
   1792       VisitWeakList<AllocationSite>(this,
   1793                                     allocation_sites_list(),
   1794                                     retainer, record_slots);
   1795   set_allocation_sites_list(allocation_site_obj);
   1796 }
   1797 
   1798 
   1799 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
   1800   DisallowHeapAllocation no_allocation;
   1801 
   1802   // Both the external string table and the string table may contain
   1803   // external strings, but neither lists them exhaustively, nor is the
   1804   // intersection set empty.  Therefore we iterate over the external string
   1805   // table first, ignoring internalized strings, and then over the
   1806   // internalized string table.
   1807 
   1808   class ExternalStringTableVisitorAdapter : public ObjectVisitor {
   1809    public:
   1810     explicit ExternalStringTableVisitorAdapter(
   1811         v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {}
   1812     virtual void VisitPointers(Object** start, Object** end) {
   1813       for (Object** p = start; p < end; p++) {
   1814         // Visit non-internalized external strings,
   1815         // since internalized strings are listed in the string table.
   1816         if (!(*p)->IsInternalizedString()) {
   1817           ASSERT((*p)->IsExternalString());
   1818           visitor_->VisitExternalString(Utils::ToLocal(
   1819               Handle<String>(String::cast(*p))));
   1820         }
   1821       }
   1822     }
   1823    private:
   1824     v8::ExternalResourceVisitor* visitor_;
   1825   } external_string_table_visitor(visitor);
   1826 
   1827   external_string_table_.Iterate(&external_string_table_visitor);
   1828 
   1829   class StringTableVisitorAdapter : public ObjectVisitor {
   1830    public:
   1831     explicit StringTableVisitorAdapter(
   1832         v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {}
   1833     virtual void VisitPointers(Object** start, Object** end) {
   1834       for (Object** p = start; p < end; p++) {
   1835         if ((*p)->IsExternalString()) {
   1836           ASSERT((*p)->IsInternalizedString());
   1837           visitor_->VisitExternalString(Utils::ToLocal(
   1838               Handle<String>(String::cast(*p))));
   1839         }
   1840       }
   1841     }
   1842    private:
   1843     v8::ExternalResourceVisitor* visitor_;
   1844   } string_table_visitor(visitor);
   1845 
   1846   string_table()->IterateElements(&string_table_visitor);
   1847 }
   1848 
   1849 
   1850 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> {
   1851  public:
   1852   static inline void VisitPointer(Heap* heap, Object** p) {
   1853     Object* object = *p;
   1854     if (!heap->InNewSpace(object)) return;
   1855     Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
   1856                          reinterpret_cast<HeapObject*>(object));
   1857   }
   1858 };
   1859 
   1860 
   1861 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
   1862                          Address new_space_front) {
   1863   do {
   1864     SemiSpace::AssertValidRange(new_space_front, new_space_.top());
   1865     // The addresses new_space_front and new_space_.top() define a
   1866     // queue of unprocessed copied objects.  Process them until the
   1867     // queue is empty.
   1868     while (new_space_front != new_space_.top()) {
   1869       if (!NewSpacePage::IsAtEnd(new_space_front)) {
   1870         HeapObject* object = HeapObject::FromAddress(new_space_front);
   1871         new_space_front +=
   1872           NewSpaceScavenger::IterateBody(object->map(), object);
   1873       } else {
   1874         new_space_front =
   1875             NewSpacePage::FromLimit(new_space_front)->next_page()->area_start();
   1876       }
   1877     }
   1878 
   1879     // Promote and process all the to-be-promoted objects.
   1880     {
   1881       StoreBufferRebuildScope scope(this,
   1882                                     store_buffer(),
   1883                                     &ScavengeStoreBufferCallback);
   1884       while (!promotion_queue()->is_empty()) {
   1885         HeapObject* target;
   1886         int size;
   1887         promotion_queue()->remove(&target, &size);
   1888 
   1889         // Promoted object might be already partially visited
   1890         // during old space pointer iteration. Thus we search specificly
   1891         // for pointers to from semispace instead of looking for pointers
   1892         // to new space.
   1893         ASSERT(!target->IsMap());
   1894         IterateAndMarkPointersToFromSpace(target->address(),
   1895                                           target->address() + size,
   1896                                           &ScavengeObject);
   1897       }
   1898     }
   1899 
   1900     // Take another spin if there are now unswept objects in new space
   1901     // (there are currently no more unswept promoted objects).
   1902   } while (new_space_front != new_space_.top());
   1903 
   1904   return new_space_front;
   1905 }
   1906 
   1907 
   1908 STATIC_ASSERT((FixedDoubleArray::kHeaderSize & kDoubleAlignmentMask) == 0);
   1909 
   1910 
   1911 INLINE(static HeapObject* EnsureDoubleAligned(Heap* heap,
   1912                                               HeapObject* object,
   1913                                               int size));
   1914 
   1915 static HeapObject* EnsureDoubleAligned(Heap* heap,
   1916                                        HeapObject* object,
   1917                                        int size) {
   1918   if ((OffsetFrom(object->address()) & kDoubleAlignmentMask) != 0) {
   1919     heap->CreateFillerObjectAt(object->address(), kPointerSize);
   1920     return HeapObject::FromAddress(object->address() + kPointerSize);
   1921   } else {
   1922     heap->CreateFillerObjectAt(object->address() + size - kPointerSize,
   1923                                kPointerSize);
   1924     return object;
   1925   }
   1926 }
   1927 
   1928 
   1929 enum LoggingAndProfiling {
   1930   LOGGING_AND_PROFILING_ENABLED,
   1931   LOGGING_AND_PROFILING_DISABLED
   1932 };
   1933 
   1934 
   1935 enum MarksHandling { TRANSFER_MARKS, IGNORE_MARKS };
   1936 
   1937 
   1938 template<MarksHandling marks_handling,
   1939          LoggingAndProfiling logging_and_profiling_mode>
   1940 class ScavengingVisitor : public StaticVisitorBase {
   1941  public:
   1942   static void Initialize() {
   1943     table_.Register(kVisitSeqOneByteString, &EvacuateSeqOneByteString);
   1944     table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString);
   1945     table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate);
   1946     table_.Register(kVisitByteArray, &EvacuateByteArray);
   1947     table_.Register(kVisitFixedArray, &EvacuateFixedArray);
   1948     table_.Register(kVisitFixedDoubleArray, &EvacuateFixedDoubleArray);
   1949 
   1950     table_.Register(kVisitNativeContext,
   1951                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1952                         template VisitSpecialized<Context::kSize>);
   1953 
   1954     table_.Register(kVisitConsString,
   1955                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1956                         template VisitSpecialized<ConsString::kSize>);
   1957 
   1958     table_.Register(kVisitSlicedString,
   1959                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1960                         template VisitSpecialized<SlicedString::kSize>);
   1961 
   1962     table_.Register(kVisitSymbol,
   1963                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1964                         template VisitSpecialized<Symbol::kSize>);
   1965 
   1966     table_.Register(kVisitSharedFunctionInfo,
   1967                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1968                         template VisitSpecialized<SharedFunctionInfo::kSize>);
   1969 
   1970     table_.Register(kVisitJSWeakMap,
   1971                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1972                     Visit);
   1973 
   1974     table_.Register(kVisitJSWeakSet,
   1975                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1976                     Visit);
   1977 
   1978     table_.Register(kVisitJSArrayBuffer,
   1979                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1980                     Visit);
   1981 
   1982     table_.Register(kVisitJSTypedArray,
   1983                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1984                     Visit);
   1985 
   1986     table_.Register(kVisitJSDataView,
   1987                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1988                     Visit);
   1989 
   1990     table_.Register(kVisitJSRegExp,
   1991                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1992                     Visit);
   1993 
   1994     if (marks_handling == IGNORE_MARKS) {
   1995       table_.Register(kVisitJSFunction,
   1996                       &ObjectEvacuationStrategy<POINTER_OBJECT>::
   1997                           template VisitSpecialized<JSFunction::kSize>);
   1998     } else {
   1999       table_.Register(kVisitJSFunction, &EvacuateJSFunction);
   2000     }
   2001 
   2002     table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>,
   2003                                    kVisitDataObject,
   2004                                    kVisitDataObjectGeneric>();
   2005 
   2006     table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
   2007                                    kVisitJSObject,
   2008                                    kVisitJSObjectGeneric>();
   2009 
   2010     table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
   2011                                    kVisitStruct,
   2012                                    kVisitStructGeneric>();
   2013   }
   2014 
   2015   static VisitorDispatchTable<ScavengingCallback>* GetTable() {
   2016     return &table_;
   2017   }
   2018 
   2019  private:
   2020   enum ObjectContents  { DATA_OBJECT, POINTER_OBJECT };
   2021 
   2022   static void RecordCopiedObject(Heap* heap, HeapObject* obj) {
   2023     bool should_record = false;
   2024 #ifdef DEBUG
   2025     should_record = FLAG_heap_stats;
   2026 #endif
   2027     should_record = should_record || FLAG_log_gc;
   2028     if (should_record) {
   2029       if (heap->new_space()->Contains(obj)) {
   2030         heap->new_space()->RecordAllocation(obj);
   2031       } else {
   2032         heap->new_space()->RecordPromotion(obj);
   2033       }
   2034     }
   2035   }
   2036 
   2037   // Helper function used by CopyObject to copy a source object to an
   2038   // allocated target object and update the forwarding pointer in the source
   2039   // object.  Returns the target object.
   2040   INLINE(static void MigrateObject(Heap* heap,
   2041                                    HeapObject* source,
   2042                                    HeapObject* target,
   2043                                    int size)) {
   2044     // Copy the content of source to target.
   2045     heap->CopyBlock(target->address(), source->address(), size);
   2046 
   2047     // Set the forwarding address.
   2048     source->set_map_word(MapWord::FromForwardingAddress(target));
   2049 
   2050     if (logging_and_profiling_mode == LOGGING_AND_PROFILING_ENABLED) {
   2051       // Update NewSpace stats if necessary.
   2052       RecordCopiedObject(heap, target);
   2053       HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address()));
   2054       Isolate* isolate = heap->isolate();
   2055       if (isolate->logger()->is_logging_code_events() ||
   2056           isolate->cpu_profiler()->is_profiling()) {
   2057         if (target->IsSharedFunctionInfo()) {
   2058           PROFILE(isolate, SharedFunctionInfoMoveEvent(
   2059               source->address(), target->address()));
   2060         }
   2061       }
   2062     }
   2063 
   2064     if (marks_handling == TRANSFER_MARKS) {
   2065       if (Marking::TransferColor(source, target)) {
   2066         MemoryChunk::IncrementLiveBytesFromGC(target->address(), size);
   2067       }
   2068     }
   2069   }
   2070 
   2071 
   2072   template<ObjectContents object_contents, int alignment>
   2073   static inline void EvacuateObject(Map* map,
   2074                                     HeapObject** slot,
   2075                                     HeapObject* object,
   2076                                     int object_size) {
   2077     SLOW_ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize);
   2078     SLOW_ASSERT(object->Size() == object_size);
   2079 
   2080     int allocation_size = object_size;
   2081     if (alignment != kObjectAlignment) {
   2082       ASSERT(alignment == kDoubleAlignment);
   2083       allocation_size += kPointerSize;
   2084     }
   2085 
   2086     Heap* heap = map->GetHeap();
   2087     if (heap->ShouldBePromoted(object->address(), object_size)) {
   2088       MaybeObject* maybe_result;
   2089 
   2090       if (object_contents == DATA_OBJECT) {
   2091         // TODO(mstarzinger): Turn this check into a regular assert soon!
   2092         CHECK(heap->AllowedToBeMigrated(object, OLD_DATA_SPACE));
   2093         maybe_result = heap->old_data_space()->AllocateRaw(allocation_size);
   2094       } else {
   2095         // TODO(mstarzinger): Turn this check into a regular assert soon!
   2096         CHECK(heap->AllowedToBeMigrated(object, OLD_POINTER_SPACE));
   2097         maybe_result = heap->old_pointer_space()->AllocateRaw(allocation_size);
   2098       }
   2099 
   2100       Object* result = NULL;  // Initialization to please compiler.
   2101       if (maybe_result->ToObject(&result)) {
   2102         HeapObject* target = HeapObject::cast(result);
   2103 
   2104         if (alignment != kObjectAlignment) {
   2105           target = EnsureDoubleAligned(heap, target, allocation_size);
   2106         }
   2107 
   2108         // Order is important: slot might be inside of the target if target
   2109         // was allocated over a dead object and slot comes from the store
   2110         // buffer.
   2111         *slot = target;
   2112         MigrateObject(heap, object, target, object_size);
   2113 
   2114         if (object_contents == POINTER_OBJECT) {
   2115           if (map->instance_type() == JS_FUNCTION_TYPE) {
   2116             heap->promotion_queue()->insert(
   2117                 target, JSFunction::kNonWeakFieldsEndOffset);
   2118           } else {
   2119             heap->promotion_queue()->insert(target, object_size);
   2120           }
   2121         }
   2122 
   2123         heap->tracer()->increment_promoted_objects_size(object_size);
   2124         return;
   2125       }
   2126     }
   2127     // TODO(mstarzinger): Turn this check into a regular assert soon!
   2128     CHECK(heap->AllowedToBeMigrated(object, NEW_SPACE));
   2129     MaybeObject* allocation = heap->new_space()->AllocateRaw(allocation_size);
   2130     heap->promotion_queue()->SetNewLimit(heap->new_space()->top());
   2131     Object* result = allocation->ToObjectUnchecked();
   2132     HeapObject* target = HeapObject::cast(result);
   2133 
   2134     if (alignment != kObjectAlignment) {
   2135       target = EnsureDoubleAligned(heap, target, allocation_size);
   2136     }
   2137 
   2138     // Order is important: slot might be inside of the target if target
   2139     // was allocated over a dead object and slot comes from the store
   2140     // buffer.
   2141     *slot = target;
   2142     MigrateObject(heap, object, target, object_size);
   2143     return;
   2144   }
   2145 
   2146 
   2147   static inline void EvacuateJSFunction(Map* map,
   2148                                         HeapObject** slot,
   2149                                         HeapObject* object) {
   2150     ObjectEvacuationStrategy<POINTER_OBJECT>::
   2151         template VisitSpecialized<JSFunction::kSize>(map, slot, object);
   2152 
   2153     HeapObject* target = *slot;
   2154     MarkBit mark_bit = Marking::MarkBitFrom(target);
   2155     if (Marking::IsBlack(mark_bit)) {
   2156       // This object is black and it might not be rescanned by marker.
   2157       // We should explicitly record code entry slot for compaction because
   2158       // promotion queue processing (IterateAndMarkPointersToFromSpace) will
   2159       // miss it as it is not HeapObject-tagged.
   2160       Address code_entry_slot =
   2161           target->address() + JSFunction::kCodeEntryOffset;
   2162       Code* code = Code::cast(Code::GetObjectFromEntryAddress(code_entry_slot));
   2163       map->GetHeap()->mark_compact_collector()->
   2164           RecordCodeEntrySlot(code_entry_slot, code);
   2165     }
   2166   }
   2167 
   2168 
   2169   static inline void EvacuateFixedArray(Map* map,
   2170                                         HeapObject** slot,
   2171                                         HeapObject* object) {
   2172     int object_size = FixedArray::BodyDescriptor::SizeOf(map, object);
   2173     EvacuateObject<POINTER_OBJECT, kObjectAlignment>(
   2174         map, slot, object, object_size);
   2175   }
   2176 
   2177 
   2178   static inline void EvacuateFixedDoubleArray(Map* map,
   2179                                               HeapObject** slot,
   2180                                               HeapObject* object) {
   2181     int length = reinterpret_cast<FixedDoubleArray*>(object)->length();
   2182     int object_size = FixedDoubleArray::SizeFor(length);
   2183     EvacuateObject<DATA_OBJECT, kDoubleAlignment>(
   2184         map, slot, object, object_size);
   2185   }
   2186 
   2187 
   2188   static inline void EvacuateByteArray(Map* map,
   2189                                        HeapObject** slot,
   2190                                        HeapObject* object) {
   2191     int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize();
   2192     EvacuateObject<DATA_OBJECT, kObjectAlignment>(
   2193         map, slot, object, object_size);
   2194   }
   2195 
   2196 
   2197   static inline void EvacuateSeqOneByteString(Map* map,
   2198                                             HeapObject** slot,
   2199                                             HeapObject* object) {
   2200     int object_size = SeqOneByteString::cast(object)->
   2201         SeqOneByteStringSize(map->instance_type());
   2202     EvacuateObject<DATA_OBJECT, kObjectAlignment>(
   2203         map, slot, object, object_size);
   2204   }
   2205 
   2206 
   2207   static inline void EvacuateSeqTwoByteString(Map* map,
   2208                                               HeapObject** slot,
   2209                                               HeapObject* object) {
   2210     int object_size = SeqTwoByteString::cast(object)->
   2211         SeqTwoByteStringSize(map->instance_type());
   2212     EvacuateObject<DATA_OBJECT, kObjectAlignment>(
   2213         map, slot, object, object_size);
   2214   }
   2215 
   2216 
   2217   static inline bool IsShortcutCandidate(int type) {
   2218     return ((type & kShortcutTypeMask) == kShortcutTypeTag);
   2219   }
   2220 
   2221   static inline void EvacuateShortcutCandidate(Map* map,
   2222                                                HeapObject** slot,
   2223                                                HeapObject* object) {
   2224     ASSERT(IsShortcutCandidate(map->instance_type()));
   2225 
   2226     Heap* heap = map->GetHeap();
   2227 
   2228     if (marks_handling == IGNORE_MARKS &&
   2229         ConsString::cast(object)->unchecked_second() ==
   2230         heap->empty_string()) {
   2231       HeapObject* first =
   2232           HeapObject::cast(ConsString::cast(object)->unchecked_first());
   2233 
   2234       *slot = first;
   2235 
   2236       if (!heap->InNewSpace(first)) {
   2237         object->set_map_word(MapWord::FromForwardingAddress(first));
   2238         return;
   2239       }
   2240 
   2241       MapWord first_word = first->map_word();
   2242       if (first_word.IsForwardingAddress()) {
   2243         HeapObject* target = first_word.ToForwardingAddress();
   2244 
   2245         *slot = target;
   2246         object->set_map_word(MapWord::FromForwardingAddress(target));
   2247         return;
   2248       }
   2249 
   2250       heap->DoScavengeObject(first->map(), slot, first);
   2251       object->set_map_word(MapWord::FromForwardingAddress(*slot));
   2252       return;
   2253     }
   2254 
   2255     int object_size = ConsString::kSize;
   2256     EvacuateObject<POINTER_OBJECT, kObjectAlignment>(
   2257         map, slot, object, object_size);
   2258   }
   2259 
   2260   template<ObjectContents object_contents>
   2261   class ObjectEvacuationStrategy {
   2262    public:
   2263     template<int object_size>
   2264     static inline void VisitSpecialized(Map* map,
   2265                                         HeapObject** slot,
   2266                                         HeapObject* object) {
   2267       EvacuateObject<object_contents, kObjectAlignment>(
   2268           map, slot, object, object_size);
   2269     }
   2270 
   2271     static inline void Visit(Map* map,
   2272                              HeapObject** slot,
   2273                              HeapObject* object) {
   2274       int object_size = map->instance_size();
   2275       EvacuateObject<object_contents, kObjectAlignment>(
   2276           map, slot, object, object_size);
   2277     }
   2278   };
   2279 
   2280   static VisitorDispatchTable<ScavengingCallback> table_;
   2281 };
   2282 
   2283 
   2284 template<MarksHandling marks_handling,
   2285          LoggingAndProfiling logging_and_profiling_mode>
   2286 VisitorDispatchTable<ScavengingCallback>
   2287     ScavengingVisitor<marks_handling, logging_and_profiling_mode>::table_;
   2288 
   2289 
   2290 static void InitializeScavengingVisitorsTables() {
   2291   ScavengingVisitor<TRANSFER_MARKS,
   2292                     LOGGING_AND_PROFILING_DISABLED>::Initialize();
   2293   ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_DISABLED>::Initialize();
   2294   ScavengingVisitor<TRANSFER_MARKS,
   2295                     LOGGING_AND_PROFILING_ENABLED>::Initialize();
   2296   ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::Initialize();
   2297 }
   2298 
   2299 
   2300 void Heap::SelectScavengingVisitorsTable() {
   2301   bool logging_and_profiling =
   2302       isolate()->logger()->is_logging() ||
   2303       isolate()->cpu_profiler()->is_profiling() ||
   2304       (isolate()->heap_profiler() != NULL &&
   2305        isolate()->heap_profiler()->is_profiling());
   2306 
   2307   if (!incremental_marking()->IsMarking()) {
   2308     if (!logging_and_profiling) {
   2309       scavenging_visitors_table_.CopyFrom(
   2310           ScavengingVisitor<IGNORE_MARKS,
   2311                             LOGGING_AND_PROFILING_DISABLED>::GetTable());
   2312     } else {
   2313       scavenging_visitors_table_.CopyFrom(
   2314           ScavengingVisitor<IGNORE_MARKS,
   2315                             LOGGING_AND_PROFILING_ENABLED>::GetTable());
   2316     }
   2317   } else {
   2318     if (!logging_and_profiling) {
   2319       scavenging_visitors_table_.CopyFrom(
   2320           ScavengingVisitor<TRANSFER_MARKS,
   2321                             LOGGING_AND_PROFILING_DISABLED>::GetTable());
   2322     } else {
   2323       scavenging_visitors_table_.CopyFrom(
   2324           ScavengingVisitor<TRANSFER_MARKS,
   2325                             LOGGING_AND_PROFILING_ENABLED>::GetTable());
   2326     }
   2327 
   2328     if (incremental_marking()->IsCompacting()) {
   2329       // When compacting forbid short-circuiting of cons-strings.
   2330       // Scavenging code relies on the fact that new space object
   2331       // can't be evacuated into evacuation candidate but
   2332       // short-circuiting violates this assumption.
   2333       scavenging_visitors_table_.Register(
   2334           StaticVisitorBase::kVisitShortcutCandidate,
   2335           scavenging_visitors_table_.GetVisitorById(
   2336               StaticVisitorBase::kVisitConsString));
   2337     }
   2338   }
   2339 }
   2340 
   2341 
   2342 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
   2343   SLOW_ASSERT(HEAP->InFromSpace(object));
   2344   MapWord first_word = object->map_word();
   2345   SLOW_ASSERT(!first_word.IsForwardingAddress());
   2346   Map* map = first_word.ToMap();
   2347   map->GetHeap()->DoScavengeObject(map, p, object);
   2348 }
   2349 
   2350 
   2351 MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type,
   2352                                       int instance_size) {
   2353   Object* result;
   2354   MaybeObject* maybe_result = AllocateRawMap();
   2355   if (!maybe_result->ToObject(&result)) return maybe_result;
   2356 
   2357   // Map::cast cannot be used due to uninitialized map field.
   2358   reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map());
   2359   reinterpret_cast<Map*>(result)->set_instance_type(instance_type);
   2360   reinterpret_cast<Map*>(result)->set_instance_size(instance_size);
   2361   reinterpret_cast<Map*>(result)->set_visitor_id(
   2362         StaticVisitorBase::GetVisitorId(instance_type, instance_size));
   2363   reinterpret_cast<Map*>(result)->set_inobject_properties(0);
   2364   reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0);
   2365   reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
   2366   reinterpret_cast<Map*>(result)->set_bit_field(0);
   2367   reinterpret_cast<Map*>(result)->set_bit_field2(0);
   2368   int bit_field3 = Map::EnumLengthBits::encode(Map::kInvalidEnumCache) |
   2369                    Map::OwnsDescriptors::encode(true);
   2370   reinterpret_cast<Map*>(result)->set_bit_field3(bit_field3);
   2371   return result;
   2372 }
   2373 
   2374 
   2375 MaybeObject* Heap::AllocateMap(InstanceType instance_type,
   2376                                int instance_size,
   2377                                ElementsKind elements_kind) {
   2378   Object* result;
   2379   MaybeObject* maybe_result = AllocateRawMap();
   2380   if (!maybe_result->To(&result)) return maybe_result;
   2381 
   2382   Map* map = reinterpret_cast<Map*>(result);
   2383   map->set_map_no_write_barrier(meta_map());
   2384   map->set_instance_type(instance_type);
   2385   map->set_visitor_id(
   2386       StaticVisitorBase::GetVisitorId(instance_type, instance_size));
   2387   map->set_prototype(null_value(), SKIP_WRITE_BARRIER);
   2388   map->set_constructor(null_value(), SKIP_WRITE_BARRIER);
   2389   map->set_instance_size(instance_size);
   2390   map->set_inobject_properties(0);
   2391   map->set_pre_allocated_property_fields(0);
   2392   map->set_code_cache(empty_fixed_array(), SKIP_WRITE_BARRIER);
   2393   map->set_dependent_code(DependentCode::cast(empty_fixed_array()),
   2394                           SKIP_WRITE_BARRIER);
   2395   map->init_back_pointer(undefined_value());
   2396   map->set_unused_property_fields(0);
   2397   map->set_instance_descriptors(empty_descriptor_array());
   2398   map->set_bit_field(0);
   2399   map->set_bit_field2(1 << Map::kIsExtensible);
   2400   int bit_field3 = Map::EnumLengthBits::encode(Map::kInvalidEnumCache) |
   2401                    Map::OwnsDescriptors::encode(true);
   2402   map->set_bit_field3(bit_field3);
   2403   map->set_elements_kind(elements_kind);
   2404 
   2405   return map;
   2406 }
   2407 
   2408 
   2409 MaybeObject* Heap::AllocateCodeCache() {
   2410   CodeCache* code_cache;
   2411   { MaybeObject* maybe_code_cache = AllocateStruct(CODE_CACHE_TYPE);
   2412     if (!maybe_code_cache->To(&code_cache)) return maybe_code_cache;
   2413   }
   2414   code_cache->set_default_cache(empty_fixed_array(), SKIP_WRITE_BARRIER);
   2415   code_cache->set_normal_type_cache(undefined_value(), SKIP_WRITE_BARRIER);
   2416   return code_cache;
   2417 }
   2418 
   2419 
   2420 MaybeObject* Heap::AllocatePolymorphicCodeCache() {
   2421   return AllocateStruct(POLYMORPHIC_CODE_CACHE_TYPE);
   2422 }
   2423 
   2424 
   2425 MaybeObject* Heap::AllocateAccessorPair() {
   2426   AccessorPair* accessors;
   2427   { MaybeObject* maybe_accessors = AllocateStruct(ACCESSOR_PAIR_TYPE);
   2428     if (!maybe_accessors->To(&accessors)) return maybe_accessors;
   2429   }
   2430   accessors->set_getter(the_hole_value(), SKIP_WRITE_BARRIER);
   2431   accessors->set_setter(the_hole_value(), SKIP_WRITE_BARRIER);
   2432   return accessors;
   2433 }
   2434 
   2435 
   2436 MaybeObject* Heap::AllocateTypeFeedbackInfo() {
   2437   TypeFeedbackInfo* info;
   2438   { MaybeObject* maybe_info = AllocateStruct(TYPE_FEEDBACK_INFO_TYPE);
   2439     if (!maybe_info->To(&info)) return maybe_info;
   2440   }
   2441   info->initialize_storage();
   2442   info->set_type_feedback_cells(TypeFeedbackCells::cast(empty_fixed_array()),
   2443                                 SKIP_WRITE_BARRIER);
   2444   return info;
   2445 }
   2446 
   2447 
   2448 MaybeObject* Heap::AllocateAliasedArgumentsEntry(int aliased_context_slot) {
   2449   AliasedArgumentsEntry* entry;
   2450   { MaybeObject* maybe_entry = AllocateStruct(ALIASED_ARGUMENTS_ENTRY_TYPE);
   2451     if (!maybe_entry->To(&entry)) return maybe_entry;
   2452   }
   2453   entry->set_aliased_context_slot(aliased_context_slot);
   2454   return entry;
   2455 }
   2456 
   2457 
   2458 const Heap::StringTypeTable Heap::string_type_table[] = {
   2459 #define STRING_TYPE_ELEMENT(type, size, name, camel_name)                      \
   2460   {type, size, k##camel_name##MapRootIndex},
   2461   STRING_TYPE_LIST(STRING_TYPE_ELEMENT)
   2462 #undef STRING_TYPE_ELEMENT
   2463 };
   2464 
   2465 
   2466 const Heap::ConstantStringTable Heap::constant_string_table[] = {
   2467 #define CONSTANT_STRING_ELEMENT(name, contents)                                \
   2468   {contents, k##name##RootIndex},
   2469   INTERNALIZED_STRING_LIST(CONSTANT_STRING_ELEMENT)
   2470 #undef CONSTANT_STRING_ELEMENT
   2471 };
   2472 
   2473 
   2474 const Heap::StructTable Heap::struct_table[] = {
   2475 #define STRUCT_TABLE_ELEMENT(NAME, Name, name)                                 \
   2476   { NAME##_TYPE, Name::kSize, k##Name##MapRootIndex },
   2477   STRUCT_LIST(STRUCT_TABLE_ELEMENT)
   2478 #undef STRUCT_TABLE_ELEMENT
   2479 };
   2480 
   2481 
   2482 bool Heap::CreateInitialMaps() {
   2483   Object* obj;
   2484   { MaybeObject* maybe_obj = AllocatePartialMap(MAP_TYPE, Map::kSize);
   2485     if (!maybe_obj->ToObject(&obj)) return false;
   2486   }
   2487   // Map::cast cannot be used due to uninitialized map field.
   2488   Map* new_meta_map = reinterpret_cast<Map*>(obj);
   2489   set_meta_map(new_meta_map);
   2490   new_meta_map->set_map(new_meta_map);
   2491 
   2492   { MaybeObject* maybe_obj =
   2493         AllocatePartialMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2494     if (!maybe_obj->ToObject(&obj)) return false;
   2495   }
   2496   set_fixed_array_map(Map::cast(obj));
   2497 
   2498   { MaybeObject* maybe_obj = AllocatePartialMap(ODDBALL_TYPE, Oddball::kSize);
   2499     if (!maybe_obj->ToObject(&obj)) return false;
   2500   }
   2501   set_oddball_map(Map::cast(obj));
   2502 
   2503   // Allocate the empty array.
   2504   { MaybeObject* maybe_obj = AllocateEmptyFixedArray();
   2505     if (!maybe_obj->ToObject(&obj)) return false;
   2506   }
   2507   set_empty_fixed_array(FixedArray::cast(obj));
   2508 
   2509   { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_POINTER_SPACE);
   2510     if (!maybe_obj->ToObject(&obj)) return false;
   2511   }
   2512   set_null_value(Oddball::cast(obj));
   2513   Oddball::cast(obj)->set_kind(Oddball::kNull);
   2514 
   2515   { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_POINTER_SPACE);
   2516     if (!maybe_obj->ToObject(&obj)) return false;
   2517   }
   2518   set_undefined_value(Oddball::cast(obj));
   2519   Oddball::cast(obj)->set_kind(Oddball::kUndefined);
   2520   ASSERT(!InNewSpace(undefined_value()));
   2521 
   2522   // Allocate the empty descriptor array.
   2523   { MaybeObject* maybe_obj = AllocateEmptyFixedArray();
   2524     if (!maybe_obj->ToObject(&obj)) return false;
   2525   }
   2526   set_empty_descriptor_array(DescriptorArray::cast(obj));
   2527 
   2528   // Fix the instance_descriptors for the existing maps.
   2529   meta_map()->set_code_cache(empty_fixed_array());
   2530   meta_map()->set_dependent_code(DependentCode::cast(empty_fixed_array()));
   2531   meta_map()->init_back_pointer(undefined_value());
   2532   meta_map()->set_instance_descriptors(empty_descriptor_array());
   2533 
   2534   fixed_array_map()->set_code_cache(empty_fixed_array());
   2535   fixed_array_map()->set_dependent_code(
   2536       DependentCode::cast(empty_fixed_array()));
   2537   fixed_array_map()->init_back_pointer(undefined_value());
   2538   fixed_array_map()->set_instance_descriptors(empty_descriptor_array());
   2539 
   2540   oddball_map()->set_code_cache(empty_fixed_array());
   2541   oddball_map()->set_dependent_code(DependentCode::cast(empty_fixed_array()));
   2542   oddball_map()->init_back_pointer(undefined_value());
   2543   oddball_map()->set_instance_descriptors(empty_descriptor_array());
   2544 
   2545   // Fix prototype object for existing maps.
   2546   meta_map()->set_prototype(null_value());
   2547   meta_map()->set_constructor(null_value());
   2548 
   2549   fixed_array_map()->set_prototype(null_value());
   2550   fixed_array_map()->set_constructor(null_value());
   2551 
   2552   oddball_map()->set_prototype(null_value());
   2553   oddball_map()->set_constructor(null_value());
   2554 
   2555   { MaybeObject* maybe_obj =
   2556         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2557     if (!maybe_obj->ToObject(&obj)) return false;
   2558   }
   2559   set_fixed_cow_array_map(Map::cast(obj));
   2560   ASSERT(fixed_array_map() != fixed_cow_array_map());
   2561 
   2562   { MaybeObject* maybe_obj =
   2563         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2564     if (!maybe_obj->ToObject(&obj)) return false;
   2565   }
   2566   set_scope_info_map(Map::cast(obj));
   2567 
   2568   { MaybeObject* maybe_obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize);
   2569     if (!maybe_obj->ToObject(&obj)) return false;
   2570   }
   2571   set_heap_number_map(Map::cast(obj));
   2572 
   2573   { MaybeObject* maybe_obj = AllocateMap(SYMBOL_TYPE, Symbol::kSize);
   2574     if (!maybe_obj->ToObject(&obj)) return false;
   2575   }
   2576   set_symbol_map(Map::cast(obj));
   2577 
   2578   { MaybeObject* maybe_obj = AllocateMap(FOREIGN_TYPE, Foreign::kSize);
   2579     if (!maybe_obj->ToObject(&obj)) return false;
   2580   }
   2581   set_foreign_map(Map::cast(obj));
   2582 
   2583   for (unsigned i = 0; i < ARRAY_SIZE(string_type_table); i++) {
   2584     const StringTypeTable& entry = string_type_table[i];
   2585     { MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size);
   2586       if (!maybe_obj->ToObject(&obj)) return false;
   2587     }
   2588     roots_[entry.index] = Map::cast(obj);
   2589   }
   2590 
   2591   { MaybeObject* maybe_obj = AllocateMap(STRING_TYPE, kVariableSizeSentinel);
   2592     if (!maybe_obj->ToObject(&obj)) return false;
   2593   }
   2594   set_undetectable_string_map(Map::cast(obj));
   2595   Map::cast(obj)->set_is_undetectable();
   2596 
   2597   { MaybeObject* maybe_obj =
   2598         AllocateMap(ASCII_STRING_TYPE, kVariableSizeSentinel);
   2599     if (!maybe_obj->ToObject(&obj)) return false;
   2600   }
   2601   set_undetectable_ascii_string_map(Map::cast(obj));
   2602   Map::cast(obj)->set_is_undetectable();
   2603 
   2604   { MaybeObject* maybe_obj =
   2605         AllocateMap(FIXED_DOUBLE_ARRAY_TYPE, kVariableSizeSentinel);
   2606     if (!maybe_obj->ToObject(&obj)) return false;
   2607   }
   2608   set_fixed_double_array_map(Map::cast(obj));
   2609 
   2610   { MaybeObject* maybe_obj =
   2611         AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel);
   2612     if (!maybe_obj->ToObject(&obj)) return false;
   2613   }
   2614   set_byte_array_map(Map::cast(obj));
   2615 
   2616   { MaybeObject* maybe_obj =
   2617         AllocateMap(FREE_SPACE_TYPE, kVariableSizeSentinel);
   2618     if (!maybe_obj->ToObject(&obj)) return false;
   2619   }
   2620   set_free_space_map(Map::cast(obj));
   2621 
   2622   { MaybeObject* maybe_obj = AllocateByteArray(0, TENURED);
   2623     if (!maybe_obj->ToObject(&obj)) return false;
   2624   }
   2625   set_empty_byte_array(ByteArray::cast(obj));
   2626 
   2627   { MaybeObject* maybe_obj =
   2628         AllocateMap(EXTERNAL_PIXEL_ARRAY_TYPE, ExternalArray::kAlignedSize);
   2629     if (!maybe_obj->ToObject(&obj)) return false;
   2630   }
   2631   set_external_pixel_array_map(Map::cast(obj));
   2632 
   2633   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE,
   2634                                          ExternalArray::kAlignedSize);
   2635     if (!maybe_obj->ToObject(&obj)) return false;
   2636   }
   2637   set_external_byte_array_map(Map::cast(obj));
   2638 
   2639   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
   2640                                          ExternalArray::kAlignedSize);
   2641     if (!maybe_obj->ToObject(&obj)) return false;
   2642   }
   2643   set_external_unsigned_byte_array_map(Map::cast(obj));
   2644 
   2645   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_SHORT_ARRAY_TYPE,
   2646                                          ExternalArray::kAlignedSize);
   2647     if (!maybe_obj->ToObject(&obj)) return false;
   2648   }
   2649   set_external_short_array_map(Map::cast(obj));
   2650 
   2651   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
   2652                                          ExternalArray::kAlignedSize);
   2653     if (!maybe_obj->ToObject(&obj)) return false;
   2654   }
   2655   set_external_unsigned_short_array_map(Map::cast(obj));
   2656 
   2657   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_INT_ARRAY_TYPE,
   2658                                          ExternalArray::kAlignedSize);
   2659     if (!maybe_obj->ToObject(&obj)) return false;
   2660   }
   2661   set_external_int_array_map(Map::cast(obj));
   2662 
   2663   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
   2664                                          ExternalArray::kAlignedSize);
   2665     if (!maybe_obj->ToObject(&obj)) return false;
   2666   }
   2667   set_external_unsigned_int_array_map(Map::cast(obj));
   2668 
   2669   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_FLOAT_ARRAY_TYPE,
   2670                                          ExternalArray::kAlignedSize);
   2671     if (!maybe_obj->ToObject(&obj)) return false;
   2672   }
   2673   set_external_float_array_map(Map::cast(obj));
   2674 
   2675   { MaybeObject* maybe_obj =
   2676         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2677     if (!maybe_obj->ToObject(&obj)) return false;
   2678   }
   2679   set_non_strict_arguments_elements_map(Map::cast(obj));
   2680 
   2681   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_DOUBLE_ARRAY_TYPE,
   2682                                          ExternalArray::kAlignedSize);
   2683     if (!maybe_obj->ToObject(&obj)) return false;
   2684   }
   2685   set_external_double_array_map(Map::cast(obj));
   2686 
   2687   { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalByteArray);
   2688     if (!maybe_obj->ToObject(&obj)) return false;
   2689   }
   2690   set_empty_external_byte_array(ExternalArray::cast(obj));
   2691 
   2692   { MaybeObject* maybe_obj =
   2693         AllocateEmptyExternalArray(kExternalUnsignedByteArray);
   2694     if (!maybe_obj->ToObject(&obj)) return false;
   2695   }
   2696   set_empty_external_unsigned_byte_array(ExternalArray::cast(obj));
   2697 
   2698   { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalShortArray);
   2699     if (!maybe_obj->ToObject(&obj)) return false;
   2700   }
   2701   set_empty_external_short_array(ExternalArray::cast(obj));
   2702 
   2703   { MaybeObject* maybe_obj = AllocateEmptyExternalArray(
   2704       kExternalUnsignedShortArray);
   2705     if (!maybe_obj->ToObject(&obj)) return false;
   2706   }
   2707   set_empty_external_unsigned_short_array(ExternalArray::cast(obj));
   2708 
   2709   { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalIntArray);
   2710     if (!maybe_obj->ToObject(&obj)) return false;
   2711   }
   2712   set_empty_external_int_array(ExternalArray::cast(obj));
   2713 
   2714   { MaybeObject* maybe_obj =
   2715         AllocateEmptyExternalArray(kExternalUnsignedIntArray);
   2716     if (!maybe_obj->ToObject(&obj)) return false;
   2717   }
   2718   set_empty_external_unsigned_int_array(ExternalArray::cast(obj));
   2719 
   2720   { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalFloatArray);
   2721     if (!maybe_obj->ToObject(&obj)) return false;
   2722   }
   2723   set_empty_external_float_array(ExternalArray::cast(obj));
   2724 
   2725   { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalDoubleArray);
   2726     if (!maybe_obj->ToObject(&obj)) return false;
   2727   }
   2728   set_empty_external_double_array(ExternalArray::cast(obj));
   2729 
   2730   { MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalPixelArray);
   2731     if (!maybe_obj->ToObject(&obj)) return false;
   2732   }
   2733   set_empty_external_pixel_array(ExternalArray::cast(obj));
   2734 
   2735   { MaybeObject* maybe_obj = AllocateMap(CODE_TYPE, kVariableSizeSentinel);
   2736     if (!maybe_obj->ToObject(&obj)) return false;
   2737   }
   2738   set_code_map(Map::cast(obj));
   2739 
   2740   { MaybeObject* maybe_obj = AllocateMap(CELL_TYPE, Cell::kSize);
   2741     if (!maybe_obj->ToObject(&obj)) return false;
   2742   }
   2743   set_cell_map(Map::cast(obj));
   2744 
   2745   { MaybeObject* maybe_obj = AllocateMap(PROPERTY_CELL_TYPE,
   2746                                          PropertyCell::kSize);
   2747     if (!maybe_obj->ToObject(&obj)) return false;
   2748   }
   2749   set_global_property_cell_map(Map::cast(obj));
   2750 
   2751   { MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, kPointerSize);
   2752     if (!maybe_obj->ToObject(&obj)) return false;
   2753   }
   2754   set_one_pointer_filler_map(Map::cast(obj));
   2755 
   2756   { MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, 2 * kPointerSize);
   2757     if (!maybe_obj->ToObject(&obj)) return false;
   2758   }
   2759   set_two_pointer_filler_map(Map::cast(obj));
   2760 
   2761   for (unsigned i = 0; i < ARRAY_SIZE(struct_table); i++) {
   2762     const StructTable& entry = struct_table[i];
   2763     { MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size);
   2764       if (!maybe_obj->ToObject(&obj)) return false;
   2765     }
   2766     roots_[entry.index] = Map::cast(obj);
   2767   }
   2768 
   2769   { MaybeObject* maybe_obj =
   2770         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2771     if (!maybe_obj->ToObject(&obj)) return false;
   2772   }
   2773   set_hash_table_map(Map::cast(obj));
   2774 
   2775   { MaybeObject* maybe_obj =
   2776         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2777     if (!maybe_obj->ToObject(&obj)) return false;
   2778   }
   2779   set_function_context_map(Map::cast(obj));
   2780 
   2781   { MaybeObject* maybe_obj =
   2782         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2783     if (!maybe_obj->ToObject(&obj)) return false;
   2784   }
   2785   set_catch_context_map(Map::cast(obj));
   2786 
   2787   { MaybeObject* maybe_obj =
   2788         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2789     if (!maybe_obj->ToObject(&obj)) return false;
   2790   }
   2791   set_with_context_map(Map::cast(obj));
   2792 
   2793   { MaybeObject* maybe_obj =
   2794         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2795     if (!maybe_obj->ToObject(&obj)) return false;
   2796   }
   2797   set_block_context_map(Map::cast(obj));
   2798 
   2799   { MaybeObject* maybe_obj =
   2800         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2801     if (!maybe_obj->ToObject(&obj)) return false;
   2802   }
   2803   set_module_context_map(Map::cast(obj));
   2804 
   2805   { MaybeObject* maybe_obj =
   2806         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2807     if (!maybe_obj->ToObject(&obj)) return false;
   2808   }
   2809   set_global_context_map(Map::cast(obj));
   2810 
   2811   { MaybeObject* maybe_obj =
   2812         AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
   2813     if (!maybe_obj->ToObject(&obj)) return false;
   2814   }
   2815   Map* native_context_map = Map::cast(obj);
   2816   native_context_map->set_dictionary_map(true);
   2817   native_context_map->set_visitor_id(StaticVisitorBase::kVisitNativeContext);
   2818   set_native_context_map(native_context_map);
   2819 
   2820   { MaybeObject* maybe_obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE,
   2821                                          SharedFunctionInfo::kAlignedSize);
   2822     if (!maybe_obj->ToObject(&obj)) return false;
   2823   }
   2824   set_shared_function_info_map(Map::cast(obj));
   2825 
   2826   { MaybeObject* maybe_obj = AllocateMap(JS_MESSAGE_OBJECT_TYPE,
   2827                                          JSMessageObject::kSize);
   2828     if (!maybe_obj->ToObject(&obj)) return false;
   2829   }
   2830   set_message_object_map(Map::cast(obj));
   2831 
   2832   Map* external_map;
   2833   { MaybeObject* maybe_obj =
   2834         AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize);
   2835     if (!maybe_obj->To(&external_map)) return false;
   2836   }
   2837   external_map->set_is_extensible(false);
   2838   set_external_map(external_map);
   2839 
   2840   ASSERT(!InNewSpace(empty_fixed_array()));
   2841   return true;
   2842 }
   2843 
   2844 
   2845 MaybeObject* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) {
   2846   // Statically ensure that it is safe to allocate heap numbers in paged
   2847   // spaces.
   2848   STATIC_ASSERT(HeapNumber::kSize <= Page::kNonCodeObjectAreaSize);
   2849   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   2850 
   2851   Object* result;
   2852   { MaybeObject* maybe_result =
   2853         AllocateRaw(HeapNumber::kSize, space, OLD_DATA_SPACE);
   2854     if (!maybe_result->ToObject(&result)) return maybe_result;
   2855   }
   2856 
   2857   HeapObject::cast(result)->set_map_no_write_barrier(heap_number_map());
   2858   HeapNumber::cast(result)->set_value(value);
   2859   return result;
   2860 }
   2861 
   2862 
   2863 MaybeObject* Heap::AllocateHeapNumber(double value) {
   2864   // Use general version, if we're forced to always allocate.
   2865   if (always_allocate()) return AllocateHeapNumber(value, TENURED);
   2866 
   2867   // This version of AllocateHeapNumber is optimized for
   2868   // allocation in new space.
   2869   STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxNonCodeHeapObjectSize);
   2870   Object* result;
   2871   { MaybeObject* maybe_result = new_space_.AllocateRaw(HeapNumber::kSize);
   2872     if (!maybe_result->ToObject(&result)) return maybe_result;
   2873   }
   2874   HeapObject::cast(result)->set_map_no_write_barrier(heap_number_map());
   2875   HeapNumber::cast(result)->set_value(value);
   2876   return result;
   2877 }
   2878 
   2879 
   2880 MaybeObject* Heap::AllocateCell(Object* value) {
   2881   Object* result;
   2882   { MaybeObject* maybe_result = AllocateRawCell();
   2883     if (!maybe_result->ToObject(&result)) return maybe_result;
   2884   }
   2885   HeapObject::cast(result)->set_map_no_write_barrier(cell_map());
   2886   Cell::cast(result)->set_value(value);
   2887   return result;
   2888 }
   2889 
   2890 
   2891 MaybeObject* Heap::AllocatePropertyCell(Object* value) {
   2892   Object* result;
   2893   MaybeObject* maybe_result = AllocateRawPropertyCell();
   2894   if (!maybe_result->ToObject(&result)) return maybe_result;
   2895 
   2896   HeapObject::cast(result)->set_map_no_write_barrier(
   2897       global_property_cell_map());
   2898   PropertyCell* cell = PropertyCell::cast(result);
   2899   cell->set_dependent_code(DependentCode::cast(empty_fixed_array()),
   2900                            SKIP_WRITE_BARRIER);
   2901   cell->set_value(value);
   2902   cell->set_type(Type::None());
   2903   maybe_result = cell->SetValueInferType(value);
   2904   if (maybe_result->IsFailure()) return maybe_result;
   2905   return result;
   2906 }
   2907 
   2908 
   2909 MaybeObject* Heap::AllocateBox(Object* value, PretenureFlag pretenure) {
   2910   Box* result;
   2911   MaybeObject* maybe_result = AllocateStruct(BOX_TYPE);
   2912   if (!maybe_result->To(&result)) return maybe_result;
   2913   result->set_value(value);
   2914   return result;
   2915 }
   2916 
   2917 
   2918 MaybeObject* Heap::AllocateAllocationSite() {
   2919   Object* result;
   2920   MaybeObject* maybe_result = Allocate(allocation_site_map(),
   2921                                        OLD_POINTER_SPACE);
   2922   if (!maybe_result->ToObject(&result)) return maybe_result;
   2923   AllocationSite* site = AllocationSite::cast(result);
   2924   site->Initialize();
   2925 
   2926   // Link the site
   2927   site->set_weak_next(allocation_sites_list());
   2928   set_allocation_sites_list(site);
   2929   return result;
   2930 }
   2931 
   2932 
   2933 MaybeObject* Heap::CreateOddball(const char* to_string,
   2934                                  Object* to_number,
   2935                                  byte kind) {
   2936   Object* result;
   2937   { MaybeObject* maybe_result = Allocate(oddball_map(), OLD_POINTER_SPACE);
   2938     if (!maybe_result->ToObject(&result)) return maybe_result;
   2939   }
   2940   return Oddball::cast(result)->Initialize(to_string, to_number, kind);
   2941 }
   2942 
   2943 
   2944 bool Heap::CreateApiObjects() {
   2945   Object* obj;
   2946 
   2947   { MaybeObject* maybe_obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
   2948     if (!maybe_obj->ToObject(&obj)) return false;
   2949   }
   2950   // Don't use Smi-only elements optimizations for objects with the neander
   2951   // map. There are too many cases where element values are set directly with a
   2952   // bottleneck to trap the Smi-only -> fast elements transition, and there
   2953   // appears to be no benefit for optimize this case.
   2954   Map* new_neander_map = Map::cast(obj);
   2955   new_neander_map->set_elements_kind(TERMINAL_FAST_ELEMENTS_KIND);
   2956   set_neander_map(new_neander_map);
   2957 
   2958   { MaybeObject* maybe_obj = AllocateJSObjectFromMap(neander_map());
   2959     if (!maybe_obj->ToObject(&obj)) return false;
   2960   }
   2961   Object* elements;
   2962   { MaybeObject* maybe_elements = AllocateFixedArray(2);
   2963     if (!maybe_elements->ToObject(&elements)) return false;
   2964   }
   2965   FixedArray::cast(elements)->set(0, Smi::FromInt(0));
   2966   JSObject::cast(obj)->set_elements(FixedArray::cast(elements));
   2967   set_message_listeners(JSObject::cast(obj));
   2968 
   2969   return true;
   2970 }
   2971 
   2972 
   2973 void Heap::CreateJSEntryStub() {
   2974   JSEntryStub stub;
   2975   set_js_entry_code(*stub.GetCode(isolate()));
   2976 }
   2977 
   2978 
   2979 void Heap::CreateJSConstructEntryStub() {
   2980   JSConstructEntryStub stub;
   2981   set_js_construct_entry_code(*stub.GetCode(isolate()));
   2982 }
   2983 
   2984 
   2985 void Heap::CreateFixedStubs() {
   2986   // Here we create roots for fixed stubs. They are needed at GC
   2987   // for cooking and uncooking (check out frames.cc).
   2988   // The eliminates the need for doing dictionary lookup in the
   2989   // stub cache for these stubs.
   2990   HandleScope scope(isolate());
   2991   // gcc-4.4 has problem generating correct code of following snippet:
   2992   // {  JSEntryStub stub;
   2993   //    js_entry_code_ = *stub.GetCode();
   2994   // }
   2995   // {  JSConstructEntryStub stub;
   2996   //    js_construct_entry_code_ = *stub.GetCode();
   2997   // }
   2998   // To workaround the problem, make separate functions without inlining.
   2999   Heap::CreateJSEntryStub();
   3000   Heap::CreateJSConstructEntryStub();
   3001 
   3002   // Create stubs that should be there, so we don't unexpectedly have to
   3003   // create them if we need them during the creation of another stub.
   3004   // Stub creation mixes raw pointers and handles in an unsafe manner so
   3005   // we cannot create stubs while we are creating stubs.
   3006   CodeStub::GenerateStubsAheadOfTime(isolate());
   3007 }
   3008 
   3009 
   3010 bool Heap::CreateInitialObjects() {
   3011   Object* obj;
   3012 
   3013   // The -0 value must be set before NumberFromDouble works.
   3014   { MaybeObject* maybe_obj = AllocateHeapNumber(-0.0, TENURED);
   3015     if (!maybe_obj->ToObject(&obj)) return false;
   3016   }
   3017   set_minus_zero_value(HeapNumber::cast(obj));
   3018   ASSERT(std::signbit(minus_zero_value()->Number()) != 0);
   3019 
   3020   { MaybeObject* maybe_obj = AllocateHeapNumber(OS::nan_value(), TENURED);
   3021     if (!maybe_obj->ToObject(&obj)) return false;
   3022   }
   3023   set_nan_value(HeapNumber::cast(obj));
   3024 
   3025   { MaybeObject* maybe_obj = AllocateHeapNumber(V8_INFINITY, TENURED);
   3026     if (!maybe_obj->ToObject(&obj)) return false;
   3027   }
   3028   set_infinity_value(HeapNumber::cast(obj));
   3029 
   3030   // The hole has not been created yet, but we want to put something
   3031   // predictable in the gaps in the string table, so lets make that Smi zero.
   3032   set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0)));
   3033 
   3034   // Allocate initial string table.
   3035   { MaybeObject* maybe_obj =
   3036         StringTable::Allocate(this, kInitialStringTableSize);
   3037     if (!maybe_obj->ToObject(&obj)) return false;
   3038   }
   3039   // Don't use set_string_table() due to asserts.
   3040   roots_[kStringTableRootIndex] = obj;
   3041 
   3042   // Finish initializing oddballs after creating the string table.
   3043   { MaybeObject* maybe_obj =
   3044         undefined_value()->Initialize("undefined",
   3045                                       nan_value(),
   3046                                       Oddball::kUndefined);
   3047     if (!maybe_obj->ToObject(&obj)) return false;
   3048   }
   3049 
   3050   // Initialize the null_value.
   3051   { MaybeObject* maybe_obj =
   3052         null_value()->Initialize("null", Smi::FromInt(0), Oddball::kNull);
   3053     if (!maybe_obj->ToObject(&obj)) return false;
   3054   }
   3055 
   3056   { MaybeObject* maybe_obj = CreateOddball("true",
   3057                                            Smi::FromInt(1),
   3058                                            Oddball::kTrue);
   3059     if (!maybe_obj->ToObject(&obj)) return false;
   3060   }
   3061   set_true_value(Oddball::cast(obj));
   3062 
   3063   { MaybeObject* maybe_obj = CreateOddball("false",
   3064                                            Smi::FromInt(0),
   3065                                            Oddball::kFalse);
   3066     if (!maybe_obj->ToObject(&obj)) return false;
   3067   }
   3068   set_false_value(Oddball::cast(obj));
   3069 
   3070   { MaybeObject* maybe_obj = CreateOddball("hole",
   3071                                            Smi::FromInt(-1),
   3072                                            Oddball::kTheHole);
   3073     if (!maybe_obj->ToObject(&obj)) return false;
   3074   }
   3075   set_the_hole_value(Oddball::cast(obj));
   3076 
   3077   { MaybeObject* maybe_obj = CreateOddball("uninitialized",
   3078                                            Smi::FromInt(-1),
   3079                                            Oddball::kUninitialized);
   3080     if (!maybe_obj->ToObject(&obj)) return false;
   3081   }
   3082   set_uninitialized_value(Oddball::cast(obj));
   3083 
   3084   { MaybeObject* maybe_obj = CreateOddball("arguments_marker",
   3085                                            Smi::FromInt(-4),
   3086                                            Oddball::kArgumentMarker);
   3087     if (!maybe_obj->ToObject(&obj)) return false;
   3088   }
   3089   set_arguments_marker(Oddball::cast(obj));
   3090 
   3091   { MaybeObject* maybe_obj = CreateOddball("no_interceptor_result_sentinel",
   3092                                            Smi::FromInt(-2),
   3093                                            Oddball::kOther);
   3094     if (!maybe_obj->ToObject(&obj)) return false;
   3095   }
   3096   set_no_interceptor_result_sentinel(obj);
   3097 
   3098   { MaybeObject* maybe_obj = CreateOddball("termination_exception",
   3099                                            Smi::FromInt(-3),
   3100                                            Oddball::kOther);
   3101     if (!maybe_obj->ToObject(&obj)) return false;
   3102   }
   3103   set_termination_exception(obj);
   3104 
   3105   for (unsigned i = 0; i < ARRAY_SIZE(constant_string_table); i++) {
   3106     { MaybeObject* maybe_obj =
   3107           InternalizeUtf8String(constant_string_table[i].contents);
   3108       if (!maybe_obj->ToObject(&obj)) return false;
   3109     }
   3110     roots_[constant_string_table[i].index] = String::cast(obj);
   3111   }
   3112 
   3113   // Allocate the hidden string which is used to identify the hidden properties
   3114   // in JSObjects. The hash code has a special value so that it will not match
   3115   // the empty string when searching for the property. It cannot be part of the
   3116   // loop above because it needs to be allocated manually with the special
   3117   // hash code in place. The hash code for the hidden_string is zero to ensure
   3118   // that it will always be at the first entry in property descriptors.
   3119   { MaybeObject* maybe_obj = AllocateOneByteInternalizedString(
   3120       OneByteVector("", 0), String::kEmptyStringHash);
   3121     if (!maybe_obj->ToObject(&obj)) return false;
   3122   }
   3123   hidden_string_ = String::cast(obj);
   3124 
   3125   // Allocate the code_stubs dictionary. The initial size is set to avoid
   3126   // expanding the dictionary during bootstrapping.
   3127   { MaybeObject* maybe_obj = UnseededNumberDictionary::Allocate(this, 128);
   3128     if (!maybe_obj->ToObject(&obj)) return false;
   3129   }
   3130   set_code_stubs(UnseededNumberDictionary::cast(obj));
   3131 
   3132 
   3133   // Allocate the non_monomorphic_cache used in stub-cache.cc. The initial size
   3134   // is set to avoid expanding the dictionary during bootstrapping.
   3135   { MaybeObject* maybe_obj = UnseededNumberDictionary::Allocate(this, 64);
   3136     if (!maybe_obj->ToObject(&obj)) return false;
   3137   }
   3138   set_non_monomorphic_cache(UnseededNumberDictionary::cast(obj));
   3139 
   3140   { MaybeObject* maybe_obj = AllocatePolymorphicCodeCache();
   3141     if (!maybe_obj->ToObject(&obj)) return false;
   3142   }
   3143   set_polymorphic_code_cache(PolymorphicCodeCache::cast(obj));
   3144 
   3145   set_instanceof_cache_function(Smi::FromInt(0));
   3146   set_instanceof_cache_map(Smi::FromInt(0));
   3147   set_instanceof_cache_answer(Smi::FromInt(0));
   3148 
   3149   CreateFixedStubs();
   3150 
   3151   // Allocate the dictionary of intrinsic function names.
   3152   { MaybeObject* maybe_obj =
   3153         NameDictionary::Allocate(this, Runtime::kNumFunctions);
   3154     if (!maybe_obj->ToObject(&obj)) return false;
   3155   }
   3156   { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(this,
   3157                                                                        obj);
   3158     if (!maybe_obj->ToObject(&obj)) return false;
   3159   }
   3160   set_intrinsic_function_names(NameDictionary::cast(obj));
   3161 
   3162   { MaybeObject* maybe_obj = AllocateInitialNumberStringCache();
   3163     if (!maybe_obj->ToObject(&obj)) return false;
   3164   }
   3165   set_number_string_cache(FixedArray::cast(obj));
   3166 
   3167   // Allocate cache for single character one byte strings.
   3168   { MaybeObject* maybe_obj =
   3169         AllocateFixedArray(String::kMaxOneByteCharCode + 1, TENURED);
   3170     if (!maybe_obj->ToObject(&obj)) return false;
   3171   }
   3172   set_single_character_string_cache(FixedArray::cast(obj));
   3173 
   3174   // Allocate cache for string split.
   3175   { MaybeObject* maybe_obj = AllocateFixedArray(
   3176       RegExpResultsCache::kRegExpResultsCacheSize, TENURED);
   3177     if (!maybe_obj->ToObject(&obj)) return false;
   3178   }
   3179   set_string_split_cache(FixedArray::cast(obj));
   3180 
   3181   { MaybeObject* maybe_obj = AllocateFixedArray(
   3182       RegExpResultsCache::kRegExpResultsCacheSize, TENURED);
   3183     if (!maybe_obj->ToObject(&obj)) return false;
   3184   }
   3185   set_regexp_multiple_cache(FixedArray::cast(obj));
   3186 
   3187   // Allocate cache for external strings pointing to native source code.
   3188   { MaybeObject* maybe_obj = AllocateFixedArray(Natives::GetBuiltinsCount());
   3189     if (!maybe_obj->ToObject(&obj)) return false;
   3190   }
   3191   set_natives_source_cache(FixedArray::cast(obj));
   3192 
   3193   // Allocate object to hold object observation state.
   3194   { MaybeObject* maybe_obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
   3195     if (!maybe_obj->ToObject(&obj)) return false;
   3196   }
   3197   { MaybeObject* maybe_obj = AllocateJSObjectFromMap(Map::cast(obj));
   3198     if (!maybe_obj->ToObject(&obj)) return false;
   3199   }
   3200   set_observation_state(JSObject::cast(obj));
   3201 
   3202   { MaybeObject* maybe_obj = AllocateSymbol();
   3203     if (!maybe_obj->ToObject(&obj)) return false;
   3204   }
   3205   set_frozen_symbol(Symbol::cast(obj));
   3206 
   3207   { MaybeObject* maybe_obj = AllocateSymbol();
   3208     if (!maybe_obj->ToObject(&obj)) return false;
   3209   }
   3210   set_elements_transition_symbol(Symbol::cast(obj));
   3211 
   3212   { MaybeObject* maybe_obj = SeededNumberDictionary::Allocate(this, 0, TENURED);
   3213     if (!maybe_obj->ToObject(&obj)) return false;
   3214   }
   3215   SeededNumberDictionary::cast(obj)->set_requires_slow_elements();
   3216   set_empty_slow_element_dictionary(SeededNumberDictionary::cast(obj));
   3217 
   3218   { MaybeObject* maybe_obj = AllocateSymbol();
   3219     if (!maybe_obj->ToObject(&obj)) return false;
   3220   }
   3221   set_observed_symbol(Symbol::cast(obj));
   3222 
   3223   // Handling of script id generation is in Factory::NewScript.
   3224   set_last_script_id(Smi::FromInt(v8::Script::kNoScriptId));
   3225 
   3226   // Initialize keyed lookup cache.
   3227   isolate_->keyed_lookup_cache()->Clear();
   3228 
   3229   // Initialize context slot cache.
   3230   isolate_->context_slot_cache()->Clear();
   3231 
   3232   // Initialize descriptor cache.
   3233   isolate_->descriptor_lookup_cache()->Clear();
   3234 
   3235   // Initialize compilation cache.
   3236   isolate_->compilation_cache()->Clear();
   3237 
   3238   return true;
   3239 }
   3240 
   3241 
   3242 bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
   3243   RootListIndex writable_roots[] = {
   3244     kStoreBufferTopRootIndex,
   3245     kStackLimitRootIndex,
   3246     kNumberStringCacheRootIndex,
   3247     kInstanceofCacheFunctionRootIndex,
   3248     kInstanceofCacheMapRootIndex,
   3249     kInstanceofCacheAnswerRootIndex,
   3250     kCodeStubsRootIndex,
   3251     kNonMonomorphicCacheRootIndex,
   3252     kPolymorphicCodeCacheRootIndex,
   3253     kLastScriptIdRootIndex,
   3254     kEmptyScriptRootIndex,
   3255     kRealStackLimitRootIndex,
   3256     kArgumentsAdaptorDeoptPCOffsetRootIndex,
   3257     kConstructStubDeoptPCOffsetRootIndex,
   3258     kGetterStubDeoptPCOffsetRootIndex,
   3259     kSetterStubDeoptPCOffsetRootIndex,
   3260     kStringTableRootIndex,
   3261   };
   3262 
   3263   for (unsigned int i = 0; i < ARRAY_SIZE(writable_roots); i++) {
   3264     if (root_index == writable_roots[i])
   3265       return true;
   3266   }
   3267   return false;
   3268 }
   3269 
   3270 
   3271 bool Heap::RootCanBeTreatedAsConstant(RootListIndex root_index) {
   3272   return !RootCanBeWrittenAfterInitialization(root_index) &&
   3273       !InNewSpace(roots_array_start()[root_index]);
   3274 }
   3275 
   3276 
   3277 Object* RegExpResultsCache::Lookup(Heap* heap,
   3278                                    String* key_string,
   3279                                    Object* key_pattern,
   3280                                    ResultsCacheType type) {
   3281   FixedArray* cache;
   3282   if (!key_string->IsInternalizedString()) return Smi::FromInt(0);
   3283   if (type == STRING_SPLIT_SUBSTRINGS) {
   3284     ASSERT(key_pattern->IsString());
   3285     if (!key_pattern->IsInternalizedString()) return Smi::FromInt(0);
   3286     cache = heap->string_split_cache();
   3287   } else {
   3288     ASSERT(type == REGEXP_MULTIPLE_INDICES);
   3289     ASSERT(key_pattern->IsFixedArray());
   3290     cache = heap->regexp_multiple_cache();
   3291   }
   3292 
   3293   uint32_t hash = key_string->Hash();
   3294   uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) &
   3295       ~(kArrayEntriesPerCacheEntry - 1));
   3296   if (cache->get(index + kStringOffset) == key_string &&
   3297       cache->get(index + kPatternOffset) == key_pattern) {
   3298     return cache->get(index + kArrayOffset);
   3299   }
   3300   index =
   3301       ((index + kArrayEntriesPerCacheEntry) & (kRegExpResultsCacheSize - 1));
   3302   if (cache->get(index + kStringOffset) == key_string &&
   3303       cache->get(index + kPatternOffset) == key_pattern) {
   3304     return cache->get(index + kArrayOffset);
   3305   }
   3306   return Smi::FromInt(0);
   3307 }
   3308 
   3309 
   3310 void RegExpResultsCache::Enter(Heap* heap,
   3311                                String* key_string,
   3312                                Object* key_pattern,
   3313                                FixedArray* value_array,
   3314                                ResultsCacheType type) {
   3315   FixedArray* cache;
   3316   if (!key_string->IsInternalizedString()) return;
   3317   if (type == STRING_SPLIT_SUBSTRINGS) {
   3318     ASSERT(key_pattern->IsString());
   3319     if (!key_pattern->IsInternalizedString()) return;
   3320     cache = heap->string_split_cache();
   3321   } else {
   3322     ASSERT(type == REGEXP_MULTIPLE_INDICES);
   3323     ASSERT(key_pattern->IsFixedArray());
   3324     cache = heap->regexp_multiple_cache();
   3325   }
   3326 
   3327   uint32_t hash = key_string->Hash();
   3328   uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) &
   3329       ~(kArrayEntriesPerCacheEntry - 1));
   3330   if (cache->get(index + kStringOffset) == Smi::FromInt(0)) {
   3331     cache->set(index + kStringOffset, key_string);
   3332     cache->set(index + kPatternOffset, key_pattern);
   3333     cache->set(index + kArrayOffset, value_array);
   3334   } else {
   3335     uint32_t index2 =
   3336         ((index + kArrayEntriesPerCacheEntry) & (kRegExpResultsCacheSize - 1));
   3337     if (cache->get(index2 + kStringOffset) == Smi::FromInt(0)) {
   3338       cache->set(index2 + kStringOffset, key_string);
   3339       cache->set(index2 + kPatternOffset, key_pattern);
   3340       cache->set(index2 + kArrayOffset, value_array);
   3341     } else {
   3342       cache->set(index2 + kStringOffset, Smi::FromInt(0));
   3343       cache->set(index2 + kPatternOffset, Smi::FromInt(0));
   3344       cache->set(index2 + kArrayOffset, Smi::FromInt(0));
   3345       cache->set(index + kStringOffset, key_string);
   3346       cache->set(index + kPatternOffset, key_pattern);
   3347       cache->set(index + kArrayOffset, value_array);
   3348     }
   3349   }
   3350   // If the array is a reasonably short list of substrings, convert it into a
   3351   // list of internalized strings.
   3352   if (type == STRING_SPLIT_SUBSTRINGS && value_array->length() < 100) {
   3353     for (int i = 0; i < value_array->length(); i++) {
   3354       String* str = String::cast(value_array->get(i));
   3355       Object* internalized_str;
   3356       MaybeObject* maybe_string = heap->InternalizeString(str);
   3357       if (maybe_string->ToObject(&internalized_str)) {
   3358         value_array->set(i, internalized_str);
   3359       }
   3360     }
   3361   }
   3362   // Convert backing store to a copy-on-write array.
   3363   value_array->set_map_no_write_barrier(heap->fixed_cow_array_map());
   3364 }
   3365 
   3366 
   3367 void RegExpResultsCache::Clear(FixedArray* cache) {
   3368   for (int i = 0; i < kRegExpResultsCacheSize; i++) {
   3369     cache->set(i, Smi::FromInt(0));
   3370   }
   3371 }
   3372 
   3373 
   3374 MaybeObject* Heap::AllocateInitialNumberStringCache() {
   3375   MaybeObject* maybe_obj =
   3376       AllocateFixedArray(kInitialNumberStringCacheSize * 2, TENURED);
   3377   return maybe_obj;
   3378 }
   3379 
   3380 
   3381 int Heap::FullSizeNumberStringCacheLength() {
   3382   // Compute the size of the number string cache based on the max newspace size.
   3383   // The number string cache has a minimum size based on twice the initial cache
   3384   // size to ensure that it is bigger after being made 'full size'.
   3385   int number_string_cache_size = max_semispace_size_ / 512;
   3386   number_string_cache_size = Max(kInitialNumberStringCacheSize * 2,
   3387                                  Min(0x4000, number_string_cache_size));
   3388   // There is a string and a number per entry so the length is twice the number
   3389   // of entries.
   3390   return number_string_cache_size * 2;
   3391 }
   3392 
   3393 
   3394 void Heap::AllocateFullSizeNumberStringCache() {
   3395   // The idea is to have a small number string cache in the snapshot to keep
   3396   // boot-time memory usage down.  If we expand the number string cache already
   3397   // while creating the snapshot then that didn't work out.
   3398   ASSERT(!Serializer::enabled() || FLAG_extra_code != NULL);
   3399   MaybeObject* maybe_obj =
   3400       AllocateFixedArray(FullSizeNumberStringCacheLength(), TENURED);
   3401   Object* new_cache;
   3402   if (maybe_obj->ToObject(&new_cache)) {
   3403     // We don't bother to repopulate the cache with entries from the old cache.
   3404     // It will be repopulated soon enough with new strings.
   3405     set_number_string_cache(FixedArray::cast(new_cache));
   3406   }
   3407   // If allocation fails then we just return without doing anything.  It is only
   3408   // a cache, so best effort is OK here.
   3409 }
   3410 
   3411 
   3412 void Heap::FlushNumberStringCache() {
   3413   // Flush the number to string cache.
   3414   int len = number_string_cache()->length();
   3415   for (int i = 0; i < len; i++) {
   3416     number_string_cache()->set_undefined(this, i);
   3417   }
   3418 }
   3419 
   3420 
   3421 static inline int double_get_hash(double d) {
   3422   DoubleRepresentation rep(d);
   3423   return static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32);
   3424 }
   3425 
   3426 
   3427 static inline int smi_get_hash(Smi* smi) {
   3428   return smi->value();
   3429 }
   3430 
   3431 
   3432 Object* Heap::GetNumberStringCache(Object* number) {
   3433   int hash;
   3434   int mask = (number_string_cache()->length() >> 1) - 1;
   3435   if (number->IsSmi()) {
   3436     hash = smi_get_hash(Smi::cast(number)) & mask;
   3437   } else {
   3438     hash = double_get_hash(number->Number()) & mask;
   3439   }
   3440   Object* key = number_string_cache()->get(hash * 2);
   3441   if (key == number) {
   3442     return String::cast(number_string_cache()->get(hash * 2 + 1));
   3443   } else if (key->IsHeapNumber() &&
   3444              number->IsHeapNumber() &&
   3445              key->Number() == number->Number()) {
   3446     return String::cast(number_string_cache()->get(hash * 2 + 1));
   3447   }
   3448   return undefined_value();
   3449 }
   3450 
   3451 
   3452 void Heap::SetNumberStringCache(Object* number, String* string) {
   3453   int hash;
   3454   int mask = (number_string_cache()->length() >> 1) - 1;
   3455   if (number->IsSmi()) {
   3456     hash = smi_get_hash(Smi::cast(number)) & mask;
   3457   } else {
   3458     hash = double_get_hash(number->Number()) & mask;
   3459   }
   3460   if (number_string_cache()->get(hash * 2) != undefined_value() &&
   3461       number_string_cache()->length() != FullSizeNumberStringCacheLength()) {
   3462     // The first time we have a hash collision, we move to the full sized
   3463     // number string cache.
   3464     AllocateFullSizeNumberStringCache();
   3465     return;
   3466   }
   3467   number_string_cache()->set(hash * 2, number);
   3468   number_string_cache()->set(hash * 2 + 1, string);
   3469 }
   3470 
   3471 
   3472 MaybeObject* Heap::NumberToString(Object* number,
   3473                                   bool check_number_string_cache,
   3474                                   PretenureFlag pretenure) {
   3475   isolate_->counters()->number_to_string_runtime()->Increment();
   3476   if (check_number_string_cache) {
   3477     Object* cached = GetNumberStringCache(number);
   3478     if (cached != undefined_value()) {
   3479       return cached;
   3480     }
   3481   }
   3482 
   3483   char arr[100];
   3484   Vector<char> buffer(arr, ARRAY_SIZE(arr));
   3485   const char* str;
   3486   if (number->IsSmi()) {
   3487     int num = Smi::cast(number)->value();
   3488     str = IntToCString(num, buffer);
   3489   } else {
   3490     double num = HeapNumber::cast(number)->value();
   3491     str = DoubleToCString(num, buffer);
   3492   }
   3493 
   3494   Object* js_string;
   3495   MaybeObject* maybe_js_string =
   3496       AllocateStringFromOneByte(CStrVector(str), pretenure);
   3497   if (maybe_js_string->ToObject(&js_string)) {
   3498     SetNumberStringCache(number, String::cast(js_string));
   3499   }
   3500   return maybe_js_string;
   3501 }
   3502 
   3503 
   3504 MaybeObject* Heap::Uint32ToString(uint32_t value,
   3505                                   bool check_number_string_cache) {
   3506   Object* number;
   3507   MaybeObject* maybe = NumberFromUint32(value);
   3508   if (!maybe->To<Object>(&number)) return maybe;
   3509   return NumberToString(number, check_number_string_cache);
   3510 }
   3511 
   3512 
   3513 Map* Heap::MapForExternalArrayType(ExternalArrayType array_type) {
   3514   return Map::cast(roots_[RootIndexForExternalArrayType(array_type)]);
   3515 }
   3516 
   3517 
   3518 Heap::RootListIndex Heap::RootIndexForExternalArrayType(
   3519     ExternalArrayType array_type) {
   3520   switch (array_type) {
   3521     case kExternalByteArray:
   3522       return kExternalByteArrayMapRootIndex;
   3523     case kExternalUnsignedByteArray:
   3524       return kExternalUnsignedByteArrayMapRootIndex;
   3525     case kExternalShortArray:
   3526       return kExternalShortArrayMapRootIndex;
   3527     case kExternalUnsignedShortArray:
   3528       return kExternalUnsignedShortArrayMapRootIndex;
   3529     case kExternalIntArray:
   3530       return kExternalIntArrayMapRootIndex;
   3531     case kExternalUnsignedIntArray:
   3532       return kExternalUnsignedIntArrayMapRootIndex;
   3533     case kExternalFloatArray:
   3534       return kExternalFloatArrayMapRootIndex;
   3535     case kExternalDoubleArray:
   3536       return kExternalDoubleArrayMapRootIndex;
   3537     case kExternalPixelArray:
   3538       return kExternalPixelArrayMapRootIndex;
   3539     default:
   3540       UNREACHABLE();
   3541       return kUndefinedValueRootIndex;
   3542   }
   3543 }
   3544 
   3545 Heap::RootListIndex Heap::RootIndexForEmptyExternalArray(
   3546     ElementsKind elementsKind) {
   3547   switch (elementsKind) {
   3548     case EXTERNAL_BYTE_ELEMENTS:
   3549       return kEmptyExternalByteArrayRootIndex;
   3550     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   3551       return kEmptyExternalUnsignedByteArrayRootIndex;
   3552     case EXTERNAL_SHORT_ELEMENTS:
   3553       return kEmptyExternalShortArrayRootIndex;
   3554     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   3555       return kEmptyExternalUnsignedShortArrayRootIndex;
   3556     case EXTERNAL_INT_ELEMENTS:
   3557       return kEmptyExternalIntArrayRootIndex;
   3558     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   3559       return kEmptyExternalUnsignedIntArrayRootIndex;
   3560     case EXTERNAL_FLOAT_ELEMENTS:
   3561       return kEmptyExternalFloatArrayRootIndex;
   3562     case EXTERNAL_DOUBLE_ELEMENTS:
   3563       return kEmptyExternalDoubleArrayRootIndex;
   3564     case EXTERNAL_PIXEL_ELEMENTS:
   3565       return kEmptyExternalPixelArrayRootIndex;
   3566     default:
   3567       UNREACHABLE();
   3568       return kUndefinedValueRootIndex;
   3569   }
   3570 }
   3571 
   3572 
   3573 ExternalArray* Heap::EmptyExternalArrayForMap(Map* map) {
   3574   return ExternalArray::cast(
   3575       roots_[RootIndexForEmptyExternalArray(map->elements_kind())]);
   3576 }
   3577 
   3578 
   3579 
   3580 
   3581 MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) {
   3582   // We need to distinguish the minus zero value and this cannot be
   3583   // done after conversion to int. Doing this by comparing bit
   3584   // patterns is faster than using fpclassify() et al.
   3585   static const DoubleRepresentation minus_zero(-0.0);
   3586 
   3587   DoubleRepresentation rep(value);
   3588   if (rep.bits == minus_zero.bits) {
   3589     return AllocateHeapNumber(-0.0, pretenure);
   3590   }
   3591 
   3592   int int_value = FastD2I(value);
   3593   if (value == int_value && Smi::IsValid(int_value)) {
   3594     return Smi::FromInt(int_value);
   3595   }
   3596 
   3597   // Materialize the value in the heap.
   3598   return AllocateHeapNumber(value, pretenure);
   3599 }
   3600 
   3601 
   3602 MaybeObject* Heap::AllocateForeign(Address address, PretenureFlag pretenure) {
   3603   // Statically ensure that it is safe to allocate foreigns in paged spaces.
   3604   STATIC_ASSERT(Foreign::kSize <= Page::kMaxNonCodeHeapObjectSize);
   3605   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   3606   Foreign* result;
   3607   MaybeObject* maybe_result = Allocate(foreign_map(), space);
   3608   if (!maybe_result->To(&result)) return maybe_result;
   3609   result->set_foreign_address(address);
   3610   return result;
   3611 }
   3612 
   3613 
   3614 MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
   3615   SharedFunctionInfo* share;
   3616   MaybeObject* maybe = Allocate(shared_function_info_map(), OLD_POINTER_SPACE);
   3617   if (!maybe->To<SharedFunctionInfo>(&share)) return maybe;
   3618 
   3619   // Set pointer fields.
   3620   share->set_name(name);
   3621   Code* illegal = isolate_->builtins()->builtin(Builtins::kIllegal);
   3622   share->set_code(illegal);
   3623   share->set_optimized_code_map(Smi::FromInt(0));
   3624   share->set_scope_info(ScopeInfo::Empty(isolate_));
   3625   Code* construct_stub =
   3626       isolate_->builtins()->builtin(Builtins::kJSConstructStubGeneric);
   3627   share->set_construct_stub(construct_stub);
   3628   share->set_instance_class_name(Object_string());
   3629   share->set_function_data(undefined_value(), SKIP_WRITE_BARRIER);
   3630   share->set_script(undefined_value(), SKIP_WRITE_BARRIER);
   3631   share->set_debug_info(undefined_value(), SKIP_WRITE_BARRIER);
   3632   share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER);
   3633   share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER);
   3634   share->set_ast_node_count(0);
   3635   share->set_counters(0);
   3636 
   3637   // Set integer fields (smi or int, depending on the architecture).
   3638   share->set_length(0);
   3639   share->set_formal_parameter_count(0);
   3640   share->set_expected_nof_properties(0);
   3641   share->set_num_literals(0);
   3642   share->set_start_position_and_type(0);
   3643   share->set_end_position(0);
   3644   share->set_function_token_position(0);
   3645   // All compiler hints default to false or 0.
   3646   share->set_compiler_hints(0);
   3647   share->set_opt_count(0);
   3648 
   3649   return share;
   3650 }
   3651 
   3652 
   3653 MaybeObject* Heap::AllocateJSMessageObject(String* type,
   3654                                            JSArray* arguments,
   3655                                            int start_position,
   3656                                            int end_position,
   3657                                            Object* script,
   3658                                            Object* stack_trace,
   3659                                            Object* stack_frames) {
   3660   Object* result;
   3661   { MaybeObject* maybe_result = Allocate(message_object_map(), NEW_SPACE);
   3662     if (!maybe_result->ToObject(&result)) return maybe_result;
   3663   }
   3664   JSMessageObject* message = JSMessageObject::cast(result);
   3665   message->set_properties(Heap::empty_fixed_array(), SKIP_WRITE_BARRIER);
   3666   message->initialize_elements();
   3667   message->set_elements(Heap::empty_fixed_array(), SKIP_WRITE_BARRIER);
   3668   message->set_type(type);
   3669   message->set_arguments(arguments);
   3670   message->set_start_position(start_position);
   3671   message->set_end_position(end_position);
   3672   message->set_script(script);
   3673   message->set_stack_trace(stack_trace);
   3674   message->set_stack_frames(stack_frames);
   3675   return result;
   3676 }
   3677 
   3678 
   3679 
   3680 // Returns true for a character in a range.  Both limits are inclusive.
   3681 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
   3682   // This makes uses of the the unsigned wraparound.
   3683   return character - from <= to - from;
   3684 }
   3685 
   3686 
   3687 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString(
   3688     Heap* heap,
   3689     uint16_t c1,
   3690     uint16_t c2) {
   3691   String* result;
   3692   // Numeric strings have a different hash algorithm not known by
   3693   // LookupTwoCharsStringIfExists, so we skip this step for such strings.
   3694   if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) &&
   3695       heap->string_table()->LookupTwoCharsStringIfExists(c1, c2, &result)) {
   3696     return result;
   3697   // Now we know the length is 2, we might as well make use of that fact
   3698   // when building the new string.
   3699   } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
   3700     // We can do this.
   3701     ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1));  // because of this.
   3702     Object* result;
   3703     { MaybeObject* maybe_result = heap->AllocateRawOneByteString(2);
   3704       if (!maybe_result->ToObject(&result)) return maybe_result;
   3705     }
   3706     uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
   3707     dest[0] = static_cast<uint8_t>(c1);
   3708     dest[1] = static_cast<uint8_t>(c2);
   3709     return result;
   3710   } else {
   3711     Object* result;
   3712     { MaybeObject* maybe_result = heap->AllocateRawTwoByteString(2);
   3713       if (!maybe_result->ToObject(&result)) return maybe_result;
   3714     }
   3715     uc16* dest = SeqTwoByteString::cast(result)->GetChars();
   3716     dest[0] = c1;
   3717     dest[1] = c2;
   3718     return result;
   3719   }
   3720 }
   3721 
   3722 
   3723 MaybeObject* Heap::AllocateConsString(String* first, String* second) {
   3724   int first_length = first->length();
   3725   if (first_length == 0) {
   3726     return second;
   3727   }
   3728 
   3729   int second_length = second->length();
   3730   if (second_length == 0) {
   3731     return first;
   3732   }
   3733 
   3734   int length = first_length + second_length;
   3735 
   3736   // Optimization for 2-byte strings often used as keys in a decompression
   3737   // dictionary.  Check whether we already have the string in the string
   3738   // table to prevent creation of many unneccesary strings.
   3739   if (length == 2) {
   3740     uint16_t c1 = first->Get(0);
   3741     uint16_t c2 = second->Get(0);
   3742     return MakeOrFindTwoCharacterString(this, c1, c2);
   3743   }
   3744 
   3745   bool first_is_one_byte = first->IsOneByteRepresentation();
   3746   bool second_is_one_byte = second->IsOneByteRepresentation();
   3747   bool is_one_byte = first_is_one_byte && second_is_one_byte;
   3748   // Make sure that an out of memory exception is thrown if the length
   3749   // of the new cons string is too large.
   3750   if (length > String::kMaxLength || length < 0) {
   3751     isolate()->context()->mark_out_of_memory();
   3752     return Failure::OutOfMemoryException(0x4);
   3753   }
   3754 
   3755   bool is_one_byte_data_in_two_byte_string = false;
   3756   if (!is_one_byte) {
   3757     // At least one of the strings uses two-byte representation so we
   3758     // can't use the fast case code for short ASCII strings below, but
   3759     // we can try to save memory if all chars actually fit in ASCII.
   3760     is_one_byte_data_in_two_byte_string =
   3761         first->HasOnlyOneByteChars() && second->HasOnlyOneByteChars();
   3762     if (is_one_byte_data_in_two_byte_string) {
   3763       isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
   3764     }
   3765   }
   3766 
   3767   // If the resulting string is small make a flat string.
   3768   if (length < ConsString::kMinLength) {
   3769     // Note that neither of the two inputs can be a slice because:
   3770     STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
   3771     ASSERT(first->IsFlat());
   3772     ASSERT(second->IsFlat());
   3773     if (is_one_byte) {
   3774       Object* result;
   3775       { MaybeObject* maybe_result = AllocateRawOneByteString(length);
   3776         if (!maybe_result->ToObject(&result)) return maybe_result;
   3777       }
   3778       // Copy the characters into the new object.
   3779       uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
   3780       // Copy first part.
   3781       const uint8_t* src;
   3782       if (first->IsExternalString()) {
   3783         src = ExternalAsciiString::cast(first)->GetChars();
   3784       } else {
   3785         src = SeqOneByteString::cast(first)->GetChars();
   3786       }
   3787       for (int i = 0; i < first_length; i++) *dest++ = src[i];
   3788       // Copy second part.
   3789       if (second->IsExternalString()) {
   3790         src = ExternalAsciiString::cast(second)->GetChars();
   3791       } else {
   3792         src = SeqOneByteString::cast(second)->GetChars();
   3793       }
   3794       for (int i = 0; i < second_length; i++) *dest++ = src[i];
   3795       return result;
   3796     } else {
   3797       if (is_one_byte_data_in_two_byte_string) {
   3798         Object* result;
   3799         { MaybeObject* maybe_result = AllocateRawOneByteString(length);
   3800           if (!maybe_result->ToObject(&result)) return maybe_result;
   3801         }
   3802         // Copy the characters into the new object.
   3803         uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
   3804         String::WriteToFlat(first, dest, 0, first_length);
   3805         String::WriteToFlat(second, dest + first_length, 0, second_length);
   3806         isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
   3807         return result;
   3808       }
   3809 
   3810       Object* result;
   3811       { MaybeObject* maybe_result = AllocateRawTwoByteString(length);
   3812         if (!maybe_result->ToObject(&result)) return maybe_result;
   3813       }
   3814       // Copy the characters into the new object.
   3815       uc16* dest = SeqTwoByteString::cast(result)->GetChars();
   3816       String::WriteToFlat(first, dest, 0, first_length);
   3817       String::WriteToFlat(second, dest + first_length, 0, second_length);
   3818       return result;
   3819     }
   3820   }
   3821 
   3822   Map* map = (is_one_byte || is_one_byte_data_in_two_byte_string) ?
   3823       cons_ascii_string_map() : cons_string_map();
   3824 
   3825   Object* result;
   3826   { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
   3827     if (!maybe_result->ToObject(&result)) return maybe_result;
   3828   }
   3829 
   3830   DisallowHeapAllocation no_gc;
   3831   ConsString* cons_string = ConsString::cast(result);
   3832   WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc);
   3833   cons_string->set_length(length);
   3834   cons_string->set_hash_field(String::kEmptyHashField);
   3835   cons_string->set_first(first, mode);
   3836   cons_string->set_second(second, mode);
   3837   return result;
   3838 }
   3839 
   3840 
   3841 MaybeObject* Heap::AllocateSubString(String* buffer,
   3842                                      int start,
   3843                                      int end,
   3844                                      PretenureFlag pretenure) {
   3845   int length = end - start;
   3846   if (length <= 0) {
   3847     return empty_string();
   3848   } else if (length == 1) {
   3849     return LookupSingleCharacterStringFromCode(buffer->Get(start));
   3850   } else if (length == 2) {
   3851     // Optimization for 2-byte strings often used as keys in a decompression
   3852     // dictionary.  Check whether we already have the string in the string
   3853     // table to prevent creation of many unnecessary strings.
   3854     uint16_t c1 = buffer->Get(start);
   3855     uint16_t c2 = buffer->Get(start + 1);
   3856     return MakeOrFindTwoCharacterString(this, c1, c2);
   3857   }
   3858 
   3859   // Make an attempt to flatten the buffer to reduce access time.
   3860   buffer = buffer->TryFlattenGetString();
   3861 
   3862   if (!FLAG_string_slices ||
   3863       !buffer->IsFlat() ||
   3864       length < SlicedString::kMinLength ||
   3865       pretenure == TENURED) {
   3866     Object* result;
   3867     // WriteToFlat takes care of the case when an indirect string has a
   3868     // different encoding from its underlying string.  These encodings may
   3869     // differ because of externalization.
   3870     bool is_one_byte = buffer->IsOneByteRepresentation();
   3871     { MaybeObject* maybe_result = is_one_byte
   3872                                   ? AllocateRawOneByteString(length, pretenure)
   3873                                   : AllocateRawTwoByteString(length, pretenure);
   3874       if (!maybe_result->ToObject(&result)) return maybe_result;
   3875     }
   3876     String* string_result = String::cast(result);
   3877     // Copy the characters into the new object.
   3878     if (is_one_byte) {
   3879       ASSERT(string_result->IsOneByteRepresentation());
   3880       uint8_t* dest = SeqOneByteString::cast(string_result)->GetChars();
   3881       String::WriteToFlat(buffer, dest, start, end);
   3882     } else {
   3883       ASSERT(string_result->IsTwoByteRepresentation());
   3884       uc16* dest = SeqTwoByteString::cast(string_result)->GetChars();
   3885       String::WriteToFlat(buffer, dest, start, end);
   3886     }
   3887     return result;
   3888   }
   3889 
   3890   ASSERT(buffer->IsFlat());
   3891 #if VERIFY_HEAP
   3892   if (FLAG_verify_heap) {
   3893     buffer->StringVerify();
   3894   }
   3895 #endif
   3896 
   3897   Object* result;
   3898   // When slicing an indirect string we use its encoding for a newly created
   3899   // slice and don't check the encoding of the underlying string.  This is safe
   3900   // even if the encodings are different because of externalization.  If an
   3901   // indirect ASCII string is pointing to a two-byte string, the two-byte char
   3902   // codes of the underlying string must still fit into ASCII (because
   3903   // externalization must not change char codes).
   3904   { Map* map = buffer->IsOneByteRepresentation()
   3905                  ? sliced_ascii_string_map()
   3906                  : sliced_string_map();
   3907     MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
   3908     if (!maybe_result->ToObject(&result)) return maybe_result;
   3909   }
   3910 
   3911   DisallowHeapAllocation no_gc;
   3912   SlicedString* sliced_string = SlicedString::cast(result);
   3913   sliced_string->set_length(length);
   3914   sliced_string->set_hash_field(String::kEmptyHashField);
   3915   if (buffer->IsConsString()) {
   3916     ConsString* cons = ConsString::cast(buffer);
   3917     ASSERT(cons->second()->length() == 0);
   3918     sliced_string->set_parent(cons->first());
   3919     sliced_string->set_offset(start);
   3920   } else if (buffer->IsSlicedString()) {
   3921     // Prevent nesting sliced strings.
   3922     SlicedString* parent_slice = SlicedString::cast(buffer);
   3923     sliced_string->set_parent(parent_slice->parent());
   3924     sliced_string->set_offset(start + parent_slice->offset());
   3925   } else {
   3926     sliced_string->set_parent(buffer);
   3927     sliced_string->set_offset(start);
   3928   }
   3929   ASSERT(sliced_string->parent()->IsSeqString() ||
   3930          sliced_string->parent()->IsExternalString());
   3931   return result;
   3932 }
   3933 
   3934 
   3935 MaybeObject* Heap::AllocateExternalStringFromAscii(
   3936     const ExternalAsciiString::Resource* resource) {
   3937   size_t length = resource->length();
   3938   if (length > static_cast<size_t>(String::kMaxLength)) {
   3939     isolate()->context()->mark_out_of_memory();
   3940     return Failure::OutOfMemoryException(0x5);
   3941   }
   3942 
   3943   Map* map = external_ascii_string_map();
   3944   Object* result;
   3945   { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
   3946     if (!maybe_result->ToObject(&result)) return maybe_result;
   3947   }
   3948 
   3949   ExternalAsciiString* external_string = ExternalAsciiString::cast(result);
   3950   external_string->set_length(static_cast<int>(length));
   3951   external_string->set_hash_field(String::kEmptyHashField);
   3952   external_string->set_resource(resource);
   3953 
   3954   return result;
   3955 }
   3956 
   3957 
   3958 MaybeObject* Heap::AllocateExternalStringFromTwoByte(
   3959     const ExternalTwoByteString::Resource* resource) {
   3960   size_t length = resource->length();
   3961   if (length > static_cast<size_t>(String::kMaxLength)) {
   3962     isolate()->context()->mark_out_of_memory();
   3963     return Failure::OutOfMemoryException(0x6);
   3964   }
   3965 
   3966   // For small strings we check whether the resource contains only
   3967   // one byte characters.  If yes, we use a different string map.
   3968   static const size_t kOneByteCheckLengthLimit = 32;
   3969   bool is_one_byte = length <= kOneByteCheckLengthLimit &&
   3970       String::IsOneByte(resource->data(), static_cast<int>(length));
   3971   Map* map = is_one_byte ?
   3972       external_string_with_one_byte_data_map() : external_string_map();
   3973   Object* result;
   3974   { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
   3975     if (!maybe_result->ToObject(&result)) return maybe_result;
   3976   }
   3977 
   3978   ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result);
   3979   external_string->set_length(static_cast<int>(length));
   3980   external_string->set_hash_field(String::kEmptyHashField);
   3981   external_string->set_resource(resource);
   3982 
   3983   return result;
   3984 }
   3985 
   3986 
   3987 MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
   3988   if (code <= String::kMaxOneByteCharCode) {
   3989     Object* value = single_character_string_cache()->get(code);
   3990     if (value != undefined_value()) return value;
   3991 
   3992     uint8_t buffer[1];
   3993     buffer[0] = static_cast<uint8_t>(code);
   3994     Object* result;
   3995     MaybeObject* maybe_result =
   3996         InternalizeOneByteString(Vector<const uint8_t>(buffer, 1));
   3997 
   3998     if (!maybe_result->ToObject(&result)) return maybe_result;
   3999     single_character_string_cache()->set(code, result);
   4000     return result;
   4001   }
   4002 
   4003   Object* result;
   4004   { MaybeObject* maybe_result = AllocateRawTwoByteString(1);
   4005     if (!maybe_result->ToObject(&result)) return maybe_result;
   4006   }
   4007   String* answer = String::cast(result);
   4008   answer->Set(0, code);
   4009   return answer;
   4010 }
   4011 
   4012 
   4013 MaybeObject* Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
   4014   if (length < 0 || length > ByteArray::kMaxLength) {
   4015     return Failure::OutOfMemoryException(0x7);
   4016   }
   4017   if (pretenure == NOT_TENURED) {
   4018     return AllocateByteArray(length);
   4019   }
   4020   int size = ByteArray::SizeFor(length);
   4021   AllocationSpace space =
   4022       (size > Page::kMaxNonCodeHeapObjectSize) ? LO_SPACE : OLD_DATA_SPACE;
   4023   Object* result;
   4024   { MaybeObject* maybe_result = AllocateRaw(size, space, space);
   4025     if (!maybe_result->ToObject(&result)) return maybe_result;
   4026   }
   4027 
   4028   reinterpret_cast<ByteArray*>(result)->set_map_no_write_barrier(
   4029       byte_array_map());
   4030   reinterpret_cast<ByteArray*>(result)->set_length(length);
   4031   return result;
   4032 }
   4033 
   4034 
   4035 MaybeObject* Heap::AllocateByteArray(int length) {
   4036   if (length < 0 || length > ByteArray::kMaxLength) {
   4037     return Failure::OutOfMemoryException(0x8);
   4038   }
   4039   int size = ByteArray::SizeFor(length);
   4040   AllocationSpace space =
   4041       (size > Page::kMaxNonCodeHeapObjectSize) ? LO_SPACE : NEW_SPACE;
   4042   Object* result;
   4043   { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
   4044     if (!maybe_result->ToObject(&result)) return maybe_result;
   4045   }
   4046 
   4047   reinterpret_cast<ByteArray*>(result)->set_map_no_write_barrier(
   4048       byte_array_map());
   4049   reinterpret_cast<ByteArray*>(result)->set_length(length);
   4050   return result;
   4051 }
   4052 
   4053 
   4054 void Heap::CreateFillerObjectAt(Address addr, int size) {
   4055   if (size == 0) return;
   4056   HeapObject* filler = HeapObject::FromAddress(addr);
   4057   if (size == kPointerSize) {
   4058     filler->set_map_no_write_barrier(one_pointer_filler_map());
   4059   } else if (size == 2 * kPointerSize) {
   4060     filler->set_map_no_write_barrier(two_pointer_filler_map());
   4061   } else {
   4062     filler->set_map_no_write_barrier(free_space_map());
   4063     FreeSpace::cast(filler)->set_size(size);
   4064   }
   4065 }
   4066 
   4067 
   4068 MaybeObject* Heap::AllocateExternalArray(int length,
   4069                                          ExternalArrayType array_type,
   4070                                          void* external_pointer,
   4071                                          PretenureFlag pretenure) {
   4072   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   4073   Object* result;
   4074   { MaybeObject* maybe_result = AllocateRaw(ExternalArray::kAlignedSize,
   4075                                             space,
   4076                                             OLD_DATA_SPACE);
   4077     if (!maybe_result->ToObject(&result)) return maybe_result;
   4078   }
   4079 
   4080   reinterpret_cast<ExternalArray*>(result)->set_map_no_write_barrier(
   4081       MapForExternalArrayType(array_type));
   4082   reinterpret_cast<ExternalArray*>(result)->set_length(length);
   4083   reinterpret_cast<ExternalArray*>(result)->set_external_pointer(
   4084       external_pointer);
   4085 
   4086   return result;
   4087 }
   4088 
   4089 
   4090 MaybeObject* Heap::CreateCode(const CodeDesc& desc,
   4091                               Code::Flags flags,
   4092                               Handle<Object> self_reference,
   4093                               bool immovable,
   4094                               bool crankshafted) {
   4095   // Allocate ByteArray before the Code object, so that we do not risk
   4096   // leaving uninitialized Code object (and breaking the heap).
   4097   ByteArray* reloc_info;
   4098   MaybeObject* maybe_reloc_info = AllocateByteArray(desc.reloc_size, TENURED);
   4099   if (!maybe_reloc_info->To(&reloc_info)) return maybe_reloc_info;
   4100 
   4101   // Compute size.
   4102   int body_size = RoundUp(desc.instr_size, kObjectAlignment);
   4103   int obj_size = Code::SizeFor(body_size);
   4104   ASSERT(IsAligned(static_cast<intptr_t>(obj_size), kCodeAlignment));
   4105   MaybeObject* maybe_result;
   4106   // Large code objects and code objects which should stay at a fixed address
   4107   // are allocated in large object space.
   4108   HeapObject* result;
   4109   bool force_lo_space = obj_size > code_space()->AreaSize();
   4110   if (force_lo_space) {
   4111     maybe_result = lo_space_->AllocateRaw(obj_size, EXECUTABLE);
   4112   } else {
   4113     maybe_result = code_space_->AllocateRaw(obj_size);
   4114   }
   4115   if (!maybe_result->To<HeapObject>(&result)) return maybe_result;
   4116 
   4117   if (immovable && !force_lo_space &&
   4118       // Objects on the first page of each space are never moved.
   4119       !code_space_->FirstPage()->Contains(result->address())) {
   4120     // Discard the first code allocation, which was on a page where it could be
   4121     // moved.
   4122     CreateFillerObjectAt(result->address(), obj_size);
   4123     maybe_result = lo_space_->AllocateRaw(obj_size, EXECUTABLE);
   4124     if (!maybe_result->To<HeapObject>(&result)) return maybe_result;
   4125   }
   4126 
   4127   // Initialize the object
   4128   result->set_map_no_write_barrier(code_map());
   4129   Code* code = Code::cast(result);
   4130   ASSERT(!isolate_->code_range()->exists() ||
   4131       isolate_->code_range()->contains(code->address()));
   4132   code->set_instruction_size(desc.instr_size);
   4133   code->set_relocation_info(reloc_info);
   4134   code->set_flags(flags);
   4135   if (code->is_call_stub() || code->is_keyed_call_stub()) {
   4136     code->set_check_type(RECEIVER_MAP_CHECK);
   4137   }
   4138   code->set_is_crankshafted(crankshafted);
   4139   code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER);
   4140   code->InitializeTypeFeedbackInfoNoWriteBarrier(undefined_value());
   4141   code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER);
   4142   code->set_gc_metadata(Smi::FromInt(0));
   4143   code->set_ic_age(global_ic_age_);
   4144   code->set_prologue_offset(kPrologueOffsetNotSet);
   4145   if (code->kind() == Code::OPTIMIZED_FUNCTION) {
   4146     code->set_marked_for_deoptimization(false);
   4147   }
   4148   // Allow self references to created code object by patching the handle to
   4149   // point to the newly allocated Code object.
   4150   if (!self_reference.is_null()) {
   4151     *(self_reference.location()) = code;
   4152   }
   4153   // Migrate generated code.
   4154   // The generated code can contain Object** values (typically from handles)
   4155   // that are dereferenced during the copy to point directly to the actual heap
   4156   // objects. These pointers can include references to the code object itself,
   4157   // through the self_reference parameter.
   4158   code->CopyFrom(desc);
   4159 
   4160 #ifdef VERIFY_HEAP
   4161   if (FLAG_verify_heap) {
   4162     code->Verify();
   4163   }
   4164 #endif
   4165   return code;
   4166 }
   4167 
   4168 
   4169 MaybeObject* Heap::CopyCode(Code* code) {
   4170   // Allocate an object the same size as the code object.
   4171   int obj_size = code->Size();
   4172   MaybeObject* maybe_result;
   4173   if (obj_size > code_space()->AreaSize()) {
   4174     maybe_result = lo_space_->AllocateRaw(obj_size, EXECUTABLE);
   4175   } else {
   4176     maybe_result = code_space_->AllocateRaw(obj_size);
   4177   }
   4178 
   4179   Object* result;
   4180   if (!maybe_result->ToObject(&result)) return maybe_result;
   4181 
   4182   // Copy code object.
   4183   Address old_addr = code->address();
   4184   Address new_addr = reinterpret_cast<HeapObject*>(result)->address();
   4185   CopyBlock(new_addr, old_addr, obj_size);
   4186   // Relocate the copy.
   4187   Code* new_code = Code::cast(result);
   4188   ASSERT(!isolate_->code_range()->exists() ||
   4189       isolate_->code_range()->contains(code->address()));
   4190   new_code->Relocate(new_addr - old_addr);
   4191   return new_code;
   4192 }
   4193 
   4194 
   4195 MaybeObject* Heap::CopyCode(Code* code, Vector<byte> reloc_info) {
   4196   // Allocate ByteArray before the Code object, so that we do not risk
   4197   // leaving uninitialized Code object (and breaking the heap).
   4198   Object* reloc_info_array;
   4199   { MaybeObject* maybe_reloc_info_array =
   4200         AllocateByteArray(reloc_info.length(), TENURED);
   4201     if (!maybe_reloc_info_array->ToObject(&reloc_info_array)) {
   4202       return maybe_reloc_info_array;
   4203     }
   4204   }
   4205 
   4206   int new_body_size = RoundUp(code->instruction_size(), kObjectAlignment);
   4207 
   4208   int new_obj_size = Code::SizeFor(new_body_size);
   4209 
   4210   Address old_addr = code->address();
   4211 
   4212   size_t relocation_offset =
   4213       static_cast<size_t>(code->instruction_end() - old_addr);
   4214 
   4215   MaybeObject* maybe_result;
   4216   if (new_obj_size > code_space()->AreaSize()) {
   4217     maybe_result = lo_space_->AllocateRaw(new_obj_size, EXECUTABLE);
   4218   } else {
   4219     maybe_result = code_space_->AllocateRaw(new_obj_size);
   4220   }
   4221 
   4222   Object* result;
   4223   if (!maybe_result->ToObject(&result)) return maybe_result;
   4224 
   4225   // Copy code object.
   4226   Address new_addr = reinterpret_cast<HeapObject*>(result)->address();
   4227 
   4228   // Copy header and instructions.
   4229   CopyBytes(new_addr, old_addr, relocation_offset);
   4230 
   4231   Code* new_code = Code::cast(result);
   4232   new_code->set_relocation_info(ByteArray::cast(reloc_info_array));
   4233 
   4234   // Copy patched rinfo.
   4235   CopyBytes(new_code->relocation_start(),
   4236             reloc_info.start(),
   4237             static_cast<size_t>(reloc_info.length()));
   4238 
   4239   // Relocate the copy.
   4240   ASSERT(!isolate_->code_range()->exists() ||
   4241       isolate_->code_range()->contains(code->address()));
   4242   new_code->Relocate(new_addr - old_addr);
   4243 
   4244 #ifdef VERIFY_HEAP
   4245   if (FLAG_verify_heap) {
   4246     code->Verify();
   4247   }
   4248 #endif
   4249   return new_code;
   4250 }
   4251 
   4252 
   4253 MaybeObject* Heap::AllocateWithAllocationSite(Map* map, AllocationSpace space,
   4254     Handle<AllocationSite> allocation_site) {
   4255   ASSERT(gc_state_ == NOT_IN_GC);
   4256   ASSERT(map->instance_type() != MAP_TYPE);
   4257   // If allocation failures are disallowed, we may allocate in a different
   4258   // space when new space is full and the object is not a large object.
   4259   AllocationSpace retry_space =
   4260       (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type());
   4261   int size = map->instance_size() + AllocationMemento::kSize;
   4262   Object* result;
   4263   MaybeObject* maybe_result = AllocateRaw(size, space, retry_space);
   4264   if (!maybe_result->ToObject(&result)) return maybe_result;
   4265   // No need for write barrier since object is white and map is in old space.
   4266   HeapObject::cast(result)->set_map_no_write_barrier(map);
   4267   AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
   4268       reinterpret_cast<Address>(result) + map->instance_size());
   4269   alloc_memento->set_map_no_write_barrier(allocation_memento_map());
   4270   alloc_memento->set_allocation_site(*allocation_site, SKIP_WRITE_BARRIER);
   4271   return result;
   4272 }
   4273 
   4274 
   4275 MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) {
   4276   ASSERT(gc_state_ == NOT_IN_GC);
   4277   ASSERT(map->instance_type() != MAP_TYPE);
   4278   // If allocation failures are disallowed, we may allocate in a different
   4279   // space when new space is full and the object is not a large object.
   4280   AllocationSpace retry_space =
   4281       (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type());
   4282   int size = map->instance_size();
   4283   Object* result;
   4284   MaybeObject* maybe_result = AllocateRaw(size, space, retry_space);
   4285   if (!maybe_result->ToObject(&result)) return maybe_result;
   4286   // No need for write barrier since object is white and map is in old space.
   4287   HeapObject::cast(result)->set_map_no_write_barrier(map);
   4288   return result;
   4289 }
   4290 
   4291 
   4292 void Heap::InitializeFunction(JSFunction* function,
   4293                               SharedFunctionInfo* shared,
   4294                               Object* prototype) {
   4295   ASSERT(!prototype->IsMap());
   4296   function->initialize_properties();
   4297   function->initialize_elements();
   4298   function->set_shared(shared);
   4299   function->set_code(shared->code());
   4300   function->set_prototype_or_initial_map(prototype);
   4301   function->set_context(undefined_value());
   4302   function->set_literals_or_bindings(empty_fixed_array());
   4303   function->set_next_function_link(undefined_value());
   4304 }
   4305 
   4306 
   4307 MaybeObject* Heap::AllocateFunctionPrototype(JSFunction* function) {
   4308   // Make sure to use globals from the function's context, since the function
   4309   // can be from a different context.
   4310   Context* native_context = function->context()->native_context();
   4311   Map* new_map;
   4312   if (function->shared()->is_generator()) {
   4313     // Generator prototypes can share maps since they don't have "constructor"
   4314     // properties.
   4315     new_map = native_context->generator_object_prototype_map();
   4316   } else {
   4317     // Each function prototype gets a fresh map to avoid unwanted sharing of
   4318     // maps between prototypes of different constructors.
   4319     JSFunction* object_function = native_context->object_function();
   4320     ASSERT(object_function->has_initial_map());
   4321     MaybeObject* maybe_map = object_function->initial_map()->Copy();
   4322     if (!maybe_map->To(&new_map)) return maybe_map;
   4323   }
   4324 
   4325   Object* prototype;
   4326   MaybeObject* maybe_prototype = AllocateJSObjectFromMap(new_map);
   4327   if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
   4328 
   4329   if (!function->shared()->is_generator()) {
   4330     MaybeObject* maybe_failure =
   4331         JSObject::cast(prototype)->SetLocalPropertyIgnoreAttributes(
   4332             constructor_string(), function, DONT_ENUM);
   4333     if (maybe_failure->IsFailure()) return maybe_failure;
   4334   }
   4335 
   4336   return prototype;
   4337 }
   4338 
   4339 
   4340 MaybeObject* Heap::AllocateFunction(Map* function_map,
   4341                                     SharedFunctionInfo* shared,
   4342                                     Object* prototype,
   4343                                     PretenureFlag pretenure) {
   4344   AllocationSpace space =
   4345       (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
   4346   Object* result;
   4347   { MaybeObject* maybe_result = Allocate(function_map, space);
   4348     if (!maybe_result->ToObject(&result)) return maybe_result;
   4349   }
   4350   InitializeFunction(JSFunction::cast(result), shared, prototype);
   4351   return result;
   4352 }
   4353 
   4354 
   4355 MaybeObject* Heap::AllocateArgumentsObject(Object* callee, int length) {
   4356   // To get fast allocation and map sharing for arguments objects we
   4357   // allocate them based on an arguments boilerplate.
   4358 
   4359   JSObject* boilerplate;
   4360   int arguments_object_size;
   4361   bool strict_mode_callee = callee->IsJSFunction() &&
   4362       !JSFunction::cast(callee)->shared()->is_classic_mode();
   4363   if (strict_mode_callee) {
   4364     boilerplate =
   4365         isolate()->context()->native_context()->
   4366             strict_mode_arguments_boilerplate();
   4367     arguments_object_size = kArgumentsObjectSizeStrict;
   4368   } else {
   4369     boilerplate =
   4370         isolate()->context()->native_context()->arguments_boilerplate();
   4371     arguments_object_size = kArgumentsObjectSize;
   4372   }
   4373 
   4374   // This calls Copy directly rather than using Heap::AllocateRaw so we
   4375   // duplicate the check here.
   4376   ASSERT(AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC);
   4377 
   4378   // Check that the size of the boilerplate matches our
   4379   // expectations. The ArgumentsAccessStub::GenerateNewObject relies
   4380   // on the size being a known constant.
   4381   ASSERT(arguments_object_size == boilerplate->map()->instance_size());
   4382 
   4383   // Do the allocation.
   4384   Object* result;
   4385   { MaybeObject* maybe_result =
   4386         AllocateRaw(arguments_object_size, NEW_SPACE, OLD_POINTER_SPACE);
   4387     if (!maybe_result->ToObject(&result)) return maybe_result;
   4388   }
   4389 
   4390   // Copy the content. The arguments boilerplate doesn't have any
   4391   // fields that point to new space so it's safe to skip the write
   4392   // barrier here.
   4393   CopyBlock(HeapObject::cast(result)->address(),
   4394             boilerplate->address(),
   4395             JSObject::kHeaderSize);
   4396 
   4397   // Set the length property.
   4398   JSObject::cast(result)->InObjectPropertyAtPut(kArgumentsLengthIndex,
   4399                                                 Smi::FromInt(length),
   4400                                                 SKIP_WRITE_BARRIER);
   4401   // Set the callee property for non-strict mode arguments object only.
   4402   if (!strict_mode_callee) {
   4403     JSObject::cast(result)->InObjectPropertyAtPut(kArgumentsCalleeIndex,
   4404                                                   callee);
   4405   }
   4406 
   4407   // Check the state of the object
   4408   ASSERT(JSObject::cast(result)->HasFastProperties());
   4409   ASSERT(JSObject::cast(result)->HasFastObjectElements());
   4410 
   4411   return result;
   4412 }
   4413 
   4414 
   4415 MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) {
   4416   ASSERT(!fun->has_initial_map());
   4417 
   4418   // First create a new map with the size and number of in-object properties
   4419   // suggested by the function.
   4420   InstanceType instance_type;
   4421   int instance_size;
   4422   int in_object_properties;
   4423   if (fun->shared()->is_generator()) {
   4424     instance_type = JS_GENERATOR_OBJECT_TYPE;
   4425     instance_size = JSGeneratorObject::kSize;
   4426     in_object_properties = 0;
   4427   } else {
   4428     instance_type = JS_OBJECT_TYPE;
   4429     instance_size = fun->shared()->CalculateInstanceSize();
   4430     in_object_properties = fun->shared()->CalculateInObjectProperties();
   4431   }
   4432   Map* map;
   4433   MaybeObject* maybe_map = AllocateMap(instance_type, instance_size);
   4434   if (!maybe_map->To(&map)) return maybe_map;
   4435 
   4436   // Fetch or allocate prototype.
   4437   Object* prototype;
   4438   if (fun->has_instance_prototype()) {
   4439     prototype = fun->instance_prototype();
   4440   } else {
   4441     MaybeObject* maybe_prototype = AllocateFunctionPrototype(fun);
   4442     if (!maybe_prototype->To(&prototype)) return maybe_prototype;
   4443   }
   4444   map->set_inobject_properties(in_object_properties);
   4445   map->set_unused_property_fields(in_object_properties);
   4446   map->set_prototype(prototype);
   4447   ASSERT(map->has_fast_object_elements());
   4448 
   4449   if (!fun->shared()->is_generator()) {
   4450     fun->shared()->StartInobjectSlackTracking(map);
   4451   }
   4452 
   4453   return map;
   4454 }
   4455 
   4456 
   4457 void Heap::InitializeJSObjectFromMap(JSObject* obj,
   4458                                      FixedArray* properties,
   4459                                      Map* map) {
   4460   obj->set_properties(properties);
   4461   obj->initialize_elements();
   4462   // TODO(1240798): Initialize the object's body using valid initial values
   4463   // according to the object's initial map.  For example, if the map's
   4464   // instance type is JS_ARRAY_TYPE, the length field should be initialized
   4465   // to a number (e.g. Smi::FromInt(0)) and the elements initialized to a
   4466   // fixed array (e.g. Heap::empty_fixed_array()).  Currently, the object
   4467   // verification code has to cope with (temporarily) invalid objects.  See
   4468   // for example, JSArray::JSArrayVerify).
   4469   Object* filler;
   4470   // We cannot always fill with one_pointer_filler_map because objects
   4471   // created from API functions expect their internal fields to be initialized
   4472   // with undefined_value.
   4473   // Pre-allocated fields need to be initialized with undefined_value as well
   4474   // so that object accesses before the constructor completes (e.g. in the
   4475   // debugger) will not cause a crash.
   4476   if (map->constructor()->IsJSFunction() &&
   4477       JSFunction::cast(map->constructor())->shared()->
   4478           IsInobjectSlackTrackingInProgress()) {
   4479     // We might want to shrink the object later.
   4480     ASSERT(obj->GetInternalFieldCount() == 0);
   4481     filler = Heap::one_pointer_filler_map();
   4482   } else {
   4483     filler = Heap::undefined_value();
   4484   }
   4485   obj->InitializeBody(map, Heap::undefined_value(), filler);
   4486 }
   4487 
   4488 
   4489 MaybeObject* Heap::AllocateJSObjectFromMap(
   4490     Map* map, PretenureFlag pretenure, bool allocate_properties) {
   4491   // JSFunctions should be allocated using AllocateFunction to be
   4492   // properly initialized.
   4493   ASSERT(map->instance_type() != JS_FUNCTION_TYPE);
   4494 
   4495   // Both types of global objects should be allocated using
   4496   // AllocateGlobalObject to be properly initialized.
   4497   ASSERT(map->instance_type() != JS_GLOBAL_OBJECT_TYPE);
   4498   ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE);
   4499 
   4500   // Allocate the backing storage for the properties.
   4501   FixedArray* properties;
   4502   if (allocate_properties) {
   4503     int prop_size = map->InitialPropertiesLength();
   4504     ASSERT(prop_size >= 0);
   4505     { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, pretenure);
   4506       if (!maybe_properties->To(&properties)) return maybe_properties;
   4507     }
   4508   } else {
   4509     properties = empty_fixed_array();
   4510   }
   4511 
   4512   // Allocate the JSObject.
   4513   AllocationSpace space =
   4514       (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
   4515   if (map->instance_size() > Page::kMaxNonCodeHeapObjectSize) space = LO_SPACE;
   4516   Object* obj;
   4517   MaybeObject* maybe_obj = Allocate(map, space);
   4518   if (!maybe_obj->To(&obj)) return maybe_obj;
   4519 
   4520   // Initialize the JSObject.
   4521   InitializeJSObjectFromMap(JSObject::cast(obj), properties, map);
   4522   ASSERT(JSObject::cast(obj)->HasFastElements() ||
   4523          JSObject::cast(obj)->HasExternalArrayElements());
   4524   return obj;
   4525 }
   4526 
   4527 
   4528 MaybeObject* Heap::AllocateJSObjectFromMapWithAllocationSite(
   4529     Map* map, Handle<AllocationSite> allocation_site) {
   4530   // JSFunctions should be allocated using AllocateFunction to be
   4531   // properly initialized.
   4532   ASSERT(map->instance_type() != JS_FUNCTION_TYPE);
   4533 
   4534   // Both types of global objects should be allocated using
   4535   // AllocateGlobalObject to be properly initialized.
   4536   ASSERT(map->instance_type() != JS_GLOBAL_OBJECT_TYPE);
   4537   ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE);
   4538 
   4539   // Allocate the backing storage for the properties.
   4540   int prop_size = map->InitialPropertiesLength();
   4541   ASSERT(prop_size >= 0);
   4542   FixedArray* properties;
   4543   { MaybeObject* maybe_properties = AllocateFixedArray(prop_size);
   4544     if (!maybe_properties->To(&properties)) return maybe_properties;
   4545   }
   4546 
   4547   // Allocate the JSObject.
   4548   AllocationSpace space = NEW_SPACE;
   4549   if (map->instance_size() > Page::kMaxNonCodeHeapObjectSize) space = LO_SPACE;
   4550   Object* obj;
   4551   MaybeObject* maybe_obj =
   4552       AllocateWithAllocationSite(map, space, allocation_site);
   4553   if (!maybe_obj->To(&obj)) return maybe_obj;
   4554 
   4555   // Initialize the JSObject.
   4556   InitializeJSObjectFromMap(JSObject::cast(obj), properties, map);
   4557   ASSERT(JSObject::cast(obj)->HasFastElements());
   4558   return obj;
   4559 }
   4560 
   4561 
   4562 MaybeObject* Heap::AllocateJSObject(JSFunction* constructor,
   4563                                     PretenureFlag pretenure) {
   4564   // Allocate the initial map if absent.
   4565   if (!constructor->has_initial_map()) {
   4566     Object* initial_map;
   4567     { MaybeObject* maybe_initial_map = AllocateInitialMap(constructor);
   4568       if (!maybe_initial_map->ToObject(&initial_map)) return maybe_initial_map;
   4569     }
   4570     constructor->set_initial_map(Map::cast(initial_map));
   4571     Map::cast(initial_map)->set_constructor(constructor);
   4572   }
   4573   // Allocate the object based on the constructors initial map.
   4574   MaybeObject* result = AllocateJSObjectFromMap(
   4575       constructor->initial_map(), pretenure);
   4576 #ifdef DEBUG
   4577   // Make sure result is NOT a global object if valid.
   4578   Object* non_failure;
   4579   ASSERT(!result->ToObject(&non_failure) || !non_failure->IsGlobalObject());
   4580 #endif
   4581   return result;
   4582 }
   4583 
   4584 
   4585 MaybeObject* Heap::AllocateJSObjectWithAllocationSite(JSFunction* constructor,
   4586     Handle<AllocationSite> allocation_site) {
   4587   // Allocate the initial map if absent.
   4588   if (!constructor->has_initial_map()) {
   4589     Object* initial_map;
   4590     { MaybeObject* maybe_initial_map = AllocateInitialMap(constructor);
   4591       if (!maybe_initial_map->ToObject(&initial_map)) return maybe_initial_map;
   4592     }
   4593     constructor->set_initial_map(Map::cast(initial_map));
   4594     Map::cast(initial_map)->set_constructor(constructor);
   4595   }
   4596   // Allocate the object based on the constructors initial map, or the payload
   4597   // advice
   4598   Map* initial_map = constructor->initial_map();
   4599 
   4600   Smi* smi = Smi::cast(allocation_site->transition_info());
   4601   ElementsKind to_kind = static_cast<ElementsKind>(smi->value());
   4602   AllocationSiteMode mode = TRACK_ALLOCATION_SITE;
   4603   if (to_kind != initial_map->elements_kind()) {
   4604     MaybeObject* maybe_new_map = initial_map->AsElementsKind(to_kind);
   4605     if (!maybe_new_map->To(&initial_map)) return maybe_new_map;
   4606     // Possibly alter the mode, since we found an updated elements kind
   4607     // in the type info cell.
   4608     mode = AllocationSite::GetMode(to_kind);
   4609   }
   4610 
   4611   MaybeObject* result;
   4612   if (mode == TRACK_ALLOCATION_SITE) {
   4613     result = AllocateJSObjectFromMapWithAllocationSite(initial_map,
   4614         allocation_site);
   4615   } else {
   4616     result = AllocateJSObjectFromMap(initial_map, NOT_TENURED);
   4617   }
   4618 #ifdef DEBUG
   4619   // Make sure result is NOT a global object if valid.
   4620   Object* non_failure;
   4621   ASSERT(!result->ToObject(&non_failure) || !non_failure->IsGlobalObject());
   4622 #endif
   4623   return result;
   4624 }
   4625 
   4626 
   4627 MaybeObject* Heap::AllocateJSGeneratorObject(JSFunction *function) {
   4628   ASSERT(function->shared()->is_generator());
   4629   Map *map;
   4630   if (function->has_initial_map()) {
   4631     map = function->initial_map();
   4632   } else {
   4633     // Allocate the initial map if absent.
   4634     MaybeObject* maybe_map = AllocateInitialMap(function);
   4635     if (!maybe_map->To(&map)) return maybe_map;
   4636     function->set_initial_map(map);
   4637     map->set_constructor(function);
   4638   }
   4639   ASSERT(map->instance_type() == JS_GENERATOR_OBJECT_TYPE);
   4640   return AllocateJSObjectFromMap(map);
   4641 }
   4642 
   4643 
   4644 MaybeObject* Heap::AllocateJSModule(Context* context, ScopeInfo* scope_info) {
   4645   // Allocate a fresh map. Modules do not have a prototype.
   4646   Map* map;
   4647   MaybeObject* maybe_map = AllocateMap(JS_MODULE_TYPE, JSModule::kSize);
   4648   if (!maybe_map->To(&map)) return maybe_map;
   4649   // Allocate the object based on the map.
   4650   JSModule* module;
   4651   MaybeObject* maybe_module = AllocateJSObjectFromMap(map, TENURED);
   4652   if (!maybe_module->To(&module)) return maybe_module;
   4653   module->set_context(context);
   4654   module->set_scope_info(scope_info);
   4655   return module;
   4656 }
   4657 
   4658 
   4659 MaybeObject* Heap::AllocateJSArrayAndStorage(
   4660     ElementsKind elements_kind,
   4661     int length,
   4662     int capacity,
   4663     ArrayStorageAllocationMode mode,
   4664     PretenureFlag pretenure) {
   4665   MaybeObject* maybe_array = AllocateJSArray(elements_kind, pretenure);
   4666   JSArray* array;
   4667   if (!maybe_array->To(&array)) return maybe_array;
   4668 
   4669   // TODO(mvstanton): this body of code is duplicate with AllocateJSArrayStorage
   4670   // for performance reasons.
   4671   ASSERT(capacity >= length);
   4672 
   4673   if (capacity == 0) {
   4674     array->set_length(Smi::FromInt(0));
   4675     array->set_elements(empty_fixed_array());
   4676     return array;
   4677   }
   4678 
   4679   FixedArrayBase* elms;
   4680   MaybeObject* maybe_elms = NULL;
   4681   if (IsFastDoubleElementsKind(elements_kind)) {
   4682     if (mode == DONT_INITIALIZE_ARRAY_ELEMENTS) {
   4683       maybe_elms = AllocateUninitializedFixedDoubleArray(capacity);
   4684     } else {
   4685       ASSERT(mode == INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
   4686       maybe_elms = AllocateFixedDoubleArrayWithHoles(capacity);
   4687     }
   4688   } else {
   4689     ASSERT(IsFastSmiOrObjectElementsKind(elements_kind));
   4690     if (mode == DONT_INITIALIZE_ARRAY_ELEMENTS) {
   4691       maybe_elms = AllocateUninitializedFixedArray(capacity);
   4692     } else {
   4693       ASSERT(mode == INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
   4694       maybe_elms = AllocateFixedArrayWithHoles(capacity);
   4695     }
   4696   }
   4697   if (!maybe_elms->To(&elms)) return maybe_elms;
   4698 
   4699   array->set_elements(elms);
   4700   array->set_length(Smi::FromInt(length));
   4701   return array;
   4702 }
   4703 
   4704 
   4705 MaybeObject* Heap::AllocateJSArrayAndStorageWithAllocationSite(
   4706     ElementsKind elements_kind,
   4707     int length,
   4708     int capacity,
   4709     Handle<AllocationSite> allocation_site,
   4710     ArrayStorageAllocationMode mode) {
   4711   MaybeObject* maybe_array = AllocateJSArrayWithAllocationSite(elements_kind,
   4712       allocation_site);
   4713   JSArray* array;
   4714   if (!maybe_array->To(&array)) return maybe_array;
   4715   return AllocateJSArrayStorage(array, length, capacity, mode);
   4716 }
   4717 
   4718 
   4719 MaybeObject* Heap::AllocateJSArrayStorage(
   4720     JSArray* array,
   4721     int length,
   4722     int capacity,
   4723     ArrayStorageAllocationMode mode) {
   4724   ASSERT(capacity >= length);
   4725 
   4726   if (capacity == 0) {
   4727     array->set_length(Smi::FromInt(0));
   4728     array->set_elements(empty_fixed_array());
   4729     return array;
   4730   }
   4731 
   4732   FixedArrayBase* elms;
   4733   MaybeObject* maybe_elms = NULL;
   4734   ElementsKind elements_kind = array->GetElementsKind();
   4735   if (IsFastDoubleElementsKind(elements_kind)) {
   4736     if (mode == DONT_INITIALIZE_ARRAY_ELEMENTS) {
   4737       maybe_elms = AllocateUninitializedFixedDoubleArray(capacity);
   4738     } else {
   4739       ASSERT(mode == INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
   4740       maybe_elms = AllocateFixedDoubleArrayWithHoles(capacity);
   4741     }
   4742   } else {
   4743     ASSERT(IsFastSmiOrObjectElementsKind(elements_kind));
   4744     if (mode == DONT_INITIALIZE_ARRAY_ELEMENTS) {
   4745       maybe_elms = AllocateUninitializedFixedArray(capacity);
   4746     } else {
   4747       ASSERT(mode == INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
   4748       maybe_elms = AllocateFixedArrayWithHoles(capacity);
   4749     }
   4750   }
   4751   if (!maybe_elms->To(&elms)) return maybe_elms;
   4752 
   4753   array->set_elements(elms);
   4754   array->set_length(Smi::FromInt(length));
   4755   return array;
   4756 }
   4757 
   4758 
   4759 MaybeObject* Heap::AllocateJSArrayWithElements(
   4760     FixedArrayBase* elements,
   4761     ElementsKind elements_kind,
   4762     int length,
   4763     PretenureFlag pretenure) {
   4764   MaybeObject* maybe_array = AllocateJSArray(elements_kind, pretenure);
   4765   JSArray* array;
   4766   if (!maybe_array->To(&array)) return maybe_array;
   4767 
   4768   array->set_elements(elements);
   4769   array->set_length(Smi::FromInt(length));
   4770   array->ValidateElements();
   4771   return array;
   4772 }
   4773 
   4774 
   4775 MaybeObject* Heap::AllocateJSProxy(Object* handler, Object* prototype) {
   4776   // Allocate map.
   4777   // TODO(rossberg): Once we optimize proxies, think about a scheme to share
   4778   // maps. Will probably depend on the identity of the handler object, too.
   4779   Map* map;
   4780   MaybeObject* maybe_map_obj = AllocateMap(JS_PROXY_TYPE, JSProxy::kSize);
   4781   if (!maybe_map_obj->To<Map>(&map)) return maybe_map_obj;
   4782   map->set_prototype(prototype);
   4783 
   4784   // Allocate the proxy object.
   4785   JSProxy* result;
   4786   MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
   4787   if (!maybe_result->To<JSProxy>(&result)) return maybe_result;
   4788   result->InitializeBody(map->instance_size(), Smi::FromInt(0));
   4789   result->set_handler(handler);
   4790   result->set_hash(undefined_value(), SKIP_WRITE_BARRIER);
   4791   return result;
   4792 }
   4793 
   4794 
   4795 MaybeObject* Heap::AllocateJSFunctionProxy(Object* handler,
   4796                                            Object* call_trap,
   4797                                            Object* construct_trap,
   4798                                            Object* prototype) {
   4799   // Allocate map.
   4800   // TODO(rossberg): Once we optimize proxies, think about a scheme to share
   4801   // maps. Will probably depend on the identity of the handler object, too.
   4802   Map* map;
   4803   MaybeObject* maybe_map_obj =
   4804       AllocateMap(JS_FUNCTION_PROXY_TYPE, JSFunctionProxy::kSize);
   4805   if (!maybe_map_obj->To<Map>(&map)) return maybe_map_obj;
   4806   map->set_prototype(prototype);
   4807 
   4808   // Allocate the proxy object.
   4809   JSFunctionProxy* result;
   4810   MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
   4811   if (!maybe_result->To<JSFunctionProxy>(&result)) return maybe_result;
   4812   result->InitializeBody(map->instance_size(), Smi::FromInt(0));
   4813   result->set_handler(handler);
   4814   result->set_hash(undefined_value(), SKIP_WRITE_BARRIER);
   4815   result->set_call_trap(call_trap);
   4816   result->set_construct_trap(construct_trap);
   4817   return result;
   4818 }
   4819 
   4820 
   4821 MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) {
   4822   ASSERT(constructor->has_initial_map());
   4823   Map* map = constructor->initial_map();
   4824   ASSERT(map->is_dictionary_map());
   4825 
   4826   // Make sure no field properties are described in the initial map.
   4827   // This guarantees us that normalizing the properties does not
   4828   // require us to change property values to PropertyCells.
   4829   ASSERT(map->NextFreePropertyIndex() == 0);
   4830 
   4831   // Make sure we don't have a ton of pre-allocated slots in the
   4832   // global objects. They will be unused once we normalize the object.
   4833   ASSERT(map->unused_property_fields() == 0);
   4834   ASSERT(map->inobject_properties() == 0);
   4835 
   4836   // Initial size of the backing store to avoid resize of the storage during
   4837   // bootstrapping. The size differs between the JS global object ad the
   4838   // builtins object.
   4839   int initial_size = map->instance_type() == JS_GLOBAL_OBJECT_TYPE ? 64 : 512;
   4840 
   4841   // Allocate a dictionary object for backing storage.
   4842   NameDictionary* dictionary;
   4843   MaybeObject* maybe_dictionary =
   4844       NameDictionary::Allocate(
   4845           this,
   4846           map->NumberOfOwnDescriptors() * 2 + initial_size);
   4847   if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   4848 
   4849   // The global object might be created from an object template with accessors.
   4850   // Fill these accessors into the dictionary.
   4851   DescriptorArray* descs = map->instance_descriptors();
   4852   for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
   4853     PropertyDetails details = descs->GetDetails(i);
   4854     ASSERT(details.type() == CALLBACKS);  // Only accessors are expected.
   4855     PropertyDetails d = PropertyDetails(details.attributes(), CALLBACKS, i + 1);
   4856     Object* value = descs->GetCallbacksObject(i);
   4857     MaybeObject* maybe_value = AllocatePropertyCell(value);
   4858     if (!maybe_value->ToObject(&value)) return maybe_value;
   4859 
   4860     MaybeObject* maybe_added = dictionary->Add(descs->GetKey(i), value, d);
   4861     if (!maybe_added->To(&dictionary)) return maybe_added;
   4862   }
   4863 
   4864   // Allocate the global object and initialize it with the backing store.
   4865   JSObject* global;
   4866   MaybeObject* maybe_global = Allocate(map, OLD_POINTER_SPACE);
   4867   if (!maybe_global->To(&global)) return maybe_global;
   4868 
   4869   InitializeJSObjectFromMap(global, dictionary, map);
   4870 
   4871   // Create a new map for the global object.
   4872   Map* new_map;
   4873   MaybeObject* maybe_map = map->CopyDropDescriptors();
   4874   if (!maybe_map->To(&new_map)) return maybe_map;
   4875   new_map->set_dictionary_map(true);
   4876 
   4877   // Set up the global object as a normalized object.
   4878   global->set_map(new_map);
   4879   global->set_properties(dictionary);
   4880 
   4881   // Make sure result is a global object with properties in dictionary.
   4882   ASSERT(global->IsGlobalObject());
   4883   ASSERT(!global->HasFastProperties());
   4884   return global;
   4885 }
   4886 
   4887 
   4888 MaybeObject* Heap::CopyJSObject(JSObject* source) {
   4889   // Never used to copy functions.  If functions need to be copied we
   4890   // have to be careful to clear the literals array.
   4891   SLOW_ASSERT(!source->IsJSFunction());
   4892 
   4893   // Make the clone.
   4894   Map* map = source->map();
   4895   int object_size = map->instance_size();
   4896   Object* clone;
   4897 
   4898   WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER;
   4899 
   4900   // If we're forced to always allocate, we use the general allocation
   4901   // functions which may leave us with an object in old space.
   4902   if (always_allocate()) {
   4903     { MaybeObject* maybe_clone =
   4904           AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE);
   4905       if (!maybe_clone->ToObject(&clone)) return maybe_clone;
   4906     }
   4907     Address clone_address = HeapObject::cast(clone)->address();
   4908     CopyBlock(clone_address,
   4909               source->address(),
   4910               object_size);
   4911     // Update write barrier for all fields that lie beyond the header.
   4912     RecordWrites(clone_address,
   4913                  JSObject::kHeaderSize,
   4914                  (object_size - JSObject::kHeaderSize) / kPointerSize);
   4915   } else {
   4916     wb_mode = SKIP_WRITE_BARRIER;
   4917 
   4918     { MaybeObject* maybe_clone = new_space_.AllocateRaw(object_size);
   4919       if (!maybe_clone->ToObject(&clone)) return maybe_clone;
   4920     }
   4921     SLOW_ASSERT(InNewSpace(clone));
   4922     // Since we know the clone is allocated in new space, we can copy
   4923     // the contents without worrying about updating the write barrier.
   4924     CopyBlock(HeapObject::cast(clone)->address(),
   4925               source->address(),
   4926               object_size);
   4927   }
   4928 
   4929   SLOW_ASSERT(
   4930       JSObject::cast(clone)->GetElementsKind() == source->GetElementsKind());
   4931   FixedArrayBase* elements = FixedArrayBase::cast(source->elements());
   4932   FixedArray* properties = FixedArray::cast(source->properties());
   4933   // Update elements if necessary.
   4934   if (elements->length() > 0) {
   4935     Object* elem;
   4936     { MaybeObject* maybe_elem;
   4937       if (elements->map() == fixed_cow_array_map()) {
   4938         maybe_elem = FixedArray::cast(elements);
   4939       } else if (source->HasFastDoubleElements()) {
   4940         maybe_elem = CopyFixedDoubleArray(FixedDoubleArray::cast(elements));
   4941       } else {
   4942         maybe_elem = CopyFixedArray(FixedArray::cast(elements));
   4943       }
   4944       if (!maybe_elem->ToObject(&elem)) return maybe_elem;
   4945     }
   4946     JSObject::cast(clone)->set_elements(FixedArrayBase::cast(elem), wb_mode);
   4947   }
   4948   // Update properties if necessary.
   4949   if (properties->length() > 0) {
   4950     Object* prop;
   4951     { MaybeObject* maybe_prop = CopyFixedArray(properties);
   4952       if (!maybe_prop->ToObject(&prop)) return maybe_prop;
   4953     }
   4954     JSObject::cast(clone)->set_properties(FixedArray::cast(prop), wb_mode);
   4955   }
   4956   // Return the new clone.
   4957   return clone;
   4958 }
   4959 
   4960 
   4961 MaybeObject* Heap::CopyJSObjectWithAllocationSite(
   4962     JSObject* source,
   4963     AllocationSite* site) {
   4964   // Never used to copy functions.  If functions need to be copied we
   4965   // have to be careful to clear the literals array.
   4966   SLOW_ASSERT(!source->IsJSFunction());
   4967 
   4968   // Make the clone.
   4969   Map* map = source->map();
   4970   int object_size = map->instance_size();
   4971   Object* clone;
   4972 
   4973   ASSERT(AllocationSite::CanTrack(map->instance_type()));
   4974   ASSERT(map->instance_type() == JS_ARRAY_TYPE);
   4975   WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER;
   4976 
   4977   // If we're forced to always allocate, we use the general allocation
   4978   // functions which may leave us with an object in old space.
   4979   int adjusted_object_size = object_size;
   4980   if (always_allocate()) {
   4981     // We'll only track origin if we are certain to allocate in new space
   4982     const int kMinFreeNewSpaceAfterGC = InitialSemiSpaceSize() * 3/4;
   4983     if ((object_size + AllocationMemento::kSize) < kMinFreeNewSpaceAfterGC) {
   4984       adjusted_object_size += AllocationMemento::kSize;
   4985     }
   4986 
   4987     { MaybeObject* maybe_clone =
   4988           AllocateRaw(adjusted_object_size, NEW_SPACE, OLD_POINTER_SPACE);
   4989       if (!maybe_clone->ToObject(&clone)) return maybe_clone;
   4990     }
   4991     Address clone_address = HeapObject::cast(clone)->address();
   4992     CopyBlock(clone_address,
   4993               source->address(),
   4994               object_size);
   4995     // Update write barrier for all fields that lie beyond the header.
   4996     int write_barrier_offset = adjusted_object_size > object_size
   4997         ? JSArray::kSize + AllocationMemento::kSize
   4998         : JSObject::kHeaderSize;
   4999     if (((object_size - write_barrier_offset) / kPointerSize) > 0) {
   5000       RecordWrites(clone_address,
   5001                    write_barrier_offset,
   5002                    (object_size - write_barrier_offset) / kPointerSize);
   5003     }
   5004 
   5005     // Track allocation site information, if we failed to allocate it inline.
   5006     if (InNewSpace(clone) &&
   5007         adjusted_object_size == object_size) {
   5008       MaybeObject* maybe_alloc_memento =
   5009           AllocateStruct(ALLOCATION_MEMENTO_TYPE);
   5010       AllocationMemento* alloc_memento;
   5011       if (maybe_alloc_memento->To(&alloc_memento)) {
   5012         alloc_memento->set_map_no_write_barrier(allocation_memento_map());
   5013         alloc_memento->set_allocation_site(site, SKIP_WRITE_BARRIER);
   5014       }
   5015     }
   5016   } else {
   5017     wb_mode = SKIP_WRITE_BARRIER;
   5018     adjusted_object_size += AllocationMemento::kSize;
   5019 
   5020     { MaybeObject* maybe_clone = new_space_.AllocateRaw(adjusted_object_size);
   5021       if (!maybe_clone->ToObject(&clone)) return maybe_clone;
   5022     }
   5023     SLOW_ASSERT(InNewSpace(clone));
   5024     // Since we know the clone is allocated in new space, we can copy
   5025     // the contents without worrying about updating the write barrier.
   5026     CopyBlock(HeapObject::cast(clone)->address(),
   5027               source->address(),
   5028               object_size);
   5029   }
   5030 
   5031   if (adjusted_object_size > object_size) {
   5032     AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
   5033         reinterpret_cast<Address>(clone) + object_size);
   5034     alloc_memento->set_map_no_write_barrier(allocation_memento_map());
   5035     alloc_memento->set_allocation_site(site, SKIP_WRITE_BARRIER);
   5036   }
   5037 
   5038   SLOW_ASSERT(
   5039       JSObject::cast(clone)->GetElementsKind() == source->GetElementsKind());
   5040   FixedArrayBase* elements = FixedArrayBase::cast(source->elements());
   5041   FixedArray* properties = FixedArray::cast(source->properties());
   5042   // Update elements if necessary.
   5043   if (elements->length() > 0) {
   5044     Object* elem;
   5045     { MaybeObject* maybe_elem;
   5046       if (elements->map() == fixed_cow_array_map()) {
   5047         maybe_elem = FixedArray::cast(elements);
   5048       } else if (source->HasFastDoubleElements()) {
   5049         maybe_elem = CopyFixedDoubleArray(FixedDoubleArray::cast(elements));
   5050       } else {
   5051         maybe_elem = CopyFixedArray(FixedArray::cast(elements));
   5052       }
   5053       if (!maybe_elem->ToObject(&elem)) return maybe_elem;
   5054     }
   5055     JSObject::cast(clone)->set_elements(FixedArrayBase::cast(elem), wb_mode);
   5056   }
   5057   // Update properties if necessary.
   5058   if (properties->length() > 0) {
   5059     Object* prop;
   5060     { MaybeObject* maybe_prop = CopyFixedArray(properties);
   5061       if (!maybe_prop->ToObject(&prop)) return maybe_prop;
   5062     }
   5063     JSObject::cast(clone)->set_properties(FixedArray::cast(prop), wb_mode);
   5064   }
   5065   // Return the new clone.
   5066   return clone;
   5067 }
   5068 
   5069 
   5070 MaybeObject* Heap::ReinitializeJSReceiver(
   5071     JSReceiver* object, InstanceType type, int size) {
   5072   ASSERT(type >= FIRST_JS_OBJECT_TYPE);
   5073 
   5074   // Allocate fresh map.
   5075   // TODO(rossberg): Once we optimize proxies, cache these maps.
   5076   Map* map;
   5077   MaybeObject* maybe = AllocateMap(type, size);
   5078   if (!maybe->To<Map>(&map)) return maybe;
   5079 
   5080   // Check that the receiver has at least the size of the fresh object.
   5081   int size_difference = object->map()->instance_size() - map->instance_size();
   5082   ASSERT(size_difference >= 0);
   5083 
   5084   map->set_prototype(object->map()->prototype());
   5085 
   5086   // Allocate the backing storage for the properties.
   5087   int prop_size = map->unused_property_fields() - map->inobject_properties();
   5088   Object* properties;
   5089   maybe = AllocateFixedArray(prop_size, TENURED);
   5090   if (!maybe->ToObject(&properties)) return maybe;
   5091 
   5092   // Functions require some allocation, which might fail here.
   5093   SharedFunctionInfo* shared = NULL;
   5094   if (type == JS_FUNCTION_TYPE) {
   5095     String* name;
   5096     maybe =
   5097         InternalizeOneByteString(STATIC_ASCII_VECTOR("<freezing call trap>"));
   5098     if (!maybe->To<String>(&name)) return maybe;
   5099     maybe = AllocateSharedFunctionInfo(name);
   5100     if (!maybe->To<SharedFunctionInfo>(&shared)) return maybe;
   5101   }
   5102 
   5103   // Because of possible retries of this function after failure,
   5104   // we must NOT fail after this point, where we have changed the type!
   5105 
   5106   // Reset the map for the object.
   5107   object->set_map(map);
   5108   JSObject* jsobj = JSObject::cast(object);
   5109 
   5110   // Reinitialize the object from the constructor map.
   5111   InitializeJSObjectFromMap(jsobj, FixedArray::cast(properties), map);
   5112 
   5113   // Functions require some minimal initialization.
   5114   if (type == JS_FUNCTION_TYPE) {
   5115     map->set_function_with_prototype(true);
   5116     InitializeFunction(JSFunction::cast(object), shared, the_hole_value());
   5117     JSFunction::cast(object)->set_context(
   5118         isolate()->context()->native_context());
   5119   }
   5120 
   5121   // Put in filler if the new object is smaller than the old.
   5122   if (size_difference > 0) {
   5123     CreateFillerObjectAt(
   5124         object->address() + map->instance_size(), size_difference);
   5125   }
   5126 
   5127   return object;
   5128 }
   5129 
   5130 
   5131 MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
   5132                                              JSGlobalProxy* object) {
   5133   ASSERT(constructor->has_initial_map());
   5134   Map* map = constructor->initial_map();
   5135 
   5136   // Check that the already allocated object has the same size and type as
   5137   // objects allocated using the constructor.
   5138   ASSERT(map->instance_size() == object->map()->instance_size());
   5139   ASSERT(map->instance_type() == object->map()->instance_type());
   5140 
   5141   // Allocate the backing storage for the properties.
   5142   int prop_size = map->unused_property_fields() - map->inobject_properties();
   5143   Object* properties;
   5144   { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, TENURED);
   5145     if (!maybe_properties->ToObject(&properties)) return maybe_properties;
   5146   }
   5147 
   5148   // Reset the map for the object.
   5149   object->set_map(constructor->initial_map());
   5150 
   5151   // Reinitialize the object from the constructor map.
   5152   InitializeJSObjectFromMap(object, FixedArray::cast(properties), map);
   5153   return object;
   5154 }
   5155 
   5156 
   5157 MaybeObject* Heap::AllocateStringFromOneByte(Vector<const uint8_t> string,
   5158                                            PretenureFlag pretenure) {
   5159   int length = string.length();
   5160   if (length == 1) {
   5161     return Heap::LookupSingleCharacterStringFromCode(string[0]);
   5162   }
   5163   Object* result;
   5164   { MaybeObject* maybe_result =
   5165         AllocateRawOneByteString(string.length(), pretenure);
   5166     if (!maybe_result->ToObject(&result)) return maybe_result;
   5167   }
   5168 
   5169   // Copy the characters into the new object.
   5170   CopyChars(SeqOneByteString::cast(result)->GetChars(),
   5171             string.start(),
   5172             length);
   5173   return result;
   5174 }
   5175 
   5176 
   5177 MaybeObject* Heap::AllocateStringFromUtf8Slow(Vector<const char> string,
   5178                                               int non_ascii_start,
   5179                                               PretenureFlag pretenure) {
   5180   // Continue counting the number of characters in the UTF-8 string, starting
   5181   // from the first non-ascii character or word.
   5182   Access<UnicodeCache::Utf8Decoder>
   5183       decoder(isolate_->unicode_cache()->utf8_decoder());
   5184   decoder->Reset(string.start() + non_ascii_start,
   5185                  string.length() - non_ascii_start);
   5186   int utf16_length = decoder->Utf16Length();
   5187   ASSERT(utf16_length > 0);
   5188   // Allocate string.
   5189   Object* result;
   5190   {
   5191     int chars = non_ascii_start + utf16_length;
   5192     MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure);
   5193     if (!maybe_result->ToObject(&result)) return maybe_result;
   5194   }
   5195   // Convert and copy the characters into the new object.
   5196   SeqTwoByteString* twobyte = SeqTwoByteString::cast(result);
   5197   // Copy ascii portion.
   5198   uint16_t* data = twobyte->GetChars();
   5199   if (non_ascii_start != 0) {
   5200     const char* ascii_data = string.start();
   5201     for (int i = 0; i < non_ascii_start; i++) {
   5202       *data++ = *ascii_data++;
   5203     }
   5204   }
   5205   // Now write the remainder.
   5206   decoder->WriteUtf16(data, utf16_length);
   5207   return result;
   5208 }
   5209 
   5210 
   5211 MaybeObject* Heap::AllocateStringFromTwoByte(Vector<const uc16> string,
   5212                                              PretenureFlag pretenure) {
   5213   // Check if the string is an ASCII string.
   5214   Object* result;
   5215   int length = string.length();
   5216   const uc16* start = string.start();
   5217 
   5218   if (String::IsOneByte(start, length)) {
   5219     MaybeObject* maybe_result = AllocateRawOneByteString(length, pretenure);
   5220     if (!maybe_result->ToObject(&result)) return maybe_result;
   5221     CopyChars(SeqOneByteString::cast(result)->GetChars(), start, length);
   5222   } else {  // It's not a one byte string.
   5223     MaybeObject* maybe_result = AllocateRawTwoByteString(length, pretenure);
   5224     if (!maybe_result->ToObject(&result)) return maybe_result;
   5225     CopyChars(SeqTwoByteString::cast(result)->GetChars(), start, length);
   5226   }
   5227   return result;
   5228 }
   5229 
   5230 
   5231 Map* Heap::InternalizedStringMapForString(String* string) {
   5232   // If the string is in new space it cannot be used as internalized.
   5233   if (InNewSpace(string)) return NULL;
   5234 
   5235   // Find the corresponding internalized string map for strings.
   5236   switch (string->map()->instance_type()) {
   5237     case STRING_TYPE: return internalized_string_map();
   5238     case ASCII_STRING_TYPE: return ascii_internalized_string_map();
   5239     case CONS_STRING_TYPE: return cons_internalized_string_map();
   5240     case CONS_ASCII_STRING_TYPE: return cons_ascii_internalized_string_map();
   5241     case EXTERNAL_STRING_TYPE: return external_internalized_string_map();
   5242     case EXTERNAL_ASCII_STRING_TYPE:
   5243       return external_ascii_internalized_string_map();
   5244     case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
   5245       return external_internalized_string_with_one_byte_data_map();
   5246     case SHORT_EXTERNAL_STRING_TYPE:
   5247       return short_external_internalized_string_map();
   5248     case SHORT_EXTERNAL_ASCII_STRING_TYPE:
   5249       return short_external_ascii_internalized_string_map();
   5250     case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
   5251       return short_external_internalized_string_with_one_byte_data_map();
   5252     default: return NULL;  // No match found.
   5253   }
   5254 }
   5255 
   5256 
   5257 static inline void WriteOneByteData(Vector<const char> vector,
   5258                                     uint8_t* chars,
   5259                                     int len) {
   5260   // Only works for ascii.
   5261   ASSERT(vector.length() == len);
   5262   OS::MemCopy(chars, vector.start(), len);
   5263 }
   5264 
   5265 static inline void WriteTwoByteData(Vector<const char> vector,
   5266                                     uint16_t* chars,
   5267                                     int len) {
   5268   const uint8_t* stream = reinterpret_cast<const uint8_t*>(vector.start());
   5269   unsigned stream_length = vector.length();
   5270   while (stream_length != 0) {
   5271     unsigned consumed = 0;
   5272     uint32_t c = unibrow::Utf8::ValueOf(stream, stream_length, &consumed);
   5273     ASSERT(c != unibrow::Utf8::kBadChar);
   5274     ASSERT(consumed <= stream_length);
   5275     stream_length -= consumed;
   5276     stream += consumed;
   5277     if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
   5278       len -= 2;
   5279       if (len < 0) break;
   5280       *chars++ = unibrow::Utf16::LeadSurrogate(c);
   5281       *chars++ = unibrow::Utf16::TrailSurrogate(c);
   5282     } else {
   5283       len -= 1;
   5284       if (len < 0) break;
   5285       *chars++ = c;
   5286     }
   5287   }
   5288   ASSERT(stream_length == 0);
   5289   ASSERT(len == 0);
   5290 }
   5291 
   5292 
   5293 static inline void WriteOneByteData(String* s, uint8_t* chars, int len) {
   5294   ASSERT(s->length() == len);
   5295   String::WriteToFlat(s, chars, 0, len);
   5296 }
   5297 
   5298 
   5299 static inline void WriteTwoByteData(String* s, uint16_t* chars, int len) {
   5300   ASSERT(s->length() == len);
   5301   String::WriteToFlat(s, chars, 0, len);
   5302 }
   5303 
   5304 
   5305 template<bool is_one_byte, typename T>
   5306 MaybeObject* Heap::AllocateInternalizedStringImpl(
   5307     T t, int chars, uint32_t hash_field) {
   5308   ASSERT(chars >= 0);
   5309   // Compute map and object size.
   5310   int size;
   5311   Map* map;
   5312 
   5313   if (is_one_byte) {
   5314     if (chars > SeqOneByteString::kMaxLength) {
   5315       return Failure::OutOfMemoryException(0x9);
   5316     }
   5317     map = ascii_internalized_string_map();
   5318     size = SeqOneByteString::SizeFor(chars);
   5319   } else {
   5320     if (chars > SeqTwoByteString::kMaxLength) {
   5321       return Failure::OutOfMemoryException(0xa);
   5322     }
   5323     map = internalized_string_map();
   5324     size = SeqTwoByteString::SizeFor(chars);
   5325   }
   5326 
   5327   // Allocate string.
   5328   Object* result;
   5329   { MaybeObject* maybe_result = (size > Page::kMaxNonCodeHeapObjectSize)
   5330                    ? lo_space_->AllocateRaw(size, NOT_EXECUTABLE)
   5331                    : old_data_space_->AllocateRaw(size);
   5332     if (!maybe_result->ToObject(&result)) return maybe_result;
   5333   }
   5334 
   5335   reinterpret_cast<HeapObject*>(result)->set_map_no_write_barrier(map);
   5336   // Set length and hash fields of the allocated string.
   5337   String* answer = String::cast(result);
   5338   answer->set_length(chars);
   5339   answer->set_hash_field(hash_field);
   5340 
   5341   ASSERT_EQ(size, answer->Size());
   5342 
   5343   if (is_one_byte) {
   5344     WriteOneByteData(t, SeqOneByteString::cast(answer)->GetChars(), chars);
   5345   } else {
   5346     WriteTwoByteData(t, SeqTwoByteString::cast(answer)->GetChars(), chars);
   5347   }
   5348   return answer;
   5349 }
   5350 
   5351 
   5352 // Need explicit instantiations.
   5353 template
   5354 MaybeObject* Heap::AllocateInternalizedStringImpl<true>(String*, int, uint32_t);
   5355 template
   5356 MaybeObject* Heap::AllocateInternalizedStringImpl<false>(
   5357     String*, int, uint32_t);
   5358 template
   5359 MaybeObject* Heap::AllocateInternalizedStringImpl<false>(
   5360     Vector<const char>, int, uint32_t);
   5361 
   5362 
   5363 MaybeObject* Heap::AllocateRawOneByteString(int length,
   5364                                             PretenureFlag pretenure) {
   5365   if (length < 0 || length > SeqOneByteString::kMaxLength) {
   5366     return Failure::OutOfMemoryException(0xb);
   5367   }
   5368   int size = SeqOneByteString::SizeFor(length);
   5369   ASSERT(size <= SeqOneByteString::kMaxSize);
   5370   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   5371   AllocationSpace retry_space = OLD_DATA_SPACE;
   5372 
   5373   if (size > Page::kMaxNonCodeHeapObjectSize) {
   5374     // Allocate in large object space, retry space will be ignored.
   5375     space = LO_SPACE;
   5376   }
   5377 
   5378   Object* result;
   5379   { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space);
   5380     if (!maybe_result->ToObject(&result)) return maybe_result;
   5381   }
   5382 
   5383   // Partially initialize the object.
   5384   HeapObject::cast(result)->set_map_no_write_barrier(ascii_string_map());
   5385   String::cast(result)->set_length(length);
   5386   String::cast(result)->set_hash_field(String::kEmptyHashField);
   5387   ASSERT_EQ(size, HeapObject::cast(result)->Size());
   5388 
   5389   return result;
   5390 }
   5391 
   5392 
   5393 MaybeObject* Heap::AllocateRawTwoByteString(int length,
   5394                                             PretenureFlag pretenure) {
   5395   if (length < 0 || length > SeqTwoByteString::kMaxLength) {
   5396     return Failure::OutOfMemoryException(0xc);
   5397   }
   5398   int size = SeqTwoByteString::SizeFor(length);
   5399   ASSERT(size <= SeqTwoByteString::kMaxSize);
   5400   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   5401   AllocationSpace retry_space = OLD_DATA_SPACE;
   5402 
   5403   if (size > Page::kMaxNonCodeHeapObjectSize) {
   5404     // Allocate in large object space, retry space will be ignored.
   5405     space = LO_SPACE;
   5406   }
   5407 
   5408   Object* result;
   5409   { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space);
   5410     if (!maybe_result->ToObject(&result)) return maybe_result;
   5411   }
   5412 
   5413   // Partially initialize the object.
   5414   HeapObject::cast(result)->set_map_no_write_barrier(string_map());
   5415   String::cast(result)->set_length(length);
   5416   String::cast(result)->set_hash_field(String::kEmptyHashField);
   5417   ASSERT_EQ(size, HeapObject::cast(result)->Size());
   5418   return result;
   5419 }
   5420 
   5421 
   5422 MaybeObject* Heap::AllocateJSArray(
   5423     ElementsKind elements_kind,
   5424     PretenureFlag pretenure) {
   5425   Context* native_context = isolate()->context()->native_context();
   5426   JSFunction* array_function = native_context->array_function();
   5427   Map* map = array_function->initial_map();
   5428   Map* transition_map = isolate()->get_initial_js_array_map(elements_kind);
   5429   if (transition_map != NULL) map = transition_map;
   5430   return AllocateJSObjectFromMap(map, pretenure);
   5431 }
   5432 
   5433 
   5434 MaybeObject* Heap::AllocateJSArrayWithAllocationSite(
   5435     ElementsKind elements_kind,
   5436     Handle<AllocationSite> allocation_site) {
   5437   Context* native_context = isolate()->context()->native_context();
   5438   JSFunction* array_function = native_context->array_function();
   5439   Map* map = array_function->initial_map();
   5440   Object* maybe_map_array = native_context->js_array_maps();
   5441   if (!maybe_map_array->IsUndefined()) {
   5442     Object* maybe_transitioned_map =
   5443         FixedArray::cast(maybe_map_array)->get(elements_kind);
   5444     if (!maybe_transitioned_map->IsUndefined()) {
   5445       map = Map::cast(maybe_transitioned_map);
   5446     }
   5447   }
   5448   return AllocateJSObjectFromMapWithAllocationSite(map, allocation_site);
   5449 }
   5450 
   5451 
   5452 MaybeObject* Heap::AllocateEmptyFixedArray() {
   5453   int size = FixedArray::SizeFor(0);
   5454   Object* result;
   5455   { MaybeObject* maybe_result =
   5456         AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE);
   5457     if (!maybe_result->ToObject(&result)) return maybe_result;
   5458   }
   5459   // Initialize the object.
   5460   reinterpret_cast<FixedArray*>(result)->set_map_no_write_barrier(
   5461       fixed_array_map());
   5462   reinterpret_cast<FixedArray*>(result)->set_length(0);
   5463   return result;
   5464 }
   5465 
   5466 
   5467 MaybeObject* Heap::AllocateEmptyExternalArray(ExternalArrayType array_type) {
   5468   return AllocateExternalArray(0, array_type, NULL, TENURED);
   5469 }
   5470 
   5471 
   5472 MaybeObject* Heap::AllocateRawFixedArray(int length) {
   5473   if (length < 0 || length > FixedArray::kMaxLength) {
   5474     return Failure::OutOfMemoryException(0xd);
   5475   }
   5476   ASSERT(length > 0);
   5477   // Use the general function if we're forced to always allocate.
   5478   if (always_allocate()) return AllocateFixedArray(length, TENURED);
   5479   // Allocate the raw data for a fixed array.
   5480   int size = FixedArray::SizeFor(length);
   5481   return size <= Page::kMaxNonCodeHeapObjectSize
   5482       ? new_space_.AllocateRaw(size)
   5483       : lo_space_->AllocateRaw(size, NOT_EXECUTABLE);
   5484 }
   5485 
   5486 
   5487 MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) {
   5488   int len = src->length();
   5489   Object* obj;
   5490   { MaybeObject* maybe_obj = AllocateRawFixedArray(len);
   5491     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   5492   }
   5493   if (InNewSpace(obj)) {
   5494     HeapObject* dst = HeapObject::cast(obj);
   5495     dst->set_map_no_write_barrier(map);
   5496     CopyBlock(dst->address() + kPointerSize,
   5497               src->address() + kPointerSize,
   5498               FixedArray::SizeFor(len) - kPointerSize);
   5499     return obj;
   5500   }
   5501   HeapObject::cast(obj)->set_map_no_write_barrier(map);
   5502   FixedArray* result = FixedArray::cast(obj);
   5503   result->set_length(len);
   5504 
   5505   // Copy the content
   5506   DisallowHeapAllocation no_gc;
   5507   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   5508   for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
   5509   return result;
   5510 }
   5511 
   5512 
   5513 MaybeObject* Heap::CopyFixedDoubleArrayWithMap(FixedDoubleArray* src,
   5514                                                Map* map) {
   5515   int len = src->length();
   5516   Object* obj;
   5517   { MaybeObject* maybe_obj = AllocateRawFixedDoubleArray(len, NOT_TENURED);
   5518     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   5519   }
   5520   HeapObject* dst = HeapObject::cast(obj);
   5521   dst->set_map_no_write_barrier(map);
   5522   CopyBlock(
   5523       dst->address() + FixedDoubleArray::kLengthOffset,
   5524       src->address() + FixedDoubleArray::kLengthOffset,
   5525       FixedDoubleArray::SizeFor(len) - FixedDoubleArray::kLengthOffset);
   5526   return obj;
   5527 }
   5528 
   5529 
   5530 MaybeObject* Heap::AllocateFixedArray(int length) {
   5531   ASSERT(length >= 0);
   5532   if (length == 0) return empty_fixed_array();
   5533   Object* result;
   5534   { MaybeObject* maybe_result = AllocateRawFixedArray(length);
   5535     if (!maybe_result->ToObject(&result)) return maybe_result;
   5536   }
   5537   // Initialize header.
   5538   FixedArray* array = reinterpret_cast<FixedArray*>(result);
   5539   array->set_map_no_write_barrier(fixed_array_map());
   5540   array->set_length(length);
   5541   // Initialize body.
   5542   ASSERT(!InNewSpace(undefined_value()));
   5543   MemsetPointer(array->data_start(), undefined_value(), length);
   5544   return result;
   5545 }
   5546 
   5547 
   5548 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) {
   5549   if (length < 0 || length > FixedArray::kMaxLength) {
   5550     return Failure::OutOfMemoryException(0xe);
   5551   }
   5552   int size = FixedArray::SizeFor(length);
   5553   AllocationSpace space =
   5554       (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
   5555   AllocationSpace retry_space = OLD_POINTER_SPACE;
   5556 
   5557   if (size > Page::kMaxNonCodeHeapObjectSize) {
   5558     // Allocate in large object space, retry space will be ignored.
   5559     space = LO_SPACE;
   5560   }
   5561 
   5562   return AllocateRaw(size, space, retry_space);
   5563 }
   5564 
   5565 
   5566 MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller(
   5567     Heap* heap,
   5568     int length,
   5569     PretenureFlag pretenure,
   5570     Object* filler) {
   5571   ASSERT(length >= 0);
   5572   ASSERT(heap->empty_fixed_array()->IsFixedArray());
   5573   if (length == 0) return heap->empty_fixed_array();
   5574 
   5575   ASSERT(!heap->InNewSpace(filler));
   5576   Object* result;
   5577   { MaybeObject* maybe_result = heap->AllocateRawFixedArray(length, pretenure);
   5578     if (!maybe_result->ToObject(&result)) return maybe_result;
   5579   }
   5580 
   5581   HeapObject::cast(result)->set_map_no_write_barrier(heap->fixed_array_map());
   5582   FixedArray* array = FixedArray::cast(result);
   5583   array->set_length(length);
   5584   MemsetPointer(array->data_start(), filler, length);
   5585   return array;
   5586 }
   5587 
   5588 
   5589 MaybeObject* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
   5590   return AllocateFixedArrayWithFiller(this,
   5591                                       length,
   5592                                       pretenure,
   5593                                       undefined_value());
   5594 }
   5595 
   5596 
   5597 MaybeObject* Heap::AllocateFixedArrayWithHoles(int length,
   5598                                                PretenureFlag pretenure) {
   5599   return AllocateFixedArrayWithFiller(this,
   5600                                       length,
   5601                                       pretenure,
   5602                                       the_hole_value());
   5603 }
   5604 
   5605 
   5606 MaybeObject* Heap::AllocateUninitializedFixedArray(int length) {
   5607   if (length == 0) return empty_fixed_array();
   5608 
   5609   Object* obj;
   5610   { MaybeObject* maybe_obj = AllocateRawFixedArray(length);
   5611     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   5612   }
   5613 
   5614   reinterpret_cast<FixedArray*>(obj)->set_map_no_write_barrier(
   5615       fixed_array_map());
   5616   FixedArray::cast(obj)->set_length(length);
   5617   return obj;
   5618 }
   5619 
   5620 
   5621 MaybeObject* Heap::AllocateEmptyFixedDoubleArray() {
   5622   int size = FixedDoubleArray::SizeFor(0);
   5623   Object* result;
   5624   { MaybeObject* maybe_result =
   5625         AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE);
   5626     if (!maybe_result->ToObject(&result)) return maybe_result;
   5627   }
   5628   // Initialize the object.
   5629   reinterpret_cast<FixedDoubleArray*>(result)->set_map_no_write_barrier(
   5630       fixed_double_array_map());
   5631   reinterpret_cast<FixedDoubleArray*>(result)->set_length(0);
   5632   return result;
   5633 }
   5634 
   5635 
   5636 MaybeObject* Heap::AllocateUninitializedFixedDoubleArray(
   5637     int length,
   5638     PretenureFlag pretenure) {
   5639   if (length == 0) return empty_fixed_array();
   5640 
   5641   Object* elements_object;
   5642   MaybeObject* maybe_obj = AllocateRawFixedDoubleArray(length, pretenure);
   5643   if (!maybe_obj->ToObject(&elements_object)) return maybe_obj;
   5644   FixedDoubleArray* elements =
   5645       reinterpret_cast<FixedDoubleArray*>(elements_object);
   5646 
   5647   elements->set_map_no_write_barrier(fixed_double_array_map());
   5648   elements->set_length(length);
   5649   return elements;
   5650 }
   5651 
   5652 
   5653 MaybeObject* Heap::AllocateFixedDoubleArrayWithHoles(
   5654     int length,
   5655     PretenureFlag pretenure) {
   5656   if (length == 0) return empty_fixed_array();
   5657 
   5658   Object* elements_object;
   5659   MaybeObject* maybe_obj = AllocateRawFixedDoubleArray(length, pretenure);
   5660   if (!maybe_obj->ToObject(&elements_object)) return maybe_obj;
   5661   FixedDoubleArray* elements =
   5662       reinterpret_cast<FixedDoubleArray*>(elements_object);
   5663 
   5664   for (int i = 0; i < length; ++i) {
   5665     elements->set_the_hole(i);
   5666   }
   5667 
   5668   elements->set_map_no_write_barrier(fixed_double_array_map());
   5669   elements->set_length(length);
   5670   return elements;
   5671 }
   5672 
   5673 
   5674 MaybeObject* Heap::AllocateRawFixedDoubleArray(int length,
   5675                                                PretenureFlag pretenure) {
   5676   if (length < 0 || length > FixedDoubleArray::kMaxLength) {
   5677     return Failure::OutOfMemoryException(0xf);
   5678   }
   5679   int size = FixedDoubleArray::SizeFor(length);
   5680   AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
   5681   AllocationSpace retry_space = OLD_DATA_SPACE;
   5682 
   5683 #ifndef V8_HOST_ARCH_64_BIT
   5684   size += kPointerSize;
   5685 #endif
   5686 
   5687   if (size > Page::kMaxNonCodeHeapObjectSize) {
   5688     // Allocate in large object space, retry space will be ignored.
   5689     space = LO_SPACE;
   5690   }
   5691 
   5692   HeapObject* object;
   5693   { MaybeObject* maybe_object = AllocateRaw(size, space, retry_space);
   5694     if (!maybe_object->To<HeapObject>(&object)) return maybe_object;
   5695   }
   5696 
   5697   return EnsureDoubleAligned(this, object, size);
   5698 }
   5699 
   5700 
   5701 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) {
   5702   Object* result;
   5703   { MaybeObject* maybe_result = AllocateFixedArray(length, pretenure);
   5704     if (!maybe_result->ToObject(&result)) return maybe_result;
   5705   }
   5706   reinterpret_cast<HeapObject*>(result)->set_map_no_write_barrier(
   5707       hash_table_map());
   5708   ASSERT(result->IsHashTable());
   5709   return result;
   5710 }
   5711 
   5712 
   5713 MaybeObject* Heap::AllocateSymbol() {
   5714   // Statically ensure that it is safe to allocate symbols in paged spaces.
   5715   STATIC_ASSERT(Symbol::kSize <= Page::kNonCodeObjectAreaSize);
   5716 
   5717   Object* result;
   5718   MaybeObject* maybe =
   5719       AllocateRaw(Symbol::kSize, OLD_POINTER_SPACE, OLD_POINTER_SPACE);
   5720   if (!maybe->ToObject(&result)) return maybe;
   5721 
   5722   HeapObject::cast(result)->set_map_no_write_barrier(symbol_map());
   5723 
   5724   // Generate a random hash value.
   5725   int hash;
   5726   int attempts = 0;
   5727   do {
   5728     hash = V8::RandomPrivate(isolate()) & Name::kHashBitMask;
   5729     attempts++;
   5730   } while (hash == 0 && attempts < 30);
   5731   if (hash == 0) hash = 1;  // never return 0
   5732 
   5733   Symbol::cast(result)->set_hash_field(
   5734       Name::kIsNotArrayIndexMask | (hash << Name::kHashShift));
   5735   Symbol::cast(result)->set_name(undefined_value());
   5736 
   5737   ASSERT(result->IsSymbol());
   5738   return result;
   5739 }
   5740 
   5741 
   5742 MaybeObject* Heap::AllocateNativeContext() {
   5743   Object* result;
   5744   { MaybeObject* maybe_result =
   5745         AllocateFixedArray(Context::NATIVE_CONTEXT_SLOTS);
   5746     if (!maybe_result->ToObject(&result)) return maybe_result;
   5747   }
   5748   Context* context = reinterpret_cast<Context*>(result);
   5749   context->set_map_no_write_barrier(native_context_map());
   5750   context->set_js_array_maps(undefined_value());
   5751   ASSERT(context->IsNativeContext());
   5752   ASSERT(result->IsContext());
   5753   return result;
   5754 }
   5755 
   5756 
   5757 MaybeObject* Heap::AllocateGlobalContext(JSFunction* function,
   5758                                          ScopeInfo* scope_info) {
   5759   Object* result;
   5760   { MaybeObject* maybe_result =
   5761         AllocateFixedArray(scope_info->ContextLength(), TENURED);
   5762     if (!maybe_result->ToObject(&result)) return maybe_result;
   5763   }
   5764   Context* context = reinterpret_cast<Context*>(result);
   5765   context->set_map_no_write_barrier(global_context_map());
   5766   context->set_closure(function);
   5767   context->set_previous(function->context());
   5768   context->set_extension(scope_info);
   5769   context->set_global_object(function->context()->global_object());
   5770   ASSERT(context->IsGlobalContext());
   5771   ASSERT(result->IsContext());
   5772   return context;
   5773 }
   5774 
   5775 
   5776 MaybeObject* Heap::AllocateModuleContext(ScopeInfo* scope_info) {
   5777   Object* result;
   5778   { MaybeObject* maybe_result =
   5779         AllocateFixedArray(scope_info->ContextLength(), TENURED);
   5780     if (!maybe_result->ToObject(&result)) return maybe_result;
   5781   }
   5782   Context* context = reinterpret_cast<Context*>(result);
   5783   context->set_map_no_write_barrier(module_context_map());
   5784   // Instance link will be set later.
   5785   context->set_extension(Smi::FromInt(0));
   5786   return context;
   5787 }
   5788 
   5789 
   5790 MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
   5791   ASSERT(length >= Context::MIN_CONTEXT_SLOTS);
   5792   Object* result;
   5793   { MaybeObject* maybe_result = AllocateFixedArray(length);
   5794     if (!maybe_result->ToObject(&result)) return maybe_result;
   5795   }
   5796   Context* context = reinterpret_cast<Context*>(result);
   5797   context->set_map_no_write_barrier(function_context_map());
   5798   context->set_closure(function);
   5799   context->set_previous(function->context());
   5800   context->set_extension(Smi::FromInt(0));
   5801   context->set_global_object(function->context()->global_object());
   5802   return context;
   5803 }
   5804 
   5805 
   5806 MaybeObject* Heap::AllocateCatchContext(JSFunction* function,
   5807                                         Context* previous,
   5808                                         String* name,
   5809                                         Object* thrown_object) {
   5810   STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == Context::THROWN_OBJECT_INDEX);
   5811   Object* result;
   5812   { MaybeObject* maybe_result =
   5813         AllocateFixedArray(Context::MIN_CONTEXT_SLOTS + 1);
   5814     if (!maybe_result->ToObject(&result)) return maybe_result;
   5815   }
   5816   Context* context = reinterpret_cast<Context*>(result);
   5817   context->set_map_no_write_barrier(catch_context_map());
   5818   context->set_closure(function);
   5819   context->set_previous(previous);
   5820   context->set_extension(name);
   5821   context->set_global_object(previous->global_object());
   5822   context->set(Context::THROWN_OBJECT_INDEX, thrown_object);
   5823   return context;
   5824 }
   5825 
   5826 
   5827 MaybeObject* Heap::AllocateWithContext(JSFunction* function,
   5828                                        Context* previous,
   5829                                        JSReceiver* extension) {
   5830   Object* result;
   5831   { MaybeObject* maybe_result = AllocateFixedArray(Context::MIN_CONTEXT_SLOTS);
   5832     if (!maybe_result->ToObject(&result)) return maybe_result;
   5833   }
   5834   Context* context = reinterpret_cast<Context*>(result);
   5835   context->set_map_no_write_barrier(with_context_map());
   5836   context->set_closure(function);
   5837   context->set_previous(previous);
   5838   context->set_extension(extension);
   5839   context->set_global_object(previous->global_object());
   5840   return context;
   5841 }
   5842 
   5843 
   5844 MaybeObject* Heap::AllocateBlockContext(JSFunction* function,
   5845                                         Context* previous,
   5846                                         ScopeInfo* scope_info) {
   5847   Object* result;
   5848   { MaybeObject* maybe_result =
   5849         AllocateFixedArrayWithHoles(scope_info->ContextLength());
   5850     if (!maybe_result->ToObject(&result)) return maybe_result;
   5851   }
   5852   Context* context = reinterpret_cast<Context*>(result);
   5853   context->set_map_no_write_barrier(block_context_map());
   5854   context->set_closure(function);
   5855   context->set_previous(previous);
   5856   context->set_extension(scope_info);
   5857   context->set_global_object(previous->global_object());
   5858   return context;
   5859 }
   5860 
   5861 
   5862 MaybeObject* Heap::AllocateScopeInfo(int length) {
   5863   FixedArray* scope_info;
   5864   MaybeObject* maybe_scope_info = AllocateFixedArray(length, TENURED);
   5865   if (!maybe_scope_info->To(&scope_info)) return maybe_scope_info;
   5866   scope_info->set_map_no_write_barrier(scope_info_map());
   5867   return scope_info;
   5868 }
   5869 
   5870 
   5871 MaybeObject* Heap::AllocateExternal(void* value) {
   5872   Foreign* foreign;
   5873   { MaybeObject* maybe_result = AllocateForeign(static_cast<Address>(value));
   5874     if (!maybe_result->To(&foreign)) return maybe_result;
   5875   }
   5876   JSObject* external;
   5877   { MaybeObject* maybe_result = AllocateJSObjectFromMap(external_map());
   5878     if (!maybe_result->To(&external)) return maybe_result;
   5879   }
   5880   external->SetInternalField(0, foreign);
   5881   return external;
   5882 }
   5883 
   5884 
   5885 MaybeObject* Heap::AllocateStruct(InstanceType type) {
   5886   Map* map;
   5887   switch (type) {
   5888 #define MAKE_CASE(NAME, Name, name) \
   5889     case NAME##_TYPE: map = name##_map(); break;
   5890 STRUCT_LIST(MAKE_CASE)
   5891 #undef MAKE_CASE
   5892     default:
   5893       UNREACHABLE();
   5894       return Failure::InternalError();
   5895   }
   5896   int size = map->instance_size();
   5897   AllocationSpace space =
   5898       (size > Page::kMaxNonCodeHeapObjectSize) ? LO_SPACE : OLD_POINTER_SPACE;
   5899   Object* result;
   5900   { MaybeObject* maybe_result = Allocate(map, space);
   5901     if (!maybe_result->ToObject(&result)) return maybe_result;
   5902   }
   5903   Struct::cast(result)->InitializeBody(size);
   5904   return result;
   5905 }
   5906 
   5907 
   5908 bool Heap::IsHeapIterable() {
   5909   return (!old_pointer_space()->was_swept_conservatively() &&
   5910           !old_data_space()->was_swept_conservatively());
   5911 }
   5912 
   5913 
   5914 void Heap::EnsureHeapIsIterable() {
   5915   ASSERT(AllowHeapAllocation::IsAllowed());
   5916   if (!IsHeapIterable()) {
   5917     CollectAllGarbage(kMakeHeapIterableMask, "Heap::EnsureHeapIsIterable");
   5918   }
   5919   ASSERT(IsHeapIterable());
   5920 }
   5921 
   5922 
   5923 void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) {
   5924   incremental_marking()->Step(step_size,
   5925                               IncrementalMarking::NO_GC_VIA_STACK_GUARD);
   5926 
   5927   if (incremental_marking()->IsComplete()) {
   5928     bool uncommit = false;
   5929     if (gc_count_at_last_idle_gc_ == gc_count_) {
   5930       // No GC since the last full GC, the mutator is probably not active.
   5931       isolate_->compilation_cache()->Clear();
   5932       uncommit = true;
   5933     }
   5934     CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental");
   5935     mark_sweeps_since_idle_round_started_++;
   5936     gc_count_at_last_idle_gc_ = gc_count_;
   5937     if (uncommit) {
   5938       new_space_.Shrink();
   5939       UncommitFromSpace();
   5940     }
   5941   }
   5942 }
   5943 
   5944 
   5945 bool Heap::IdleNotification(int hint) {
   5946   // Hints greater than this value indicate that
   5947   // the embedder is requesting a lot of GC work.
   5948   const int kMaxHint = 1000;
   5949   const int kMinHintForIncrementalMarking = 10;
   5950   // Minimal hint that allows to do full GC.
   5951   const int kMinHintForFullGC = 100;
   5952   intptr_t size_factor = Min(Max(hint, 20), kMaxHint) / 4;
   5953   // The size factor is in range [5..250]. The numbers here are chosen from
   5954   // experiments. If you changes them, make sure to test with
   5955   // chrome/performance_ui_tests --gtest_filter="GeneralMixMemoryTest.*
   5956   intptr_t step_size =
   5957       size_factor * IncrementalMarking::kAllocatedThreshold;
   5958 
   5959   if (contexts_disposed_ > 0) {
   5960     if (hint >= kMaxHint) {
   5961       // The embedder is requesting a lot of GC work after context disposal,
   5962       // we age inline caches so that they don't keep objects from
   5963       // the old context alive.
   5964       AgeInlineCaches();
   5965     }
   5966     int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000);
   5967     if (hint >= mark_sweep_time && !FLAG_expose_gc &&
   5968         incremental_marking()->IsStopped()) {
   5969       HistogramTimerScope scope(isolate_->counters()->gc_context());
   5970       CollectAllGarbage(kReduceMemoryFootprintMask,
   5971                         "idle notification: contexts disposed");
   5972     } else {
   5973       AdvanceIdleIncrementalMarking(step_size);
   5974       contexts_disposed_ = 0;
   5975     }
   5976     // After context disposal there is likely a lot of garbage remaining, reset
   5977     // the idle notification counters in order to trigger more incremental GCs
   5978     // on subsequent idle notifications.
   5979     StartIdleRound();
   5980     return false;
   5981   }
   5982 
   5983   if (!FLAG_incremental_marking || FLAG_expose_gc || Serializer::enabled()) {
   5984     return IdleGlobalGC();
   5985   }
   5986 
   5987   // By doing small chunks of GC work in each IdleNotification,
   5988   // perform a round of incremental GCs and after that wait until
   5989   // the mutator creates enough garbage to justify a new round.
   5990   // An incremental GC progresses as follows:
   5991   // 1. many incremental marking steps,
   5992   // 2. one old space mark-sweep-compact,
   5993   // 3. many lazy sweep steps.
   5994   // Use mark-sweep-compact events to count incremental GCs in a round.
   5995 
   5996   if (incremental_marking()->IsStopped()) {
   5997     if (!mark_compact_collector()->AreSweeperThreadsActivated() &&
   5998         !IsSweepingComplete() &&
   5999         !AdvanceSweepers(static_cast<int>(step_size))) {
   6000       return false;
   6001     }
   6002   }
   6003 
   6004   if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
   6005     if (EnoughGarbageSinceLastIdleRound()) {
   6006       StartIdleRound();
   6007     } else {
   6008       return true;
   6009     }
   6010   }
   6011 
   6012   int remaining_mark_sweeps = kMaxMarkSweepsInIdleRound -
   6013                               mark_sweeps_since_idle_round_started_;
   6014 
   6015   if (incremental_marking()->IsStopped()) {
   6016     // If there are no more than two GCs left in this idle round and we are
   6017     // allowed to do a full GC, then make those GCs full in order to compact
   6018     // the code space.
   6019     // TODO(ulan): Once we enable code compaction for incremental marking,
   6020     // we can get rid of this special case and always start incremental marking.
   6021     if (remaining_mark_sweeps <= 2 && hint >= kMinHintForFullGC) {
   6022       CollectAllGarbage(kReduceMemoryFootprintMask,
   6023                         "idle notification: finalize idle round");
   6024       mark_sweeps_since_idle_round_started_++;
   6025     } else if (hint > kMinHintForIncrementalMarking) {
   6026       incremental_marking()->Start();
   6027     }
   6028   }
   6029   if (!incremental_marking()->IsStopped() &&
   6030       hint > kMinHintForIncrementalMarking) {
   6031     AdvanceIdleIncrementalMarking(step_size);
   6032   }
   6033 
   6034   if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
   6035     FinishIdleRound();
   6036     return true;
   6037   }
   6038 
   6039   return false;
   6040 }
   6041 
   6042 
   6043 bool Heap::IdleGlobalGC() {
   6044   static const int kIdlesBeforeScavenge = 4;
   6045   static const int kIdlesBeforeMarkSweep = 7;
   6046   static const int kIdlesBeforeMarkCompact = 8;
   6047   static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1;
   6048   static const unsigned int kGCsBetweenCleanup = 4;
   6049 
   6050   if (!last_idle_notification_gc_count_init_) {
   6051     last_idle_notification_gc_count_ = gc_count_;
   6052     last_idle_notification_gc_count_init_ = true;
   6053   }
   6054 
   6055   bool uncommit = true;
   6056   bool finished = false;
   6057 
   6058   // Reset the number of idle notifications received when a number of
   6059   // GCs have taken place. This allows another round of cleanup based
   6060   // on idle notifications if enough work has been carried out to
   6061   // provoke a number of garbage collections.
   6062   if (gc_count_ - last_idle_notification_gc_count_ < kGCsBetweenCleanup) {
   6063     number_idle_notifications_ =
   6064         Min(number_idle_notifications_ + 1, kMaxIdleCount);
   6065   } else {
   6066     number_idle_notifications_ = 0;
   6067     last_idle_notification_gc_count_ = gc_count_;
   6068   }
   6069 
   6070   if (number_idle_notifications_ == kIdlesBeforeScavenge) {
   6071     CollectGarbage(NEW_SPACE, "idle notification");
   6072     new_space_.Shrink();
   6073     last_idle_notification_gc_count_ = gc_count_;
   6074   } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) {
   6075     // Before doing the mark-sweep collections we clear the
   6076     // compilation cache to avoid hanging on to source code and
   6077     // generated code for cached functions.
   6078     isolate_->compilation_cache()->Clear();
   6079 
   6080     CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification");
   6081     new_space_.Shrink();
   6082     last_idle_notification_gc_count_ = gc_count_;
   6083 
   6084   } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) {
   6085     CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification");
   6086     new_space_.Shrink();
   6087     last_idle_notification_gc_count_ = gc_count_;
   6088     number_idle_notifications_ = 0;
   6089     finished = true;
   6090   } else if (number_idle_notifications_ > kIdlesBeforeMarkCompact) {
   6091     // If we have received more than kIdlesBeforeMarkCompact idle
   6092     // notifications we do not perform any cleanup because we don't
   6093     // expect to gain much by doing so.
   6094     finished = true;
   6095   }
   6096 
   6097   if (uncommit) UncommitFromSpace();
   6098 
   6099   return finished;
   6100 }
   6101 
   6102 
   6103 #ifdef DEBUG
   6104 
   6105 void Heap::Print() {
   6106   if (!HasBeenSetUp()) return;
   6107   isolate()->PrintStack(stdout);
   6108   AllSpaces spaces(this);
   6109   for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
   6110     space->Print();
   6111   }
   6112 }
   6113 
   6114 
   6115 void Heap::ReportCodeStatistics(const char* title) {
   6116   PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title);
   6117   PagedSpace::ResetCodeStatistics();
   6118   // We do not look for code in new space, map space, or old space.  If code
   6119   // somehow ends up in those spaces, we would miss it here.
   6120   code_space_->CollectCodeStatistics();
   6121   lo_space_->CollectCodeStatistics();
   6122   PagedSpace::ReportCodeStatistics();
   6123 }
   6124 
   6125 
   6126 // This function expects that NewSpace's allocated objects histogram is
   6127 // populated (via a call to CollectStatistics or else as a side effect of a
   6128 // just-completed scavenge collection).
   6129 void Heap::ReportHeapStatistics(const char* title) {
   6130   USE(title);
   6131   PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n",
   6132          title, gc_count_);
   6133   PrintF("old_generation_allocation_limit_ %" V8_PTR_PREFIX "d\n",
   6134          old_generation_allocation_limit_);
   6135 
   6136   PrintF("\n");
   6137   PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles(isolate_));
   6138   isolate_->global_handles()->PrintStats();
   6139   PrintF("\n");
   6140 
   6141   PrintF("Heap statistics : ");
   6142   isolate_->memory_allocator()->ReportStatistics();
   6143   PrintF("To space : ");
   6144   new_space_.ReportStatistics();
   6145   PrintF("Old pointer space : ");
   6146   old_pointer_space_->ReportStatistics();
   6147   PrintF("Old data space : ");
   6148   old_data_space_->ReportStatistics();
   6149   PrintF("Code space : ");
   6150   code_space_->ReportStatistics();
   6151   PrintF("Map space : ");
   6152   map_space_->ReportStatistics();
   6153   PrintF("Cell space : ");
   6154   cell_space_->ReportStatistics();
   6155   PrintF("PropertyCell space : ");
   6156   property_cell_space_->ReportStatistics();
   6157   PrintF("Large object space : ");
   6158   lo_space_->ReportStatistics();
   6159   PrintF(">>>>>> ========================================= >>>>>>\n");
   6160 }
   6161 
   6162 #endif  // DEBUG
   6163 
   6164 bool Heap::Contains(HeapObject* value) {
   6165   return Contains(value->address());
   6166 }
   6167 
   6168 
   6169 bool Heap::Contains(Address addr) {
   6170   if (OS::IsOutsideAllocatedSpace(addr)) return false;
   6171   return HasBeenSetUp() &&
   6172     (new_space_.ToSpaceContains(addr) ||
   6173      old_pointer_space_->Contains(addr) ||
   6174      old_data_space_->Contains(addr) ||
   6175      code_space_->Contains(addr) ||
   6176      map_space_->Contains(addr) ||
   6177      cell_space_->Contains(addr) ||
   6178      property_cell_space_->Contains(addr) ||
   6179      lo_space_->SlowContains(addr));
   6180 }
   6181 
   6182 
   6183 bool Heap::InSpace(HeapObject* value, AllocationSpace space) {
   6184   return InSpace(value->address(), space);
   6185 }
   6186 
   6187 
   6188 bool Heap::InSpace(Address addr, AllocationSpace space) {
   6189   if (OS::IsOutsideAllocatedSpace(addr)) return false;
   6190   if (!HasBeenSetUp()) return false;
   6191 
   6192   switch (space) {
   6193     case NEW_SPACE:
   6194       return new_space_.ToSpaceContains(addr);
   6195     case OLD_POINTER_SPACE:
   6196       return old_pointer_space_->Contains(addr);
   6197     case OLD_DATA_SPACE:
   6198       return old_data_space_->Contains(addr);
   6199     case CODE_SPACE:
   6200       return code_space_->Contains(addr);
   6201     case MAP_SPACE:
   6202       return map_space_->Contains(addr);
   6203     case CELL_SPACE:
   6204       return cell_space_->Contains(addr);
   6205     case PROPERTY_CELL_SPACE:
   6206       return property_cell_space_->Contains(addr);
   6207     case LO_SPACE:
   6208       return lo_space_->SlowContains(addr);
   6209   }
   6210 
   6211   return false;
   6212 }
   6213 
   6214 
   6215 #ifdef VERIFY_HEAP
   6216 void Heap::Verify() {
   6217   CHECK(HasBeenSetUp());
   6218 
   6219   store_buffer()->Verify();
   6220 
   6221   VerifyPointersVisitor visitor;
   6222   IterateRoots(&visitor, VISIT_ONLY_STRONG);
   6223 
   6224   new_space_.Verify();
   6225 
   6226   old_pointer_space_->Verify(&visitor);
   6227   map_space_->Verify(&visitor);
   6228 
   6229   VerifyPointersVisitor no_dirty_regions_visitor;
   6230   old_data_space_->Verify(&no_dirty_regions_visitor);
   6231   code_space_->Verify(&no_dirty_regions_visitor);
   6232   cell_space_->Verify(&no_dirty_regions_visitor);
   6233   property_cell_space_->Verify(&no_dirty_regions_visitor);
   6234 
   6235   lo_space_->Verify();
   6236 }
   6237 #endif
   6238 
   6239 
   6240 MaybeObject* Heap::InternalizeUtf8String(Vector<const char> string) {
   6241   Object* result = NULL;
   6242   Object* new_table;
   6243   { MaybeObject* maybe_new_table =
   6244         string_table()->LookupUtf8String(string, &result);
   6245     if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
   6246   }
   6247   // Can't use set_string_table because StringTable::cast knows that
   6248   // StringTable is a singleton and checks for identity.
   6249   roots_[kStringTableRootIndex] = new_table;
   6250   ASSERT(result != NULL);
   6251   return result;
   6252 }
   6253 
   6254 
   6255 MaybeObject* Heap::InternalizeOneByteString(Vector<const uint8_t> string) {
   6256   Object* result = NULL;
   6257   Object* new_table;
   6258   { MaybeObject* maybe_new_table =
   6259         string_table()->LookupOneByteString(string, &result);
   6260     if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
   6261   }
   6262   // Can't use set_string_table because StringTable::cast knows that
   6263   // StringTable is a singleton and checks for identity.
   6264   roots_[kStringTableRootIndex] = new_table;
   6265   ASSERT(result != NULL);
   6266   return result;
   6267 }
   6268 
   6269 
   6270 MaybeObject* Heap::InternalizeOneByteString(Handle<SeqOneByteString> string,
   6271                                      int from,
   6272                                      int length) {
   6273   Object* result = NULL;
   6274   Object* new_table;
   6275   { MaybeObject* maybe_new_table =
   6276         string_table()->LookupSubStringOneByteString(string,
   6277                                                    from,
   6278                                                    length,
   6279                                                    &result);
   6280     if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
   6281   }
   6282   // Can't use set_string_table because StringTable::cast knows that
   6283   // StringTable is a singleton and checks for identity.
   6284   roots_[kStringTableRootIndex] = new_table;
   6285   ASSERT(result != NULL);
   6286   return result;
   6287 }
   6288 
   6289 
   6290 MaybeObject* Heap::InternalizeTwoByteString(Vector<const uc16> string) {
   6291   Object* result = NULL;
   6292   Object* new_table;
   6293   { MaybeObject* maybe_new_table =
   6294         string_table()->LookupTwoByteString(string, &result);
   6295     if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
   6296   }
   6297   // Can't use set_string_table because StringTable::cast knows that
   6298   // StringTable is a singleton and checks for identity.
   6299   roots_[kStringTableRootIndex] = new_table;
   6300   ASSERT(result != NULL);
   6301   return result;
   6302 }
   6303 
   6304 
   6305 MaybeObject* Heap::InternalizeString(String* string) {
   6306   if (string->IsInternalizedString()) return string;
   6307   Object* result = NULL;
   6308   Object* new_table;
   6309   { MaybeObject* maybe_new_table =
   6310         string_table()->LookupString(string, &result);
   6311     if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
   6312   }
   6313   // Can't use set_string_table because StringTable::cast knows that
   6314   // StringTable is a singleton and checks for identity.
   6315   roots_[kStringTableRootIndex] = new_table;
   6316   ASSERT(result != NULL);
   6317   return result;
   6318 }
   6319 
   6320 
   6321 bool Heap::InternalizeStringIfExists(String* string, String** result) {
   6322   if (string->IsInternalizedString()) {
   6323     *result = string;
   6324     return true;
   6325   }
   6326   return string_table()->LookupStringIfExists(string, result);
   6327 }
   6328 
   6329 
   6330 void Heap::ZapFromSpace() {
   6331   NewSpacePageIterator it(new_space_.FromSpaceStart(),
   6332                           new_space_.FromSpaceEnd());
   6333   while (it.has_next()) {
   6334     NewSpacePage* page = it.next();
   6335     for (Address cursor = page->area_start(), limit = page->area_end();
   6336          cursor < limit;
   6337          cursor += kPointerSize) {
   6338       Memory::Address_at(cursor) = kFromSpaceZapValue;
   6339     }
   6340   }
   6341 }
   6342 
   6343 
   6344 void Heap::IterateAndMarkPointersToFromSpace(Address start,
   6345                                              Address end,
   6346                                              ObjectSlotCallback callback) {
   6347   Address slot_address = start;
   6348 
   6349   // We are not collecting slots on new space objects during mutation
   6350   // thus we have to scan for pointers to evacuation candidates when we
   6351   // promote objects. But we should not record any slots in non-black
   6352   // objects. Grey object's slots would be rescanned.
   6353   // White object might not survive until the end of collection
   6354   // it would be a violation of the invariant to record it's slots.
   6355   bool record_slots = false;
   6356   if (incremental_marking()->IsCompacting()) {
   6357     MarkBit mark_bit = Marking::MarkBitFrom(HeapObject::FromAddress(start));
   6358     record_slots = Marking::IsBlack(mark_bit);
   6359   }
   6360 
   6361   while (slot_address < end) {
   6362     Object** slot = reinterpret_cast<Object**>(slot_address);
   6363     Object* object = *slot;
   6364     // If the store buffer becomes overfull we mark pages as being exempt from
   6365     // the store buffer.  These pages are scanned to find pointers that point
   6366     // to the new space.  In that case we may hit newly promoted objects and
   6367     // fix the pointers before the promotion queue gets to them.  Thus the 'if'.
   6368     if (object->IsHeapObject()) {
   6369       if (Heap::InFromSpace(object)) {
   6370         callback(reinterpret_cast<HeapObject**>(slot),
   6371                  HeapObject::cast(object));
   6372         Object* new_object = *slot;
   6373         if (InNewSpace(new_object)) {
   6374           SLOW_ASSERT(Heap::InToSpace(new_object));
   6375           SLOW_ASSERT(new_object->IsHeapObject());
   6376           store_buffer_.EnterDirectlyIntoStoreBuffer(
   6377               reinterpret_cast<Address>(slot));
   6378         }
   6379         SLOW_ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(new_object));
   6380       } else if (record_slots &&
   6381                  MarkCompactCollector::IsOnEvacuationCandidate(object)) {
   6382         mark_compact_collector()->RecordSlot(slot, slot, object);
   6383       }
   6384     }
   6385     slot_address += kPointerSize;
   6386   }
   6387 }
   6388 
   6389 
   6390 #ifdef DEBUG
   6391 typedef bool (*CheckStoreBufferFilter)(Object** addr);
   6392 
   6393 
   6394 bool IsAMapPointerAddress(Object** addr) {
   6395   uintptr_t a = reinterpret_cast<uintptr_t>(addr);
   6396   int mod = a % Map::kSize;
   6397   return mod >= Map::kPointerFieldsBeginOffset &&
   6398          mod < Map::kPointerFieldsEndOffset;
   6399 }
   6400 
   6401 
   6402 bool EverythingsAPointer(Object** addr) {
   6403   return true;
   6404 }
   6405 
   6406 
   6407 static void CheckStoreBuffer(Heap* heap,
   6408                              Object** current,
   6409                              Object** limit,
   6410                              Object**** store_buffer_position,
   6411                              Object*** store_buffer_top,
   6412                              CheckStoreBufferFilter filter,
   6413                              Address special_garbage_start,
   6414                              Address special_garbage_end) {
   6415   Map* free_space_map = heap->free_space_map();
   6416   for ( ; current < limit; current++) {
   6417     Object* o = *current;
   6418     Address current_address = reinterpret_cast<Address>(current);
   6419     // Skip free space.
   6420     if (o == free_space_map) {
   6421       Address current_address = reinterpret_cast<Address>(current);
   6422       FreeSpace* free_space =
   6423           FreeSpace::cast(HeapObject::FromAddress(current_address));
   6424       int skip = free_space->Size();
   6425       ASSERT(current_address + skip <= reinterpret_cast<Address>(limit));
   6426       ASSERT(skip > 0);
   6427       current_address += skip - kPointerSize;
   6428       current = reinterpret_cast<Object**>(current_address);
   6429       continue;
   6430     }
   6431     // Skip the current linear allocation space between top and limit which is
   6432     // unmarked with the free space map, but can contain junk.
   6433     if (current_address == special_garbage_start &&
   6434         special_garbage_end != special_garbage_start) {
   6435       current_address = special_garbage_end - kPointerSize;
   6436       current = reinterpret_cast<Object**>(current_address);
   6437       continue;
   6438     }
   6439     if (!(*filter)(current)) continue;
   6440     ASSERT(current_address < special_garbage_start ||
   6441            current_address >= special_garbage_end);
   6442     ASSERT(reinterpret_cast<uintptr_t>(o) != kFreeListZapValue);
   6443     // We have to check that the pointer does not point into new space
   6444     // without trying to cast it to a heap object since the hash field of
   6445     // a string can contain values like 1 and 3 which are tagged null
   6446     // pointers.
   6447     if (!heap->InNewSpace(o)) continue;
   6448     while (**store_buffer_position < current &&
   6449            *store_buffer_position < store_buffer_top) {
   6450       (*store_buffer_position)++;
   6451     }
   6452     if (**store_buffer_position != current ||
   6453         *store_buffer_position == store_buffer_top) {
   6454       Object** obj_start = current;
   6455       while (!(*obj_start)->IsMap()) obj_start--;
   6456       UNREACHABLE();
   6457     }
   6458   }
   6459 }
   6460 
   6461 
   6462 // Check that the store buffer contains all intergenerational pointers by
   6463 // scanning a page and ensuring that all pointers to young space are in the
   6464 // store buffer.
   6465 void Heap::OldPointerSpaceCheckStoreBuffer() {
   6466   OldSpace* space = old_pointer_space();
   6467   PageIterator pages(space);
   6468 
   6469   store_buffer()->SortUniq();
   6470 
   6471   while (pages.has_next()) {
   6472     Page* page = pages.next();
   6473     Object** current = reinterpret_cast<Object**>(page->area_start());
   6474 
   6475     Address end = page->area_end();
   6476 
   6477     Object*** store_buffer_position = store_buffer()->Start();
   6478     Object*** store_buffer_top = store_buffer()->Top();
   6479 
   6480     Object** limit = reinterpret_cast<Object**>(end);
   6481     CheckStoreBuffer(this,
   6482                      current,
   6483                      limit,
   6484                      &store_buffer_position,
   6485                      store_buffer_top,
   6486                      &EverythingsAPointer,
   6487                      space->top(),
   6488                      space->limit());
   6489   }
   6490 }
   6491 
   6492 
   6493 void Heap::MapSpaceCheckStoreBuffer() {
   6494   MapSpace* space = map_space();
   6495   PageIterator pages(space);
   6496 
   6497   store_buffer()->SortUniq();
   6498 
   6499   while (pages.has_next()) {
   6500     Page* page = pages.next();
   6501     Object** current = reinterpret_cast<Object**>(page->area_start());
   6502 
   6503     Address end = page->area_end();
   6504 
   6505     Object*** store_buffer_position = store_buffer()->Start();
   6506     Object*** store_buffer_top = store_buffer()->Top();
   6507 
   6508     Object** limit = reinterpret_cast<Object**>(end);
   6509     CheckStoreBuffer(this,
   6510                      current,
   6511                      limit,
   6512                      &store_buffer_position,
   6513                      store_buffer_top,
   6514                      &IsAMapPointerAddress,
   6515                      space->top(),
   6516                      space->limit());
   6517   }
   6518 }
   6519 
   6520 
   6521 void Heap::LargeObjectSpaceCheckStoreBuffer() {
   6522   LargeObjectIterator it(lo_space());
   6523   for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) {
   6524     // We only have code, sequential strings, or fixed arrays in large
   6525     // object space, and only fixed arrays can possibly contain pointers to
   6526     // the young generation.
   6527     if (object->IsFixedArray()) {
   6528       Object*** store_buffer_position = store_buffer()->Start();
   6529       Object*** store_buffer_top = store_buffer()->Top();
   6530       Object** current = reinterpret_cast<Object**>(object->address());
   6531       Object** limit =
   6532           reinterpret_cast<Object**>(object->address() + object->Size());
   6533       CheckStoreBuffer(this,
   6534                        current,
   6535                        limit,
   6536                        &store_buffer_position,
   6537                        store_buffer_top,
   6538                        &EverythingsAPointer,
   6539                        NULL,
   6540                        NULL);
   6541     }
   6542   }
   6543 }
   6544 #endif
   6545 
   6546 
   6547 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) {
   6548   IterateStrongRoots(v, mode);
   6549   IterateWeakRoots(v, mode);
   6550 }
   6551 
   6552 
   6553 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) {
   6554   v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex]));
   6555   v->Synchronize(VisitorSynchronization::kStringTable);
   6556   if (mode != VISIT_ALL_IN_SCAVENGE &&
   6557       mode != VISIT_ALL_IN_SWEEP_NEWSPACE) {
   6558     // Scavenge collections have special processing for this.
   6559     external_string_table_.Iterate(v);
   6560   }
   6561   v->Synchronize(VisitorSynchronization::kExternalStringsTable);
   6562 }
   6563 
   6564 
   6565 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
   6566   v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]);
   6567   v->Synchronize(VisitorSynchronization::kStrongRootList);
   6568 
   6569   v->VisitPointer(BitCast<Object**>(&hidden_string_));
   6570   v->Synchronize(VisitorSynchronization::kInternalizedString);
   6571 
   6572   isolate_->bootstrapper()->Iterate(v);
   6573   v->Synchronize(VisitorSynchronization::kBootstrapper);
   6574   isolate_->Iterate(v);
   6575   v->Synchronize(VisitorSynchronization::kTop);
   6576   Relocatable::Iterate(v);
   6577   v->Synchronize(VisitorSynchronization::kRelocatable);
   6578 
   6579 #ifdef ENABLE_DEBUGGER_SUPPORT
   6580   isolate_->debug()->Iterate(v);
   6581   if (isolate_->deoptimizer_data() != NULL) {
   6582     isolate_->deoptimizer_data()->Iterate(v);
   6583   }
   6584 #endif
   6585   v->Synchronize(VisitorSynchronization::kDebug);
   6586   isolate_->compilation_cache()->Iterate(v);
   6587   v->Synchronize(VisitorSynchronization::kCompilationCache);
   6588 
   6589   // Iterate over local handles in handle scopes.
   6590   isolate_->handle_scope_implementer()->Iterate(v);
   6591   isolate_->IterateDeferredHandles(v);
   6592   v->Synchronize(VisitorSynchronization::kHandleScope);
   6593 
   6594   // Iterate over the builtin code objects and code stubs in the
   6595   // heap. Note that it is not necessary to iterate over code objects
   6596   // on scavenge collections.
   6597   if (mode != VISIT_ALL_IN_SCAVENGE) {
   6598     isolate_->builtins()->IterateBuiltins(v);
   6599   }
   6600   v->Synchronize(VisitorSynchronization::kBuiltins);
   6601 
   6602   // Iterate over global handles.
   6603   switch (mode) {
   6604     case VISIT_ONLY_STRONG:
   6605       isolate_->global_handles()->IterateStrongRoots(v);
   6606       break;
   6607     case VISIT_ALL_IN_SCAVENGE:
   6608       isolate_->global_handles()->IterateNewSpaceStrongAndDependentRoots(v);
   6609       break;
   6610     case VISIT_ALL_IN_SWEEP_NEWSPACE:
   6611     case VISIT_ALL:
   6612       isolate_->global_handles()->IterateAllRoots(v);
   6613       break;
   6614   }
   6615   v->Synchronize(VisitorSynchronization::kGlobalHandles);
   6616 
   6617   // Iterate over eternal handles.
   6618   if (mode == VISIT_ALL_IN_SCAVENGE) {
   6619     isolate_->eternal_handles()->IterateNewSpaceRoots(v);
   6620   } else {
   6621     isolate_->eternal_handles()->IterateAllRoots(v);
   6622   }
   6623   v->Synchronize(VisitorSynchronization::kEternalHandles);
   6624 
   6625   // Iterate over pointers being held by inactive threads.
   6626   isolate_->thread_manager()->Iterate(v);
   6627   v->Synchronize(VisitorSynchronization::kThreadManager);
   6628 
   6629   // Iterate over the pointers the Serialization/Deserialization code is
   6630   // holding.
   6631   // During garbage collection this keeps the partial snapshot cache alive.
   6632   // During deserialization of the startup snapshot this creates the partial
   6633   // snapshot cache and deserializes the objects it refers to.  During
   6634   // serialization this does nothing, since the partial snapshot cache is
   6635   // empty.  However the next thing we do is create the partial snapshot,
   6636   // filling up the partial snapshot cache with objects it needs as we go.
   6637   SerializerDeserializer::Iterate(v);
   6638   // We don't do a v->Synchronize call here, because in debug mode that will
   6639   // output a flag to the snapshot.  However at this point the serializer and
   6640   // deserializer are deliberately a little unsynchronized (see above) so the
   6641   // checking of the sync flag in the snapshot would fail.
   6642 }
   6643 
   6644 
   6645 // TODO(1236194): Since the heap size is configurable on the command line
   6646 // and through the API, we should gracefully handle the case that the heap
   6647 // size is not big enough to fit all the initial objects.
   6648 bool Heap::ConfigureHeap(int max_semispace_size,
   6649                          intptr_t max_old_gen_size,
   6650                          intptr_t max_executable_size) {
   6651   if (HasBeenSetUp()) return false;
   6652 
   6653   if (FLAG_stress_compaction) {
   6654     // This will cause more frequent GCs when stressing.
   6655     max_semispace_size_ = Page::kPageSize;
   6656   }
   6657 
   6658   if (max_semispace_size > 0) {
   6659     if (max_semispace_size < Page::kPageSize) {
   6660       max_semispace_size = Page::kPageSize;
   6661       if (FLAG_trace_gc) {
   6662         PrintPID("Max semispace size cannot be less than %dkbytes\n",
   6663                  Page::kPageSize >> 10);
   6664       }
   6665     }
   6666     max_semispace_size_ = max_semispace_size;
   6667   }
   6668 
   6669   if (Snapshot::IsEnabled()) {
   6670     // If we are using a snapshot we always reserve the default amount
   6671     // of memory for each semispace because code in the snapshot has
   6672     // write-barrier code that relies on the size and alignment of new
   6673     // space.  We therefore cannot use a larger max semispace size
   6674     // than the default reserved semispace size.
   6675     if (max_semispace_size_ > reserved_semispace_size_) {
   6676       max_semispace_size_ = reserved_semispace_size_;
   6677       if (FLAG_trace_gc) {
   6678         PrintPID("Max semispace size cannot be more than %dkbytes\n",
   6679                  reserved_semispace_size_ >> 10);
   6680       }
   6681     }
   6682   } else {
   6683     // If we are not using snapshots we reserve space for the actual
   6684     // max semispace size.
   6685     reserved_semispace_size_ = max_semispace_size_;
   6686   }
   6687 
   6688   if (max_old_gen_size > 0) max_old_generation_size_ = max_old_gen_size;
   6689   if (max_executable_size > 0) {
   6690     max_executable_size_ = RoundUp(max_executable_size, Page::kPageSize);
   6691   }
   6692 
   6693   // The max executable size must be less than or equal to the max old
   6694   // generation size.
   6695   if (max_executable_size_ > max_old_generation_size_) {
   6696     max_executable_size_ = max_old_generation_size_;
   6697   }
   6698 
   6699   // The new space size must be a power of two to support single-bit testing
   6700   // for containment.
   6701   max_semispace_size_ = RoundUpToPowerOf2(max_semispace_size_);
   6702   reserved_semispace_size_ = RoundUpToPowerOf2(reserved_semispace_size_);
   6703   initial_semispace_size_ = Min(initial_semispace_size_, max_semispace_size_);
   6704 
   6705   // The external allocation limit should be below 256 MB on all architectures
   6706   // to avoid unnecessary low memory notifications, as that is the threshold
   6707   // for some embedders.
   6708   external_allocation_limit_ = 12 * max_semispace_size_;
   6709   ASSERT(external_allocation_limit_ <= 256 * MB);
   6710 
   6711   // The old generation is paged and needs at least one page for each space.
   6712   int paged_space_count = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1;
   6713   max_old_generation_size_ = Max(static_cast<intptr_t>(paged_space_count *
   6714                                                        Page::kPageSize),
   6715                                  RoundUp(max_old_generation_size_,
   6716                                          Page::kPageSize));
   6717 
   6718   configured_ = true;
   6719   return true;
   6720 }
   6721 
   6722 
   6723 bool Heap::ConfigureHeapDefault() {
   6724   return ConfigureHeap(static_cast<intptr_t>(FLAG_max_new_space_size / 2) * KB,
   6725                        static_cast<intptr_t>(FLAG_max_old_space_size) * MB,
   6726                        static_cast<intptr_t>(FLAG_max_executable_size) * MB);
   6727 }
   6728 
   6729 
   6730 void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
   6731   *stats->start_marker = HeapStats::kStartMarker;
   6732   *stats->end_marker = HeapStats::kEndMarker;
   6733   *stats->new_space_size = new_space_.SizeAsInt();
   6734   *stats->new_space_capacity = static_cast<int>(new_space_.Capacity());
   6735   *stats->old_pointer_space_size = old_pointer_space_->SizeOfObjects();
   6736   *stats->old_pointer_space_capacity = old_pointer_space_->Capacity();
   6737   *stats->old_data_space_size = old_data_space_->SizeOfObjects();
   6738   *stats->old_data_space_capacity = old_data_space_->Capacity();
   6739   *stats->code_space_size = code_space_->SizeOfObjects();
   6740   *stats->code_space_capacity = code_space_->Capacity();
   6741   *stats->map_space_size = map_space_->SizeOfObjects();
   6742   *stats->map_space_capacity = map_space_->Capacity();
   6743   *stats->cell_space_size = cell_space_->SizeOfObjects();
   6744   *stats->cell_space_capacity = cell_space_->Capacity();
   6745   *stats->property_cell_space_size = property_cell_space_->SizeOfObjects();
   6746   *stats->property_cell_space_capacity = property_cell_space_->Capacity();
   6747   *stats->lo_space_size = lo_space_->Size();
   6748   isolate_->global_handles()->RecordStats(stats);
   6749   *stats->memory_allocator_size = isolate()->memory_allocator()->Size();
   6750   *stats->memory_allocator_capacity =
   6751       isolate()->memory_allocator()->Size() +
   6752       isolate()->memory_allocator()->Available();
   6753   *stats->os_error = OS::GetLastError();
   6754       isolate()->memory_allocator()->Available();
   6755   if (take_snapshot) {
   6756     HeapIterator iterator(this);
   6757     for (HeapObject* obj = iterator.next();
   6758          obj != NULL;
   6759          obj = iterator.next()) {
   6760       InstanceType type = obj->map()->instance_type();
   6761       ASSERT(0 <= type && type <= LAST_TYPE);
   6762       stats->objects_per_type[type]++;
   6763       stats->size_per_type[type] += obj->Size();
   6764     }
   6765   }
   6766 }
   6767 
   6768 
   6769 intptr_t Heap::PromotedSpaceSizeOfObjects() {
   6770   return old_pointer_space_->SizeOfObjects()
   6771       + old_data_space_->SizeOfObjects()
   6772       + code_space_->SizeOfObjects()
   6773       + map_space_->SizeOfObjects()
   6774       + cell_space_->SizeOfObjects()
   6775       + property_cell_space_->SizeOfObjects()
   6776       + lo_space_->SizeOfObjects();
   6777 }
   6778 
   6779 
   6780 intptr_t Heap::PromotedExternalMemorySize() {
   6781   if (amount_of_external_allocated_memory_
   6782       <= amount_of_external_allocated_memory_at_last_global_gc_) return 0;
   6783   return amount_of_external_allocated_memory_
   6784       - amount_of_external_allocated_memory_at_last_global_gc_;
   6785 }
   6786 
   6787 
   6788 V8_DECLARE_ONCE(initialize_gc_once);
   6789 
   6790 static void InitializeGCOnce() {
   6791   InitializeScavengingVisitorsTables();
   6792   NewSpaceScavenger::Initialize();
   6793   MarkCompactCollector::Initialize();
   6794 }
   6795 
   6796 
   6797 bool Heap::SetUp() {
   6798 #ifdef DEBUG
   6799   allocation_timeout_ = FLAG_gc_interval;
   6800 #endif
   6801 
   6802   // Initialize heap spaces and initial maps and objects. Whenever something
   6803   // goes wrong, just return false. The caller should check the results and
   6804   // call Heap::TearDown() to release allocated memory.
   6805   //
   6806   // If the heap is not yet configured (e.g. through the API), configure it.
   6807   // Configuration is based on the flags new-space-size (really the semispace
   6808   // size) and old-space-size if set or the initial values of semispace_size_
   6809   // and old_generation_size_ otherwise.
   6810   if (!configured_) {
   6811     if (!ConfigureHeapDefault()) return false;
   6812   }
   6813 
   6814   CallOnce(&initialize_gc_once, &InitializeGCOnce);
   6815 
   6816   MarkMapPointersAsEncoded(false);
   6817 
   6818   // Set up memory allocator.
   6819   if (!isolate_->memory_allocator()->SetUp(MaxReserved(), MaxExecutableSize()))
   6820       return false;
   6821 
   6822   // Set up new space.
   6823   if (!new_space_.SetUp(reserved_semispace_size_, max_semispace_size_)) {
   6824     return false;
   6825   }
   6826 
   6827   // Initialize old pointer space.
   6828   old_pointer_space_ =
   6829       new OldSpace(this,
   6830                    max_old_generation_size_,
   6831                    OLD_POINTER_SPACE,
   6832                    NOT_EXECUTABLE);
   6833   if (old_pointer_space_ == NULL) return false;
   6834   if (!old_pointer_space_->SetUp()) return false;
   6835 
   6836   // Initialize old data space.
   6837   old_data_space_ =
   6838       new OldSpace(this,
   6839                    max_old_generation_size_,
   6840                    OLD_DATA_SPACE,
   6841                    NOT_EXECUTABLE);
   6842   if (old_data_space_ == NULL) return false;
   6843   if (!old_data_space_->SetUp()) return false;
   6844 
   6845   // Initialize the code space, set its maximum capacity to the old
   6846   // generation size. It needs executable memory.
   6847   // On 64-bit platform(s), we put all code objects in a 2 GB range of
   6848   // virtual address space, so that they can call each other with near calls.
   6849   if (code_range_size_ > 0) {
   6850     if (!isolate_->code_range()->SetUp(code_range_size_)) {
   6851       return false;
   6852     }
   6853   }
   6854 
   6855   code_space_ =
   6856       new OldSpace(this, max_old_generation_size_, CODE_SPACE, EXECUTABLE);
   6857   if (code_space_ == NULL) return false;
   6858   if (!code_space_->SetUp()) return false;
   6859 
   6860   // Initialize map space.
   6861   map_space_ = new MapSpace(this, max_old_generation_size_, MAP_SPACE);
   6862   if (map_space_ == NULL) return false;
   6863   if (!map_space_->SetUp()) return false;
   6864 
   6865   // Initialize simple cell space.
   6866   cell_space_ = new CellSpace(this, max_old_generation_size_, CELL_SPACE);
   6867   if (cell_space_ == NULL) return false;
   6868   if (!cell_space_->SetUp()) return false;
   6869 
   6870   // Initialize global property cell space.
   6871   property_cell_space_ = new PropertyCellSpace(this, max_old_generation_size_,
   6872                                                PROPERTY_CELL_SPACE);
   6873   if (property_cell_space_ == NULL) return false;
   6874   if (!property_cell_space_->SetUp()) return false;
   6875 
   6876   // The large object code space may contain code or data.  We set the memory
   6877   // to be non-executable here for safety, but this means we need to enable it
   6878   // explicitly when allocating large code objects.
   6879   lo_space_ = new LargeObjectSpace(this, max_old_generation_size_, LO_SPACE);
   6880   if (lo_space_ == NULL) return false;
   6881   if (!lo_space_->SetUp()) return false;
   6882 
   6883   // Set up the seed that is used to randomize the string hash function.
   6884   ASSERT(hash_seed() == 0);
   6885   if (FLAG_randomize_hashes) {
   6886     if (FLAG_hash_seed == 0) {
   6887       set_hash_seed(
   6888           Smi::FromInt(V8::RandomPrivate(isolate()) & 0x3fffffff));
   6889     } else {
   6890       set_hash_seed(Smi::FromInt(FLAG_hash_seed));
   6891     }
   6892   }
   6893 
   6894   LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
   6895   LOG(isolate_, IntPtrTEvent("heap-available", Available()));
   6896 
   6897   store_buffer()->SetUp();
   6898 
   6899   if (FLAG_parallel_recompilation) relocation_mutex_ = OS::CreateMutex();
   6900 #ifdef DEBUG
   6901   relocation_mutex_locked_by_optimizer_thread_ = false;
   6902 #endif  // DEBUG
   6903 
   6904   return true;
   6905 }
   6906 
   6907 
   6908 bool Heap::CreateHeapObjects() {
   6909   // Create initial maps.
   6910   if (!CreateInitialMaps()) return false;
   6911   if (!CreateApiObjects()) return false;
   6912 
   6913   // Create initial objects
   6914   if (!CreateInitialObjects()) return false;
   6915 
   6916   native_contexts_list_ = undefined_value();
   6917   array_buffers_list_ = undefined_value();
   6918   allocation_sites_list_ = undefined_value();
   6919   return true;
   6920 }
   6921 
   6922 
   6923 void Heap::SetStackLimits() {
   6924   ASSERT(isolate_ != NULL);
   6925   ASSERT(isolate_ == isolate());
   6926   // On 64 bit machines, pointers are generally out of range of Smis.  We write
   6927   // something that looks like an out of range Smi to the GC.
   6928 
   6929   // Set up the special root array entries containing the stack limits.
   6930   // These are actually addresses, but the tag makes the GC ignore it.
   6931   roots_[kStackLimitRootIndex] =
   6932       reinterpret_cast<Object*>(
   6933           (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag);
   6934   roots_[kRealStackLimitRootIndex] =
   6935       reinterpret_cast<Object*>(
   6936           (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag);
   6937 }
   6938 
   6939 
   6940 void Heap::TearDown() {
   6941 #ifdef VERIFY_HEAP
   6942   if (FLAG_verify_heap) {
   6943     Verify();
   6944   }
   6945 #endif
   6946 
   6947   if (FLAG_print_cumulative_gc_stat) {
   6948     PrintF("\n");
   6949     PrintF("gc_count=%d ", gc_count_);
   6950     PrintF("mark_sweep_count=%d ", ms_count_);
   6951     PrintF("max_gc_pause=%.1f ", get_max_gc_pause());
   6952     PrintF("total_gc_time=%.1f ", total_gc_time_ms_);
   6953     PrintF("min_in_mutator=%.1f ", get_min_in_mutator());
   6954     PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ",
   6955            get_max_alive_after_gc());
   6956     PrintF("total_marking_time=%.1f ", marking_time());
   6957     PrintF("total_sweeping_time=%.1f ", sweeping_time());
   6958     PrintF("\n\n");
   6959   }
   6960 
   6961   TearDownArrayBuffers();
   6962 
   6963   isolate_->global_handles()->TearDown();
   6964 
   6965   external_string_table_.TearDown();
   6966 
   6967   mark_compact_collector()->TearDown();
   6968 
   6969   new_space_.TearDown();
   6970 
   6971   if (old_pointer_space_ != NULL) {
   6972     old_pointer_space_->TearDown();
   6973     delete old_pointer_space_;
   6974     old_pointer_space_ = NULL;
   6975   }
   6976 
   6977   if (old_data_space_ != NULL) {
   6978     old_data_space_->TearDown();
   6979     delete old_data_space_;
   6980     old_data_space_ = NULL;
   6981   }
   6982 
   6983   if (code_space_ != NULL) {
   6984     code_space_->TearDown();
   6985     delete code_space_;
   6986     code_space_ = NULL;
   6987   }
   6988 
   6989   if (map_space_ != NULL) {
   6990     map_space_->TearDown();
   6991     delete map_space_;
   6992     map_space_ = NULL;
   6993   }
   6994 
   6995   if (cell_space_ != NULL) {
   6996     cell_space_->TearDown();
   6997     delete cell_space_;
   6998     cell_space_ = NULL;
   6999   }
   7000 
   7001   if (property_cell_space_ != NULL) {
   7002     property_cell_space_->TearDown();
   7003     delete property_cell_space_;
   7004     property_cell_space_ = NULL;
   7005   }
   7006 
   7007   if (lo_space_ != NULL) {
   7008     lo_space_->TearDown();
   7009     delete lo_space_;
   7010     lo_space_ = NULL;
   7011   }
   7012 
   7013   store_buffer()->TearDown();
   7014   incremental_marking()->TearDown();
   7015 
   7016   isolate_->memory_allocator()->TearDown();
   7017 
   7018   delete relocation_mutex_;
   7019 }
   7020 
   7021 
   7022 void Heap::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
   7023   ASSERT(callback != NULL);
   7024   GCPrologueCallbackPair pair(callback, gc_type);
   7025   ASSERT(!gc_prologue_callbacks_.Contains(pair));
   7026   return gc_prologue_callbacks_.Add(pair);
   7027 }
   7028 
   7029 
   7030 void Heap::RemoveGCPrologueCallback(GCPrologueCallback callback) {
   7031   ASSERT(callback != NULL);
   7032   for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) {
   7033     if (gc_prologue_callbacks_[i].callback == callback) {
   7034       gc_prologue_callbacks_.Remove(i);
   7035       return;
   7036     }
   7037   }
   7038   UNREACHABLE();
   7039 }
   7040 
   7041 
   7042 void Heap::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
   7043   ASSERT(callback != NULL);
   7044   GCEpilogueCallbackPair pair(callback, gc_type);
   7045   ASSERT(!gc_epilogue_callbacks_.Contains(pair));
   7046   return gc_epilogue_callbacks_.Add(pair);
   7047 }
   7048 
   7049 
   7050 void Heap::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
   7051   ASSERT(callback != NULL);
   7052   for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
   7053     if (gc_epilogue_callbacks_[i].callback == callback) {
   7054       gc_epilogue_callbacks_.Remove(i);
   7055       return;
   7056     }
   7057   }
   7058   UNREACHABLE();
   7059 }
   7060 
   7061 
   7062 #ifdef DEBUG
   7063 
   7064 class PrintHandleVisitor: public ObjectVisitor {
   7065  public:
   7066   void VisitPointers(Object** start, Object** end) {
   7067     for (Object** p = start; p < end; p++)
   7068       PrintF("  handle %p to %p\n",
   7069              reinterpret_cast<void*>(p),
   7070              reinterpret_cast<void*>(*p));
   7071   }
   7072 };
   7073 
   7074 
   7075 void Heap::PrintHandles() {
   7076   PrintF("Handles:\n");
   7077   PrintHandleVisitor v;
   7078   isolate_->handle_scope_implementer()->Iterate(&v);
   7079 }
   7080 
   7081 #endif
   7082 
   7083 
   7084 Space* AllSpaces::next() {
   7085   switch (counter_++) {
   7086     case NEW_SPACE:
   7087       return heap_->new_space();
   7088     case OLD_POINTER_SPACE:
   7089       return heap_->old_pointer_space();
   7090     case OLD_DATA_SPACE:
   7091       return heap_->old_data_space();
   7092     case CODE_SPACE:
   7093       return heap_->code_space();
   7094     case MAP_SPACE:
   7095       return heap_->map_space();
   7096     case CELL_SPACE:
   7097       return heap_->cell_space();
   7098     case PROPERTY_CELL_SPACE:
   7099       return heap_->property_cell_space();
   7100     case LO_SPACE:
   7101       return heap_->lo_space();
   7102     default:
   7103       return NULL;
   7104   }
   7105 }
   7106 
   7107 
   7108 PagedSpace* PagedSpaces::next() {
   7109   switch (counter_++) {
   7110     case OLD_POINTER_SPACE:
   7111       return heap_->old_pointer_space();
   7112     case OLD_DATA_SPACE:
   7113       return heap_->old_data_space();
   7114     case CODE_SPACE:
   7115       return heap_->code_space();
   7116     case MAP_SPACE:
   7117       return heap_->map_space();
   7118     case CELL_SPACE:
   7119       return heap_->cell_space();
   7120     case PROPERTY_CELL_SPACE:
   7121       return heap_->property_cell_space();
   7122     default:
   7123       return NULL;
   7124   }
   7125 }
   7126 
   7127 
   7128 
   7129 OldSpace* OldSpaces::next() {
   7130   switch (counter_++) {
   7131     case OLD_POINTER_SPACE:
   7132       return heap_->old_pointer_space();
   7133     case OLD_DATA_SPACE:
   7134       return heap_->old_data_space();
   7135     case CODE_SPACE:
   7136       return heap_->code_space();
   7137     default:
   7138       return NULL;
   7139   }
   7140 }
   7141 
   7142 
   7143 SpaceIterator::SpaceIterator(Heap* heap)
   7144     : heap_(heap),
   7145       current_space_(FIRST_SPACE),
   7146       iterator_(NULL),
   7147       size_func_(NULL) {
   7148 }
   7149 
   7150 
   7151 SpaceIterator::SpaceIterator(Heap* heap, HeapObjectCallback size_func)
   7152     : heap_(heap),
   7153       current_space_(FIRST_SPACE),
   7154       iterator_(NULL),
   7155       size_func_(size_func) {
   7156 }
   7157 
   7158 
   7159 SpaceIterator::~SpaceIterator() {
   7160   // Delete active iterator if any.
   7161   delete iterator_;
   7162 }
   7163 
   7164 
   7165 bool SpaceIterator::has_next() {
   7166   // Iterate until no more spaces.
   7167   return current_space_ != LAST_SPACE;
   7168 }
   7169 
   7170 
   7171 ObjectIterator* SpaceIterator::next() {
   7172   if (iterator_ != NULL) {
   7173     delete iterator_;
   7174     iterator_ = NULL;
   7175     // Move to the next space
   7176     current_space_++;
   7177     if (current_space_ > LAST_SPACE) {
   7178       return NULL;
   7179     }
   7180   }
   7181 
   7182   // Return iterator for the new current space.
   7183   return CreateIterator();
   7184 }
   7185 
   7186 
   7187 // Create an iterator for the space to iterate.
   7188 ObjectIterator* SpaceIterator::CreateIterator() {
   7189   ASSERT(iterator_ == NULL);
   7190 
   7191   switch (current_space_) {
   7192     case NEW_SPACE:
   7193       iterator_ = new SemiSpaceIterator(heap_->new_space(), size_func_);
   7194       break;
   7195     case OLD_POINTER_SPACE:
   7196       iterator_ =
   7197           new HeapObjectIterator(heap_->old_pointer_space(), size_func_);
   7198       break;
   7199     case OLD_DATA_SPACE:
   7200       iterator_ = new HeapObjectIterator(heap_->old_data_space(), size_func_);
   7201       break;
   7202     case CODE_SPACE:
   7203       iterator_ = new HeapObjectIterator(heap_->code_space(), size_func_);
   7204       break;
   7205     case MAP_SPACE:
   7206       iterator_ = new HeapObjectIterator(heap_->map_space(), size_func_);
   7207       break;
   7208     case CELL_SPACE:
   7209       iterator_ = new HeapObjectIterator(heap_->cell_space(), size_func_);
   7210       break;
   7211     case PROPERTY_CELL_SPACE:
   7212       iterator_ = new HeapObjectIterator(heap_->property_cell_space(),
   7213                                          size_func_);
   7214       break;
   7215     case LO_SPACE:
   7216       iterator_ = new LargeObjectIterator(heap_->lo_space(), size_func_);
   7217       break;
   7218   }
   7219 
   7220   // Return the newly allocated iterator;
   7221   ASSERT(iterator_ != NULL);
   7222   return iterator_;
   7223 }
   7224 
   7225 
   7226 class HeapObjectsFilter {
   7227  public:
   7228   virtual ~HeapObjectsFilter() {}
   7229   virtual bool SkipObject(HeapObject* object) = 0;
   7230 };
   7231 
   7232 
   7233 class UnreachableObjectsFilter : public HeapObjectsFilter {
   7234  public:
   7235   UnreachableObjectsFilter() {
   7236     MarkReachableObjects();
   7237   }
   7238 
   7239   ~UnreachableObjectsFilter() {
   7240     Isolate::Current()->heap()->mark_compact_collector()->ClearMarkbits();
   7241   }
   7242 
   7243   bool SkipObject(HeapObject* object) {
   7244     MarkBit mark_bit = Marking::MarkBitFrom(object);
   7245     return !mark_bit.Get();
   7246   }
   7247 
   7248  private:
   7249   class MarkingVisitor : public ObjectVisitor {
   7250    public:
   7251     MarkingVisitor() : marking_stack_(10) {}
   7252 
   7253     void VisitPointers(Object** start, Object** end) {
   7254       for (Object** p = start; p < end; p++) {
   7255         if (!(*p)->IsHeapObject()) continue;
   7256         HeapObject* obj = HeapObject::cast(*p);
   7257         MarkBit mark_bit = Marking::MarkBitFrom(obj);
   7258         if (!mark_bit.Get()) {
   7259           mark_bit.Set();
   7260           marking_stack_.Add(obj);
   7261         }
   7262       }
   7263     }
   7264 
   7265     void TransitiveClosure() {
   7266       while (!marking_stack_.is_empty()) {
   7267         HeapObject* obj = marking_stack_.RemoveLast();
   7268         obj->Iterate(this);
   7269       }
   7270     }
   7271 
   7272    private:
   7273     List<HeapObject*> marking_stack_;
   7274   };
   7275 
   7276   void MarkReachableObjects() {
   7277     Heap* heap = Isolate::Current()->heap();
   7278     MarkingVisitor visitor;
   7279     heap->IterateRoots(&visitor, VISIT_ALL);
   7280     visitor.TransitiveClosure();
   7281   }
   7282 
   7283   DisallowHeapAllocation no_allocation_;
   7284 };
   7285 
   7286 
   7287 HeapIterator::HeapIterator(Heap* heap)
   7288     : heap_(heap),
   7289       filtering_(HeapIterator::kNoFiltering),
   7290       filter_(NULL) {
   7291   Init();
   7292 }
   7293 
   7294 
   7295 HeapIterator::HeapIterator(Heap* heap,
   7296                            HeapIterator::HeapObjectsFiltering filtering)
   7297     : heap_(heap),
   7298       filtering_(filtering),
   7299       filter_(NULL) {
   7300   Init();
   7301 }
   7302 
   7303 
   7304 HeapIterator::~HeapIterator() {
   7305   Shutdown();
   7306 }
   7307 
   7308 
   7309 void HeapIterator::Init() {
   7310   // Start the iteration.
   7311   space_iterator_ = new SpaceIterator(heap_);
   7312   switch (filtering_) {
   7313     case kFilterUnreachable:
   7314       filter_ = new UnreachableObjectsFilter;
   7315       break;
   7316     default:
   7317       break;
   7318   }
   7319   object_iterator_ = space_iterator_->next();
   7320 }
   7321 
   7322 
   7323 void HeapIterator::Shutdown() {
   7324 #ifdef DEBUG
   7325   // Assert that in filtering mode we have iterated through all
   7326   // objects. Otherwise, heap will be left in an inconsistent state.
   7327   if (filtering_ != kNoFiltering) {
   7328     ASSERT(object_iterator_ == NULL);
   7329   }
   7330 #endif
   7331   // Make sure the last iterator is deallocated.
   7332   delete space_iterator_;
   7333   space_iterator_ = NULL;
   7334   object_iterator_ = NULL;
   7335   delete filter_;
   7336   filter_ = NULL;
   7337 }
   7338 
   7339 
   7340 HeapObject* HeapIterator::next() {
   7341   if (filter_ == NULL) return NextObject();
   7342 
   7343   HeapObject* obj = NextObject();
   7344   while (obj != NULL && filter_->SkipObject(obj)) obj = NextObject();
   7345   return obj;
   7346 }
   7347 
   7348 
   7349 HeapObject* HeapIterator::NextObject() {
   7350   // No iterator means we are done.
   7351   if (object_iterator_ == NULL) return NULL;
   7352 
   7353   if (HeapObject* obj = object_iterator_->next_object()) {
   7354     // If the current iterator has more objects we are fine.
   7355     return obj;
   7356   } else {
   7357     // Go though the spaces looking for one that has objects.
   7358     while (space_iterator_->has_next()) {
   7359       object_iterator_ = space_iterator_->next();
   7360       if (HeapObject* obj = object_iterator_->next_object()) {
   7361         return obj;
   7362       }
   7363     }
   7364   }
   7365   // Done with the last space.
   7366   object_iterator_ = NULL;
   7367   return NULL;
   7368 }
   7369 
   7370 
   7371 void HeapIterator::reset() {
   7372   // Restart the iterator.
   7373   Shutdown();
   7374   Init();
   7375 }
   7376 
   7377 
   7378 #ifdef DEBUG
   7379 
   7380 Object* const PathTracer::kAnyGlobalObject = NULL;
   7381 
   7382 class PathTracer::MarkVisitor: public ObjectVisitor {
   7383  public:
   7384   explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
   7385   void VisitPointers(Object** start, Object** end) {
   7386     // Scan all HeapObject pointers in [start, end)
   7387     for (Object** p = start; !tracer_->found() && (p < end); p++) {
   7388       if ((*p)->IsHeapObject())
   7389         tracer_->MarkRecursively(p, this);
   7390     }
   7391   }
   7392 
   7393  private:
   7394   PathTracer* tracer_;
   7395 };
   7396 
   7397 
   7398 class PathTracer::UnmarkVisitor: public ObjectVisitor {
   7399  public:
   7400   explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
   7401   void VisitPointers(Object** start, Object** end) {
   7402     // Scan all HeapObject pointers in [start, end)
   7403     for (Object** p = start; p < end; p++) {
   7404       if ((*p)->IsHeapObject())
   7405         tracer_->UnmarkRecursively(p, this);
   7406     }
   7407   }
   7408 
   7409  private:
   7410   PathTracer* tracer_;
   7411 };
   7412 
   7413 
   7414 void PathTracer::VisitPointers(Object** start, Object** end) {
   7415   bool done = ((what_to_find_ == FIND_FIRST) && found_target_);
   7416   // Visit all HeapObject pointers in [start, end)
   7417   for (Object** p = start; !done && (p < end); p++) {
   7418     if ((*p)->IsHeapObject()) {
   7419       TracePathFrom(p);
   7420       done = ((what_to_find_ == FIND_FIRST) && found_target_);
   7421     }
   7422   }
   7423 }
   7424 
   7425 
   7426 void PathTracer::Reset() {
   7427   found_target_ = false;
   7428   object_stack_.Clear();
   7429 }
   7430 
   7431 
   7432 void PathTracer::TracePathFrom(Object** root) {
   7433   ASSERT((search_target_ == kAnyGlobalObject) ||
   7434          search_target_->IsHeapObject());
   7435   found_target_in_trace_ = false;
   7436   Reset();
   7437 
   7438   MarkVisitor mark_visitor(this);
   7439   MarkRecursively(root, &mark_visitor);
   7440 
   7441   UnmarkVisitor unmark_visitor(this);
   7442   UnmarkRecursively(root, &unmark_visitor);
   7443 
   7444   ProcessResults();
   7445 }
   7446 
   7447 
   7448 static bool SafeIsNativeContext(HeapObject* obj) {
   7449   return obj->map() == obj->GetHeap()->raw_unchecked_native_context_map();
   7450 }
   7451 
   7452 
   7453 void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) {
   7454   if (!(*p)->IsHeapObject()) return;
   7455 
   7456   HeapObject* obj = HeapObject::cast(*p);
   7457 
   7458   Object* map = obj->map();
   7459 
   7460   if (!map->IsHeapObject()) return;  // visited before
   7461 
   7462   if (found_target_in_trace_) return;  // stop if target found
   7463   object_stack_.Add(obj);
   7464   if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) ||
   7465       (obj == search_target_)) {
   7466     found_target_in_trace_ = true;
   7467     found_target_ = true;
   7468     return;
   7469   }
   7470 
   7471   bool is_native_context = SafeIsNativeContext(obj);
   7472 
   7473   // not visited yet
   7474   Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map));
   7475 
   7476   Address map_addr = map_p->address();
   7477 
   7478   obj->set_map_no_write_barrier(reinterpret_cast<Map*>(map_addr + kMarkTag));
   7479 
   7480   // Scan the object body.
   7481   if (is_native_context && (visit_mode_ == VISIT_ONLY_STRONG)) {
   7482     // This is specialized to scan Context's properly.
   7483     Object** start = reinterpret_cast<Object**>(obj->address() +
   7484                                                 Context::kHeaderSize);
   7485     Object** end = reinterpret_cast<Object**>(obj->address() +
   7486         Context::kHeaderSize + Context::FIRST_WEAK_SLOT * kPointerSize);
   7487     mark_visitor->VisitPointers(start, end);
   7488   } else {
   7489     obj->IterateBody(map_p->instance_type(),
   7490                      obj->SizeFromMap(map_p),
   7491                      mark_visitor);
   7492   }
   7493 
   7494   // Scan the map after the body because the body is a lot more interesting
   7495   // when doing leak detection.
   7496   MarkRecursively(&map, mark_visitor);
   7497 
   7498   if (!found_target_in_trace_)  // don't pop if found the target
   7499     object_stack_.RemoveLast();
   7500 }
   7501 
   7502 
   7503 void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) {
   7504   if (!(*p)->IsHeapObject()) return;
   7505 
   7506   HeapObject* obj = HeapObject::cast(*p);
   7507 
   7508   Object* map = obj->map();
   7509 
   7510   if (map->IsHeapObject()) return;  // unmarked already
   7511 
   7512   Address map_addr = reinterpret_cast<Address>(map);
   7513 
   7514   map_addr -= kMarkTag;
   7515 
   7516   ASSERT_TAG_ALIGNED(map_addr);
   7517 
   7518   HeapObject* map_p = HeapObject::FromAddress(map_addr);
   7519 
   7520   obj->set_map_no_write_barrier(reinterpret_cast<Map*>(map_p));
   7521 
   7522   UnmarkRecursively(reinterpret_cast<Object**>(&map_p), unmark_visitor);
   7523 
   7524   obj->IterateBody(Map::cast(map_p)->instance_type(),
   7525                    obj->SizeFromMap(Map::cast(map_p)),
   7526                    unmark_visitor);
   7527 }
   7528 
   7529 
   7530 void PathTracer::ProcessResults() {
   7531   if (found_target_) {
   7532     PrintF("=====================================\n");
   7533     PrintF("====        Path to object       ====\n");
   7534     PrintF("=====================================\n\n");
   7535 
   7536     ASSERT(!object_stack_.is_empty());
   7537     for (int i = 0; i < object_stack_.length(); i++) {
   7538       if (i > 0) PrintF("\n     |\n     |\n     V\n\n");
   7539       Object* obj = object_stack_[i];
   7540       obj->Print();
   7541     }
   7542     PrintF("=====================================\n");
   7543   }
   7544 }
   7545 
   7546 
   7547 // Triggers a depth-first traversal of reachable objects from one
   7548 // given root object and finds a path to a specific heap object and
   7549 // prints it.
   7550 void Heap::TracePathToObjectFrom(Object* target, Object* root) {
   7551   PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
   7552   tracer.VisitPointer(&root);
   7553 }
   7554 
   7555 
   7556 // Triggers a depth-first traversal of reachable objects from roots
   7557 // and finds a path to a specific heap object and prints it.
   7558 void Heap::TracePathToObject(Object* target) {
   7559   PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
   7560   IterateRoots(&tracer, VISIT_ONLY_STRONG);
   7561 }
   7562 
   7563 
   7564 // Triggers a depth-first traversal of reachable objects from roots
   7565 // and finds a path to any global object and prints it. Useful for
   7566 // determining the source for leaks of global objects.
   7567 void Heap::TracePathToGlobal() {
   7568   PathTracer tracer(PathTracer::kAnyGlobalObject,
   7569                     PathTracer::FIND_ALL,
   7570                     VISIT_ALL);
   7571   IterateRoots(&tracer, VISIT_ONLY_STRONG);
   7572 }
   7573 #endif
   7574 
   7575 
   7576 static intptr_t CountTotalHolesSize(Heap* heap) {
   7577   intptr_t holes_size = 0;
   7578   OldSpaces spaces(heap);
   7579   for (OldSpace* space = spaces.next();
   7580        space != NULL;
   7581        space = spaces.next()) {
   7582     holes_size += space->Waste() + space->Available();
   7583   }
   7584   return holes_size;
   7585 }
   7586 
   7587 
   7588 GCTracer::GCTracer(Heap* heap,
   7589                    const char* gc_reason,
   7590                    const char* collector_reason)
   7591     : start_time_(0.0),
   7592       start_object_size_(0),
   7593       start_memory_size_(0),
   7594       gc_count_(0),
   7595       full_gc_count_(0),
   7596       allocated_since_last_gc_(0),
   7597       spent_in_mutator_(0),
   7598       promoted_objects_size_(0),
   7599       nodes_died_in_new_space_(0),
   7600       nodes_copied_in_new_space_(0),
   7601       nodes_promoted_(0),
   7602       heap_(heap),
   7603       gc_reason_(gc_reason),
   7604       collector_reason_(collector_reason) {
   7605   if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return;
   7606   start_time_ = OS::TimeCurrentMillis();
   7607   start_object_size_ = heap_->SizeOfObjects();
   7608   start_memory_size_ = heap_->isolate()->memory_allocator()->Size();
   7609 
   7610   for (int i = 0; i < Scope::kNumberOfScopes; i++) {
   7611     scopes_[i] = 0;
   7612   }
   7613 
   7614   in_free_list_or_wasted_before_gc_ = CountTotalHolesSize(heap);
   7615 
   7616   allocated_since_last_gc_ =
   7617       heap_->SizeOfObjects() - heap_->alive_after_last_gc_;
   7618 
   7619   if (heap_->last_gc_end_timestamp_ > 0) {
   7620     spent_in_mutator_ = Max(start_time_ - heap_->last_gc_end_timestamp_, 0.0);
   7621   }
   7622 
   7623   steps_count_ = heap_->incremental_marking()->steps_count();
   7624   steps_took_ = heap_->incremental_marking()->steps_took();
   7625   longest_step_ = heap_->incremental_marking()->longest_step();
   7626   steps_count_since_last_gc_ =
   7627       heap_->incremental_marking()->steps_count_since_last_gc();
   7628   steps_took_since_last_gc_ =
   7629       heap_->incremental_marking()->steps_took_since_last_gc();
   7630 }
   7631 
   7632 
   7633 GCTracer::~GCTracer() {
   7634   // Printf ONE line iff flag is set.
   7635   if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return;
   7636 
   7637   bool first_gc = (heap_->last_gc_end_timestamp_ == 0);
   7638 
   7639   heap_->alive_after_last_gc_ = heap_->SizeOfObjects();
   7640   heap_->last_gc_end_timestamp_ = OS::TimeCurrentMillis();
   7641 
   7642   double time = heap_->last_gc_end_timestamp_ - start_time_;
   7643 
   7644   // Update cumulative GC statistics if required.
   7645   if (FLAG_print_cumulative_gc_stat) {
   7646     heap_->total_gc_time_ms_ += time;
   7647     heap_->max_gc_pause_ = Max(heap_->max_gc_pause_, time);
   7648     heap_->max_alive_after_gc_ = Max(heap_->max_alive_after_gc_,
   7649                                      heap_->alive_after_last_gc_);
   7650     if (!first_gc) {
   7651       heap_->min_in_mutator_ = Min(heap_->min_in_mutator_,
   7652                                    spent_in_mutator_);
   7653     }
   7654   } else if (FLAG_trace_gc_verbose) {
   7655     heap_->total_gc_time_ms_ += time;
   7656   }
   7657 
   7658   if (collector_ == SCAVENGER && FLAG_trace_gc_ignore_scavenger) return;
   7659 
   7660   heap_->AddMarkingTime(scopes_[Scope::MC_MARK]);
   7661 
   7662   if (FLAG_print_cumulative_gc_stat && !FLAG_trace_gc) return;
   7663   PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init());
   7664 
   7665   if (!FLAG_trace_gc_nvp) {
   7666     int external_time = static_cast<int>(scopes_[Scope::EXTERNAL]);
   7667 
   7668     double end_memory_size_mb =
   7669         static_cast<double>(heap_->isolate()->memory_allocator()->Size()) / MB;
   7670 
   7671     PrintF("%s %.1f (%.1f) -> %.1f (%.1f) MB, ",
   7672            CollectorString(),
   7673            static_cast<double>(start_object_size_) / MB,
   7674            static_cast<double>(start_memory_size_) / MB,
   7675            SizeOfHeapObjects(),
   7676            end_memory_size_mb);
   7677 
   7678     if (external_time > 0) PrintF("%d / ", external_time);
   7679     PrintF("%.1f ms", time);
   7680     if (steps_count_ > 0) {
   7681       if (collector_ == SCAVENGER) {
   7682         PrintF(" (+ %.1f ms in %d steps since last GC)",
   7683                steps_took_since_last_gc_,
   7684                steps_count_since_last_gc_);
   7685       } else {
   7686         PrintF(" (+ %.1f ms in %d steps since start of marking, "
   7687                    "biggest step %.1f ms)",
   7688                steps_took_,
   7689                steps_count_,
   7690                longest_step_);
   7691       }
   7692     }
   7693 
   7694     if (gc_reason_ != NULL) {
   7695       PrintF(" [%s]", gc_reason_);
   7696     }
   7697 
   7698     if (collector_reason_ != NULL) {
   7699       PrintF(" [%s]", collector_reason_);
   7700     }
   7701 
   7702     PrintF(".\n");
   7703   } else {
   7704     PrintF("pause=%.1f ", time);
   7705     PrintF("mutator=%.1f ", spent_in_mutator_);
   7706     PrintF("gc=");
   7707     switch (collector_) {
   7708       case SCAVENGER:
   7709         PrintF("s");
   7710         break;
   7711       case MARK_COMPACTOR:
   7712         PrintF("ms");
   7713         break;
   7714       default:
   7715         UNREACHABLE();
   7716     }
   7717     PrintF(" ");
   7718 
   7719     PrintF("external=%.1f ", scopes_[Scope::EXTERNAL]);
   7720     PrintF("mark=%.1f ", scopes_[Scope::MC_MARK]);
   7721     PrintF("sweep=%.1f ", scopes_[Scope::MC_SWEEP]);
   7722     PrintF("sweepns=%.1f ", scopes_[Scope::MC_SWEEP_NEWSPACE]);
   7723     PrintF("evacuate=%.1f ", scopes_[Scope::MC_EVACUATE_PAGES]);
   7724     PrintF("new_new=%.1f ", scopes_[Scope::MC_UPDATE_NEW_TO_NEW_POINTERS]);
   7725     PrintF("root_new=%.1f ", scopes_[Scope::MC_UPDATE_ROOT_TO_NEW_POINTERS]);
   7726     PrintF("old_new=%.1f ", scopes_[Scope::MC_UPDATE_OLD_TO_NEW_POINTERS]);
   7727     PrintF("compaction_ptrs=%.1f ",
   7728         scopes_[Scope::MC_UPDATE_POINTERS_TO_EVACUATED]);
   7729     PrintF("intracompaction_ptrs=%.1f ",
   7730         scopes_[Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED]);
   7731     PrintF("misc_compaction=%.1f ", scopes_[Scope::MC_UPDATE_MISC_POINTERS]);
   7732     PrintF("weakcollection_process=%.1f ",
   7733         scopes_[Scope::MC_WEAKCOLLECTION_PROCESS]);
   7734     PrintF("weakcollection_clear=%.1f ",
   7735         scopes_[Scope::MC_WEAKCOLLECTION_CLEAR]);
   7736 
   7737     PrintF("total_size_before=%" V8_PTR_PREFIX "d ", start_object_size_);
   7738     PrintF("total_size_after=%" V8_PTR_PREFIX "d ", heap_->SizeOfObjects());
   7739     PrintF("holes_size_before=%" V8_PTR_PREFIX "d ",
   7740            in_free_list_or_wasted_before_gc_);
   7741     PrintF("holes_size_after=%" V8_PTR_PREFIX "d ", CountTotalHolesSize(heap_));
   7742 
   7743     PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc_);
   7744     PrintF("promoted=%" V8_PTR_PREFIX "d ", promoted_objects_size_);
   7745     PrintF("nodes_died_in_new=%d ", nodes_died_in_new_space_);
   7746     PrintF("nodes_copied_in_new=%d ", nodes_copied_in_new_space_);
   7747     PrintF("nodes_promoted=%d ", nodes_promoted_);
   7748 
   7749     if (collector_ == SCAVENGER) {
   7750       PrintF("stepscount=%d ", steps_count_since_last_gc_);
   7751       PrintF("stepstook=%.1f ", steps_took_since_last_gc_);
   7752     } else {
   7753       PrintF("stepscount=%d ", steps_count_);
   7754       PrintF("stepstook=%.1f ", steps_took_);
   7755       PrintF("longeststep=%.1f ", longest_step_);
   7756     }
   7757 
   7758     PrintF("\n");
   7759   }
   7760 
   7761   heap_->PrintShortHeapStatistics();
   7762 }
   7763 
   7764 
   7765 const char* GCTracer::CollectorString() {
   7766   switch (collector_) {
   7767     case SCAVENGER:
   7768       return "Scavenge";
   7769     case MARK_COMPACTOR:
   7770       return "Mark-sweep";
   7771   }
   7772   return "Unknown GC";
   7773 }
   7774 
   7775 
   7776 int KeyedLookupCache::Hash(Map* map, Name* name) {
   7777   // Uses only lower 32 bits if pointers are larger.
   7778   uintptr_t addr_hash =
   7779       static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map)) >> kMapHashShift;
   7780   return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask);
   7781 }
   7782 
   7783 
   7784 int KeyedLookupCache::Lookup(Map* map, Name* name) {
   7785   int index = (Hash(map, name) & kHashMask);
   7786   for (int i = 0; i < kEntriesPerBucket; i++) {
   7787     Key& key = keys_[index + i];
   7788     if ((key.map == map) && key.name->Equals(name)) {
   7789       return field_offsets_[index + i];
   7790     }
   7791   }
   7792   return kNotFound;
   7793 }
   7794 
   7795 
   7796 void KeyedLookupCache::Update(Map* map, Name* name, int field_offset) {
   7797   if (!name->IsUniqueName()) {
   7798     String* internalized_string;
   7799     if (!HEAP->InternalizeStringIfExists(
   7800             String::cast(name), &internalized_string)) {
   7801       return;
   7802     }
   7803     name = internalized_string;
   7804   }
   7805   // This cache is cleared only between mark compact passes, so we expect the
   7806   // cache to only contain old space names.
   7807   ASSERT(!HEAP->InNewSpace(name));
   7808 
   7809   int index = (Hash(map, name) & kHashMask);
   7810   // After a GC there will be free slots, so we use them in order (this may
   7811   // help to get the most frequently used one in position 0).
   7812   for (int i = 0; i< kEntriesPerBucket; i++) {
   7813     Key& key = keys_[index];
   7814     Object* free_entry_indicator = NULL;
   7815     if (key.map == free_entry_indicator) {
   7816       key.map = map;
   7817       key.name = name;
   7818       field_offsets_[index + i] = field_offset;
   7819       return;
   7820     }
   7821   }
   7822   // No free entry found in this bucket, so we move them all down one and
   7823   // put the new entry at position zero.
   7824   for (int i = kEntriesPerBucket - 1; i > 0; i--) {
   7825     Key& key = keys_[index + i];
   7826     Key& key2 = keys_[index + i - 1];
   7827     key = key2;
   7828     field_offsets_[index + i] = field_offsets_[index + i - 1];
   7829   }
   7830 
   7831   // Write the new first entry.
   7832   Key& key = keys_[index];
   7833   key.map = map;
   7834   key.name = name;
   7835   field_offsets_[index] = field_offset;
   7836 }
   7837 
   7838 
   7839 void KeyedLookupCache::Clear() {
   7840   for (int index = 0; index < kLength; index++) keys_[index].map = NULL;
   7841 }
   7842 
   7843 
   7844 void DescriptorLookupCache::Clear() {
   7845   for (int index = 0; index < kLength; index++) keys_[index].source = NULL;
   7846 }
   7847 
   7848 
   7849 #ifdef DEBUG
   7850 void Heap::GarbageCollectionGreedyCheck() {
   7851   ASSERT(FLAG_gc_greedy);
   7852   if (isolate_->bootstrapper()->IsActive()) return;
   7853   if (disallow_allocation_failure()) return;
   7854   CollectGarbage(NEW_SPACE);
   7855 }
   7856 #endif
   7857 
   7858 
   7859 TranscendentalCache::SubCache::SubCache(Type t)
   7860   : type_(t),
   7861     isolate_(Isolate::Current()) {
   7862   uint32_t in0 = 0xffffffffu;  // Bit-pattern for a NaN that isn't
   7863   uint32_t in1 = 0xffffffffu;  // generated by the FPU.
   7864   for (int i = 0; i < kCacheSize; i++) {
   7865     elements_[i].in[0] = in0;
   7866     elements_[i].in[1] = in1;
   7867     elements_[i].output = NULL;
   7868   }
   7869 }
   7870 
   7871 
   7872 void TranscendentalCache::Clear() {
   7873   for (int i = 0; i < kNumberOfCaches; i++) {
   7874     if (caches_[i] != NULL) {
   7875       delete caches_[i];
   7876       caches_[i] = NULL;
   7877     }
   7878   }
   7879 }
   7880 
   7881 
   7882 void ExternalStringTable::CleanUp() {
   7883   int last = 0;
   7884   for (int i = 0; i < new_space_strings_.length(); ++i) {
   7885     if (new_space_strings_[i] == heap_->the_hole_value()) {
   7886       continue;
   7887     }
   7888     if (heap_->InNewSpace(new_space_strings_[i])) {
   7889       new_space_strings_[last++] = new_space_strings_[i];
   7890     } else {
   7891       old_space_strings_.Add(new_space_strings_[i]);
   7892     }
   7893   }
   7894   new_space_strings_.Rewind(last);
   7895   new_space_strings_.Trim();
   7896 
   7897   last = 0;
   7898   for (int i = 0; i < old_space_strings_.length(); ++i) {
   7899     if (old_space_strings_[i] == heap_->the_hole_value()) {
   7900       continue;
   7901     }
   7902     ASSERT(!heap_->InNewSpace(old_space_strings_[i]));
   7903     old_space_strings_[last++] = old_space_strings_[i];
   7904   }
   7905   old_space_strings_.Rewind(last);
   7906   old_space_strings_.Trim();
   7907 #ifdef VERIFY_HEAP
   7908   if (FLAG_verify_heap) {
   7909     Verify();
   7910   }
   7911 #endif
   7912 }
   7913 
   7914 
   7915 void ExternalStringTable::TearDown() {
   7916   new_space_strings_.Free();
   7917   old_space_strings_.Free();
   7918 }
   7919 
   7920 
   7921 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) {
   7922   chunk->set_next_chunk(chunks_queued_for_free_);
   7923   chunks_queued_for_free_ = chunk;
   7924 }
   7925 
   7926 
   7927 void Heap::FreeQueuedChunks() {
   7928   if (chunks_queued_for_free_ == NULL) return;
   7929   MemoryChunk* next;
   7930   MemoryChunk* chunk;
   7931   for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) {
   7932     next = chunk->next_chunk();
   7933     chunk->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED);
   7934 
   7935     if (chunk->owner()->identity() == LO_SPACE) {
   7936       // StoreBuffer::Filter relies on MemoryChunk::FromAnyPointerAddress.
   7937       // If FromAnyPointerAddress encounters a slot that belongs to a large
   7938       // chunk queued for deletion it will fail to find the chunk because
   7939       // it try to perform a search in the list of pages owned by of the large
   7940       // object space and queued chunks were detached from that list.
   7941       // To work around this we split large chunk into normal kPageSize aligned
   7942       // pieces and initialize size, owner and flags field of every piece.
   7943       // If FromAnyPointerAddress encounters a slot that belongs to one of
   7944       // these smaller pieces it will treat it as a slot on a normal Page.
   7945       Address chunk_end = chunk->address() + chunk->size();
   7946       MemoryChunk* inner = MemoryChunk::FromAddress(
   7947           chunk->address() + Page::kPageSize);
   7948       MemoryChunk* inner_last = MemoryChunk::FromAddress(chunk_end - 1);
   7949       while (inner <= inner_last) {
   7950         // Size of a large chunk is always a multiple of
   7951         // OS::AllocateAlignment() so there is always
   7952         // enough space for a fake MemoryChunk header.
   7953         Address area_end = Min(inner->address() + Page::kPageSize, chunk_end);
   7954         // Guard against overflow.
   7955         if (area_end < inner->address()) area_end = chunk_end;
   7956         inner->SetArea(inner->address(), area_end);
   7957         inner->set_size(Page::kPageSize);
   7958         inner->set_owner(lo_space());
   7959         inner->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED);
   7960         inner = MemoryChunk::FromAddress(
   7961             inner->address() + Page::kPageSize);
   7962       }
   7963     }
   7964   }
   7965   isolate_->heap()->store_buffer()->Compact();
   7966   isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED);
   7967   for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) {
   7968     next = chunk->next_chunk();
   7969     isolate_->memory_allocator()->Free(chunk);
   7970   }
   7971   chunks_queued_for_free_ = NULL;
   7972 }
   7973 
   7974 
   7975 void Heap::RememberUnmappedPage(Address page, bool compacted) {
   7976   uintptr_t p = reinterpret_cast<uintptr_t>(page);
   7977   // Tag the page pointer to make it findable in the dump file.
   7978   if (compacted) {
   7979     p ^= 0xc1ead & (Page::kPageSize - 1);  // Cleared.
   7980   } else {
   7981     p ^= 0x1d1ed & (Page::kPageSize - 1);  // I died.
   7982   }
   7983   remembered_unmapped_pages_[remembered_unmapped_pages_index_] =
   7984       reinterpret_cast<Address>(p);
   7985   remembered_unmapped_pages_index_++;
   7986   remembered_unmapped_pages_index_ %= kRememberedUnmappedPages;
   7987 }
   7988 
   7989 
   7990 void Heap::ClearObjectStats(bool clear_last_time_stats) {
   7991   memset(object_counts_, 0, sizeof(object_counts_));
   7992   memset(object_sizes_, 0, sizeof(object_sizes_));
   7993   if (clear_last_time_stats) {
   7994     memset(object_counts_last_time_, 0, sizeof(object_counts_last_time_));
   7995     memset(object_sizes_last_time_, 0, sizeof(object_sizes_last_time_));
   7996   }
   7997 }
   7998 
   7999 
   8000 static LazyMutex checkpoint_object_stats_mutex = LAZY_MUTEX_INITIALIZER;
   8001 
   8002 
   8003 void Heap::CheckpointObjectStats() {
   8004   ScopedLock lock(checkpoint_object_stats_mutex.Pointer());
   8005   Counters* counters = isolate()->counters();
   8006 #define ADJUST_LAST_TIME_OBJECT_COUNT(name)                                    \
   8007   counters->count_of_##name()->Increment(                                      \
   8008       static_cast<int>(object_counts_[name]));                                 \
   8009   counters->count_of_##name()->Decrement(                                      \
   8010       static_cast<int>(object_counts_last_time_[name]));                       \
   8011   counters->size_of_##name()->Increment(                                       \
   8012       static_cast<int>(object_sizes_[name]));                                  \
   8013   counters->size_of_##name()->Decrement(                                       \
   8014       static_cast<int>(object_sizes_last_time_[name]));
   8015   INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
   8016 #undef ADJUST_LAST_TIME_OBJECT_COUNT
   8017   int index;
   8018 #define ADJUST_LAST_TIME_OBJECT_COUNT(name)               \
   8019   index = FIRST_CODE_KIND_SUB_TYPE + Code::name;          \
   8020   counters->count_of_CODE_TYPE_##name()->Increment(       \
   8021       static_cast<int>(object_counts_[index]));           \
   8022   counters->count_of_CODE_TYPE_##name()->Decrement(       \
   8023       static_cast<int>(object_counts_last_time_[index])); \
   8024   counters->size_of_CODE_TYPE_##name()->Increment(        \
   8025       static_cast<int>(object_sizes_[index]));            \
   8026   counters->size_of_CODE_TYPE_##name()->Decrement(        \
   8027       static_cast<int>(object_sizes_last_time_[index]));
   8028   CODE_KIND_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
   8029 #undef ADJUST_LAST_TIME_OBJECT_COUNT
   8030 #define ADJUST_LAST_TIME_OBJECT_COUNT(name)               \
   8031   index = FIRST_FIXED_ARRAY_SUB_TYPE + name;              \
   8032   counters->count_of_FIXED_ARRAY_##name()->Increment(     \
   8033       static_cast<int>(object_counts_[index]));           \
   8034   counters->count_of_FIXED_ARRAY_##name()->Decrement(     \
   8035       static_cast<int>(object_counts_last_time_[index])); \
   8036   counters->size_of_FIXED_ARRAY_##name()->Increment(      \
   8037       static_cast<int>(object_sizes_[index]));            \
   8038   counters->size_of_FIXED_ARRAY_##name()->Decrement(      \
   8039       static_cast<int>(object_sizes_last_time_[index]));
   8040   FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
   8041 #undef ADJUST_LAST_TIME_OBJECT_COUNT
   8042 
   8043   OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_));
   8044   OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_));
   8045   ClearObjectStats();
   8046 }
   8047 
   8048 
   8049 Heap::RelocationLock::RelocationLock(Heap* heap) : heap_(heap) {
   8050   if (FLAG_parallel_recompilation) {
   8051     heap_->relocation_mutex_->Lock();
   8052 #ifdef DEBUG
   8053     heap_->relocation_mutex_locked_by_optimizer_thread_ =
   8054         heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread();
   8055 #endif  // DEBUG
   8056   }
   8057 }
   8058 
   8059 } }  // namespace v8::internal
   8060